Tcl Library Source Code

Changes On Branch amg-pipeline
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch amg-pipeline Excluding Merge-Ins

This is equivalent to a diff from 50fdc84e6c to e7b61937e1

2019-11-24
21:24
Merge trunk Leaf check-in: e7b61937e1 user: andy tags: amg-pipeline
2019-11-23
05:02
1. Integrated markdown work. Updated local documentation. 2. Reworked the collection and post processing of per-test(suite) timings added in commit [6b2f59f4e4] for faster sorting. Further fixed an issue with the collection of the per-test timings in the face of variable-field data. 3. Switching the 8.6 series from 8.6.9 to 8.6.10 for testing caused failures (hook, string::token::shell) due to changes in command name reporting (FQN in a few places where plain names were reported before). This actually looks to be a bug fix, restoring 8.5 behaviour. These testsuite issues were fixed by extending the test code used to select the expected result by core version. Added a new test utility command `byConstraint` to help with that, allowing for easy multi-way selection. check-in: b99647b031 user: aku tags: trunk
2019-04-17
06:45
Allow parse_args-style comments check-in: 487e9d220e user: andy tags: amg-argparse
2019-04-15
04:04
Import pipeline version 0.3 which adds -params and -init switches to [pipeline::loop]. makes -separate not require -buffer, and adds [pipeline::procLoop] check-in: 840e4efea8 user: andy tags: amg-pipeline
03:44
Merge amg-argparse check-in: ec05a2e2e4 user: andy tags: amg-pipeline
03:44
Import argparse version 0.4 which adds the ability to put overall options directly in the parameter definition list, a feature needed by the latest version of pipeline check-in: 50fdc84e6c user: andy tags: amg-argparse
2019-04-08
07:19
Begin adding argparse package check-in: ef01ec1300 user: andy tags: amg-argparse

Added .fossil-settings/ignore-glob.











>
>
>
>
>
1
2
3
4
5
M
MSG*
X.*
_work
modules/tcllibc

Changes to .github/CONTRIBUTING.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Hello.

You are currently using the github __mirror__ of the Tcllib sources.

This is __not__ the location where development takes place.

We are not tracking issues entered here.  With the exception of the
maintainer of the mirroring setup nobody will even see such issues.

Please go to the
[official location of the sources](https://core.tcl.tk/tcllib)
and enter your ticket into the
[official ticket tracker](https://core.tcl.tk/tcllib/reportlist)
instead.

Thank you for your consideration.

|



|

|



|

|



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Hello. __Attention please__

You are currently using the github __mirror__ of the Tcllib sources.

This is __not__ the location where Tcllib development takes place.

We are __not tracking issues entered here__. With the exception of the
maintainer of the mirroring setup nobody will even see such issues.

Please go to the
[official location of the sources](https://core.tcl-lang.org/tcllib)
and enter your ticket into the
[official ticket tracker](https://core.tcl-lang.org/tcllib/reportlist)
instead.

Thank you for your consideration.

Changes to .github/ISSUE_TEMPLATE.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Hello.

You are currently using the github __mirror__ of the Tcllib sources.

This is __not__ the location where development takes place.

We are not tracking issues entered here.  With the exception of the
maintainer of the mirroring setup nobody will even see such issues.

Please go to the
[official location of the sources](https://core.tcl.tk/tcllib)
and enter your ticket into the
[official ticket tracker](https://core.tcl.tk/tcllib/reportlist)
instead.

Thank you for your consideration.

|



|

|



|

|



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Hello. __Attention please__

You are currently using the github __mirror__ of the Tcllib sources.

This is __not__ the location where Tcllib development takes place.

We are __not tracking issues entered here__. With the exception of the
maintainer of the mirroring setup nobody will even see such issues.

Please go to the
[official location of the sources](https://core.tcl-lang.org/tcllib)
and enter your ticket into the
[official ticket tracker](https://core.tcl-lang.org/tcllib/reportlist)
instead.

Thank you for your consideration.

Changes to .github/PULL_REQUEST_TEMPLATE.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Hello.

You are currently using the github __mirror__ of the Tcllib sources.

This is __not__ the location where development takes place.

We are not tracking issues entered here.  With the exception of the
maintainer of the mirroring setup nobody will even see such issues.

Please go to the
[official location of the sources](https://core.tcl.tk/tcllib)
and enter your ticket into the
[official ticket tracker](https://core.tcl.tk/tcllib/reportlist)
instead.

Thank you for your consideration.

|



|

|



|

|



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Hello. __Attention please__

You are currently using the github __mirror__ of the Tcllib sources.

This is __not__ the location where Tcllib development takes place.

We are __not tracking issues entered here__. With the exception of the
maintainer of the mirroring setup nobody will even see such issues.

Please go to the
[official location of the sources](https://core.tcl-lang.org/tcllib)
and enter your ticket into the
[official ticket tracker](https://core.tcl-lang.org/tcllib/reportlist)
instead.

Thank you for your consideration.

Deleted INSTALL.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
How to install Tcllib
=====================

Introduction
------------

The tcllib distribution, whether a snapshot directly from CVS, or
officially released, offers a single method for installing tcllib,
based on Tcl itself.

This is based on the assumption that for tcllib to be of use Tcl has
to be present, and therefore can be used.

This single method however can be used in a variety of ways.

0	For an unwrapped (= directory) distribution or CVS snapshot

	a.	either call the application 'installer.tcl' directly,
	b	or use

			% configure ; make install

		The latter is provided for people which are used to
		this method and more comfortable with it. In end this
		boils down into a call of 'installer.tcl' too.

1.	A starpack distribution (window-only) is a self-extracting
	installer which internally uses the aforementioned installer.

2.	A starkit distribution is very much like a starpack, but
	required an external interpreyter to run. This can be any tcl
	interpreter which has all the packages to support starkits
	(tclvfs, memchan, trf).

3.	A distribution in a tarball has to be unpacked first, then any
	of the methods described in (0) can be used.


Usage of the installer
----------------------

The installer selects automatically either a gui based mode, or a
command line based mode. If the package Tk is present and can be
loaded, then the GUI mode is entered, else the system falls back to
the command line.

Note that it is possible to specify options on the command line even
if the installer ultimatively selects a gui mode. In that case the
hardwired defaults and the options determine the data presented to the
user for editing.

Command line help can be asked for by using the option -help when
running the installer (3) or the distribution itself in the case of
(1) or (2).

The installer will select a number of defaults for the locations of
packages, examples, and documentation, and also the format of the
documentation. The user can overide these defaults in the GUI, or by
specifying additional options.

The defaults depend on the platform detected (unix/windows) and the
executable used to run the installer. In the case of a starpack
distribution (1) this means that _no defaults_ are possible for the
various locations as the executable is part of the distribution and
has no knowledge of its environment.

In all other cases the intepreter executable is outside of the
distribution, which means that its location can be used to determine
sensible defaults.

Notes
-----

The installer will overwrite an existing installation of tcllib 1.6
without asking back after the initial confirmation is given. And if
the user chooses the same directory as for tcllib 1.4, or 1.3, etc.
then the installer will overwrite that too.
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































































Deleted README.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
RCS: @(#) $Id: README,v 1.9 2007/08/30 17:24:13 andreas_kupries Exp $

Welcome to the Tcllib, the Tcl Standard Library.  This package is
intended to be a collection of Tcl packages that provide utility
functions useful to a large collection of Tcl programmers.

The home web site for this code is http://core.tcl.tk/tcllib/ .
At this web site, you will find mailing lists, web forums, databases
for bug reports and feature requests, the CVS repository (browsable on
the web, or read-only accessible via CVS ), and more.

The structure of the tcllib source hierarchy is:

tcllib
 +- modules
     +- <module1>
     +- <module2>
     +- ...


The install hierarchy is:

.../lib/tcllib
        +- <module1>
        +- <module2>
        +- ...

There are some base requirements that a module must meet before it
will be added to tcllib:

* the module must be a proper Tcl package
* the module must use a namespace for its commands and variables
* the name of the package must be the same as the name of the
  namespace
* the module must reside in a subdirectory of the modules directory in
  the source hierarchy, and that subdirectory must have the same name
  as the package and namespace
* the module must be released under the BSD License, the terms of
  which can be found in the toplevel tcllib source directory in the file
  license.terms
* the module should have both documentation ([*]) and a test suite
  (in the form of a group of *.test files in the module directory).

  [*] Possible forms: doctools, TMML/XML, nroff (man), or HTML.
      The first format is the most preferred as it can be processed with
      tools provided by tcllib itself (See module doctools). The first
      two are preferred in general as they are semantic markup and thus
      easier to convert into other formats.

* the module must have either documentation or a test suite.  It can
  not have neither.
* the module should adhere to Tcl coding standards

When adding a module to tcllib, be sure to add it to the files listed below.

* installed_modules.tcl

  contains a table listing all modules to be installed, modules
  excluded, and names the actions to be taken during installation
  of each module. Add a line to this table naming your module and
  its actions.

  Three actions have to be specified, for the package itself, its
  documentation, and the examples demonstrating it.

  The _null action can be used everywhere and signals that there is
  nothing to do. Although it is possible to use it for the package
  action it does make no sense there, as that means that no package
  code is installed.

  Other package actions are _tcl, _tci, and _text. The first causes
  the installer to copy all .tcl files from the source directory for
  the module into the appropriate module directory. _tci does all that
  and also expects a tclIndex file to copy. _tex is like _tcl, however
  it also copies all .tex files found in the source directory for the
  module.

  There is currently only one true documentation action. This action
  is _doc. It converts all documentation in doctools format into the
  format chosen by the user for installation and copies the result
  into the appropriate directory.

  There is currently one true action for examples, _exa. It copies all
  files in the source directory for examples into the directory chosen
  by the user as destination for examples.

Each module source directory should have no subdirectories (other than
the CVS directory), and should contain the following files:

* source code		*.tcl
* package index		pkgIndex.tcl
* tests			*.test
* documentation		*.man, *.n, *.xml

If you do not follow this directory structure, the tcllib Makefile
will fail to locate the files from the new module.
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































Deleted README.developer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
RCS: @(#) $Id: README.developer,v 1.6 2009/06/02 22:49:55 andreas_kupries Exp $

Welcome to the tcllib, the Tcl Standard Library.
================================================

Introduction
------------

This README is intended to be a guide to the tools available to a

	Developer

working on Tcllib to help him with his tasks, i.e. making the tasks easier
to perform. It is our hope that this will improve the quality of even
non-released revisions of Tcllib, and make the work of the release
manager easier as well.

Audience
--------

The intended audience are, first and foremost, developers beginning to
work on Tcllib. To an experienced developer this document will be less
of a guide and more of a reference. Anybody else interested in working
on Tcllib is invited as well.


Directory hierarchy and file basics
------------------------------------

The main directories under the tcllib top directory are

	modules/
	examples/
and	apps/

Each directory FOO under modules/ represents one package, sometimes
more. In the case of the latter the packages are usually related in
some way. Examples are the base64, math, and struct modules, with
loose (base64) to strong (math) relations between the packages.

Examples associated with a module FOO, if there are any, are placed
into the directory

	examples/FOO

Any type of distributable application can be found under apps/,
together with their documentation, if any. Note that the apps/
directory is currently not split into sub-directories.

Regarding the files in Tcllib, the most common types found are

	.tcl	Tcl code for a package.

	.man	Documentation for a package, in doctools format.

	.test	Test suite for a package, or part of. Based on tcltest.

	.bench	Performance benchmarks for a package, or part of.
		Based on modules/bench

	.pcx	Syntax rules for TclDevKit's tclchecker. Using these
		rules allows tclchecker to check the use of commands
		of a Tcllib package X without having to scan the
		implementation of X, i.e. its .tcl files.


Adding a new module
-------------------

Assuming that FOO is the name of the new module, and T is the toplevel
directory of the Tcllib sources

(1)	Create the directory T/modules/FOO and put all the files of
	the module into it. Note:

	* The file 'pkgIndex.tcl' is required.

	* Implementation files should have the extension '.tcl',
	  naturally.

	* If available, documentation should be in doctools format,
          and the files should have the extension '.man' for SAK to
          recognize them.

	* If available the testsuite(s) should use 'tcltest' and the
	  general format as used by the other modules in Tcllib
	  (declaration of minimally needed Tcl, tcltest, supporting
	  packages, etc.). The file(s) should have the extension
	  '.test' for SAK to recognize them.

	  Note that an empty testsuite, or a testsuite which does not
	  perform any tests is less than useful and will not be
	  accepted.

	* If available the benchmark(s) should use 'bench' and the
          general format as used by the other modules in Tcllib. The
          file(s) should have the extension '.bench' for SAK to
          recognize them.

	* Other files can be named and placed as the module sees fit.

(2)	If the new module has an example application A which is
	polished enough for general use, put this application into the
	file "T/apps/A.tcl", and its documentation into the file
	"T/apps/A.man". While documentation for the application is
	optional, it is preferred.

	For examples which are not full-fledged applications, a
	skeleton, or not really polished for use, etc., create the
	directory T/examples/FOO/ and put them there.

	A key difference is what happens to them on installation, and
	what the target audience is.

	The examples are for developers using packages in Tcllib,
	whereas the applications are also for users of Tcllib which do
	not have an interest in developing for and with it. As such,
	they are installed as regular commands, accessible through the
	PATH, and example files are not installed.

(3)	To make Tcllib's installer aware of FOO, edit the file

		T/support/installation/modules.tcl

	Add a line 'Module FOO $impaction $docaction $exaction'. The
	various actions describe to the installer how to install the
	implementation files, the documentation, and the examples.

	Add a line 'Application A' for any application A which was
	added to T/apps for FOO.

	The following actions are available:

	Implementation

		_tcl - Copy all .tcl files in T/modules/FOO into the installation.
		_tcr - See above, does it for .tcl files in subdirectories as well.
		_tci - _tcl + Copying of a tclIndex - special to modules 'math', 'control'.
		_msg - _tcl + Copying of subdir 'msgs' - special to modules 'dns', 'log'.
		_doc - _tcl + Copying of subdir 'mpformats' - special to module 'doctools'.
		_tex - _tcl + Copying of .tex files - special to module 'textutil'.

		The _null action, see below, is available in principle
		too, but a module without implementation does not make
		sense.

	Documentation

		_null - Module has no documentation, do nothing.
		_man  - Process the .man files in T/modules/FOO and
			install the results (nroff and/or HTML) in the
			proper location, as given to the installer.

	Examples

		_null - Module has no examples, do nothing
		_exa  - Copy the directory T/examples/FOO
			(recursively) to the install location for
			examples.


Testing modules
---------------

To run the testsuite of a module FOO in tcllib use the 'test run'
argument of sak.tcl, like so:

	% pwd
	/the/tcllib/toplevel/directory

	% ./sak.tcl test run FOO
or	% ./sak.tcl test run modules/FOO

To run the testsuites of all modules either invoke 'test run' without a
module name, or use 'make test'. The latter assumes that configure was
run for Tcllib before, i.e.:

	% ./sak.tcl test run
or	% ./sak.tcl test run
	% make test

In all of the above cases the result will be a combination of progress
display and testsuite log, showing for each module the tests that pass
or failed and how many of each in a summary at the end.

To get a detailed log, it is necessary to invoke 'test run' with
additional options.

First example:
	% ./sak.tcl test run -l LOG FOO

This shows the same short log on the terminal, and writes a detailed
log to the file LOG.log, and excerpts to other files (LOG.summary,
LOG.failures, etc.).

Second example:
	% ./sak.tcl test run -v FOO
	% make test > LOG

This writes the detailed log to stdout, or to the file LOG, instead of
the short log. In all cases, the detailed log contains a list of all
test cases executed, which failed, and how they failed (expected
versus actual results).

Note:
The commands
	% make test
and	% make test > LOG

are able to generate different output (short vs long log) because the
Makefile target contains code which detects that stdout has been
redirected to a file and acts accordingly.

Non-developers should reports problems in Tcllib's bug tracker.
Information about its location and the relevant category can be found
in the section 'BUGS, IDEAS, FEEDBACK' of the manpage of the module
and/or package.

Module documentation
--------------------

The main format used for the documentation of packages in Tcllib is
'doctools', the support packages of which are part of Tcllib, see the
module 'doctools'.

To convert this documentation to HTML or nroff manpages, or some other
format use the 'doc' argument of sak.tcl, like so:

	% pwd
	/the/tcllib/toplevel/directory

	% ./sak.tcl doc html FOO
or	% ./sak.tcl doc html modules/FOO

The result of the conversion can be found in the newly-created 'doc'
directory in the current working directory.

The set of formats the documentation can be converted into can be
queried via

	% ./sak.tcl help doc


To convert the documentation of all modules either invoke 'test run'
without a module name, or use 'make html-doc', etc.. The latter
assumes that configure was run for Tcllib before, i.e.:

	% ./sak.tcl doc html
	% make html-doc

Note the special format 'validate'. Using this format does not convert
the documentation to anything (and the sub-directory 'doc' will not be
created), it just checks that the documentation is syntactically
correct. I.e.

	% ./sak.tcldoc validate modules/FOO
	% ./sak.tcldoc validate


Validating modules
------------------

Running the testsuite of a module, or checking the syntax of its
documentation (see the previous sections) are two forms of validation.

The 'validate' command of sak.tcl provides a few more. The online
documentation of this command is available via

	% ./sak.tcl help validate

The validated parts are man pages, testsuites, version information,
and syntax. The latter only if various static syntax checkers are
available on the PATH, like TclDevKit's tclchecker.

Note that testsuite validation is not the execution of the testsuites,
only if a package has a testsuite or not.

It is strongly recommended to validate a module before committing any
type of change made to it.

It is recommended to validate all modules before committing any type
of change made to one of them. We have package inter-dependencies
between packages in Tcllib, thus changing one package may break
others, and just validating the changed package will not catch such
problems.


Writing Tests
-------------

While a previous section talked about running the testsuite for a
module and the packages therein this has no meaning if the module in
question has no testsuites at all.

This section gives a very basic overview on methodologies for writing
tests and testsuites.

First there are "drudgery" tests. Written to check absolutely basic
assumptions which should never fail.

Example:

	For a command FOO taking two arguments, three tests calling it
	with zero, one, and three arguments. The basic checks that the
	command fails if it has not enough arguments, or too many.

After that come the tests checking things based on our knowledge of
the command, about its properties and assumptions. Some examples based
on the graph operations added during Google's Summer of Code 2009.

**	The BellmanFord command in struct::graph::ops takes a
	_startnode_ as argument, and this node should be a node of the
	graph. equals one test case checking the behavior when the
	specified node is not a node a graph.

	This often gives rise to code in the implementation which
	explicitly checks the assumption and throws a nice error.
	Instead of letting the algorithm fails later in some weird
	non-deterministic way.

	Such checks cannot be done always. The graph argument for
	example is just a command in itself, and while we expect it to
	exhibit a certain interface, i.e. set of sub-commands aka
	methods, we cannot check that it has them, except by actually
	trying to use them. That is done by the algorithm anyway, so
	an explicit check is just overhead we can get by without.

**	IIRC one of the distinguishing characteristic of either
	BellmanFord and/or Johnson is that they are able to handle
	negative weights. Whereas Dijkstra requires positive weights.

	This induces (at least) three testcases ... Graph with all
	positive weights, all negative, and a mix of positive and
	negative weights.

	Thinking further does the algorithm handle the weight '0' as
	well ? Another test case, or several, if we mix zero with
	positive and negative weights.

**	The two algorithms we are currently thinking about are about
	distances between nodes, and distance can be 'Inf'inity,
	i.e. nodes may not be connected. This means that good test
	cases are

	(1)	Strongly connected graph
	(2)	Connected graph
	(3)	Disconnected graph.

	At the extremes of (1) and (3) we have the fully connected
	graphs and graphs without edges, only nodes, i.e. completely
	disconnected.

**	IIRC both of the algorithms take weighted arcs, and fill in a
	default if arcs are left unweighted in the input graph.

	This also induces three test cases:

	(1)	Graph will all arcs with explicit weights.
	(2)	Graph without weights at all.
	(3)	Graph with mixture of weighted and unweighted graphs.


What was described above via examples is called 'black-box' testing.
Test cases are designed and written based on our knowledge of the
properties of the algorithm and its inputs, without referencing a
particular implementation.

Going further, a complement to 'black-box' testing is 'white-box'. For
this we know the implementation of the algorithm, we look at it and
design our tests cases so that they force the code through all
possible paths in the implementation. Wherever a decision is made we
have a test cases forcing a specific direction of the decision, for
all possible directions.

In practice I often hope that the black-box tests I have made are
enough to cover all the paths, obviating the need for white-box tests.

So, if you, dear reader, now believe that writing tests for an
algorithm takes at least as much time as coding the algorithm, and
often more time, then you are completely right. It does. Much more
time. See for example also http://sqlite.org/testing.html, a writeup
on how the Sqlite database engine is tested.



An interesting connection is to documentation. In one direction, the
properties you are checking with black-box testing are properties
which should be documented in the algorithm man page. And conversely,
if you have documentation of properties of an algorithm then this is a
good reference to base black-box tests on.

In practice test cases and documentation often get written together,
cross-influencing each other. And the actual writing of test cases is
a mix of black and white box, possibly influencing the implementation
while writing the tests. Like writing test for 'startnode not in input
graph' serving as reminder to put in a check for this into the code.
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































































































































































































































































































































































































































































































































































































































































































































































































Changes to README.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17

































Hello.

If you are reading this then you are very likely at the github
__mirror__ of the Tcllib sources.

This means that the
[official location of the sources](https://core.tcl.tk/tcllib)
is somewhere else, just follow the link.

This is also where our issue tracking is done.  We are not tracking
issues at github.  With the exeception of the maintainer of the
mirroring setup nobody will even see issues created at github.


Please use the
[official ticket tracker](https://core.tcl.tk/tcllib/reportlist)
instead.
































|
<

<
<
|
<
|
<

<
|
|
>


|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1

2


3

4

5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# Attention




:warning: 

This repository is mirrored to [github](https://github.com/tcltk/tcllib).



We are __not tracking issues at github__.  With the exeception of the
maintainer of the mirroring setup nobody will even see issues created
at github.

Please use the
[official ticket tracker](https://core.tcl-lang.org/tcllib/reportlist)
instead.

# Welcome

Welcome to Tcllib, the Tcl Standard Library. Note that Tcllib is not a
package itself. It is a collection of (semi-independent) Tcl packages
that provide utility functions useful to a large collection of Tcl
programmers.

At our [home site](http://core.tcl-lang.org/tcllib) you will find the
official fossil repository used to manage our sources, together with
the bug tracker. This is also the main location for releases to
download from.

We have a
[secondary download location](https://sourceforge.net/projects/tcllib/files)
where the Tcllib sources were hosted in the past. SourceForge is also
where our [mailing lists](https://sourceforge.net/p/tcllib/mailman)
are (still) hosted.

Another location to find these sources at is the
[github mirror](https://github.com/tcltk/tcllib).

Please note the :warning: at the top.

# Guides To Tcllib

   * [Tcl Community - Kind Communication](embedded/www/tcllib/files/devdoc/tcl_community_communication.html)
   * [License](embedded/www/tcllib/files/devdoc/tcllib_license.html)
   * [How To Get The Sources](embedded/www/tcllib/files/devdoc/tcllib_sources.html)
   * [How To Build And Install Tcllib](embedded/www/tcllib/files/devdoc/tcllib_installer.html)
   * [The Developer's Guide](embedded/www/tcllib/files/devdoc/tcllib_devguide.html)
   * [The Release Manager's Guide](embedded/www/tcllib/files/devdoc/tcllib_releasemgr.html)

Deleted README.releasemgr.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
RCS: @(#) $Id: README.releasemgr,v 1.2 2009/07/10 16:33:31 andreas_kupries Exp $

Welcome to the tcllib, the Tcl Standard Library.
================================================

Introduction
------------

This README is intended to be a guide to the tools available to a

	Release manager

working on the creation of a release of Tcllib.

Audience
--------

The intended audience is the release manager of Tcllib, his deputies,
and anybody else interested in the task.

Basics
------

< Flesh this out >

	sak.tcl validate
	sak.tcl test run
	sak.tcl review
	sak.tcl readme
	sak.tcl localdoc
	sak.tcl release (change to include rpmspec+gentip55+yml)

< Tasks, and how to perform them >

  	 Making a release (candidate) branch.
	 Readying the release in the branch.
	 Make the release official, merging the branch back.

Uploading and releasing files
--------------------------------------------

(1) Create a proper fossil event for the release, via

      http://core.tcl.tk/tcllib/eventedit

    See existing events (*) for a template

    (Ad *) http://core.tcl.tk/tcllib/event/dac0ddcd2e990234143196b4dc438fe01e7b9817

(2) Update the following web locations

    (a) Home page:	http://core.tcl.tk/tcllib/home
    (b) Downloads:	http://core.tcl.tk/tcllib/wiki?name=Downloads 
    (c) Past Releases:	http://core.tcl.tk/tcllib/wiki?name=Past+Releases

    Admin access to the fossil repository required

    (d) http://www.tcl.tk/home/release.txt
    (e) http://www.tcl.tk/software/tcllib/*.tml

    ssh access to tcl.activestate.com
    aka        	  www.tcl.tk
    required.

    (f) http://wiki.tcl.tk/1246
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































































































































Changes to apps/dtplite.man.

439
440
441
442
443
444
445
446
447

They are left in place, i.e. not deleted, to serve as demonstrations
of doctoc and docidx markup.

[list_end]

[vset CATEGORY doctools]
[include ../modules/doctools2base/include/feedback.inc]
[manpage_end]







|

439
440
441
442
443
444
445
446
447

They are left in place, i.e. not deleted, to serve as demonstrations
of doctoc and docidx markup.

[list_end]

[vset CATEGORY doctools]
[include ../modules/common-text/feedback.inc]
[manpage_end]

Changes to apps/nns.man.

135
136
137
138
139
140
141
142
143
If this option is not specified it defaults to [const 38573]. It
specifies the TCP port the name service to talk to is listening on for
requests.

[list_end]

[vset CATEGORY nameserv]
[include ../modules/doctools2base/include/feedback.inc]
[manpage_end]







|

135
136
137
138
139
140
141
142
143
If this option is not specified it defaults to [const 38573]. It
specifies the TCP port the name service to talk to is listening on for
requests.

[list_end]

[vset CATEGORY nameserv]
[include ../modules/common-text/feedback.inc]
[manpage_end]

Changes to apps/nnsd.man.

83
84
85
86
87
88
89
90
91

If this option is not specified it defaults to [const 38573]. It
specifies the TCP port the server has to listen on for requests.

[list_end]

[vset CATEGORY nameserv]
[include ../modules/doctools2base/include/feedback.inc]
[manpage_end]







|

83
84
85
86
87
88
89
90
91

If this option is not specified it defaults to [const 38573]. It
specifies the TCP port the server has to listen on for requests.

[list_end]

[vset CATEGORY nameserv]
[include ../modules/common-text/feedback.inc]
[manpage_end]

Changes to apps/nnslog.man.

85
86
87
88
89
90
91
92
93
If this option is not specified it defaults to [const 38573]. It
specifies the TCP port the name service to talk to is listening on for
requests.

[list_end]

[vset CATEGORY nameserv]
[include ../modules/doctools2base/include/feedback.inc]
[manpage_end]







|

85
86
87
88
89
90
91
92
93
If this option is not specified it defaults to [const 38573]. It
specifies the TCP port the name service to talk to is listening on for
requests.

[list_end]

[vset CATEGORY nameserv]
[include ../modules/common-text/feedback.inc]
[manpage_end]

Changes to apps/page.man.

459
460
461
462
463
464
465
466
467
[para]

The contents of both environment variables and registry entries are
interpreted as a list of paths, with the elements separated by either
colon (Unix), or semicolon (Windows).

[vset CATEGORY page]
[include ../modules/doctools2base/include/feedback.inc]
[manpage_end]







|

459
460
461
462
463
464
465
466
467
[para]

The contents of both environment variables and registry entries are
interpreted as a list of paths, with the elements separated by either
colon (Unix), or semicolon (Windows).

[vset CATEGORY page]
[include ../modules/common-text/feedback.inc]
[manpage_end]

Changes to apps/tcldocstrip.man.

189
190
191
192
193
194
195
196
197
Preambles, when active, are written before the actual content of a
generated file. In the same manner postambles are, when active,
written after the actual content of a generated file.

[list_end]

[vset CATEGORY docstrip]
[include ../modules/doctools2base/include/feedback.inc]
[manpage_end]







|

189
190
191
192
193
194
195
196
197
Preambles, when active, are written before the actual content of a
generated file. In the same manner postambles are, when active,
written after the actual content of a generated file.

[list_end]

[vset CATEGORY docstrip]
[include ../modules/common-text/feedback.inc]
[manpage_end]

Added devdoc/README.developer.

























































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
RCS: @(#) $Id: README.developer,v 1.6 2009/06/02 22:49:55 andreas_kupries Exp $

Welcome to the tcllib, the Tcl Standard Library.
================================================

Introduction
------------

This README is intended to be a guide to the tools available to a

	Developer

working on Tcllib to help him with his tasks, i.e. making the tasks easier
to perform. It is our hope that this will improve the quality of even
non-released revisions of Tcllib, and make the work of the release
manager easier as well.

Audience
--------

The intended audience are, first and foremost, developers beginning to
work on Tcllib. To an experienced developer this document will be less
of a guide and more of a reference. Anybody else interested in working
on Tcllib is invited as well.


Directory hierarchy and file basics
------------------------------------

The main directories under the tcllib top directory are

	modules/
	examples/
and	apps/

Each directory FOO under modules/ represents one package, sometimes
more. In the case of the latter the packages are usually related in
some way. Examples are the base64, math, and struct modules, with
loose (base64) to strong (math) relations between the packages.

Examples associated with a module FOO, if there are any, are placed
into the directory

	examples/FOO

Any type of distributable application can be found under apps/,
together with their documentation, if any. Note that the apps/
directory is currently not split into sub-directories.

Regarding the files in Tcllib, the most common types found are

	.tcl	Tcl code for a package.

	.man	Documentation for a package, in doctools format.

	.test	Test suite for a package, or part of. Based on tcltest.

	.bench	Performance benchmarks for a package, or part of.
		Based on modules/bench

	.pcx	Syntax rules for TclDevKit's tclchecker. Using these
		rules allows tclchecker to check the use of commands
		of a Tcllib package X without having to scan the
		implementation of X, i.e. its .tcl files.


Adding a new module
-------------------

Assuming that FOO is the name of the new module, and T is the toplevel
directory of the Tcllib sources

(1)	Create the directory T/modules/FOO and put all the files of
	the module into it. Note:

	* The file 'pkgIndex.tcl' is required.

	* Implementation files should have the extension '.tcl',
	  naturally.

	* If available, documentation should be in doctools format,
          and the files should have the extension '.man' for SAK to
          recognize them.

	* If available the testsuite(s) should use 'tcltest' and the
	  general format as used by the other modules in Tcllib
	  (declaration of minimally needed Tcl, tcltest, supporting
	  packages, etc.). The file(s) should have the extension
	  '.test' for SAK to recognize them.

	  Note that an empty testsuite, or a testsuite which does not
	  perform any tests is less than useful and will not be
	  accepted.

	* If available the benchmark(s) should use 'bench' and the
          general format as used by the other modules in Tcllib. The
          file(s) should have the extension '.bench' for SAK to
          recognize them.

	* Other files can be named and placed as the module sees fit.

(2)	If the new module has an example application A which is
	polished enough for general use, put this application into the
	file "T/apps/A.tcl", and its documentation into the file
	"T/apps/A.man". While documentation for the application is
	optional, it is preferred.

	For examples which are not full-fledged applications, a
	skeleton, or not really polished for use, etc., create the
	directory T/examples/FOO/ and put them there.

	A key difference is what happens to them on installation, and
	what the target audience is.

	The examples are for developers using packages in Tcllib,
	whereas the applications are also for users of Tcllib which do
	not have an interest in developing for and with it. As such,
	they are installed as regular commands, accessible through the
	PATH, and example files are not installed.

(3)	To make Tcllib's installer aware of FOO, edit the file

		T/support/installation/modules.tcl

	Add a line 'Module FOO $impaction $docaction $exaction'. The
	various actions describe to the installer how to install the
	implementation files, the documentation, and the examples.

	Add a line 'Application A' for any application A which was
	added to T/apps for FOO.

	The following actions are available:

	Implementation

		_tcl - Copy all .tcl files in T/modules/FOO into the installation.
		_tcr - See above, does it for .tcl files in subdirectories as well.
		_tci - _tcl + Copying of a tclIndex - special to modules 'math', 'control'.
		_msg - _tcl + Copying of subdir 'msgs' - special to modules 'dns', 'log'.
		_doc - _tcl + Copying of subdir 'mpformats' - special to module 'doctools'.
		_tex - _tcl + Copying of .tex files - special to module 'textutil'.

		The _null action, see below, is available in principle
		too, but a module without implementation does not make
		sense.

	Documentation

		_null - Module has no documentation, do nothing.
		_man  - Process the .man files in T/modules/FOO and
			install the results (nroff and/or HTML) in the
			proper location, as given to the installer.

	Examples

		_null - Module has no examples, do nothing
		_exa  - Copy the directory T/examples/FOO
			(recursively) to the install location for
			examples.


Testing modules
---------------

To run the testsuite of a module FOO in tcllib use the 'test run'
argument of sak.tcl, like so:

	% pwd
	/the/tcllib/toplevel/directory

	% ./sak.tcl test run FOO
or	% ./sak.tcl test run modules/FOO

To run the testsuites of all modules either invoke 'test run' without a
module name, or use 'make test'. The latter assumes that configure was
run for Tcllib before, i.e.:

	% ./sak.tcl test run
or	% ./sak.tcl test run
	% make test

In all of the above cases the result will be a combination of progress
display and testsuite log, showing for each module the tests that pass
or failed and how many of each in a summary at the end.

To get a detailed log, it is necessary to invoke 'test run' with
additional options.

First example:
	% ./sak.tcl test run -l LOG FOO

This shows the same short log on the terminal, and writes a detailed
log to the file LOG.log, and excerpts to other files (LOG.summary,
LOG.failures, etc.).

Second example:
	% ./sak.tcl test run -v FOO
	% make test > LOG

This writes the detailed log to stdout, or to the file LOG, instead of
the short log. In all cases, the detailed log contains a list of all
test cases executed, which failed, and how they failed (expected
versus actual results).

Note:
The commands
	% make test
and	% make test > LOG

are able to generate different output (short vs long log) because the
Makefile target contains code which detects that stdout has been
redirected to a file and acts accordingly.

Non-developers should reports problems in Tcllib's bug tracker.
Information about its location and the relevant category can be found
in the section 'BUGS, IDEAS, FEEDBACK' of the manpage of the module
and/or package.

Module documentation
--------------------

The main format used for the documentation of packages in Tcllib is
'doctools', the support packages of which are part of Tcllib, see the
module 'doctools'.

To convert this documentation to HTML or nroff manpages, or some other
format use the 'doc' argument of sak.tcl, like so:

	% pwd
	/the/tcllib/toplevel/directory

	% ./sak.tcl doc html FOO
or	% ./sak.tcl doc html modules/FOO

The result of the conversion can be found in the newly-created 'doc'
directory in the current working directory.

The set of formats the documentation can be converted into can be
queried via

	% ./sak.tcl help doc


To convert the documentation of all modules either invoke 'test run'
without a module name, or use 'make html-doc', etc.. The latter
assumes that configure was run for Tcllib before, i.e.:

	% ./sak.tcl doc html
	% make html-doc

Note the special format 'validate'. Using this format does not convert
the documentation to anything (and the sub-directory 'doc' will not be
created), it just checks that the documentation is syntactically
correct. I.e.

	% ./sak.tcldoc validate modules/FOO
	% ./sak.tcldoc validate


Validating modules
------------------

Running the testsuite of a module, or checking the syntax of its
documentation (see the previous sections) are two forms of validation.

The 'validate' command of sak.tcl provides a few more. The online
documentation of this command is available via

	% ./sak.tcl help validate

The validated parts are man pages, testsuites, version information,
and syntax. The latter only if various static syntax checkers are
available on the PATH, like TclDevKit's tclchecker.

Note that testsuite validation is not the execution of the testsuites,
only if a package has a testsuite or not.

It is strongly recommended to validate a module before committing any
type of change made to it.

It is recommended to validate all modules before committing any type
of change made to one of them. We have package inter-dependencies
between packages in Tcllib, thus changing one package may break
others, and just validating the changed package will not catch such
problems.


Writing Tests
-------------

While a previous section talked about running the testsuite for a
module and the packages therein this has no meaning if the module in
question has no testsuites at all.

This section gives a very basic overview on methodologies for writing
tests and testsuites.

First there are "drudgery" tests. Written to check absolutely basic
assumptions which should never fail.

Example:

	For a command FOO taking two arguments, three tests calling it
	with zero, one, and three arguments. The basic checks that the
	command fails if it has not enough arguments, or too many.

After that come the tests checking things based on our knowledge of
the command, about its properties and assumptions. Some examples based
on the graph operations added during Google's Summer of Code 2009.

**	The BellmanFord command in struct::graph::ops takes a
	_startnode_ as argument, and this node should be a node of the
	graph. equals one test case checking the behavior when the
	specified node is not a node a graph.

	This often gives rise to code in the implementation which
	explicitly checks the assumption and throws a nice error.
	Instead of letting the algorithm fails later in some weird
	non-deterministic way.

	Such checks cannot be done always. The graph argument for
	example is just a command in itself, and while we expect it to
	exhibit a certain interface, i.e. set of sub-commands aka
	methods, we cannot check that it has them, except by actually
	trying to use them. That is done by the algorithm anyway, so
	an explicit check is just overhead we can get by without.

**	IIRC one of the distinguishing characteristic of either
	BellmanFord and/or Johnson is that they are able to handle
	negative weights. Whereas Dijkstra requires positive weights.

	This induces (at least) three testcases ... Graph with all
	positive weights, all negative, and a mix of positive and
	negative weights.

	Thinking further does the algorithm handle the weight '0' as
	well ? Another test case, or several, if we mix zero with
	positive and negative weights.

**	The two algorithms we are currently thinking about are about
	distances between nodes, and distance can be 'Inf'inity,
	i.e. nodes may not be connected. This means that good test
	cases are

	(1)	Strongly connected graph
	(2)	Connected graph
	(3)	Disconnected graph.

	At the extremes of (1) and (3) we have the fully connected
	graphs and graphs without edges, only nodes, i.e. completely
	disconnected.

**	IIRC both of the algorithms take weighted arcs, and fill in a
	default if arcs are left unweighted in the input graph.

	This also induces three test cases:

	(1)	Graph will all arcs with explicit weights.
	(2)	Graph without weights at all.
	(3)	Graph with mixture of weighted and unweighted graphs.


What was described above via examples is called 'black-box' testing.
Test cases are designed and written based on our knowledge of the
properties of the algorithm and its inputs, without referencing a
particular implementation.

Going further, a complement to 'black-box' testing is 'white-box'. For
this we know the implementation of the algorithm, we look at it and
design our tests cases so that they force the code through all
possible paths in the implementation. Wherever a decision is made we
have a test cases forcing a specific direction of the decision, for
all possible directions.

In practice I often hope that the black-box tests I have made are
enough to cover all the paths, obviating the need for white-box tests.

So, if you, dear reader, now believe that writing tests for an
algorithm takes at least as much time as coding the algorithm, and
often more time, then you are completely right. It does. Much more
time. See for example also http://sqlite.org/testing.html, a writeup
on how the Sqlite database engine is tested.



An interesting connection is to documentation. In one direction, the
properties you are checking with black-box testing are properties
which should be documented in the algorithm man page. And conversely,
if you have documentation of properties of an algorithm then this is a
good reference to base black-box tests on.

In practice test cases and documentation often get written together,
cross-influencing each other. And the actual writing of test cases is
a mix of black and white box, possibly influencing the implementation
while writing the tests. Like writing test for 'startnode not in input
graph' serving as reminder to put in a check for this into the code.

Deleted devdoc/cvs.branches.fig.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#FIG 3.2
Landscape
Center
Inches
Letter  
100.00
Single
-2
1200 2
6 3000 2025 5400 2400
4 0 12 50 0 0 14 0.0000 4 150 2385 3000 2175 Point releases are branched\001
4 0 12 50 0 0 14 0.0000 4 150 1530 3000 2370 from RELEASES\001
-6
6 2400 750 5700 1200
4 0 1 50 0 0 14 0.0000 4 195 3225 2400 900 Developer performs internal releases,\001
4 0 1 50 0 0 14 0.0000 4 195 3285 2400 1095 merging from HEAD into RELEASES\001
-6
2 1 0 4 0 7 50 0 -1 0.000 0 0 7 1 0 2
	2 1 4.00 240.00 480.00
	 300 600 5700 600
2 1 0 2 1 7 50 0 -1 0.000 0 0 -1 1 0 2
	2 1 2.00 120.00 240.00
	 2100 600 2400 1800
2 1 0 5 12 7 50 0 -1 0.000 0 0 -1 1 0 3
	2 1 5.00 300.00 600.00
	 2700 1800 3000 3000 5700 3000
2 1 0 4 17 7 50 0 -1 0.000 0 0 7 1 0 3
	2 1 4.00 240.00 480.00
	 1200 600 1500 1800 5700 1800
4 0 0 50 0 0 14 0.0000 4 195 2835 3150 1575 Staging for release : RELEASES\001
4 0 0 50 0 0 14 0.0000 4 195 1905 3900 300 Development : HEAD\001
4 0 0 50 0 0 14 0.0000 4 150 930 4800 2700 Tcllib 1.2.0\001
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































Deleted devdoc/devguide.html.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!- Guide for Tcllib developers -->

<h1>Guide for Tcllib developers.
</h1>
<hr>

<h2>CVS Repository
</h2>
<table><tr><td valign=top>
      <!-- The local source of this image is
		tcllib/devel/cvs.branches.*
	-->
      <img src="http://sourceforge.net/dbimage.php?id=2221">
</td><td valign=top><p>

The CVS repository for Tcllib contains two main branches, the HEAD for
development, and RELEASES as the staging area for official
releases. At RELEASES the minor branches containing the various
official releases are anchored at.
</p></td></tr></table>

<p>All the branches are of interest to the developers for
      Tcllib. Ongoing development happens in HEAD, which can be
      unstable or may not work at all. Whenever a developer considers
      a piece of code, or module, he is responsible for as
      sufficiently stable she has to perform an internal release which
      merges this part from HEAD into RELEASES. Tools to help with
      this will be provided.
</p>

<p>The branches for the official releases of tcllib are of interest to
      a developer because it is expected that fixes for important bugs
      not only go into the HEAD branch but also into the release
      branches for the release they were found in and all releases
      following that one. This is to allow the release manager to
      create patch releases of existing releases distributing important
      bugfixes as well.
</p>

<p>Version numbers for modules are handled as described below. This
      way of handling them was chosen so that the modules in the
      development branch always uses version numbers different from
      the version numbers in the official releases made so far.
</p>
<ul>
<li>Whenever an internal release of a module FOO is done, the
	developer performing this internal release has to increment
	the version number of the module <b>after</b> the release was
	executed.
</ul>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































Deleted devdoc/installation.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
Tcllib installation directory layout
====================================

This document describes the possible layouts for an installed tcllib,
discusses their pro and contra and makes a choice for Tcllib 1.4. A
roadmap of changes in the future is made available as appendix.

[L1/D] Deep layout
------------------

	This is the layout of Tcllib 1.3 (and versions before that).

	A single directory tcllib<version> is created, and all
	subdirectories of the 'modules' subdirectory in the
	distribution is copied into it. This is restricted at large to
	*.tcl files, with exception made for some modules with special
	needs.

	Pro:
	Contra:
		Makes the handling of the various package indices,
		well, not difficult, but uncomfortable.


[L2/Fa] Flat layout 1
---------------------

	A directory is created for each module of tcllib.

	Pro:
		Handling of package indices is easier than for L1/D, a
		toplevel index file with all its problems is not
		required anymore.

	Contra:
		Directories should be versioned to avoid conflicts
		between multiple releases. modules have no
		version. This can be faked for modules containing one
		package, but not for the modules with more.


[L2/Fb] Flat layout 2
---------------------

	A directory is created for each package in tcllib.

	Pro
		Handling of package indices is easy, one per package.

	Contra:
		Modules containing more than one package are difficult
		to handle. The system has to split them into the
		individual packages. This rendered very difficult
		because of shared package index files.
	
		This can be solved by moving tcllib (back) towards of
		one package per module. When that goal is reached
		L2/Fa and L2/Fb become the same, and the contra for
		L2/Fa vanishes too as an exact version number can be
		associated with each directory.

Chosen layout for Tcllib 1.4
----------------------------

	L2/D

	Despite the problems with package indices the contras against
	the flat structures are too strong at this point in
	time. Automatic solutions are not really possible, or require
	a very high effort.

Roadmap
-------
	Change the module directories of tcllib to contain exactly one
	package per directory, with appropriate index (and meta data).

	This not only makes sense for easier handling of installation
	and package indices, but also in the greater context of
	wrapping code for deployment.


-----------------------------------
This document is in the public domain.

			Andreas Kupries	<[email protected]>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































































































































Added devdoc/parts/b_critcl.inc.













































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

While the majority of Tcllib consists of packages written in pure Tcl
a number of packages also have [term accelerators] associated with them.

These are [syscmd critcl]-based C packages whose use will boost the
performance of the packages using them.

These accelerators are optional, and they are not installed by
default.

[para] To build the accelerators the normally optional dependency on
       [syscmd critcl] becomes required.

[para] To build and install Tcllib with the accelerators in a
       Unix-like environment invoke:

[example {
  ./configure
  make critcl # This builds the shared library holding
              # the accelerators
  make install
}]

[para] The underlying tool is [file sak.tcl] in the toplevel directory
of Tcllib and the command [cmd {make critcl}] is just a wrapper around

[example {
  ./sak.tcl critcl
}]

[para] Therefore in a Windows environment instead invoke

[example {
  ./sak.tcl critcl
  ./installer.tcl
}]

from within a DOS window, i.e. [syscmd cmd.exe].

Added devdoc/parts/b_tooling.inc.



























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

The core of Tcllib's build system is the script [file installer.tcl]
found in the toplevel directory of a checkout or release.

[para] The
       [example {
         configure ; make install
       }]
       setup available to
       developers on Unix-like systems is just a wrapper around it.

       To go beyond the standard embodied in the wrapper it is
       necessary to directly invoke this script.

[para] On Windows system using it directly is the only way to invoke
       it.

[para] For basic help invoke it as

       [example {
         ./installer.tcl -help
       }]

       This will print a short list of all the available options to
       the standard output channel.

[para] The commands associated with the various [term install] targets
       in the [term Makefile.in] for Unix can be used as additional
       examples on how to use this tool as well.

[para] The installer can operate in GUI and CLI modes.

       By default it chooses the mode automatically, based on if the
       Tcl package [package Tk] can be used or not.

       The option [option -no-gui] can be used to force CLI mode.

[para] Note that it is possible to specify options on the command line
       even if the installer ultimatively selects GUI mode. In that
       case the hardwired defaults and the options determine the data
       presented to the user for editing.

[para] The installer will select a number of defaults for the
       locations of packages, examples, and documentation, and also
       the format of the documentation. The user can overide these
       defaults in the GUI, or by specifying additional options.

       The defaults depend on the platform detected (Unix/Windows) and
       on the [syscmd tclsh] executable used to run the installer.

[para][emph Options]

[list_begin options]
[opt_def -help]

Show the list of options explained here on the standard output channel
and exit.

[opt_def +excluded]

Include deprecated packages in the installation.

[opt_def -no-gui]

Force command line operation of the installer

[opt_def -no-wait]

In CLI mode the installer will by default ask the user to confirm that
the chosen configuration (destination paths, things to install) is
correct before performing any action. Using this option causes the
installer to skip this query and immediately jump to installation.

[opt_def -app-path [arg path]]
[opt_def -example-path [arg path]]
[opt_def -html-path [arg path]]
[opt_def -nroff-path [arg path]]
[opt_def -pkg-path [arg path]]

Declare the destination paths for the applications, examples, html
documentation, nroff manpages, and packages. The defaults are derived
from the location of the [syscmd tclsh] used to run the installer.

[opt_def -dry-run]
[opt_def -simulate]

Run the installer without modifying the destination directories.

[opt_def -apps]
[opt_def -no-apps]
[opt_def -examples]
[opt_def -no-examples]
[opt_def -pkgs]
[opt_def -no-pkgs]
[opt_def -html]
[opt_def -no-html]
[opt_def -nroff]
[opt_def -no-nroff]

(De)activate the installation of applications, examples, packages,
html documentation, and nroff manpages.

[para] Applications, examples, and packages are installed by default.

[para] On Windows the html documentation is installed by default.

[para] On Unix the nroff manpages are installed by default.

[list_end]

Added devdoc/parts/b_unix.inc.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

For [term Unix]-like environments Tcllib comes with the standard set
of files to make

[example {
  ./configure
  make install
}]

a suitable way of installing it.

This is a standard non-interactive install automatically figuring out
where to place everything, i.e. packages, applications, and the
manpages.

[para] To get a graphical installer invoke

[example {
  ./installer.tcl
}]

instead.

Added devdoc/parts/b_windows.inc.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

In a Windows environment we have the [cmd installer.tcl] script to
perform installation.

[para] If the desired [syscmd tclsh] is associated [file .tcl] files
       then double-clicking / opening the [cmd installer.tcl] is
       enough to invoke it in graphical mode.

       This assumes that [term Tk] is installed and available as well.

[para] Without [term Tk] the only way to invoke the installer are to
       open a DOS window, i.e. [syscmd cmd.exe], and then to invoke
      
[example {
  ./installer.tcl
}]

inside it.

Added devdoc/parts/d_bf_branchcmds.inc.



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

In the hope of engendering good work practices now a few example
operations which will come up with branches, and their associated
fossil command (sequences).

[list_begin definitions]

[comment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~]
[def [emph Awareness]]
[include d_op_aware.inc]

[comment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~]
[def [emph {Clean checkouts}]]
[include d_op_clean.inc]

[comment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~]
[def [emph {Starting a new branch}]]
[include d_op_branch_open.inc]

[comment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~]
[def [emph {Merging a branch into trunk}]]
[include d_op_branch_close.inc]

[comment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~]
[def [emph {Merging from trunk}]]
[include d_op_branch_import.inc]

[list_end]

Added devdoc/parts/d_bf_branches.inc.











































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

Given the constraints placed on the [term trunk] branch of the
repository it is (strongly) recommended to perform any development
going beyond trivial changes on a non-trunk branch.

[para] Outside of the trunk developers are allowed to commit
       intermediate broken states of their work.

       Only at the end of a development cycle, when the relevant
       branch is considered ready for merging, will it be necessary to
       perform full the set of validations ensuring that the merge to
       come will create a good commit on trunk.

[para] Note that while a review from a second developer is not a
       required condition for merging a branch it is recommended to
       seek out such an independent opinion as a means of
       cross-checking the work.

[para] It also recommended to give any new branch a name which aids in
       determining additional details about it. Examples of good
       things to stick into a branch name would be

[list_begin itemized]
[item]	Developer (nick)name
[item]	Ticket hash/reference
[item]	One or two keywords applicable to the work
[item]	...
[list_end]

[para] Further, while most development branches are likely quite
       short-lived, no prohibitions exist against making longer-lived
       branches.

       Creators should however be mindful that the longer such a
       branch exists without merges the more divergent they will tend
       to be, with an associated increase in the effort which will
       have to be spent on either merging from and merging to trunk.

Added devdoc/parts/d_bf_dependencies.inc.



























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

Regarding packages and dependencies between them Tcllib occupies a
middle position between two extremes:

[list_begin enumerated]

[enum] On one side a strongly interdependent set of packages, usually
       by a single author, for a single project. Looking at my
       (Andreas Kupries) own work examples of such are
       [uri https://core.tcl.tk/akupries/marpa/index Marpa],
       [uri https://core.tcl.tk/akupries/crimp/index CRIMP],
       [uri https://core.tcl.tk/akupries/kinetcl/index Kinetcl], etc.

[para] For every change the author of the project handles all the
       modifications cascading from any incompatibilities it
       introduced to the system.

[enum] On the other side, the world of semi-independent projects by
       many different authors where authors know what packages their
       own creations depend on, yet usually do not know who else
       depends on them.

[para] The best thing an author making an (incompatible) change to
       their project can do is to for one announce such changes in
       some way, and for two use versioning to distinguish the code
       before and after the change.

[para] The world is then responsible for adapting, be it by updating
       their own projects to the new version, or by sticking to the
       old.

[list_end]

As mentioned already, Tcllib lives in the middle of that.

[para] While we as maintainers cannot be aware of all users of
       Tcllib's packages, and thus have to rely on the mechanisms
       touched on in point 2 above for that, the dependencies between
       the packages contained in Tcllib are a different matter.

[para] As we are collectively responsible for the usability of Tcllib
       in toto to the outside world, it behooves us to be individually
       mindful even of Tcllib packages we are not directly
       maintaining, when they depend on packages under our
       maintainership.

       This may be as simple as coordinating with the maintainers of
       the affected packages.

       It may also require us to choose how to adapt affected packages
       which do not have maintainers, i.e. modify them to use our
       changed package properly, or modify them to properly depend on
       the unchanged version of our package.

[para] Note that the above is not only a chore but an opportunity as
       well.

       Additional insight can be had by forcing ourselves to look at
       our package and the planned change(s) from an outside
       perspective, to consider the ramifications of our actions on
       others in general, and on dependent packages in particular.

Added devdoc/parts/d_bf_trunk.inc.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

The management and use of branches is an important part of working
with a [term {Distributed Version Control System}] ([term DVCS]) like
[uri https://www.fossil-scm.org/ fossil].

[para] For Tcllib the main branch of the collection is
       [term trunk]. In [term git] this branch would be called
       [term master], and this is exactly the case in the
       [uri https://github.com/tcltk/tcllib/ {github mirror}] of
       Tcllib.

[para] To properly support debugging [emph {each commit}] on this
       branch [emph {has to pass the entire testsuite}] of the
       collection. Using bisection to determine when an issue appeared
       is an example of an action made easier by this constraint.

[para] This is part of our collective responsibility for the usability
       of Tcllib in toto to the outside world.

       As [term fossil] has no mechanism to enforce this condition
       this is handled on the honor system for developers and maintainers.

[para] To make the task easier Tcllib comes with a tool
       ([file sak.tcl]) providing a number of commands in
       support. These commands are explained in the following sections
       of this guide.

[para] While it is possible and allowed to commit directly to trunk
       remember the above constraint regarding the testsuite, and the
       coming notes about other possible issues with a commit.

Added devdoc/parts/d_bf_versions.inc.

























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
In Tcllib all changes to a package have to come with an increment of
its version number. What part is incremented (patchlevel, minor, major
version) depends on the kind of change made. With multiple changes in
a commit the highest "wins".

[para] When working in a development branch the version change can be
       deferred until it is time to merge, and then has to cover all
       the changes in the branch.

[para] Below a list of the kinds of changes and their associated
       version increments:

[list_begin definitions]
[def [term {D - documentation}]] No increment
[def [term {T - testsuite}]] No increment
[def [term {B - bugfix}]] Patchlevel
[def [term {I - implementation tweak}]] Patchlevel
[def [term {P - performance tweak}]] Patchlevel
[def [term {E - backward-compatible extension}]] Minor
[def [term {API - incompatible change}]] Major
[list_end]

[para] Note that a commit containing a version increment has to
       mention the new version number in its commit message, as well
       as the kind of change which caused it.

[para] Note further that the version number of a package currently
       exists in three places. An increment has to update all of them:

[list_begin enumerated]
[enum] The package implementation.
[enum] The package index ([file pkgIndex.tcl])
[enum] The package documentation.
[list_end]

[para] The [file sak.tcl] command [cmd {validate version}] helps
       finding discrepancies between the first two.

       All the other [cmd validate] methods are also of interest to
       any developer. Invoke it with

       [example { sak.tcl help validate }]

       to see their documentation.

Added devdoc/parts/d_branchflow.inc.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[comment {===================================================================}]
[subsection {Package Dependencies}]
[include d_bf_dependencies.inc]

[comment {===================================================================}]
[subsection Trunk]
[include d_bf_trunk.inc]

[comment {===================================================================}]
[subsection Branches]
[include d_bf_branches.inc]

[comment {===================================================================}]
[subsection {Working with Branches}]
[include d_bf_branchcmds.inc]

[comment {===================================================================}]
[subsection {Version numbers}]
[include d_bf_versions.inc]

Added devdoc/parts/d_contrib.inc.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

As a contributor to Tcllib you are committing yourself to:

[list_begin enumerated]

[enum] keep the guidelines written down in
       [term {Tcl Community - Kind Communication}] in your mind.
       The main point to take away from there is
       [emph {to be kind to each other}].

[enum] Your contributions getting distributed under a BSD/MIT license.
       For the details see [term {Tcllib - License}]

[list_end]

Contributions are made by entering tickets into our tracker, providing
patches, bundles or branches of code for inclusion, or posting to the
Tcllib related mailing lists.

Added devdoc/parts/d_dirlayout.inc.











































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

[subsection {Main Directories}]

The main directories in the Tcllib toplevel directory and of interest
to a developer are:

[list_begin definitions]

[def [file modules]]

Each child directory represents one or more packages.

In the case of the latter the packages are usually related in some
way. Examples are [file base64], [file math], and [file struct], with
loose (base64) to strong (math) relations between the packages in the
directory.

[def [file apps]]

This directory contains all the installable applications, with their
documentation. Note that this directory is currently [emph not] split
into sub-directories.

[def [file examples]]

Each child directory [file foo] contains one or more example
application for the packages in [file modules/foo]. These examples are
generally not polished enough to be considered for installation.

[list_end]

[subsection {More Directories}]

[list_begin definitions]

[def [file config]]

This directory contains files supporting the Unix build system,
i.e. [file configure] and [file Makefile.in].

[def [file devdoc]]

This directories contains the doctools sources for the global
documentation, like this document and its sibling guides.

[def [file embedded]]

This directory contains the entire documentation formatted for
[term HTML] and styled to properly mix into the web site generated by
fossil for the repository.

[para] This is the documentation accessible from the Tcllib home
directory, represented in the repository as [file embedded/index.md].

[def [file idoc]]

This directory contains the entire documentation formatted for
[term nroff] and [term HTML], the latter without any styling.
This is the documentation which will be installed.

[def [file support]]

This directory contains the sources of internal packages and utilities
used in the implementation of the [file installer.tcl] and
[file sak.tcl] scripts/tools.

[list_end]

[subsection {Top Files}]

[list_begin definitions]
[def [file aclocal.m4]]
[def [file configure]]
[def [file configure.in]]
[def [file Makefile.in]]

These four files comprise the Unix build system layered on top of the
[file installer.tcl] script.

[def [file installer.tcl]]

The Tcl-based installation script/tool.

[def [file project.shed]]

Configuration file for [term {Sean Wood}]'s [syscmd PracTcl]
buildsystem.

[def [file sak.tcl]]
This is the main tool for developers and release managers, the
[term {Swiss Army Knife}] of management operations on the collection.

[def [file ChangeLog]]

The log of changes to the global support, when the sources were held
in [term CVS]. Not relevant any longer with the switch to the
[term fossil] SCM.

[def [file license.terms]]

The license in plain ASCII. See also [term {Tcllib - License}] for the
nicely formatted form. The text is identical.

[def [file README.md]]
[def [file .github/CONTRIBUTING.md]]
[def [file .github/ISSUE_TEMPLATE.md]]
[def [file .github/PULL_REQUEST_TEMPLATE.md]]

These markdown-formatted documents are used and shown by the github
mirror of these sources, pointing people back to the official location
and issue trackers.

[def [file DESCRIPTION.txt]]
[def [file STATUS]]
[def [file tcllib.spec]]
[def [file tcllib.tap]]
[def [file tcllib.yml]]

????

[list_end]

[subsection {File Types}]

The most common file types, by file extension, are:

[list_begin definitions]

[def [file .tcl]]
Tcl code for a package, application, or example.

[def [file .man]]
Doctools-formatted documentation, usually for a package.

[def [file .test]]
Test suite for a package, or part of.
Based on [package tcltest].

[def [file .bench]]
Performance benchmarks for a package, or part of.
Based on [file modules/bench].

[def [file .pcx]]
Syntax rules for [term TclDevKit]'s [syscmd tclchecker]. Using these
rules allows the checker to validate the use of commands of a Tcllib
package [package foo] without having to scan the [file .tcl] files
implementing it.

[list_end]

Added devdoc/parts/d_documentation.inc.

























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

The standard format used for documentation of packages and other
things in Tcllib is [term doctools].

Its supporting packages are a part of Tcllib, see the directories
[file modules/doctools] and [file modules/dtplite]. The latter is
an application package, with the actual application
[file apps/dtplite] a light wrapper around it.

[para] Tcllib developers gain access to these through the [cmd doc]
method of the [file sak.tcl] tool, another (internal) wrapper around
the [file modules/dtplite] application package.

[comment {===================================================================}]
[subsection {Generate documentation for a specific module}]

Invoke either

[example {  ./sak.tcl doc html foo }]

or

[example {  ./sak.tcl doc html modules/foo }]

to generate HTML for the documentation found in the module [file foo].

Instead of [const html] any other supported format can be used here,
of course.

[para] The generated formatted documentation will be placed into a
directory [file doc] in the current working directory.

[comment {===================================================================}]
[subsection {Generate documentation for all modules}]

Invoke the tool without a module name, i.e.

[example {  ./sak.tcl doc html }]

to generate HTML for the documentation found in all modules.

Instead of [const html] any other supported format can be used here,
of course.

[para] The generated formatted documentation will be placed into a
directory [file doc] in the current working directory.

[comment {===================================================================}]
[subsection {Available output formats, help}]

Invoke the tool as

[example {  ./sak.tcl help doc }]

to see the entire set of supported output formats which can be
generated.

[comment {===================================================================}]
[subsection {Validation without output}]

Note the special format [const validate].

[para] Using this value as the name of the format to generate forces
the tool to simply check that the documentation is syntactically
correct, without generating actual output.

[para] Invoke it as either

[example {  ./sak.tcl doc validate (modules/)foo }]

or

[example {  ./sak.tcl doc validate }]

to either check the packages of a specific module or check all of
them.

Added devdoc/parts/d_installation.inc.





























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
A last thing to consider when adding a new package to the collection
is installation.

[para] How to [emph use] the [file installer.tcl] script is documented
in [term {Tcllib - The Installer's Guide}].

[para] Here we document how to extend said installer so that it may
install new package(s) and/or application(s).

[para] In most cases only a single file has to be modified, the
[file support/installation/modules.tcl] holding one command per module
and application to install.

[para] The relevant commands are:

[list_begin definitions]

[call [cmd Module] [arg name] \
      	   [arg code-action] \
      	   [arg doc-action] \
	   [arg example-action]]

Install the packages of module [arg name], found in
[file modules/[arg name]].

[para] The [arg code-action] is responsible for installing the
packages and their index. The system currently provides

[list_begin definitions]

[def [cmd _tcl]] Copy all [file .tcl] files found in
[file modules/[arg name]] into the installation.

[def [cmd _tcr]] As [cmd _tcl], copy the [file .tcl] files found in
the subdirectories of [file modules/[arg name]] as well.

[def [cmd _tci]] As [cmd _tcl], and copy the [file tclIndex.tcl] file
as well.

[def [cmd _msg]] As [cmd _tcl], and copy the subdirectory [file msgs]
as well.

[def [cmd _doc]] As [cmd _tcl], and copy the subdirectory
[file mpformats] as well.

[def [cmd _tex]] As [cmd _tcl], and copy [file .tex] files as well.

[list_end]

[para] The [arg doc-action] is responsible for installing the package
documentation. The system currently provides

[list_begin definitions]
[def [cmd _null]] No documentation available, do nothing.

[def [cmd _man]] Process the [file .man] files found in
[file modules/[arg name]] and install the results (nroff and/or HTML)
in the proper location, as given to the installer.

[para] This is actually a fallback, normally the installer uses the
pre-made formatted documentation found under [file idoc].

[list_end]

[para] The [arg example-action] is responsible for installing the
examples. The system currently provides

[list_begin definitions]
[def [cmd _null]] No examples available, do nothing.

[def [cmd _exa]] Copy the the directory [file examples/[arg name]]
recursively to the install location for examples.

[list_end]

[call [cmd Application] [arg name]]

Install the application with [arg name], found in [file apps].


[call [cmd Exclude] [arg name]]

This command signals to the installer which of the listed modules to
[emph not] install. I.e. they name the deprecated modules of Tcllib.

[list_end]

[para] If, and only if the above actions are not suitable for the new
module then a second file has to be modified,
[file support/installation/actions.tcl].

[para] This file contains the implementations of the available
actions, and is the place where any custom action needed to handle the
special circumstances of module has to be added.

Added devdoc/parts/d_maintain.inc.















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

When contributing one or more packages for full inclusion into Tcllib
you are committing yourself to

[list_begin enumerated]

[enum] Keep the guidelines written down in
       [term {Tcl Community - Kind Communication}]
       (as any contributor) in your mind. The main point to take away
       from there is [emph {to be kind to each other}].

[enum] Your packages getting distributed under a BSD/MIT license.  For
       the details see [term {Tcllib - License}]

[enum] Maintenance of the new packages for a period of two years under
       the following rules, and responsibilities:

       [list_begin enumerated]

       [enum] A maintainer may step down after the mandatory period as
       	      they see fit.

       [enum] A maintainer may step down before the end of the
      	      mandatory period, under the condition that a replacement
      	      maintainer is immediately available and has agreed to
      	      serve the remainder of the period, plus their own
      	      mandatory period (see below).

       [enum] When stepping down without a replacement maintainer
      	      taking over the relevant packages have to be flagged as
      	      [const unmaintained].

       [enum] When a replacement mantainer is brought in for a package
      	      it is (kept) marked as [const maintained] (again).

       [para] A replacement maintainer is bound by the same rules as
	      the original maintainer, except that the mandatory
	      period of maintenance is shortened to one year.

       [enum] For any [const unmaintained] package a contributor
       	      interested in becoming its maintainer can become so by
       	      flagging them as [const maintained] with their name and
       	      contact information, committing themselves to the rules
       	      of a replacement maintainer (see previous point).

       [enum] For any already [const maintained] package a contributor
       	      interested in becoming a co-maintainer can become so
       	      with the agreement of the existing maintainer(s),
       	      committing themselves to the rules of a replacement
       	      maintainer (see two points previous).

       [list_end]

       [para] The responsibilities as a maintainer include:

       [list_begin enumerated]

       [enum] Watching Tcllib's ticket tracker for bugs, bug fixes,
       	      and feature requests related to the new packages.

       [enum] Reviewing the aforementioned tickets, rejecting or
       	      applying them

       [enum] Coordination and discussion with ticket submitter during
       	      the development and/or application of bug fixes.

       [list_end]

[enum] Follow the [sectref {Branching and Workflow}] of this guide.

[list_end]

Added devdoc/parts/d_op_aware.inc.



















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

When developing we have to keep ourselves aware of the context of our
work. On what branch are we ? What files have we changed ? What new
files are not yet known to the repository ? What has happened remotely
since we used our checkout ?

The answers to these questions become especially important when using
a long-lived checkout and coming back to it after some time away.

[para] Commands to answer questions like the above are:

[list_begin definitions]

[def [cmd {fossil pull}]]

       Get all changes done on the remote since the last pull or sync
       from it. This has to be done first, before any of the commands
       below.

[para] Even if the commit in our checkout refers to the branch we want
       right now control operations committed to the remote may have
       changed that from underneath us.

[def [cmd {fossil info | grep tags}]]
[def [cmd {fossil branch list | grep '\*'}]]

       Two different ways of determining the branch our checkout is
       on.

[def [cmd {fossil timeline}]]

       What have we (and others) done recently ?

[para] [emph Attention], this information is very likely outdated, the
       more the longer we did not use this checkout.

       Run [cmd {fossil pull}] first to get latest information from
       the remote repository of the project.

[def [cmd {fossil timeline current}]]

       Place the commit our checkout is based on at the top of the
       timeline.

[def [cmd {fossil changes}]]

       Lists the files we have changed compared to the commit the
       checkout is based on.

[def [cmd {fossil extra}]]

       Lists the files we have in the checkout the repository does not
       know about. This may be leftover chaff from our work, or
       something we have forgotten to [cmd {fossil add}] to the
       repository yet.

[list_end]

Added devdoc/parts/d_op_branch_close.inc.



















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

Be aware of where you are (see first definition).

[para] Ensure that you have clean checkout (see second definition).

       In the full-blown sequence (zig-zag) it is [emph required], due
       to the merging from trunk. In the shorter sequence it is only
       desired. That said, keeping the checkout clean before
       any major operations is a good habit to have, in my opinion.

[para] The full-blown sequencing with checks all the way is to

[list_begin enumerated]

[enum] Validate the checkout, i.e. last commit on your branch. Run the
       full test suite and other validations, fix all the issues which
       have cropped up.

[enum] Merge the latest state of the [term trunk] (see next definition).

[enum] Validate the checkout again. The incoming trunk changes may
       have broken something now. Do any required fixes.

[enum] Now merge to the trunk using

[example {
    fossil update trunk
    fossil merge --integrate YOUR_BRANCH
}]

[enum] At this point the checkout should be in the same state as at
       the end of point (3) above, because we resolved any issues with
       the trunk already. Thus a simple

[example {
    fossil commit ...
}]

       should be sufficient now to commit the merge back and close the
       branch (due to the [option --integrate] we used on the merge).

[para] The more paranoid may validate the checkout a third time before
       commiting.
[list_end]

[para] I call this a [term {zig-zag merge}] because of how the arrows
       look in the timeline, from trunk to feature branch for the
       first merge, and then back for the final merge.

[para] A less paranoid can do what I call a [term {simple merge}],
       which moves step (2) after step (4) and skips step (3)
       entirely. The resulting shorter sequence is

[list_begin enumerated]
[enum] Validate
[enum] Merge to trunk
[enum] Validate again
[enum] Commit to trunk
[list_end]

The last step after either zig-zag or plain merge is to

[example {
    fossil sync
}]

This saves our work to the remote side, and further gives us any other
work done while we were doing our merge. It especially allows us to
check if we raced somebody else, resulting in a split trunk.

[para] When that happens we should coordinate with the other developer
       on who fixes the split, to ensure that we do not race each
       other again.

Added devdoc/parts/d_op_branch_import.inc.

































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

Be aware of where you are (see first definition).

[para] Ensure that you have clean checkout (see second definition).
       It is [emph required].
       
[para] In most situations you want to import the latest commit of
       branch [term trunk] (or other origin). To get it use

[example {
    fossil pull
}]

[para] With that done we can now import this commit into our current
       branch with

[example {
    fossil merge trunk
}]

[para] Even if [syscmd fossil] does not report any conflicts it is a
       good idea to check that the operation has not broken the new
       and/or changed functionality we are working on.

[para] With the establishment of a good merge we then save the state
       with

[example {
    fossil commit ...
}]

before continuing development.

Added devdoc/parts/d_op_branch_open.inc.























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

Be aware of where you are (see first definition).

[para] Ensure that you have clean checkout (see second definition).
       It is [emph required].

[para] In most situations you want to be on branch [term trunk], and
       you want to be on the latest commit for it. To get there use

[example {
    fossil pull
    fossil update trunk
}]

If some other branch is desired as the starting point for the coming
work replace [term trunk] in the commands above with the name of that
branch.

[para] With the base line established we now have two ways of creating
       the new branch, with differing (dis)advantages.

       The simpler way is to

[example {
    fossil branch new NAME_OF_NEW_BRANCH
}]

and start developing. The advantage here is that you cannot forget to
create the branch. The disadvantages are that we have a branch commit
unchanged from where we branched from, and that we have to use
high-handed techniques like hiding or shunning to get rid of the
commit should we decide to abandon the work before the first actual
commit on the branch.

[para] The other way of creating the branch is to start developing,
and then on the first commit use the option [option --branch] to tell
[syscmd fossil] that we are starting a branch now. I.e. run

[example {
    fossil commit --branch NAME_OF_NEW_BRANCH ...
}]

where [term ...] are any other options used to supply the commit
message, files to commit, etc.

[para] The (dis)advantages are now reversed.

[para] We have no superflous commit, only what is actually
       developed. The work is hidden until we commit to make our first
       commit.

[para] We may forget to use [option {--branch NAME_OF_NEW_BRANCH}] and
       then have to correct that oversight via the fossil web
       interface (I am currently unaware of ways of doing such from
       the command line, although some magic incantantion of
       [cmd {fossil tag create}] may work).

[para] It helps to keep awareness, like checking before any commit
       that we are on the desired branch.

Added devdoc/parts/d_op_clean.inc.





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Be aware of where you are (see first definition).

[para] For pretty much all the operation recipes below a clean
       checkout is at least desired, often required.
       To check that a checkout is clean invoke

[example {
    fossil changes
    fossil extra
}]

How to clean up when uncommitted changes of all sorts are found is
context-specific and outside of the scope of this guide.

Added devdoc/parts/d_testing.inc.





















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

Testsuites in Tcllib are based on Tcl's standard test package
[package tcltest], plus utilities found in the directory
[file modules/devtools]

[para] Tcllib developers invoke the suites through the
[cmd {test run}] method of the [file sak.tcl] tool, with other methods
of [cmd test] providing management operations, for example setting a
list of standard Tcl shells to use.

[comment {===================================================================}]
[subsection {Invoke the testsuites of a specific module}]

Invoke either

[example {  ./sak.tcl test run foo }]

or

[example {  ./sak.tcl test run modules/foo }]

to invoke the testsuites found in a specific module [file foo].

[comment {===================================================================}]
[subsection {Invoke the testsuites of all modules}]

Invoke the tool without a module name, i.e.

[example {  ./sak.tcl test run }]

to invoke the testsuites of all modules.

[comment {===================================================================}]
[subsection {Detailed Test Logs}]

In all the previous examples the test runner will write a combination
of progress display and testsuite log to the standard output, showing
for each module only the tests that passed or failed and how many of
each in a summary at the end.

[para] To get a detailed log, it is necessary to invoke the test
runner with additional options.

[para] For one:

[example {
   ./sak.tcl test run --log LOG foo
}]

While this shows the same short log on the terminal as before, it also
writes a detailed log to the file [file LOG.log], and excerpts to
other files ([file LOG.summary], [file LOG.failures], etc.).

[para] For two:

[example {
  ./sak.tcl test run -v foo
}]

This writes the detailed log to the standard output, instead of the
short log.

[para] Regardless of form, the detailed log contains a list of all test
cases executed, which failed, and how they failed (expected versus
actual results).

[comment {===================================================================}]
[subsection {Shell Selection}]

By default the test runner will use all the Tcl shells specified via
[cmd {test add}] to invoke the specified testsuites, if any. If no
such are specified it will fall back to the Tcl shell used to run the
tool itself.

[para] Use option [option --shell] to explicitly specify the Tcl shell
to use, like

[example {
  ./sak.tcl test run --shell /path/to/tclsh ...
}]

[comment {===================================================================}]
[subsection Help]

Invoke the tool as

[example {  ./sak.tcl help test }]

to see the detailed help for all methods of [cmd test], and the
associated options.

Added devdoc/parts/d_testwrite.inc.















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

While previous sections talked about running the testsuites for a
module and the packages therein, this has no meaning if the module in
question has no testsuites at all.

[para] This section gives a very basic overview on possible
methodologies for writing tests and testsuites.

[para] First there are "drudgery" tests. Written to check absolutely
basic assumptions which should never fail.

[para] For example for a command FOO taking two arguments, three tests
calling it with zero, one, and three arguments. The basic checks that
the command fails if it has not enough arguments, or too many.

[para] After that come the tests checking things based on our
knowledge of the command, about its properties and assumptions. Some
examples based on the graph operations added during Google's Summer of
Code 2009 are:

[list_begin itemized]

[item]	The BellmanFord command in struct::graph::ops takes a
	[arg startnode] as argument, and this node should be a node of
	the graph. This equals one test case checking the behavior when the
	specified node is not a node of the graph.

[para]  This often gives rise to code in the implementation which
	explicitly checks the assumption and throws an understandable error,
	instead of letting the algorithm fail later in some weird
	non-deterministic way.

[para]  It is not always possible to do such checks. The graph argument
	for example is just a command in itself, and while we expect
	it to exhibit a certain interface, i.e. a set of sub-commands
	aka methods, we cannot check that it has them, except by
	actually trying to use them. That is done by the algorithm
	anyway, so an explicit check is just overhead we can get by
	without.

[item]  IIRC one of the distinguishing characteristic of either
	BellmanFord and/or Johnson is that they are able to handle
	negative weights. Whereas Dijkstra requires positive weights.

[para]	This induces (at least) three testcases ... Graph with all
	positive weights, all negative, and a mix of positive and
	negative weights.

	Thinking further does the algorithm handle the weight
	[const 0] as well ? Another test case, or several, if we mix
	zero with positive and negative weights.

[item]	The two algorithms we are currently thinking about are about
	distances between nodes, and distance can be 'Inf'inity,
	i.e. nodes may not be connected. This means that good test
	cases are

	[list_begin enumerated]
	[enum]	Strongly connected graph
	[enum]	Connected graph
	[enum]	Disconnected graph.
	[list_end]

	[para] At the extremes of strongly connected and disconnected
	we have the fully connected graphs and graphs without edges,
	only nodes, i.e. completely disconnected.

[item]	IIRC both of the algorithms take weighted arcs, and fill in a
	default if arcs are left unweighted in the input graph.

	[para] This also induces three test cases:

	[list_begin enumerated]
	[enum]	Graph will all arcs with explicit weights.
	[enum]	Graph without weights at all.
	[enum]	Graph with mixture of weighted and unweighted graphs.
	[list_end]
[list_end]

[para] What was described above via examples is called
[term black-box] testing. Test cases are designed and written based on
the developer's knowledge of the properties of the algorithm and its
inputs, without referencing a particular implementation.

[para] Going further, a complement to [term black-box] testing is
[term white-box]. For this we know the implementation of the
algorithm, we look at it and design our tests cases so that they force
the code through all possible paths in the implementation. Wherever a
decision is made we have a test case forcing a specific direction of
the decision, for all possible combinations and directions. It is easy
to get a combinatorial explosion in the number of needed test-cases.

[para] In practice I often hope that the black-box tests I have made
are enough to cover all the paths, obviating the need for white-box
tests.

[para] The above should be enough to make it clear that writing tests
for an algorithm takes at least as much time as coding the algorithm,
and often more time. Much more time.

See for example also [uri http://sqlite.org/testing.html], a writeup
on how the Sqlite database engine is tested. Another article of
interest might be [uri https://www.researchgate.net/publication/298896236].
While geared to a particular numerical algorithm it still shows that
even a simple-looking algorithm can lead to an incredible number of
test cases.

[para] An interesting connection is to documentation. In one
direction, the properties checked with black-box testing are exactly
the properties which should be documented in the algorithm's man
page. And conversely, the documentation of the properties of an
algorithm makes a good reference to base the black-box tests on.

[para] In practice test cases and documentation often get written
together, cross-influencing each other. And the actual writing of test
cases is a mix of black and white box, possibly influencing the
implementation while writing the tests. Like writing a test for a
condition like [term {startnode not in input graph}] serving as
reminder to put a check for this condition into the code.

Added devdoc/parts/rm_distribute.inc.















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

With the release made it has to be published and the world notified of
its existence.

[list_begin enumerated]

[enum]	    Create a proper fossil event for the release, via
	    [uri http://core.tcl-lang.org/tcllib/eventedit].

[para]	    An [uri http://core.tcl-lang.org/tcllib/event/dac0ddcd2e990234143196b4dc438fe01e7b9817 {existing event}] should be used as template.

[enum]	    Update a number of web locations:

[list_begin enumerated]
[enum]	    [uri http://core.tcl-lang.org/tcllib/doc/trunk/embedded/index.md {Home page}]
[enum]	    [uri http://core.tcl-lang.org/tcllib/wiki?name=Downloads     Downloads]
[enum]	    [uri http://core.tcl-lang.org/tcllib/wiki?name=Past+Releases {Past Releases}]
[enum]	    [uri http://www.tcl-lang.org/home/release.txt     ]
[enum]	    [uri http://www.tcl-lang.org/software/tcllib/*.tml]
[enum]	    [uri http://wiki.tcl-lang.org/page/Tcllib]
[list_end]

The first location maps to the file [file embedded/index.md] in the
repository itself, as such it can edited as part of the release
process. This is where reference to the new fossil event is added, as
the new current release.

[para] The next two locations are in the fossil tcllib wiki and
require admin or wiki write permissions for
[uri http://core.tcl-lang.org/tcllib].

[para] The last two locations require ssh access to
[uri http://www.tcl-lang.org] and permission to edit
files in the web area.


[enum]	***TODO*** mailing lists and other places to send notes to.

[list_end]

Added devdoc/parts/rm_final.inc.



>
1
todo: finalize release, make candidate official

Added devdoc/parts/rm_start.inc.



>
1
todo: open a candidate for release

Added devdoc/parts/rm_tooling.inc.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

The [file sak.tcl] script in the toplevel directory of a Tcllib
checkout is the one tool used by the release manager to perform its
[sectref Tasks].

[para] The main commands to be used are

[example {
    sak.tcl validate
    sak.tcl test run
    sak.tcl review
    sak.tcl readme
    sak.tcl localdoc
    sak.tcl release
}]

More detail will be provided in the explanations of the various
[sectref Tasks].

Added devdoc/parts/rm_work.inc.















>
>
>
>
>
>
>
1
2
3
4
5
6
7
todo: test, validate and check that the candidate is worthy of release
fix testsuites, possibly fix packages, documentation
regenerate docs
coordinate with package maintainers wrt fixes

big thing: going over the packages, classify changes since last
release to generate a nice readme.

Added devdoc/parts/rq_critcl.inc.







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

[subsection Critcl]

The [syscmd critcl] tool is an [emph optional] dependency.

[para] It is only required when trying to build the C-based
[term accelerators] for a number of packages, as explained in
[sectref {Critcl & Accelerators}]

[para] Tcllib's build system looks for it in the [variable PATH],
using the name [syscmd critcl]. This is for Unix.

On Windows on the other hand the search is more complex. First we look
for a proper application [syscmd critcl.exe]. When that is not found
we look for a combination of interpreter ([syscmd tclkitsh.exe],
[syscmd tclsh.exe]) and starkit ([syscmd critcl.kit], [syscmd critcl])
instead. [emph Note] that the choice of starkit can be overriden via
the environment variable [variable CRITCL].

[para] Tcllib requires Critcl version 2 or higher.

[para] The github repository providing releases of version 2 and
higher, and the associated sources, can be found at
[uri http://andreas-kupries.github.com/critcl].

[para] Any branch of the repository can be used (if not using the
prebuild starkit or starpack), although the use of the stable branch
[emph master] is recommended.

[para] At the above url is also an explanation on how to build and
install Critcl, including a list of its dependencies.

[para] Its instructions will not be repeated here. If there are
problems with these directions please file a ticket against the
[term Critcl] project, and not Tcllib.

Added devdoc/parts/rq_tcl.inc.





























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

[subsection Tcl]

As we are installing a number of Tcl packages and applications it
should be pretty much obvious that a working installation of Tcl
itself is needed, and I will not belabor the point.

[para] Out of the many possibilities use whatever you are comfortable
with, as long as it provides at the very least Tcl 8.2, or higher.

This may be a Tcl installation provided by your operating system
distribution, from a distribution-independent vendor, or built by
yourself.

[para] [emph Note] that the packages in Tcllib have begun to require
8.4, 8.5, and even 8.6. Older versions of Tcl will not be able to use
such packages. Trying to use them will result in
[emph {package not found}] errors, as their package index files will
not register them in versions of the core unable to use them.

[para] Myself, I used (and still use)
[uri http://www.activestate.com ActiveState's]
ActiveTcl 8.5 distribution during development, as I am most familiar
with it.

[para] [emph {(Disclosure: I, Andreas Kupries, worked for ActiveState until 2016, maintaining ActiveTcl and TclDevKit for them).}].
I am currently working for SUSE Software Canada ULC, although not in
Tcl-related areas.

[para] This distribution can be found at
[uri http://www.activestate.com/activetcl]. Retrieve the archive of
ActiveTcl 8.5 (or higher) for your platform and install it as directed
by ActiveState.

[para] For those wishing to build and install Tcl on their own, the
relevant sources can be found at

[list_begin definitions]
[def Tcl] [uri http://core.tcl-lang.org/tcl/]
[list_end]

together with the necessary instructions on how to build it.

[para] If there are problems with building, installing, or using Tcl,
please file a ticket against [term Tcl], or the vendor of your
distribution, and [emph not] [term Tcllib].

Added devdoc/parts/welcome.inc.













>
>
>
>
>
>
1
2
3
4
5
6

Welcome to Tcllib, the Tcl Standard Library. Note that Tcllib is not a
package itself. It is a collection of (semi-independent) [term Tcl]
packages that provide utility functions useful to a large collection
of Tcl programmers.

Deleted devdoc/releaseguide.html.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<!- Guide to the creation of source releases for Tcllib -->

<h1>Guide to the creation of source releases for Tcllib
</h1>
<hr>

<h2>Recap
</h2>
<table><tr><td valign=top>
      <!-- The local source of this image is
		tcllib/devel/cvs.branches.*
	-->
      <img src="http://sourceforge.net/dbimage.php?id=2221">
</td><td valign=top><p>
The CVS repository for Tcllib contains two main branches,
      the HEAD for development, and RELEASES as the staging area for
      official releases.
</p></td></tr></table>

<h2>Dependencies
</h2>

<h2>Creation of a new official release
</h2>

<p>To create a new official release of Tcllib the release manager has
      to perform the steps described below:
</p>


<ol>
<li> Retrieve the sources at the current head
	from the CVS repository, using a command like
<pre>
	  CVSROOT=:pserver:[email protected]:/cvsroot/tcllib
	  cvs -d${CVSROOT} co tcllib
</pre>
	Vary this command according to taste as long as the overall
	meaning is not changed. Compression options and the like.

<li> Tag these sources with a new branch tag for the new release of
	  tcllib, like
<pre>
	  cvs -d${CVSROOT} rtag tcllib
</pre>

<li> Commit the changes, then update the working directory.

<li> Use a tclsh to run the <b>sak</b> tool with the argument <i>gendist</i>, like
<pre>
    tclsh /path/to/tcllib/sak.tcl gendist
</pre>

<li> This results in the creation of a <i>tcllib-VERSION</i> directory
in the current working directory, and of two archives, <i>.zip</i>,
and <i>.tar.gz</i>. A starkit will be created if <b>sdx</b> is present
in the PATH. If additionally a file named <b>tclkit</b> is present in
the current working directory a starpack will be created too, using
this tclkit as the runtime.


<li> Now follow the instructions in the Sourceforge site documentation
		    for uploading the archives generated by the last
		    step to
		    <b>ftp://upload.sourceforge.net/incoming</b>, and
		    follow the procedures for creating packages and
		    releases at Sourceforge.
</ol>

<p>At last notify the relevant persons in other communities like
Debian (See list of contacts) about the new release.
</p>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















































































































































Added devdoc/tcl_community_communication.man.





































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin tcl_community_communication n 1]
[titledesc {Tcl Community - Kind Communication}]
[description]

The Tcl Community encourages contributions from anyone who wishes to
advance the development of:

[list_begin itemized]
[item] The Tcl Language
[item] Tcl derived languages
[item] Tcl related libraries
[item] Tcl extensions
[item] External Projects that Integrate Tcl
[list_end]

[para] We welcome those contributions from anyone. We are blind to
gender, race, religion, cultural background, cybernetic nature, and
any other demographic characteristics, as well as personal political
views.

[para] A community lives and dies by communications. And occasionally
our communications are peppered with patterns that are harsh,
unfriendly, unwelcoming and/or otherwise unkind. As a volunteer
community, we need all of the help we can get. Therefore, we ask all
contributors to make a conscious effort, in Tcl Community discussions,
to communicate in ways that are welcoming. Ways that are
friendly. Ways that are, in a word: kind.

[para] These guidelines suggest specific ways to accomplish that goal.

[para] Please note: for the balance of this document any reference to
"People", "Persons", "anybody" or "somebody" can refer to any sentient
being, not merely corporeal members of the species Homo Sapien.

[list_begin definitions]

[def {We are a Sanctuary not a Clubhouse}]

The Tcl Community is a collective of amateurs and professionals who
code, test, and use tools. Our community is open to all. There is no
velvet rope. There is no bouncer at the door. There are no secret
handshakes. Any sentient being who enters our midst is welcome. If
someone is ever asked to leave, it is only because they are being
disruptive to the functioning of the community.

[def {We Merit Ideas, Not People}]

A good idea can come from anyone, regardless of how little time they
have been with us. A bad idea can come from anyone, regardless of how
much time or how little time they have been with us. We judge a
concept by how it stands up to scrutiny of logic, implementation, and
regression testing. We don’t judge ideas based on who had the idea
first, who agrees with the idea, or who disagrees with it.

[def {Treat Everyone with Respect}]

Everyone is deserving of respect and courtesy at all times.

[def {Refer to people by the names they use.}]

If grammar requires you to state a gender for a person, honor their
preferences about their gender identity. If you are unsure as to the
gender of an individual, ask. If someone had to guess about your
gender and got it wrong, please correct them and do not take it
personally.

[def {Do not take a harsh tone towards other participants.}]

Do not make personal attacks against anyone (participant or not.)

[para] Criticize statements and actions, never people.

[def {Don’t Take Things Personally}]

When in doubt, assume the best in people. A criticism of your
statements is not a personal attack on you.

[def {Persons, not People}]

Stereotypes are an unhelpful tool on many accounts. They are generally
oversimplified. They are usually flat out wrong. And even if "right"
they are of absolutely no utility in determining the capabilities,
motivations, or fitness of an individual.

[para] Don’t use them in Tcl Community communications.

[def {Mistakes Happen}]

The human condition is a series of trials and errors. Progress is when
we get one more trial than error. Being wrong or making a mistake is
the default state of humanity. Accept the errors of your fellow
sentient beings, and be aware that you are also fallible.

[def {Keep it Real}]

Please respond to what people actually say. We are all amazing
individuals, but none among us are mind readers. If you find yourself
responding to what you imagine someone is thinking, odds are you are
going to be wrong.

[para] If you must criticize someone, stick to things they have
actually done. Never criticize for something you speculate they have
done. Or imagine they have done. Or something someone who shares some
attribute with them has done in the past.

[para] Keep discussions about any non-Tcl subjects to what can be
stated factually and without emotion or judgement.

[def {When Trouble Arises, Don’t Escalate}]

If you feel you are being personally attacked or offended, take the
high road. Punching back in a public forum will only makes things
worse. Address the matter in a private correspondence. Be
polite. Express your feelings, but note that you are expressing your
feelings. When writing, look for a way to calm matters down. And when
in doubt, sleep on your letter before pressing send. And when not in
doubt, sleep on it for another day after that.

[para] If you are a spectator to a fight in progress, politely request
the two parties take the matter to a more private forum.

[def {Always get the Last Word: I’m Sorry}]

If an personal argument does arise, be the first to apologize. An
apology does not concede a logical point. It merely acknowledges that
at some point the discussion left either logic, community decency, or
both. Return to the topic when cooler heads can prevail.

[def {Nobody is Keeping Score}]

There is no prize for being right. There is no cost for being wrong. A
hard sell is not going to advance your idea along any more than a
logical argument. You aren’t running for office. This isn’t debate
club. If you find yourself continuing a discussion beyond where a
topic can be logically discussed, stop.

[def {No Evangelizing}]

The Tcl Community is not the place to promote your chosen operating
system, political outlook, religion, marketing scheme, or economic
model. Period.

[para] (And if you do bring it up, be prepared to have your chosen
topic discussed logically. And odds are, not favorably.)

[def {Respect the Community}]

If the Community has come to a decision on a course of action, please
stop arguing.

[para] If someone complains about how you are expressing your ideas,
listen.

[para] If your words are hurting people, stop. There is no amount of
being "right" that makes up for someone leaving our midst because they
felt insulted, threatened, or ignored.

[list_end]

By following these guidelines, we will build our community, encourage
more contribution to our projects, and our discussions will be
friendlier and reach conclusions more easily.

[para] Thank You.

[section Signatories]
[list_begin itemized]
[item] Sean "the Hypnotoad" Woods
[item] Andreas Kupries
[list_end]

[section Authors]
[list_begin definitions]
[def Primary] Sean "the Hypnotoad" Woods
[def {Light editing}] Andreas Kupries
[list_end]
[manpage_end]

Added devdoc/tcllib_devguide.man.





























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin tcllib_devguide n 1]
[titledesc {Tcllib - The Developer's Guide}]
[description]
[include parts/welcome.inc]

[para]

This document is a guide for developers working on Tcllib,
i.e. maintainers fixing bugs, extending the collection's
functionality, etc.

[para]

Please read

[list_begin enum]
[enum] [term {Tcllib - How To Get The Sources}] and
[enum] [term {Tcllib - The Installer's Guide}]
[list_end]

first, if that was not done already.

[para] Here we assume that the sources are already available in a
directory of your choice, and that you not only know how to build and
install them, but also have all the necessary requisites to actually
do so. The guide to the sources in particular also explains which
source code management system is used, where to find it, how to set it
up, etc.

[comment {===================================================================}]
[section Commitments]
[subsection Contributor][include parts/d_contrib.inc]
[subsection Maintainer][include parts/d_maintain.inc]

[comment {===================================================================}]
[section {Branching and Workflow}]
[include parts/d_branchflow.inc]

[comment {===================================================================}]
[section {Structural Overview}]
[include parts/d_dirlayout.inc]

[comment {===================================================================}]
[section {Testsuite Tooling}]
[include parts/d_testing.inc]

[comment {===================================================================}]
[section {Documentation Tooling}]
[include parts/d_documentation.inc]

[comment {===================================================================}]
[section {Notes On Writing A Testsuite}]
[include parts/d_testwrite.inc]

[comment {===================================================================}]
[section {Installation Tooling}]
[include parts/d_installation.inc]

[comment {===================================================================}]
[manpage_end]

Added devdoc/tcllib_installer.man.





















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin tcllib_install_guide n 1]
[titledesc {Tcllib - The Installer's Guide}]
[description]
[include parts/welcome.inc]

[para]

The audience of this document is anyone wishing to build and install
the packages found in Tcllib, for either themselves, or others.

[para]

For developers intending to work on the packages themselves we
additionally provide

[list_begin enum]
[enum] [term {Tcllib - The Developer's Guide}].
[list_end]

[para]

Please read [term {Tcllib - How To Get The Sources}] first, if that
was not done already. Here we assume that the sources are already
available in a directory of your choice.

[para]

[comment {===================================================================}]
[section Requisites]

Before Tcllib can be build and used a number of requisites must be installed.

These are:

[list_begin enumerated]
[enum] The scripting language Tcl.
       For details see [sectref Tcl].
[enum] Optionally, the [package critcl] package (C embedding) for [syscmd Tcl].
       For details see [sectref CriTcl].
[list_end]

This list assumes that the machine where Tcllib is to be installed is
essentially clean. Of course, if parts of the dependencies listed
below are already installed the associated steps can be skipped. It is
still recommended to read their sections though, to validate that the
dependencies they talk about are indeed installed.

[include parts/rq_tcl.inc]
[include parts/rq_critcl.inc]

[comment {= build instructions ==============================================}]
[section {Build & Installation Instructions}]

As Tcllib is mainly a bundle of packages written in pure Tcl building
it is the same as installing it. The exceptions to this have their own
subsection, [sectref {Critcl & Accelerators}], later on.

[para] Before that however comes the standard case, differentiated by
       the platforms with material differences in the instruction, i.e.
       [term Unix]-like, versus [term Windows].

[para] Regarding the latter it should also be noted that it is
       possible set up an [term Unix]-like environment using projects
       like [term MSYS], [term Cygwin], and others. In that case the
       user has the choice of which instructions to follow.

[para] Regardless of environment or platform, a suitable [term Tcl]
       has to be installed, and its [syscmd tclsh] should be placed on
       the [variable PATH] ([term Unix]) or associated with
       [file .tcl] files ([term Windows]).

[comment %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%]
[subsection {Installing on Unix}]
[include parts/b_unix.inc]

[comment %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%]
[subsection {Installing on Windows}]
[include parts/b_windows.inc]

[comment %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%]
[subsection {Critcl & Accelerators}]
[include parts/b_critcl.inc]

[comment %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%]
[subsection Tooling]
[include parts/b_tooling.inc]

[manpage_end]

Added devdoc/tcllib_license.man.



























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin tcllib_license n 1]
[titledesc {Tcllib - License}]
[description]
[include parts/welcome.inc]

[para] The collection is under the BSD license.

[section License]

[para]

This software is copyrighted by Ajuba Solutions and other parties.
The following terms apply to all files associated with the software
unless explicitly disclaimed in individual files.

[para]

The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose,
provided that existing copyright notices are retained in all copies
and that this notice is included verbatim in any distributions. No
written agreement, license, or royalty fee is required for any of the
authorized uses.  Modifications to this software may be copyrighted by
their authors and need not follow the licensing terms described here,
provided that the new terms are clearly indicated on the first page of
each file where they apply.

[para]

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

[para]

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

[para]

GOVERNMENT USE: If you are acquiring this software on behalf of the
U.S. government, the Government shall have only "Restricted Rights" in
the software and related documentation as defined in the Federal
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
are acquiring the software on behalf of the Department of Defense, the
software shall be classified as "Commercial Computer Software" and the
Government shall have only "Restricted Rights" as defined in Clause
252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license.

[manpage_end]

Added devdoc/tcllib_releasemgr.man.



























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin tcllib_releasemgr n 1]
[titledesc {Tcllib - The Release Manager's Guide}]
[description]
[include parts/welcome.inc]

[para]

The audience of this document is the release manager for Tcllib, their
deputies, and anybody else interested in the task of creating
an official release of Tcllib for distribution.

[para]

Please read [term {Tcllib - How To Get The Sources}] first, if that
was not done already. Here we assume that the sources are already
available in a directory of your choice.

[para]

[comment {===================================================================}]
[section Tools]
[include parts/rm_tooling.inc]

[comment {===================================================================}]
[section Tasks]

[comment {===================================================================}]
[subsection {Start a release candidate}]
[include parts/rm_start.inc]

[comment {===================================================================}]
[subsection {Ready the candidate}]
[include parts/rm_work.inc]

[comment {===================================================================}]
[subsection {Make it official}]
[include parts/rm_final.inc]

[comment {===================================================================}]
[subsection {Distribute the release}]
[include parts/rm_distribute.inc]

[manpage_end]

Added devdoc/tcllib_sources.man.











































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin tcllib_sources n 1]
[titledesc {Tcllib - How To Get The Sources}]
[description]
[include parts/welcome.inc]

[para]

The audience of this document is anyone wishing to either have just a
look at Tcllib's source code, or build the packages, or to extend and
modify them.

[para] For builders and developers we additionally provide

[list_begin enum]
[enum] [term {Tcllib - The Installer's Guide}].
[enum] [term {Tcllib - The Developer's Guide}].
[list_end]

respectively.

[section {Source Location}]

The official repository for Tcllib can be found at
[uri http://core.tcl-lang.org/tcllib]

[section Retrieval]

Assuming that you simply wish to look at the sources, or build a
specific revision, the easiest way of retrieving it is to:

[list_begin enum]
[enum] Log into this site, as "anonymous", using the semi-random password in the captcha.
[enum] Go to the "Timeline".
[enum] Choose the revision you wish to have.
[enum] Follow its link to its detailed information page.
[enum] On that page, choose either the "ZIP" or "Tarball" link to get
a copy of this revision in the format of your choice.
[list_end]

[section {Source Code Management}]

For the curious (or a developer-to-be), the sources are managed by the
[uri http://www.fossil-scm.org {Fossil SCM}].

Binaries for popular platforms can be found directly at its
[uri http://www.fossil-scm.org/download.html {download page}].

[para]

With that tool available the full history can be retrieved via:

[example {
    fossil clone \
	http://core.tcl-lang.org/tcllib \
        tcllib.fossil
}]

followed by

[example {
    mkdir tcllib
    cd tcllib
    fossil open ../tcllib.fossil
}]

to get a checkout of the head of the trunk.

[manpage_end]

Changes to embedded/index.md.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17









18
19
20
21
22
23
24
<div class='fossil-doc' data-title='Tcl Library Source Code'>

<h1 align="center">Tcl Library Source Code</h1>

<center>
Packages
- [Table Of Contents](md/toc.md)

- [Keyword Index](md/index.md)
</center>

<center>
	<form action='../../../docsrch' method='GET'>
	<input type="text" name="s" size="40" autofocus>
	<input type="submit" value="Search Package Documentation">
	</form>
</center>










## Discussion & Contact

Tcllib has two
[mailing lists](https://sourceforge.net/p/tcllib/mailman/).

One for notifications (commits, ticket changes), the other for general
discussion. These are managed at SourceForge, at the aforementioned





<
|
>
|









>
>
>
>
>
>
>
>
>







1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<div class='fossil-doc' data-title='Tcl Library Source Code'>

<h1 align="center">Tcl Library Source Code</h1>

<center>

Packages - [Table Of Contents](md/toc.md)
&nbsp;&nbsp;&nbsp;
[Keyword Index](md/index.md)
</center>

<center>
	<form action='../../../docsrch' method='GET'>
	<input type="text" name="s" size="40" autofocus>
	<input type="submit" value="Search Package Documentation">
	</form>
</center>

## Guides to Tcllib

   * [Tcl Community - Kind Communication](md/tcllib/files/devdoc/tcl_community_communication.md)
   * [License](md/tcllib/files/devdoc/tcllib_license.md)
   * [How To Get The Sources](md/tcllib/files/devdoc/tcllib_sources.md)
   * [How To Build And Install Tcllib](md/tcllib/files/devdoc/tcllib_installer.md)
   * [The Developer's Guide](md/tcllib/files/devdoc/tcllib_devguide.md)
   * [The Release Manager's Guide](md/tcllib/files/devdoc/tcllib_releasemgr.md)

## Discussion & Contact

Tcllib has two
[mailing lists](https://sourceforge.net/p/tcllib/mailman/).

One for notifications (commits, ticket changes), the other for general
discussion. These are managed at SourceForge, at the aforementioned

Changes to embedded/md/index.md.

230
231
232
233
234
235
236


237
238
239
240
241
242
243
|<a name='\_dev\_null'></a>/dev/null|[tcl::chan::null](tcllib/files/modules/virtchannel\_base/tcllib\_null\.md) &#183; [tcl::chan::nullzero](tcllib/files/modules/virtchannel\_base/nullzero\.md)|
|<a name='\_dev\_random'></a>/dev/random|[tcl::chan::random](tcllib/files/modules/virtchannel\_base/tcllib\_random\.md) &#183; [tcl::randomseed](tcllib/files/modules/virtchannel\_base/randseed\.md)|
|<a name='\_dev\_zero'></a>/dev/zero|[tcl::chan::nullzero](tcllib/files/modules/virtchannel\_base/nullzero\.md) &#183; [tcl::chan::zero](tcllib/files/modules/virtchannel\_base/tcllib\_zero\.md)|
|<a name='diameter'></a>diameter|[struct::graph::op](tcllib/files/modules/struct/graphops\.md)|
|<a name='dict'></a>dict|[dicttool](tcllib/files/modules/dicttool/dicttool\.md)|
|<a name='diff'></a>diff|[docstrip\_util](tcllib/files/modules/docstrip/docstrip\_util\.md) &#183; [struct::list](tcllib/files/modules/struct/struct\_list\.md)|
|<a name='diff\_n\_format'></a>diff \-n format|[rcs](tcllib/files/modules/rcs/rcs\.md)|


|<a name='difference'></a>difference|[struct::set](tcllib/files/modules/struct/struct\_set\.md)|
|<a name='differential'></a>differential|[struct::list](tcllib/files/modules/struct/struct\_list\.md)|
|<a name='differential\_equations'></a>differential equations|[math::calculus](tcllib/files/modules/math/calculus\.md)|
|<a name='dijkstra'></a>dijkstra|[struct::graph::op](tcllib/files/modules/struct/graphops\.md)|
|<a name='directory\_access'></a>directory access|[ldap](tcllib/files/modules/ldap/ldap\.md) &#183; [ldapx](tcllib/files/modules/ldap/ldapx\.md)|
|<a name='directory\_traversal'></a>directory traversal|[fileutil\_traverse](tcllib/files/modules/fileutil/traverse\.md)|
|<a name='discover'></a>Discover|[valtype::creditcard::discover](tcllib/files/modules/valtype/cc\_discover\.md)|







>
>







230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
|<a name='\_dev\_null'></a>/dev/null|[tcl::chan::null](tcllib/files/modules/virtchannel\_base/tcllib\_null\.md) &#183; [tcl::chan::nullzero](tcllib/files/modules/virtchannel\_base/nullzero\.md)|
|<a name='\_dev\_random'></a>/dev/random|[tcl::chan::random](tcllib/files/modules/virtchannel\_base/tcllib\_random\.md) &#183; [tcl::randomseed](tcllib/files/modules/virtchannel\_base/randseed\.md)|
|<a name='\_dev\_zero'></a>/dev/zero|[tcl::chan::nullzero](tcllib/files/modules/virtchannel\_base/nullzero\.md) &#183; [tcl::chan::zero](tcllib/files/modules/virtchannel\_base/tcllib\_zero\.md)|
|<a name='diameter'></a>diameter|[struct::graph::op](tcllib/files/modules/struct/graphops\.md)|
|<a name='dict'></a>dict|[dicttool](tcllib/files/modules/dicttool/dicttool\.md)|
|<a name='diff'></a>diff|[docstrip\_util](tcllib/files/modules/docstrip/docstrip\_util\.md) &#183; [struct::list](tcllib/files/modules/struct/struct\_list\.md)|
|<a name='diff\_n\_format'></a>diff \-n format|[rcs](tcllib/files/modules/rcs/rcs\.md)|
|<a name='diff\_run'></a>diff \-ruN|[textutil::patch](tcllib/files/modules/textutil/patch\.md)|
|<a name='diff\_unified\_format'></a>diff, unified format|[textutil::patch](tcllib/files/modules/textutil/patch\.md)|
|<a name='difference'></a>difference|[struct::set](tcllib/files/modules/struct/struct\_set\.md)|
|<a name='differential'></a>differential|[struct::list](tcllib/files/modules/struct/struct\_list\.md)|
|<a name='differential\_equations'></a>differential equations|[math::calculus](tcllib/files/modules/math/calculus\.md)|
|<a name='dijkstra'></a>dijkstra|[struct::graph::op](tcllib/files/modules/struct/graphops\.md)|
|<a name='directory\_access'></a>directory access|[ldap](tcllib/files/modules/ldap/ldap\.md) &#183; [ldapx](tcllib/files/modules/ldap/ldapx\.md)|
|<a name='directory\_traversal'></a>directory traversal|[fileutil\_traverse](tcllib/files/modules/fileutil/traverse\.md)|
|<a name='discover'></a>Discover|[valtype::creditcard::discover](tcllib/files/modules/valtype/cc\_discover\.md)|
342
343
344
345
346
347
348

349
350
351
352
353
354
355
|<a name='foldr'></a>foldr|[generator](tcllib/files/modules/generator/generator\.md)|
|<a name='foreach'></a>foreach|[generator](tcllib/files/modules/generator/generator\.md)|
|<a name='form'></a>form|[html](tcllib/files/modules/html/html\.md) &#183; [ncgi](tcllib/files/modules/ncgi/ncgi\.md)|
|<a name='format\_conversion'></a>format conversion|[pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md)|
|<a name='formatter'></a>formatter|[doctools\_plugin\_apiref](tcllib/files/modules/doctools/doctools\_plugin\_apiref\.md)|
|<a name='formatting'></a>formatting|[bench::in](tcllib/files/modules/bench/bench\_read\.md) &#183; [bench::out::csv](tcllib/files/modules/bench/bench\_wcsv\.md) &#183; [bench::out::text](tcllib/files/modules/bench/bench\_wtext\.md) &#183; [doctools2idx\_introduction](tcllib/files/modules/doctools2idx/idx\_introduction\.md) &#183; [doctools2toc\_introduction](tcllib/files/modules/doctools2toc/toc\_introduction\.md) &#183; [doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::toc](tcllib/files/modules/doctools2toc/toc\_container\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md) &#183; [textutil](tcllib/files/modules/textutil/textutil\.md) &#183; [textutil::adjust](tcllib/files/modules/textutil/adjust\.md) &#183; [textutil::string](tcllib/files/modules/textutil/textutil\_string\.md) &#183; [textutil::tabify](tcllib/files/modules/textutil/tabify\.md)|
|<a name='formatting\_engine'></a>formatting engine|[docidx\_plugin\_apiref](tcllib/files/modules/doctools/docidx\_plugin\_apiref\.md) &#183; [doctoc\_plugin\_apiref](tcllib/files/modules/doctools/doctoc\_plugin\_apiref\.md) &#183; [doctools\_plugin\_apiref](tcllib/files/modules/doctools/doctools\_plugin\_apiref\.md)|

|<a name='fourier\_transform'></a>Fourier transform|[math::fourier](tcllib/files/modules/math/fourier\.md)|
|<a name='fr'></a>FR|[doctools::msgcat::idx::fr](tcllib/files/modules/doctools2idx/idx\_msgcat\_fr\.md) &#183; [doctools::msgcat::toc::fr](tcllib/files/modules/doctools2toc/toc\_msgcat\_fr\.md)|
|<a name='frame'></a>frame|[term::ansi::code::macros](tcllib/files/modules/term/ansi\_cmacros\.md)|
|<a name='framework'></a>framework|[tool](tcllib/files/modules/tool/tool\.md)|
|<a name='ftp'></a>ftp|[ftp](tcllib/files/modules/ftp/ftp\.md) &#183; [ftp::geturl](tcllib/files/modules/ftp/ftp\_geturl\.md) &#183; [ftpd](tcllib/files/modules/ftpd/ftpd\.md) &#183; [uri](tcllib/files/modules/uri/uri\.md)|
|<a name='ftpd'></a>ftpd|[ftpd](tcllib/files/modules/ftpd/ftpd\.md)|
|<a name='ftpserver'></a>ftpserver|[ftpd](tcllib/files/modules/ftpd/ftpd\.md)|







>







344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
|<a name='foldr'></a>foldr|[generator](tcllib/files/modules/generator/generator\.md)|
|<a name='foreach'></a>foreach|[generator](tcllib/files/modules/generator/generator\.md)|
|<a name='form'></a>form|[html](tcllib/files/modules/html/html\.md) &#183; [ncgi](tcllib/files/modules/ncgi/ncgi\.md)|
|<a name='format\_conversion'></a>format conversion|[pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md)|
|<a name='formatter'></a>formatter|[doctools\_plugin\_apiref](tcllib/files/modules/doctools/doctools\_plugin\_apiref\.md)|
|<a name='formatting'></a>formatting|[bench::in](tcllib/files/modules/bench/bench\_read\.md) &#183; [bench::out::csv](tcllib/files/modules/bench/bench\_wcsv\.md) &#183; [bench::out::text](tcllib/files/modules/bench/bench\_wtext\.md) &#183; [doctools2idx\_introduction](tcllib/files/modules/doctools2idx/idx\_introduction\.md) &#183; [doctools2toc\_introduction](tcllib/files/modules/doctools2toc/toc\_introduction\.md) &#183; [doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::toc](tcllib/files/modules/doctools2toc/toc\_container\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md) &#183; [textutil](tcllib/files/modules/textutil/textutil\.md) &#183; [textutil::adjust](tcllib/files/modules/textutil/adjust\.md) &#183; [textutil::string](tcllib/files/modules/textutil/textutil\_string\.md) &#183; [textutil::tabify](tcllib/files/modules/textutil/tabify\.md)|
|<a name='formatting\_engine'></a>formatting engine|[docidx\_plugin\_apiref](tcllib/files/modules/doctools/docidx\_plugin\_apiref\.md) &#183; [doctoc\_plugin\_apiref](tcllib/files/modules/doctools/doctoc\_plugin\_apiref\.md) &#183; [doctools\_plugin\_apiref](tcllib/files/modules/doctools/doctools\_plugin\_apiref\.md)|
|<a name='fossil'></a>fossil|[textutil::patch](tcllib/files/modules/textutil/patch\.md)|
|<a name='fourier\_transform'></a>Fourier transform|[math::fourier](tcllib/files/modules/math/fourier\.md)|
|<a name='fr'></a>FR|[doctools::msgcat::idx::fr](tcllib/files/modules/doctools2idx/idx\_msgcat\_fr\.md) &#183; [doctools::msgcat::toc::fr](tcllib/files/modules/doctools2toc/toc\_msgcat\_fr\.md)|
|<a name='frame'></a>frame|[term::ansi::code::macros](tcllib/files/modules/term/ansi\_cmacros\.md)|
|<a name='framework'></a>framework|[tool](tcllib/files/modules/tool/tool\.md)|
|<a name='ftp'></a>ftp|[ftp](tcllib/files/modules/ftp/ftp\.md) &#183; [ftp::geturl](tcllib/files/modules/ftp/ftp\_geturl\.md) &#183; [ftpd](tcllib/files/modules/ftpd/ftpd\.md) &#183; [uri](tcllib/files/modules/uri/uri\.md)|
|<a name='ftpd'></a>ftpd|[ftpd](tcllib/files/modules/ftpd/ftpd\.md)|
|<a name='ftpserver'></a>ftpserver|[ftpd](tcllib/files/modules/ftpd/ftpd\.md)|
365
366
367
368
369
370
371

372
373
374
375
376
377
378
|<a name='generation'></a>generation|[doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::toc](tcllib/files/modules/doctools2toc/toc\_container\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md)|
|<a name='generator'></a>generator|[generator](tcllib/files/modules/generator/generator\.md)|
|<a name='geocoding'></a>geocoding|[map::geocode::nominatim](tcllib/files/modules/map/map\_geocode\_nominatim\.md)|
|<a name='geodesy'></a>geodesy|[map::slippy](tcllib/files/modules/map/map\_slippy\.md) &#183; [mapproj](tcllib/files/modules/mapproj/mapproj\.md)|
|<a name='geography'></a>geography|[map::slippy](tcllib/files/modules/map/map\_slippy\.md)|
|<a name='get\_character'></a>get character|[term::receive](tcllib/files/modules/term/receive\.md)|
|<a name='gets'></a>gets|[coroutine](tcllib/files/modules/coroutine/tcllib\_coroutine\.md) &#183; [coroutine::auto](tcllib/files/modules/coroutine/coro\_auto\.md)|

|<a name='global'></a>global|[coroutine](tcllib/files/modules/coroutine/tcllib\_coroutine\.md) &#183; [coroutine::auto](tcllib/files/modules/coroutine/coro\_auto\.md)|
|<a name='golang'></a>golang|[defer](tcllib/files/modules/defer/defer\.md)|
|<a name='gopher'></a>gopher|[uri](tcllib/files/modules/uri/uri\.md)|
|<a name='gps'></a>gps|[gpx](tcllib/files/modules/gpx/gpx\.md) &#183; [nmea](tcllib/files/modules/nmea/nmea\.md)|
|<a name='gpx'></a>gpx|[gpx](tcllib/files/modules/gpx/gpx\.md)|
|<a name='grammar'></a>grammar|[grammar::aycock](tcllib/files/modules/grammar\_aycock/aycock\.md) &#183; [grammar::fa](tcllib/files/modules/grammar\_fa/fa\.md) &#183; [grammar::fa::dacceptor](tcllib/files/modules/grammar\_fa/dacceptor\.md) &#183; [grammar::fa::dexec](tcllib/files/modules/grammar\_fa/dexec\.md) &#183; [grammar::fa::op](tcllib/files/modules/grammar\_fa/faop\.md) &#183; [grammar::me::cpu](tcllib/files/modules/grammar\_me/me\_cpu\.md) &#183; [grammar::me::cpu::core](tcllib/files/modules/grammar\_me/me\_cpucore\.md) &#183; [grammar::me::cpu::gasm](tcllib/files/modules/grammar\_me/gasm\.md) &#183; [grammar::me::tcl](tcllib/files/modules/grammar\_me/me\_tcl\.md) &#183; [grammar::me\_intro](tcllib/files/modules/grammar\_me/me\_intro\.md) &#183; [grammar::me\_vm](tcllib/files/modules/grammar\_me/me\_vm\.md) &#183; [grammar::peg](tcllib/files/modules/grammar\_peg/peg\.md) &#183; [grammar::peg::interp](tcllib/files/modules/grammar\_peg/peg\_interp\.md) &#183; [pt](tcllib/files/apps/pt\.md) &#183; [pt::ast](tcllib/files/modules/pt/pt\_astree\.md) &#183; [pt::cparam::configuration::critcl](tcllib/files/modules/pt/pt\_cparam\_config\_critcl\.md) &#183; [pt::cparam::configuration::tea](tcllib/files/modules/pt/pt\_cparam\_config\_tea\.md) &#183; [pt::json\_language](tcllib/files/modules/pt/pt\_json\_language\.md) &#183; [pt::param](tcllib/files/modules/pt/pt\_param\.md) &#183; [pt::pe](tcllib/files/modules/pt/pt\_pexpression\.md) &#183; [pt::pe::op](tcllib/files/modules/pt/pt\_pexpr\_op\.md) &#183; [pt::peg](tcllib/files/modules/pt/pt\_pegrammar\.md) &#183; [pt::peg::container](tcllib/files/modules/pt/pt\_peg\_container\.md) &#183; [pt::peg::container::peg](tcllib/files/modules/pt/pt\_peg\_container\_peg\.md) &#183; [pt::peg::export](tcllib/files/modules/pt/pt\_peg\_export\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::container](tcllib/files/modules/pt/pt\_peg\_from\_container\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import](tcllib/files/modules/pt/pt\_peg\_import\.md) &#183; [pt::peg::import::container](tcllib/files/modules/pt/pt\_peg\_import\_container\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::interp](tcllib/files/modules/pt/pt\_peg\_interp\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [pt::peg\_language](tcllib/files/modules/pt/pt\_peg\_language\.md) &#183; [pt::pegrammar](tcllib/files/modules/pt/pt\_peg\_introduction\.md) &#183; [pt::pgen](tcllib/files/modules/pt/pt\_pgen\.md) &#183; [pt::rde](tcllib/files/modules/pt/pt\_rdengine\.md) &#183; [pt::tclparam::configuration::nx](tcllib/files/modules/pt/pt\_tclparam\_config\_nx\.md) &#183; [pt::tclparam::configuration::snit](tcllib/files/modules/pt/pt\_tclparam\_config\_snit\.md) &#183; [pt::tclparam::configuration::tcloo](tcllib/files/modules/pt/pt\_tclparam\_config\_tcloo\.md) &#183; [pt::util](tcllib/files/modules/pt/pt\_util\.md) &#183; [pt\_export\_api](tcllib/files/modules/pt/pt\_to\_api\.md) &#183; [pt\_import\_api](tcllib/files/modules/pt/pt\_from\_api\.md) &#183; [pt\_introduction](tcllib/files/modules/pt/pt\_introduction\.md) &#183; [pt\_parse\_peg](tcllib/files/modules/pt/pt\_parse\_peg\.md) &#183; [pt\_parser\_api](tcllib/files/modules/pt/pt\_parser\_api\.md) &#183; [pt\_peg\_op](tcllib/files/modules/pt/pt\_peg\_op\.md)|
|<a name='graph'></a>graph|[grammar::me::cpu::gasm](tcllib/files/modules/grammar\_me/gasm\.md) &#183; [struct::graph](tcllib/files/modules/struct/graph\.md) &#183; [struct::graph::op](tcllib/files/modules/struct/graphops\.md) &#183; [struct::graph\_v1](tcllib/files/modules/struct/graph1\.md) &#183; [struct::queue](tcllib/files/modules/struct/queue\.md) &#183; [struct::stack](tcllib/files/modules/struct/stack\.md)|







>







368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
|<a name='generation'></a>generation|[doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::toc](tcllib/files/modules/doctools2toc/toc\_container\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md)|
|<a name='generator'></a>generator|[generator](tcllib/files/modules/generator/generator\.md)|
|<a name='geocoding'></a>geocoding|[map::geocode::nominatim](tcllib/files/modules/map/map\_geocode\_nominatim\.md)|
|<a name='geodesy'></a>geodesy|[map::slippy](tcllib/files/modules/map/map\_slippy\.md) &#183; [mapproj](tcllib/files/modules/mapproj/mapproj\.md)|
|<a name='geography'></a>geography|[map::slippy](tcllib/files/modules/map/map\_slippy\.md)|
|<a name='get\_character'></a>get character|[term::receive](tcllib/files/modules/term/receive\.md)|
|<a name='gets'></a>gets|[coroutine](tcllib/files/modules/coroutine/tcllib\_coroutine\.md) &#183; [coroutine::auto](tcllib/files/modules/coroutine/coro\_auto\.md)|
|<a name='git'></a>git|[textutil::patch](tcllib/files/modules/textutil/patch\.md)|
|<a name='global'></a>global|[coroutine](tcllib/files/modules/coroutine/tcllib\_coroutine\.md) &#183; [coroutine::auto](tcllib/files/modules/coroutine/coro\_auto\.md)|
|<a name='golang'></a>golang|[defer](tcllib/files/modules/defer/defer\.md)|
|<a name='gopher'></a>gopher|[uri](tcllib/files/modules/uri/uri\.md)|
|<a name='gps'></a>gps|[gpx](tcllib/files/modules/gpx/gpx\.md) &#183; [nmea](tcllib/files/modules/nmea/nmea\.md)|
|<a name='gpx'></a>gpx|[gpx](tcllib/files/modules/gpx/gpx\.md)|
|<a name='grammar'></a>grammar|[grammar::aycock](tcllib/files/modules/grammar\_aycock/aycock\.md) &#183; [grammar::fa](tcllib/files/modules/grammar\_fa/fa\.md) &#183; [grammar::fa::dacceptor](tcllib/files/modules/grammar\_fa/dacceptor\.md) &#183; [grammar::fa::dexec](tcllib/files/modules/grammar\_fa/dexec\.md) &#183; [grammar::fa::op](tcllib/files/modules/grammar\_fa/faop\.md) &#183; [grammar::me::cpu](tcllib/files/modules/grammar\_me/me\_cpu\.md) &#183; [grammar::me::cpu::core](tcllib/files/modules/grammar\_me/me\_cpucore\.md) &#183; [grammar::me::cpu::gasm](tcllib/files/modules/grammar\_me/gasm\.md) &#183; [grammar::me::tcl](tcllib/files/modules/grammar\_me/me\_tcl\.md) &#183; [grammar::me\_intro](tcllib/files/modules/grammar\_me/me\_intro\.md) &#183; [grammar::me\_vm](tcllib/files/modules/grammar\_me/me\_vm\.md) &#183; [grammar::peg](tcllib/files/modules/grammar\_peg/peg\.md) &#183; [grammar::peg::interp](tcllib/files/modules/grammar\_peg/peg\_interp\.md) &#183; [pt](tcllib/files/apps/pt\.md) &#183; [pt::ast](tcllib/files/modules/pt/pt\_astree\.md) &#183; [pt::cparam::configuration::critcl](tcllib/files/modules/pt/pt\_cparam\_config\_critcl\.md) &#183; [pt::cparam::configuration::tea](tcllib/files/modules/pt/pt\_cparam\_config\_tea\.md) &#183; [pt::json\_language](tcllib/files/modules/pt/pt\_json\_language\.md) &#183; [pt::param](tcllib/files/modules/pt/pt\_param\.md) &#183; [pt::pe](tcllib/files/modules/pt/pt\_pexpression\.md) &#183; [pt::pe::op](tcllib/files/modules/pt/pt\_pexpr\_op\.md) &#183; [pt::peg](tcllib/files/modules/pt/pt\_pegrammar\.md) &#183; [pt::peg::container](tcllib/files/modules/pt/pt\_peg\_container\.md) &#183; [pt::peg::container::peg](tcllib/files/modules/pt/pt\_peg\_container\_peg\.md) &#183; [pt::peg::export](tcllib/files/modules/pt/pt\_peg\_export\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::container](tcllib/files/modules/pt/pt\_peg\_from\_container\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import](tcllib/files/modules/pt/pt\_peg\_import\.md) &#183; [pt::peg::import::container](tcllib/files/modules/pt/pt\_peg\_import\_container\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::interp](tcllib/files/modules/pt/pt\_peg\_interp\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [pt::peg\_language](tcllib/files/modules/pt/pt\_peg\_language\.md) &#183; [pt::pegrammar](tcllib/files/modules/pt/pt\_peg\_introduction\.md) &#183; [pt::pgen](tcllib/files/modules/pt/pt\_pgen\.md) &#183; [pt::rde](tcllib/files/modules/pt/pt\_rdengine\.md) &#183; [pt::tclparam::configuration::nx](tcllib/files/modules/pt/pt\_tclparam\_config\_nx\.md) &#183; [pt::tclparam::configuration::snit](tcllib/files/modules/pt/pt\_tclparam\_config\_snit\.md) &#183; [pt::tclparam::configuration::tcloo](tcllib/files/modules/pt/pt\_tclparam\_config\_tcloo\.md) &#183; [pt::util](tcllib/files/modules/pt/pt\_util\.md) &#183; [pt\_export\_api](tcllib/files/modules/pt/pt\_to\_api\.md) &#183; [pt\_import\_api](tcllib/files/modules/pt/pt\_from\_api\.md) &#183; [pt\_introduction](tcllib/files/modules/pt/pt\_introduction\.md) &#183; [pt\_parse\_peg](tcllib/files/modules/pt/pt\_parse\_peg\.md) &#183; [pt\_parser\_api](tcllib/files/modules/pt/pt\_parser\_api\.md) &#183; [pt\_peg\_op](tcllib/files/modules/pt/pt\_peg\_op\.md)|
|<a name='graph'></a>graph|[grammar::me::cpu::gasm](tcllib/files/modules/grammar\_me/gasm\.md) &#183; [struct::graph](tcllib/files/modules/struct/graph\.md) &#183; [struct::graph::op](tcllib/files/modules/struct/graphops\.md) &#183; [struct::graph\_v1](tcllib/files/modules/struct/graph1\.md) &#183; [struct::queue](tcllib/files/modules/struct/queue\.md) &#183; [struct::stack](tcllib/files/modules/struct/stack\.md)|
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
|<a name='hex'></a>hex|[base32::hex](tcllib/files/modules/base32/base32hex\.md)|
|<a name='hexadecimal'></a>hexadecimal|[tcl::transform::hex](tcllib/files/modules/virtchannel\_transform/hex\.md)|
|<a name='histogram'></a>histogram|[counter](tcllib/files/modules/counter/counter\.md)|
|<a name='hook'></a>hook|[hook](tcllib/files/modules/hook/hook\.md) &#183; [uevent](tcllib/files/modules/uev/uevent\.md)|
|<a name='horspool'></a>horspool|[grammar::aycock](tcllib/files/modules/grammar\_aycock/aycock\.md)|
|<a name='html'></a>HTML|[doctools](tcllib/files/modules/doctools/doctools\.md) &#183; [doctools::html::cssdefaults](tcllib/files/modules/doctools2base/html\_cssdefaults\.md) &#183; [doctools::idx](tcllib/files/modules/doctools/docidx\.md) &#183; [doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::idx::export::html](tcllib/files/modules/doctools2idx/idx\_export\_html\.md) &#183; [doctools::toc](tcllib/files/modules/doctools2toc/toc\_container\.md) &#183; [doctools::toc](tcllib/files/modules/doctools/doctoc\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md) &#183; [doctools::toc::export::html](tcllib/files/modules/doctools2toc/toc\_export\_html\.md) &#183; [dtplite](tcllib/files/modules/dtplite/pkg\_dtplite\.md) &#183; [dtplite](tcllib/files/apps/dtplite\.md) &#183; [mpexpand](tcllib/files/modules/doctools/mpexpand\.md)|
|<a name='html'></a>html|[html](tcllib/files/modules/html/html\.md) &#183; [htmlparse](tcllib/files/modules/htmlparse/htmlparse\.md) &#183; [javascript](tcllib/files/modules/javascript/javascript\.md) &#183; [ncgi](tcllib/files/modules/ncgi/ncgi\.md)|
|<a name='http'></a>http|[autoproxy](tcllib/files/modules/http/autoproxy\.md) &#183; [map::geocode::nominatim](tcllib/files/modules/map/map\_geocode\_nominatim\.md) &#183; [map::slippy::fetcher](tcllib/files/modules/map/map\_slippy\_fetcher\.md) &#183; [tool](tcllib/files/modules/httpd/httpd\.md) &#183; [uri](tcllib/files/modules/uri/uri\.md) &#183; [websocket](tcllib/files/modules/websocket/websocket\.md)|
|<a name='httpd'></a>httpd|[tool](tcllib/files/modules/httpd/httpd\.md)|
|<a name='https'></a>https|[uri](tcllib/files/modules/uri/uri\.md)|
|<a name='httpserver'></a>httpserver|[tool](tcllib/files/modules/httpd/httpd\.md)|
|<a name='huddle'></a>huddle|[huddle](tcllib/files/modules/yaml/huddle\.md) &#183; [yaml](tcllib/files/modules/yaml/yaml\.md)|
|<a name='human\_readable'></a>human readable|[bench::in](tcllib/files/modules/bench/bench\_read\.md) &#183; [bench::out::text](tcllib/files/modules/bench/bench\_wtext\.md)|
|<a name='hyphenation'></a>hyphenation|[textutil](tcllib/files/modules/textutil/textutil\.md) &#183; [textutil::adjust](tcllib/files/modules/textutil/adjust\.md)|


#### <a name='cI'></a>Keywords: I








|
|

|







396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
|<a name='hex'></a>hex|[base32::hex](tcllib/files/modules/base32/base32hex\.md)|
|<a name='hexadecimal'></a>hexadecimal|[tcl::transform::hex](tcllib/files/modules/virtchannel\_transform/hex\.md)|
|<a name='histogram'></a>histogram|[counter](tcllib/files/modules/counter/counter\.md)|
|<a name='hook'></a>hook|[hook](tcllib/files/modules/hook/hook\.md) &#183; [uevent](tcllib/files/modules/uev/uevent\.md)|
|<a name='horspool'></a>horspool|[grammar::aycock](tcllib/files/modules/grammar\_aycock/aycock\.md)|
|<a name='html'></a>HTML|[doctools](tcllib/files/modules/doctools/doctools\.md) &#183; [doctools::html::cssdefaults](tcllib/files/modules/doctools2base/html\_cssdefaults\.md) &#183; [doctools::idx](tcllib/files/modules/doctools/docidx\.md) &#183; [doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::idx::export::html](tcllib/files/modules/doctools2idx/idx\_export\_html\.md) &#183; [doctools::toc](tcllib/files/modules/doctools2toc/toc\_container\.md) &#183; [doctools::toc](tcllib/files/modules/doctools/doctoc\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md) &#183; [doctools::toc::export::html](tcllib/files/modules/doctools2toc/toc\_export\_html\.md) &#183; [dtplite](tcllib/files/modules/dtplite/pkg\_dtplite\.md) &#183; [dtplite](tcllib/files/apps/dtplite\.md) &#183; [mpexpand](tcllib/files/modules/doctools/mpexpand\.md)|
|<a name='html'></a>html|[html](tcllib/files/modules/html/html\.md) &#183; [htmlparse](tcllib/files/modules/htmlparse/htmlparse\.md) &#183; [javascript](tcllib/files/modules/javascript/javascript\.md) &#183; [ncgi](tcllib/files/modules/ncgi/ncgi\.md)|
|<a name='http'></a>http|[autoproxy](tcllib/files/modules/http/autoproxy\.md) &#183; [httpd](tcllib/files/modules/httpd/httpd\.md) &#183; [map::geocode::nominatim](tcllib/files/modules/map/map\_geocode\_nominatim\.md) &#183; [map::slippy::fetcher](tcllib/files/modules/map/map\_slippy\_fetcher\.md) &#183; [uri](tcllib/files/modules/uri/uri\.md) &#183; [websocket](tcllib/files/modules/websocket/websocket\.md)|
|<a name='httpd'></a>httpd|[httpd](tcllib/files/modules/httpd/httpd\.md)|
|<a name='https'></a>https|[uri](tcllib/files/modules/uri/uri\.md)|
|<a name='httpserver'></a>httpserver|[httpd](tcllib/files/modules/httpd/httpd\.md)|
|<a name='huddle'></a>huddle|[huddle](tcllib/files/modules/yaml/huddle\.md) &#183; [yaml](tcllib/files/modules/yaml/yaml\.md)|
|<a name='human\_readable'></a>human readable|[bench::in](tcllib/files/modules/bench/bench\_read\.md) &#183; [bench::out::text](tcllib/files/modules/bench/bench\_wtext\.md)|
|<a name='hyphenation'></a>hyphenation|[textutil](tcllib/files/modules/textutil/textutil\.md) &#183; [textutil::adjust](tcllib/files/modules/textutil/adjust\.md)|


#### <a name='cI'></a>Keywords: I

529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
|<a name='manpage'></a>manpage|[doctools](tcllib/files/modules/doctools/doctools\.md) &#183; [doctools::idx](tcllib/files/modules/doctools/docidx\.md) &#183; [doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::idx::import](tcllib/files/modules/doctools2idx/idx\_import\.md) &#183; [doctools::toc](tcllib/files/modules/doctools/doctoc\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md) &#183; [doctools::toc::import](tcllib/files/modules/doctools2toc/toc\_import\.md) &#183; [doctools\_plugin\_apiref](tcllib/files/modules/doctools/doctools\_plugin\_apiref\.md) &#183; [dtplite](tcllib/files/modules/dtplite/pkg\_dtplite\.md) &#183; [dtplite](tcllib/files/apps/dtplite\.md) &#183; [mpexpand](tcllib/files/modules/doctools/mpexpand\.md)|
|<a name='map'></a>map|[generator](tcllib/files/modules/generator/generator\.md) &#183; [map::geocode::nominatim](tcllib/files/modules/map/map\_geocode\_nominatim\.md) &#183; [map::slippy](tcllib/files/modules/map/map\_slippy\.md) &#183; [map::slippy::cache](tcllib/files/modules/map/map\_slippy\_cache\.md) &#183; [map::slippy::fetcher](tcllib/files/modules/map/map\_slippy\_fetcher\.md) &#183; [mapproj](tcllib/files/modules/mapproj/mapproj\.md) &#183; [struct::list](tcllib/files/modules/struct/struct\_list\.md)|
|<a name='markdown'></a>markdown|[doctools](tcllib/files/modules/doctools/doctools\.md) &#183; [doctools::idx](tcllib/files/modules/doctools/docidx\.md) &#183; [doctools::toc](tcllib/files/modules/doctools/doctoc\.md)|
|<a name='markup'></a>markup|[docidx\_intro](tcllib/files/modules/doctools/docidx\_intro\.md) &#183; [docidx\_lang\_cmdref](tcllib/files/modules/doctools/docidx\_lang\_cmdref\.md) &#183; [docidx\_lang\_faq](tcllib/files/modules/doctools/docidx\_lang\_faq\.md) &#183; [docidx\_lang\_intro](tcllib/files/modules/doctools/docidx\_lang\_intro\.md) &#183; [docidx\_lang\_syntax](tcllib/files/modules/doctools/docidx\_lang\_syntax\.md) &#183; [docidx\_plugin\_apiref](tcllib/files/modules/doctools/docidx\_plugin\_apiref\.md) &#183; [doctoc\_intro](tcllib/files/modules/doctools/doctoc\_intro\.md) &#183; [doctoc\_lang\_cmdref](tcllib/files/modules/doctools/doctoc\_lang\_cmdref\.md) &#183; [doctoc\_lang\_faq](tcllib/files/modules/doctools/doctoc\_lang\_faq\.md) &#183; [doctoc\_lang\_intro](tcllib/files/modules/doctools/doctoc\_lang\_intro\.md) &#183; [doctoc\_lang\_syntax](tcllib/files/modules/doctools/doctoc\_lang\_syntax\.md) &#183; [doctoc\_plugin\_apiref](tcllib/files/modules/doctools/doctoc\_plugin\_apiref\.md) &#183; [doctools](tcllib/files/modules/doctools/doctools\.md) &#183; [doctools2idx\_introduction](tcllib/files/modules/doctools2idx/idx\_introduction\.md) &#183; [doctools2toc\_introduction](tcllib/files/modules/doctools2toc/toc\_introduction\.md) &#183; [doctools::idx](tcllib/files/modules/doctools/docidx\.md) &#183; [doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::idx::import](tcllib/files/modules/doctools2idx/idx\_import\.md) &#183; [doctools::toc](tcllib/files/modules/doctools2toc/toc\_container\.md) &#183; [doctools::toc](tcllib/files/modules/doctools/doctoc\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md) &#183; [doctools::toc::import](tcllib/files/modules/doctools2toc/toc\_import\.md) &#183; [doctools\_intro](tcllib/files/modules/doctools/doctools\_intro\.md) &#183; [doctools\_lang\_cmdref](tcllib/files/modules/doctools/doctools\_lang\_cmdref\.md) &#183; [doctools\_lang\_faq](tcllib/files/modules/doctools/doctools\_lang\_faq\.md) &#183; [doctools\_lang\_intro](tcllib/files/modules/doctools/doctools\_lang\_intro\.md) &#183; [doctools\_lang\_syntax](tcllib/files/modules/doctools/doctools\_lang\_syntax\.md) &#183; [doctools\_plugin\_apiref](tcllib/files/modules/doctools/doctools\_plugin\_apiref\.md) &#183; [dtplite](tcllib/files/modules/dtplite/pkg\_dtplite\.md) &#183; [dtplite](tcllib/files/apps/dtplite\.md) &#183; [mpexpand](tcllib/files/modules/doctools/mpexpand\.md) &#183; [tcldocstrip](tcllib/files/apps/tcldocstrip\.md)|
|<a name='mastercard'></a>MasterCard|[valtype::creditcard::mastercard](tcllib/files/modules/valtype/cc\_mastercard\.md)|
|<a name='matching'></a>matching|[grammar::me\_intro](tcllib/files/modules/grammar\_me/me\_intro\.md) &#183; [grammar::peg::interp](tcllib/files/modules/grammar\_peg/peg\_interp\.md) &#183; [pt](tcllib/files/apps/pt\.md) &#183; [pt::ast](tcllib/files/modules/pt/pt\_astree\.md) &#183; [pt::cparam::configuration::critcl](tcllib/files/modules/pt/pt\_cparam\_config\_critcl\.md) &#183; [pt::cparam::configuration::tea](tcllib/files/modules/pt/pt\_cparam\_config\_tea\.md) &#183; [pt::json\_language](tcllib/files/modules/pt/pt\_json\_language\.md) &#183; [pt::param](tcllib/files/modules/pt/pt\_param\.md) &#183; [pt::pe](tcllib/files/modules/pt/pt\_pexpression\.md) &#183; [pt::pe::op](tcllib/files/modules/pt/pt\_pexpr\_op\.md) &#183; [pt::peg](tcllib/files/modules/pt/pt\_pegrammar\.md) &#183; [pt::peg::container](tcllib/files/modules/pt/pt\_peg\_container\.md) &#183; [pt::peg::container::peg](tcllib/files/modules/pt/pt\_peg\_container\_peg\.md) &#183; [pt::peg::export](tcllib/files/modules/pt/pt\_peg\_export\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::container](tcllib/files/modules/pt/pt\_peg\_from\_container\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import](tcllib/files/modules/pt/pt\_peg\_import\.md) &#183; [pt::peg::import::container](tcllib/files/modules/pt/pt\_peg\_import\_container\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::interp](tcllib/files/modules/pt/pt\_peg\_interp\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [pt::peg\_language](tcllib/files/modules/pt/pt\_peg\_language\.md) &#183; [pt::pegrammar](tcllib/files/modules/pt/pt\_peg\_introduction\.md) &#183; [pt::pgen](tcllib/files/modules/pt/pt\_pgen\.md) &#183; [pt::rde](tcllib/files/modules/pt/pt\_rdengine\.md) &#183; [pt::tclparam::configuration::nx](tcllib/files/modules/pt/pt\_tclparam\_config\_nx\.md) &#183; [pt::tclparam::configuration::snit](tcllib/files/modules/pt/pt\_tclparam\_config\_snit\.md) &#183; [pt::tclparam::configuration::tcloo](tcllib/files/modules/pt/pt\_tclparam\_config\_tcloo\.md) &#183; [pt::util](tcllib/files/modules/pt/pt\_util\.md) &#183; [pt\_export\_api](tcllib/files/modules/pt/pt\_to\_api\.md) &#183; [pt\_import\_api](tcllib/files/modules/pt/pt\_from\_api\.md) &#183; [pt\_introduction](tcllib/files/modules/pt/pt\_introduction\.md) &#183; [pt\_parse\_peg](tcllib/files/modules/pt/pt\_parse\_peg\.md) &#183; [pt\_parser\_api](tcllib/files/modules/pt/pt\_parser\_api\.md) &#183; [pt\_peg\_op](tcllib/files/modules/pt/pt\_peg\_op\.md) &#183; [struct::graph::op](tcllib/files/modules/struct/graphops\.md)|
|<a name='math'></a>math|[math](tcllib/files/modules/math/math\.md) &#183; [math::bigfloat](tcllib/files/modules/math/bigfloat\.md) &#183; [math::bignum](tcllib/files/modules/math/bignum\.md) &#183; [math::calculus](tcllib/files/modules/math/calculus\.md) &#183; [math::complexnumbers](tcllib/files/modules/math/qcomplex\.md) &#183; [math::constants](tcllib/files/modules/math/constants\.md) &#183; [math::decimal](tcllib/files/modules/math/decimal\.md) &#183; [math::fuzzy](tcllib/files/modules/math/fuzzy\.md) &#183; [math::geometry](tcllib/files/modules/math/math\_geometry\.md) &#183; [math::interpolate](tcllib/files/modules/math/interpolate\.md) &#183; [math::linearalgebra](tcllib/files/modules/math/linalg\.md) &#183; [math::optimize](tcllib/files/modules/math/optimize\.md) &#183; [math::PCA](tcllib/files/modules/math/pca\.md) &#183; [math::polynomials](tcllib/files/modules/math/polynomials\.md) &#183; [math::rationalfunctions](tcllib/files/modules/math/rational\_funcs\.md) &#183; [math::special](tcllib/files/modules/math/special\.md) &#183; [math::trig](tcllib/files/modules/math/trig\.md) &#183; [simulation::annealing](tcllib/files/modules/simulation/annealing\.md) &#183; [simulation::montecarlo](tcllib/files/modules/simulation/montecarlo\.md) &#183; [simulation::random](tcllib/files/modules/simulation/simulation\_random\.md)|
|<a name='mathematics'></a>mathematics|[math::fourier](tcllib/files/modules/math/fourier\.md) &#183; [math::statistics](tcllib/files/modules/math/statistics\.md)|
|<a name='matrices'></a>matrices|[math::linearalgebra](tcllib/files/modules/math/linalg\.md)|
|<a name='matrix'></a>matrix|[csv](tcllib/files/modules/csv/csv\.md) &#183; [math::linearalgebra](tcllib/files/modules/math/linalg\.md) &#183; [report](tcllib/files/modules/report/report\.md) &#183; [struct::matrix](tcllib/files/modules/struct/matrix\.md) &#183; [struct::matrix\_v1](tcllib/files/modules/struct/matrix1\.md) &#183; [struct::queue](tcllib/files/modules/struct/queue\.md) &#183; [struct::stack](tcllib/files/modules/struct/stack\.md)|
|<a name='max\_cut'></a>max cut|[struct::graph::op](tcllib/files/modules/struct/graphops\.md)|
|<a name='maximum'></a>maximum|[math::optimize](tcllib/files/modules/math/optimize\.md)|
|<a name='maximum\_flow'></a>maximum flow|[struct::graph::op](tcllib/files/modules/struct/graphops\.md)|
|<a name='md4'></a>md4|[md4](tcllib/files/modules/md4/md4\.md) &#183; [ripemd128](tcllib/files/modules/ripemd/ripemd128\.md) &#183; [ripemd160](tcllib/files/modules/ripemd/ripemd160\.md)|
|<a name='md5'></a>md5|[md5](tcllib/files/modules/md5/md5\.md) &#183; [md5crypt](tcllib/files/modules/md5crypt/md5crypt\.md)|







|







533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
|<a name='manpage'></a>manpage|[doctools](tcllib/files/modules/doctools/doctools\.md) &#183; [doctools::idx](tcllib/files/modules/doctools/docidx\.md) &#183; [doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::idx::import](tcllib/files/modules/doctools2idx/idx\_import\.md) &#183; [doctools::toc](tcllib/files/modules/doctools/doctoc\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md) &#183; [doctools::toc::import](tcllib/files/modules/doctools2toc/toc\_import\.md) &#183; [doctools\_plugin\_apiref](tcllib/files/modules/doctools/doctools\_plugin\_apiref\.md) &#183; [dtplite](tcllib/files/modules/dtplite/pkg\_dtplite\.md) &#183; [dtplite](tcllib/files/apps/dtplite\.md) &#183; [mpexpand](tcllib/files/modules/doctools/mpexpand\.md)|
|<a name='map'></a>map|[generator](tcllib/files/modules/generator/generator\.md) &#183; [map::geocode::nominatim](tcllib/files/modules/map/map\_geocode\_nominatim\.md) &#183; [map::slippy](tcllib/files/modules/map/map\_slippy\.md) &#183; [map::slippy::cache](tcllib/files/modules/map/map\_slippy\_cache\.md) &#183; [map::slippy::fetcher](tcllib/files/modules/map/map\_slippy\_fetcher\.md) &#183; [mapproj](tcllib/files/modules/mapproj/mapproj\.md) &#183; [struct::list](tcllib/files/modules/struct/struct\_list\.md)|
|<a name='markdown'></a>markdown|[doctools](tcllib/files/modules/doctools/doctools\.md) &#183; [doctools::idx](tcllib/files/modules/doctools/docidx\.md) &#183; [doctools::toc](tcllib/files/modules/doctools/doctoc\.md)|
|<a name='markup'></a>markup|[docidx\_intro](tcllib/files/modules/doctools/docidx\_intro\.md) &#183; [docidx\_lang\_cmdref](tcllib/files/modules/doctools/docidx\_lang\_cmdref\.md) &#183; [docidx\_lang\_faq](tcllib/files/modules/doctools/docidx\_lang\_faq\.md) &#183; [docidx\_lang\_intro](tcllib/files/modules/doctools/docidx\_lang\_intro\.md) &#183; [docidx\_lang\_syntax](tcllib/files/modules/doctools/docidx\_lang\_syntax\.md) &#183; [docidx\_plugin\_apiref](tcllib/files/modules/doctools/docidx\_plugin\_apiref\.md) &#183; [doctoc\_intro](tcllib/files/modules/doctools/doctoc\_intro\.md) &#183; [doctoc\_lang\_cmdref](tcllib/files/modules/doctools/doctoc\_lang\_cmdref\.md) &#183; [doctoc\_lang\_faq](tcllib/files/modules/doctools/doctoc\_lang\_faq\.md) &#183; [doctoc\_lang\_intro](tcllib/files/modules/doctools/doctoc\_lang\_intro\.md) &#183; [doctoc\_lang\_syntax](tcllib/files/modules/doctools/doctoc\_lang\_syntax\.md) &#183; [doctoc\_plugin\_apiref](tcllib/files/modules/doctools/doctoc\_plugin\_apiref\.md) &#183; [doctools](tcllib/files/modules/doctools/doctools\.md) &#183; [doctools2idx\_introduction](tcllib/files/modules/doctools2idx/idx\_introduction\.md) &#183; [doctools2toc\_introduction](tcllib/files/modules/doctools2toc/toc\_introduction\.md) &#183; [doctools::idx](tcllib/files/modules/doctools/docidx\.md) &#183; [doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::idx::import](tcllib/files/modules/doctools2idx/idx\_import\.md) &#183; [doctools::toc](tcllib/files/modules/doctools2toc/toc\_container\.md) &#183; [doctools::toc](tcllib/files/modules/doctools/doctoc\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md) &#183; [doctools::toc::import](tcllib/files/modules/doctools2toc/toc\_import\.md) &#183; [doctools\_intro](tcllib/files/modules/doctools/doctools\_intro\.md) &#183; [doctools\_lang\_cmdref](tcllib/files/modules/doctools/doctools\_lang\_cmdref\.md) &#183; [doctools\_lang\_faq](tcllib/files/modules/doctools/doctools\_lang\_faq\.md) &#183; [doctools\_lang\_intro](tcllib/files/modules/doctools/doctools\_lang\_intro\.md) &#183; [doctools\_lang\_syntax](tcllib/files/modules/doctools/doctools\_lang\_syntax\.md) &#183; [doctools\_plugin\_apiref](tcllib/files/modules/doctools/doctools\_plugin\_apiref\.md) &#183; [dtplite](tcllib/files/modules/dtplite/pkg\_dtplite\.md) &#183; [dtplite](tcllib/files/apps/dtplite\.md) &#183; [mpexpand](tcllib/files/modules/doctools/mpexpand\.md) &#183; [tcldocstrip](tcllib/files/apps/tcldocstrip\.md)|
|<a name='mastercard'></a>MasterCard|[valtype::creditcard::mastercard](tcllib/files/modules/valtype/cc\_mastercard\.md)|
|<a name='matching'></a>matching|[grammar::me\_intro](tcllib/files/modules/grammar\_me/me\_intro\.md) &#183; [grammar::peg::interp](tcllib/files/modules/grammar\_peg/peg\_interp\.md) &#183; [pt](tcllib/files/apps/pt\.md) &#183; [pt::ast](tcllib/files/modules/pt/pt\_astree\.md) &#183; [pt::cparam::configuration::critcl](tcllib/files/modules/pt/pt\_cparam\_config\_critcl\.md) &#183; [pt::cparam::configuration::tea](tcllib/files/modules/pt/pt\_cparam\_config\_tea\.md) &#183; [pt::json\_language](tcllib/files/modules/pt/pt\_json\_language\.md) &#183; [pt::param](tcllib/files/modules/pt/pt\_param\.md) &#183; [pt::pe](tcllib/files/modules/pt/pt\_pexpression\.md) &#183; [pt::pe::op](tcllib/files/modules/pt/pt\_pexpr\_op\.md) &#183; [pt::peg](tcllib/files/modules/pt/pt\_pegrammar\.md) &#183; [pt::peg::container](tcllib/files/modules/pt/pt\_peg\_container\.md) &#183; [pt::peg::container::peg](tcllib/files/modules/pt/pt\_peg\_container\_peg\.md) &#183; [pt::peg::export](tcllib/files/modules/pt/pt\_peg\_export\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::container](tcllib/files/modules/pt/pt\_peg\_from\_container\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import](tcllib/files/modules/pt/pt\_peg\_import\.md) &#183; [pt::peg::import::container](tcllib/files/modules/pt/pt\_peg\_import\_container\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::interp](tcllib/files/modules/pt/pt\_peg\_interp\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [pt::peg\_language](tcllib/files/modules/pt/pt\_peg\_language\.md) &#183; [pt::pegrammar](tcllib/files/modules/pt/pt\_peg\_introduction\.md) &#183; [pt::pgen](tcllib/files/modules/pt/pt\_pgen\.md) &#183; [pt::rde](tcllib/files/modules/pt/pt\_rdengine\.md) &#183; [pt::tclparam::configuration::nx](tcllib/files/modules/pt/pt\_tclparam\_config\_nx\.md) &#183; [pt::tclparam::configuration::snit](tcllib/files/modules/pt/pt\_tclparam\_config\_snit\.md) &#183; [pt::tclparam::configuration::tcloo](tcllib/files/modules/pt/pt\_tclparam\_config\_tcloo\.md) &#183; [pt::util](tcllib/files/modules/pt/pt\_util\.md) &#183; [pt\_export\_api](tcllib/files/modules/pt/pt\_to\_api\.md) &#183; [pt\_import\_api](tcllib/files/modules/pt/pt\_from\_api\.md) &#183; [pt\_introduction](tcllib/files/modules/pt/pt\_introduction\.md) &#183; [pt\_parse\_peg](tcllib/files/modules/pt/pt\_parse\_peg\.md) &#183; [pt\_parser\_api](tcllib/files/modules/pt/pt\_parser\_api\.md) &#183; [pt\_peg\_op](tcllib/files/modules/pt/pt\_peg\_op\.md) &#183; [struct::graph::op](tcllib/files/modules/struct/graphops\.md)|
|<a name='math'></a>math|[math](tcllib/files/modules/math/math\.md) &#183; [math::bigfloat](tcllib/files/modules/math/bigfloat\.md) &#183; [math::bignum](tcllib/files/modules/math/bignum\.md) &#183; [math::calculus](tcllib/files/modules/math/calculus\.md) &#183; [math::complexnumbers](tcllib/files/modules/math/qcomplex\.md) &#183; [math::constants](tcllib/files/modules/math/constants\.md) &#183; [math::decimal](tcllib/files/modules/math/decimal\.md) &#183; [math::fuzzy](tcllib/files/modules/math/fuzzy\.md) &#183; [math::geometry](tcllib/files/modules/math/math\_geometry\.md) &#183; [math::interpolate](tcllib/files/modules/math/interpolate\.md) &#183; [math::linearalgebra](tcllib/files/modules/math/linalg\.md) &#183; [math::optimize](tcllib/files/modules/math/optimize\.md) &#183; [math::PCA](tcllib/files/modules/math/pca\.md) &#183; [math::polynomials](tcllib/files/modules/math/polynomials\.md) &#183; [math::rationalfunctions](tcllib/files/modules/math/rational\_funcs\.md) &#183; [math::special](tcllib/files/modules/math/special\.md) &#183; [math::trig](tcllib/files/modules/math/trig\.md) &#183; [simulation::annealing](tcllib/files/modules/simulation/annealing\.md) &#183; [simulation::montecarlo](tcllib/files/modules/simulation/montecarlo\.md) &#183; [simulation::random](tcllib/files/modules/simulation/simulation\_random\.md)|
|<a name='mathematics'></a>mathematics|[math::fourier](tcllib/files/modules/math/fourier\.md) &#183; [math::quasirandom](tcllib/files/modules/math/quasirandom\.md) &#183; [math::statistics](tcllib/files/modules/math/statistics\.md)|
|<a name='matrices'></a>matrices|[math::linearalgebra](tcllib/files/modules/math/linalg\.md)|
|<a name='matrix'></a>matrix|[csv](tcllib/files/modules/csv/csv\.md) &#183; [math::linearalgebra](tcllib/files/modules/math/linalg\.md) &#183; [report](tcllib/files/modules/report/report\.md) &#183; [struct::matrix](tcllib/files/modules/struct/matrix\.md) &#183; [struct::matrix\_v1](tcllib/files/modules/struct/matrix1\.md) &#183; [struct::queue](tcllib/files/modules/struct/queue\.md) &#183; [struct::stack](tcllib/files/modules/struct/stack\.md)|
|<a name='max\_cut'></a>max cut|[struct::graph::op](tcllib/files/modules/struct/graphops\.md)|
|<a name='maximum'></a>maximum|[math::optimize](tcllib/files/modules/math/optimize\.md)|
|<a name='maximum\_flow'></a>maximum flow|[struct::graph::op](tcllib/files/modules/struct/graphops\.md)|
|<a name='md4'></a>md4|[md4](tcllib/files/modules/md4/md4\.md) &#183; [ripemd128](tcllib/files/modules/ripemd/ripemd128\.md) &#183; [ripemd160](tcllib/files/modules/ripemd/ripemd160\.md)|
|<a name='md5'></a>md5|[md5](tcllib/files/modules/md5/md5\.md) &#183; [md5crypt](tcllib/files/modules/md5crypt/md5crypt\.md)|
610
611
612
613
614
615
616

617
618
619
620
621
622
623
|<a name='oauth'></a>oauth|[oauth](tcllib/files/modules/oauth/oauth\.md)|
|<a name='object'></a>object|[snit](tcllib/files/modules/snit/snit\.md) &#183; [snitfaq](tcllib/files/modules/snit/snitfaq\.md) &#183; [stooop](tcllib/files/modules/stooop/stooop\.md) &#183; [switched](tcllib/files/modules/stooop/switched\.md)|
|<a name='object\_oriented'></a>object oriented|[snit](tcllib/files/modules/snit/snit\.md) &#183; [snitfaq](tcllib/files/modules/snit/snitfaq\.md) &#183; [stooop](tcllib/files/modules/stooop/stooop\.md) &#183; [switched](tcllib/files/modules/stooop/switched\.md)|
|<a name='observer'></a>observer|[hook](tcllib/files/modules/hook/hook\.md) &#183; [tcl::transform::observe](tcllib/files/modules/virtchannel\_transform/observe\.md)|
|<a name='odie'></a>odie|[cron](tcllib/files/modules/cron/cron\.md) &#183; [nettool](tcllib/files/modules/nettool/nettool\.md) &#183; [processman](tcllib/files/modules/processman/processman\.md)|
|<a name='on\_idle'></a>on\-idle|[uevent::onidle](tcllib/files/modules/uev/uevent\_onidle\.md)|
|<a name='one\_time\_pad'></a>one time pad|[tcl::transform::otp](tcllib/files/modules/virtchannel\_transform/vt\_otp\.md)|

|<a name='optimization'></a>optimization|[math::optimize](tcllib/files/modules/math/optimize\.md) &#183; [simulation::annealing](tcllib/files/modules/simulation/annealing\.md)|
|<a name='ordered\_list'></a>ordered list|[struct::prioqueue](tcllib/files/modules/struct/prioqueue\.md)|
|<a name='otp'></a>otp|[tcl::transform::otp](tcllib/files/modules/virtchannel\_transform/vt\_otp\.md)|
|<a name='outer\_join'></a>outer join|[struct::list](tcllib/files/modules/struct/struct\_list\.md)|


#### <a name='cP'></a>Keywords: P







>







614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
|<a name='oauth'></a>oauth|[oauth](tcllib/files/modules/oauth/oauth\.md)|
|<a name='object'></a>object|[snit](tcllib/files/modules/snit/snit\.md) &#183; [snitfaq](tcllib/files/modules/snit/snitfaq\.md) &#183; [stooop](tcllib/files/modules/stooop/stooop\.md) &#183; [switched](tcllib/files/modules/stooop/switched\.md)|
|<a name='object\_oriented'></a>object oriented|[snit](tcllib/files/modules/snit/snit\.md) &#183; [snitfaq](tcllib/files/modules/snit/snitfaq\.md) &#183; [stooop](tcllib/files/modules/stooop/stooop\.md) &#183; [switched](tcllib/files/modules/stooop/switched\.md)|
|<a name='observer'></a>observer|[hook](tcllib/files/modules/hook/hook\.md) &#183; [tcl::transform::observe](tcllib/files/modules/virtchannel\_transform/observe\.md)|
|<a name='odie'></a>odie|[cron](tcllib/files/modules/cron/cron\.md) &#183; [nettool](tcllib/files/modules/nettool/nettool\.md) &#183; [processman](tcllib/files/modules/processman/processman\.md)|
|<a name='on\_idle'></a>on\-idle|[uevent::onidle](tcllib/files/modules/uev/uevent\_onidle\.md)|
|<a name='one\_time\_pad'></a>one time pad|[tcl::transform::otp](tcllib/files/modules/virtchannel\_transform/vt\_otp\.md)|
|<a name='oo'></a>oo|[clay](tcllib/files/modules/clay/clay\.md)|
|<a name='optimization'></a>optimization|[math::optimize](tcllib/files/modules/math/optimize\.md) &#183; [simulation::annealing](tcllib/files/modules/simulation/annealing\.md)|
|<a name='ordered\_list'></a>ordered list|[struct::prioqueue](tcllib/files/modules/struct/prioqueue\.md)|
|<a name='otp'></a>otp|[tcl::transform::otp](tcllib/files/modules/virtchannel\_transform/vt\_otp\.md)|
|<a name='outer\_join'></a>outer join|[struct::list](tcllib/files/modules/struct/struct\_list\.md)|


#### <a name='cP'></a>Keywords: P
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
|<a name='parsing\_expression'></a>parsing expression|[grammar::peg](tcllib/files/modules/grammar\_peg/peg\.md) &#183; [grammar::peg::interp](tcllib/files/modules/grammar\_peg/peg\_interp\.md) &#183; [pt](tcllib/files/apps/pt\.md) &#183; [pt::ast](tcllib/files/modules/pt/pt\_astree\.md) &#183; [pt::cparam::configuration::critcl](tcllib/files/modules/pt/pt\_cparam\_config\_critcl\.md) &#183; [pt::cparam::configuration::tea](tcllib/files/modules/pt/pt\_cparam\_config\_tea\.md) &#183; [pt::json\_language](tcllib/files/modules/pt/pt\_json\_language\.md) &#183; [pt::param](tcllib/files/modules/pt/pt\_param\.md) &#183; [pt::pe](tcllib/files/modules/pt/pt\_pexpression\.md) &#183; [pt::pe::op](tcllib/files/modules/pt/pt\_pexpr\_op\.md) &#183; [pt::peg](tcllib/files/modules/pt/pt\_pegrammar\.md) &#183; [pt::peg::container](tcllib/files/modules/pt/pt\_peg\_container\.md) &#183; [pt::peg::container::peg](tcllib/files/modules/pt/pt\_peg\_container\_peg\.md) &#183; [pt::peg::export](tcllib/files/modules/pt/pt\_peg\_export\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::container](tcllib/files/modules/pt/pt\_peg\_from\_container\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import](tcllib/files/modules/pt/pt\_peg\_import\.md) &#183; [pt::peg::import::container](tcllib/files/modules/pt/pt\_peg\_import\_container\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::interp](tcllib/files/modules/pt/pt\_peg\_interp\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [pt::peg\_language](tcllib/files/modules/pt/pt\_peg\_language\.md) &#183; [pt::pegrammar](tcllib/files/modules/pt/pt\_peg\_introduction\.md) &#183; [pt::pgen](tcllib/files/modules/pt/pt\_pgen\.md) &#183; [pt::rde](tcllib/files/modules/pt/pt\_rdengine\.md) &#183; [pt::tclparam::configuration::nx](tcllib/files/modules/pt/pt\_tclparam\_config\_nx\.md) &#183; [pt::tclparam::configuration::snit](tcllib/files/modules/pt/pt\_tclparam\_config\_snit\.md) &#183; [pt::tclparam::configuration::tcloo](tcllib/files/modules/pt/pt\_tclparam\_config\_tcloo\.md) &#183; [pt::util](tcllib/files/modules/pt/pt\_util\.md) &#183; [pt\_export\_api](tcllib/files/modules/pt/pt\_to\_api\.md) &#183; [pt\_import\_api](tcllib/files/modules/pt/pt\_from\_api\.md) &#183; [pt\_introduction](tcllib/files/modules/pt/pt\_introduction\.md) &#183; [pt\_parse\_peg](tcllib/files/modules/pt/pt\_parse\_peg\.md) &#183; [pt\_parser\_api](tcllib/files/modules/pt/pt\_parser\_api\.md) &#183; [pt\_peg\_op](tcllib/files/modules/pt/pt\_peg\_op\.md)|
|<a name='parsing\_expression\_grammar'></a>parsing expression grammar|[grammar::me\_intro](tcllib/files/modules/grammar\_me/me\_intro\.md) &#183; [grammar::peg](tcllib/files/modules/grammar\_peg/peg\.md) &#183; [grammar::peg::interp](tcllib/files/modules/grammar\_peg/peg\_interp\.md) &#183; [page\_util\_peg](tcllib/files/modules/page/page\_util\_peg\.md) &#183; [pt](tcllib/files/apps/pt\.md) &#183; [pt::ast](tcllib/files/modules/pt/pt\_astree\.md) &#183; [pt::cparam::configuration::critcl](tcllib/files/modules/pt/pt\_cparam\_config\_critcl\.md) &#183; [pt::cparam::configuration::tea](tcllib/files/modules/pt/pt\_cparam\_config\_tea\.md) &#183; [pt::json\_language](tcllib/files/modules/pt/pt\_json\_language\.md) &#183; [pt::param](tcllib/files/modules/pt/pt\_param\.md) &#183; [pt::pe](tcllib/files/modules/pt/pt\_pexpression\.md) &#183; [pt::pe::op](tcllib/files/modules/pt/pt\_pexpr\_op\.md) &#183; [pt::peg](tcllib/files/modules/pt/pt\_pegrammar\.md) &#183; [pt::peg::container](tcllib/files/modules/pt/pt\_peg\_container\.md) &#183; [pt::peg::container::peg](tcllib/files/modules/pt/pt\_peg\_container\_peg\.md) &#183; [pt::peg::export](tcllib/files/modules/pt/pt\_peg\_export\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::container](tcllib/files/modules/pt/pt\_peg\_from\_container\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import](tcllib/files/modules/pt/pt\_peg\_import\.md) &#183; [pt::peg::import::container](tcllib/files/modules/pt/pt\_peg\_import\_container\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::interp](tcllib/files/modules/pt/pt\_peg\_interp\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [pt::peg\_language](tcllib/files/modules/pt/pt\_peg\_language\.md) &#183; [pt::pegrammar](tcllib/files/modules/pt/pt\_peg\_introduction\.md) &#183; [pt::pgen](tcllib/files/modules/pt/pt\_pgen\.md) &#183; [pt::rde](tcllib/files/modules/pt/pt\_rdengine\.md) &#183; [pt::tclparam::configuration::nx](tcllib/files/modules/pt/pt\_tclparam\_config\_nx\.md) &#183; [pt::tclparam::configuration::snit](tcllib/files/modules/pt/pt\_tclparam\_config\_snit\.md) &#183; [pt::tclparam::configuration::tcloo](tcllib/files/modules/pt/pt\_tclparam\_config\_tcloo\.md) &#183; [pt::util](tcllib/files/modules/pt/pt\_util\.md) &#183; [pt\_export\_api](tcllib/files/modules/pt/pt\_to\_api\.md) &#183; [pt\_import\_api](tcllib/files/modules/pt/pt\_from\_api\.md) &#183; [pt\_introduction](tcllib/files/modules/pt/pt\_introduction\.md) &#183; [pt\_parse\_peg](tcllib/files/modules/pt/pt\_parse\_peg\.md) &#183; [pt\_parser\_api](tcllib/files/modules/pt/pt\_parser\_api\.md) &#183; [pt\_peg\_op](tcllib/files/modules/pt/pt\_peg\_op\.md)|
|<a name='partial\_application'></a>partial application|[lambda](tcllib/files/modules/lambda/lambda\.md)|
|<a name='partition'></a>partition|[struct::disjointset](tcllib/files/modules/struct/disjointset\.md)|
|<a name='partitioned\_set'></a>partitioned set|[struct::disjointset](tcllib/files/modules/struct/disjointset\.md)|
|<a name='passive'></a>passive|[transfer::connect](tcllib/files/modules/transfer/connect\.md)|
|<a name='password'></a>password|[otp](tcllib/files/modules/otp/otp\.md)|
|<a name='patch'></a>patch|[docstrip\_util](tcllib/files/modules/docstrip/docstrip\_util\.md)|
|<a name='patching'></a>patching|[rcs](tcllib/files/modules/rcs/rcs\.md)|
|<a name='pca'></a>PCA|[math::PCA](tcllib/files/modules/math/pca\.md)|
|<a name='peg'></a>PEG|[grammar::me\_intro](tcllib/files/modules/grammar\_me/me\_intro\.md) &#183; [page\_util\_norm\_peg](tcllib/files/modules/page/page\_util\_norm\_peg\.md) &#183; [page\_util\_peg](tcllib/files/modules/page/page\_util\_peg\.md) &#183; [pt](tcllib/files/apps/pt\.md) &#183; [pt::ast](tcllib/files/modules/pt/pt\_astree\.md) &#183; [pt::cparam::configuration::critcl](tcllib/files/modules/pt/pt\_cparam\_config\_critcl\.md) &#183; [pt::cparam::configuration::tea](tcllib/files/modules/pt/pt\_cparam\_config\_tea\.md) &#183; [pt::json\_language](tcllib/files/modules/pt/pt\_json\_language\.md) &#183; [pt::param](tcllib/files/modules/pt/pt\_param\.md) &#183; [pt::pe](tcllib/files/modules/pt/pt\_pexpression\.md) &#183; [pt::pe::op](tcllib/files/modules/pt/pt\_pexpr\_op\.md) &#183; [pt::peg](tcllib/files/modules/pt/pt\_pegrammar\.md) &#183; [pt::peg::container](tcllib/files/modules/pt/pt\_peg\_container\.md) &#183; [pt::peg::container::peg](tcllib/files/modules/pt/pt\_peg\_container\_peg\.md) &#183; [pt::peg::export](tcllib/files/modules/pt/pt\_peg\_export\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::container](tcllib/files/modules/pt/pt\_peg\_from\_container\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import](tcllib/files/modules/pt/pt\_peg\_import\.md) &#183; [pt::peg::import::container](tcllib/files/modules/pt/pt\_peg\_import\_container\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::interp](tcllib/files/modules/pt/pt\_peg\_interp\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [pt::peg\_language](tcllib/files/modules/pt/pt\_peg\_language\.md) &#183; [pt::pegrammar](tcllib/files/modules/pt/pt\_peg\_introduction\.md) &#183; [pt::pgen](tcllib/files/modules/pt/pt\_pgen\.md) &#183; [pt::rde](tcllib/files/modules/pt/pt\_rdengine\.md) &#183; [pt::tclparam::configuration::nx](tcllib/files/modules/pt/pt\_tclparam\_config\_nx\.md) &#183; [pt::tclparam::configuration::snit](tcllib/files/modules/pt/pt\_tclparam\_config\_snit\.md) &#183; [pt::tclparam::configuration::tcloo](tcllib/files/modules/pt/pt\_tclparam\_config\_tcloo\.md) &#183; [pt::util](tcllib/files/modules/pt/pt\_util\.md) &#183; [pt\_export\_api](tcllib/files/modules/pt/pt\_to\_api\.md) &#183; [pt\_import\_api](tcllib/files/modules/pt/pt\_from\_api\.md) &#183; [pt\_introduction](tcllib/files/modules/pt/pt\_introduction\.md) &#183; [pt\_parse\_peg](tcllib/files/modules/pt/pt\_parse\_peg\.md) &#183; [pt\_parser\_api](tcllib/files/modules/pt/pt\_parser\_api\.md) &#183; [pt\_peg\_op](tcllib/files/modules/pt/pt\_peg\_op\.md)|
|<a name='performance'></a>performance|[bench](tcllib/files/modules/bench/bench\.md) &#183; [bench::in](tcllib/files/modules/bench/bench\_read\.md) &#183; [bench::out::csv](tcllib/files/modules/bench/bench\_wcsv\.md) &#183; [bench::out::text](tcllib/files/modules/bench/bench\_wtext\.md) &#183; [bench\_intro](tcllib/files/modules/bench/bench\_intro\.md) &#183; [bench\_lang\_intro](tcllib/files/modules/bench/bench\_lang\_intro\.md) &#183; [bench\_lang\_spec](tcllib/files/modules/bench/bench\_lang\_spec\.md) &#183; [profiler](tcllib/files/modules/profiler/profiler\.md)|
|<a name='permutation'></a>permutation|[struct::list](tcllib/files/modules/struct/struct\_list\.md)|
|<a name='persistence'></a>persistence|[tie](tcllib/files/modules/tie/tie\_std\.md) &#183; [tie](tcllib/files/modules/tie/tie\.md)|
|<a name='phone'></a>phone|[valtype::imei](tcllib/files/modules/valtype/imei\.md)|







|







642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
|<a name='parsing\_expression'></a>parsing expression|[grammar::peg](tcllib/files/modules/grammar\_peg/peg\.md) &#183; [grammar::peg::interp](tcllib/files/modules/grammar\_peg/peg\_interp\.md) &#183; [pt](tcllib/files/apps/pt\.md) &#183; [pt::ast](tcllib/files/modules/pt/pt\_astree\.md) &#183; [pt::cparam::configuration::critcl](tcllib/files/modules/pt/pt\_cparam\_config\_critcl\.md) &#183; [pt::cparam::configuration::tea](tcllib/files/modules/pt/pt\_cparam\_config\_tea\.md) &#183; [pt::json\_language](tcllib/files/modules/pt/pt\_json\_language\.md) &#183; [pt::param](tcllib/files/modules/pt/pt\_param\.md) &#183; [pt::pe](tcllib/files/modules/pt/pt\_pexpression\.md) &#183; [pt::pe::op](tcllib/files/modules/pt/pt\_pexpr\_op\.md) &#183; [pt::peg](tcllib/files/modules/pt/pt\_pegrammar\.md) &#183; [pt::peg::container](tcllib/files/modules/pt/pt\_peg\_container\.md) &#183; [pt::peg::container::peg](tcllib/files/modules/pt/pt\_peg\_container\_peg\.md) &#183; [pt::peg::export](tcllib/files/modules/pt/pt\_peg\_export\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::container](tcllib/files/modules/pt/pt\_peg\_from\_container\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import](tcllib/files/modules/pt/pt\_peg\_import\.md) &#183; [pt::peg::import::container](tcllib/files/modules/pt/pt\_peg\_import\_container\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::interp](tcllib/files/modules/pt/pt\_peg\_interp\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [pt::peg\_language](tcllib/files/modules/pt/pt\_peg\_language\.md) &#183; [pt::pegrammar](tcllib/files/modules/pt/pt\_peg\_introduction\.md) &#183; [pt::pgen](tcllib/files/modules/pt/pt\_pgen\.md) &#183; [pt::rde](tcllib/files/modules/pt/pt\_rdengine\.md) &#183; [pt::tclparam::configuration::nx](tcllib/files/modules/pt/pt\_tclparam\_config\_nx\.md) &#183; [pt::tclparam::configuration::snit](tcllib/files/modules/pt/pt\_tclparam\_config\_snit\.md) &#183; [pt::tclparam::configuration::tcloo](tcllib/files/modules/pt/pt\_tclparam\_config\_tcloo\.md) &#183; [pt::util](tcllib/files/modules/pt/pt\_util\.md) &#183; [pt\_export\_api](tcllib/files/modules/pt/pt\_to\_api\.md) &#183; [pt\_import\_api](tcllib/files/modules/pt/pt\_from\_api\.md) &#183; [pt\_introduction](tcllib/files/modules/pt/pt\_introduction\.md) &#183; [pt\_parse\_peg](tcllib/files/modules/pt/pt\_parse\_peg\.md) &#183; [pt\_parser\_api](tcllib/files/modules/pt/pt\_parser\_api\.md) &#183; [pt\_peg\_op](tcllib/files/modules/pt/pt\_peg\_op\.md)|
|<a name='parsing\_expression\_grammar'></a>parsing expression grammar|[grammar::me\_intro](tcllib/files/modules/grammar\_me/me\_intro\.md) &#183; [grammar::peg](tcllib/files/modules/grammar\_peg/peg\.md) &#183; [grammar::peg::interp](tcllib/files/modules/grammar\_peg/peg\_interp\.md) &#183; [page\_util\_peg](tcllib/files/modules/page/page\_util\_peg\.md) &#183; [pt](tcllib/files/apps/pt\.md) &#183; [pt::ast](tcllib/files/modules/pt/pt\_astree\.md) &#183; [pt::cparam::configuration::critcl](tcllib/files/modules/pt/pt\_cparam\_config\_critcl\.md) &#183; [pt::cparam::configuration::tea](tcllib/files/modules/pt/pt\_cparam\_config\_tea\.md) &#183; [pt::json\_language](tcllib/files/modules/pt/pt\_json\_language\.md) &#183; [pt::param](tcllib/files/modules/pt/pt\_param\.md) &#183; [pt::pe](tcllib/files/modules/pt/pt\_pexpression\.md) &#183; [pt::pe::op](tcllib/files/modules/pt/pt\_pexpr\_op\.md) &#183; [pt::peg](tcllib/files/modules/pt/pt\_pegrammar\.md) &#183; [pt::peg::container](tcllib/files/modules/pt/pt\_peg\_container\.md) &#183; [pt::peg::container::peg](tcllib/files/modules/pt/pt\_peg\_container\_peg\.md) &#183; [pt::peg::export](tcllib/files/modules/pt/pt\_peg\_export\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::container](tcllib/files/modules/pt/pt\_peg\_from\_container\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import](tcllib/files/modules/pt/pt\_peg\_import\.md) &#183; [pt::peg::import::container](tcllib/files/modules/pt/pt\_peg\_import\_container\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::interp](tcllib/files/modules/pt/pt\_peg\_interp\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [pt::peg\_language](tcllib/files/modules/pt/pt\_peg\_language\.md) &#183; [pt::pegrammar](tcllib/files/modules/pt/pt\_peg\_introduction\.md) &#183; [pt::pgen](tcllib/files/modules/pt/pt\_pgen\.md) &#183; [pt::rde](tcllib/files/modules/pt/pt\_rdengine\.md) &#183; [pt::tclparam::configuration::nx](tcllib/files/modules/pt/pt\_tclparam\_config\_nx\.md) &#183; [pt::tclparam::configuration::snit](tcllib/files/modules/pt/pt\_tclparam\_config\_snit\.md) &#183; [pt::tclparam::configuration::tcloo](tcllib/files/modules/pt/pt\_tclparam\_config\_tcloo\.md) &#183; [pt::util](tcllib/files/modules/pt/pt\_util\.md) &#183; [pt\_export\_api](tcllib/files/modules/pt/pt\_to\_api\.md) &#183; [pt\_import\_api](tcllib/files/modules/pt/pt\_from\_api\.md) &#183; [pt\_introduction](tcllib/files/modules/pt/pt\_introduction\.md) &#183; [pt\_parse\_peg](tcllib/files/modules/pt/pt\_parse\_peg\.md) &#183; [pt\_parser\_api](tcllib/files/modules/pt/pt\_parser\_api\.md) &#183; [pt\_peg\_op](tcllib/files/modules/pt/pt\_peg\_op\.md)|
|<a name='partial\_application'></a>partial application|[lambda](tcllib/files/modules/lambda/lambda\.md)|
|<a name='partition'></a>partition|[struct::disjointset](tcllib/files/modules/struct/disjointset\.md)|
|<a name='partitioned\_set'></a>partitioned set|[struct::disjointset](tcllib/files/modules/struct/disjointset\.md)|
|<a name='passive'></a>passive|[transfer::connect](tcllib/files/modules/transfer/connect\.md)|
|<a name='password'></a>password|[otp](tcllib/files/modules/otp/otp\.md)|
|<a name='patch'></a>patch|[docstrip\_util](tcllib/files/modules/docstrip/docstrip\_util\.md) &#183; [textutil::patch](tcllib/files/modules/textutil/patch\.md)|
|<a name='patching'></a>patching|[rcs](tcllib/files/modules/rcs/rcs\.md)|
|<a name='pca'></a>PCA|[math::PCA](tcllib/files/modules/math/pca\.md)|
|<a name='peg'></a>PEG|[grammar::me\_intro](tcllib/files/modules/grammar\_me/me\_intro\.md) &#183; [page\_util\_norm\_peg](tcllib/files/modules/page/page\_util\_norm\_peg\.md) &#183; [page\_util\_peg](tcllib/files/modules/page/page\_util\_peg\.md) &#183; [pt](tcllib/files/apps/pt\.md) &#183; [pt::ast](tcllib/files/modules/pt/pt\_astree\.md) &#183; [pt::cparam::configuration::critcl](tcllib/files/modules/pt/pt\_cparam\_config\_critcl\.md) &#183; [pt::cparam::configuration::tea](tcllib/files/modules/pt/pt\_cparam\_config\_tea\.md) &#183; [pt::json\_language](tcllib/files/modules/pt/pt\_json\_language\.md) &#183; [pt::param](tcllib/files/modules/pt/pt\_param\.md) &#183; [pt::pe](tcllib/files/modules/pt/pt\_pexpression\.md) &#183; [pt::pe::op](tcllib/files/modules/pt/pt\_pexpr\_op\.md) &#183; [pt::peg](tcllib/files/modules/pt/pt\_pegrammar\.md) &#183; [pt::peg::container](tcllib/files/modules/pt/pt\_peg\_container\.md) &#183; [pt::peg::container::peg](tcllib/files/modules/pt/pt\_peg\_container\_peg\.md) &#183; [pt::peg::export](tcllib/files/modules/pt/pt\_peg\_export\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::container](tcllib/files/modules/pt/pt\_peg\_from\_container\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import](tcllib/files/modules/pt/pt\_peg\_import\.md) &#183; [pt::peg::import::container](tcllib/files/modules/pt/pt\_peg\_import\_container\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::interp](tcllib/files/modules/pt/pt\_peg\_interp\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [pt::peg\_language](tcllib/files/modules/pt/pt\_peg\_language\.md) &#183; [pt::pegrammar](tcllib/files/modules/pt/pt\_peg\_introduction\.md) &#183; [pt::pgen](tcllib/files/modules/pt/pt\_pgen\.md) &#183; [pt::rde](tcllib/files/modules/pt/pt\_rdengine\.md) &#183; [pt::tclparam::configuration::nx](tcllib/files/modules/pt/pt\_tclparam\_config\_nx\.md) &#183; [pt::tclparam::configuration::snit](tcllib/files/modules/pt/pt\_tclparam\_config\_snit\.md) &#183; [pt::tclparam::configuration::tcloo](tcllib/files/modules/pt/pt\_tclparam\_config\_tcloo\.md) &#183; [pt::util](tcllib/files/modules/pt/pt\_util\.md) &#183; [pt\_export\_api](tcllib/files/modules/pt/pt\_to\_api\.md) &#183; [pt\_import\_api](tcllib/files/modules/pt/pt\_from\_api\.md) &#183; [pt\_introduction](tcllib/files/modules/pt/pt\_introduction\.md) &#183; [pt\_parse\_peg](tcllib/files/modules/pt/pt\_parse\_peg\.md) &#183; [pt\_parser\_api](tcllib/files/modules/pt/pt\_parser\_api\.md) &#183; [pt\_peg\_op](tcllib/files/modules/pt/pt\_peg\_op\.md)|
|<a name='performance'></a>performance|[bench](tcllib/files/modules/bench/bench\.md) &#183; [bench::in](tcllib/files/modules/bench/bench\_read\.md) &#183; [bench::out::csv](tcllib/files/modules/bench/bench\_wcsv\.md) &#183; [bench::out::text](tcllib/files/modules/bench/bench\_wtext\.md) &#183; [bench\_intro](tcllib/files/modules/bench/bench\_intro\.md) &#183; [bench\_lang\_intro](tcllib/files/modules/bench/bench\_lang\_intro\.md) &#183; [bench\_lang\_spec](tcllib/files/modules/bench/bench\_lang\_spec\.md) &#183; [profiler](tcllib/files/modules/profiler/profiler\.md)|
|<a name='permutation'></a>permutation|[struct::list](tcllib/files/modules/struct/struct\_list\.md)|
|<a name='persistence'></a>persistence|[tie](tcllib/files/modules/tie/tie\_std\.md) &#183; [tie](tcllib/files/modules/tie/tie\.md)|
|<a name='phone'></a>phone|[valtype::imei](tcllib/files/modules/valtype/imei\.md)|
683
684
685
686
687
688
689

690
691
692
693
694
695
696
|<a name='push\_down\_automaton'></a>push down automaton|[grammar::me\_intro](tcllib/files/modules/grammar\_me/me\_intro\.md) &#183; [grammar::peg](tcllib/files/modules/grammar\_peg/peg\.md) &#183; [grammar::peg::interp](tcllib/files/modules/grammar\_peg/peg\_interp\.md) &#183; [pt](tcllib/files/apps/pt\.md) &#183; [pt::ast](tcllib/files/modules/pt/pt\_astree\.md) &#183; [pt::cparam::configuration::critcl](tcllib/files/modules/pt/pt\_cparam\_config\_critcl\.md) &#183; [pt::cparam::configuration::tea](tcllib/files/modules/pt/pt\_cparam\_config\_tea\.md) &#183; [pt::json\_language](tcllib/files/modules/pt/pt\_json\_language\.md) &#183; [pt::param](tcllib/files/modules/pt/pt\_param\.md) &#183; [pt::pe](tcllib/files/modules/pt/pt\_pexpression\.md) &#183; [pt::pe::op](tcllib/files/modules/pt/pt\_pexpr\_op\.md) &#183; [pt::peg](tcllib/files/modules/pt/pt\_pegrammar\.md) &#183; [pt::peg::container](tcllib/files/modules/pt/pt\_peg\_container\.md) &#183; [pt::peg::container::peg](tcllib/files/modules/pt/pt\_peg\_container\_peg\.md) &#183; [pt::peg::export](tcllib/files/modules/pt/pt\_peg\_export\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::container](tcllib/files/modules/pt/pt\_peg\_from\_container\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import](tcllib/files/modules/pt/pt\_peg\_import\.md) &#183; [pt::peg::import::container](tcllib/files/modules/pt/pt\_peg\_import\_container\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::interp](tcllib/files/modules/pt/pt\_peg\_interp\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [pt::peg\_language](tcllib/files/modules/pt/pt\_peg\_language\.md) &#183; [pt::pegrammar](tcllib/files/modules/pt/pt\_peg\_introduction\.md) &#183; [pt::pgen](tcllib/files/modules/pt/pt\_pgen\.md) &#183; [pt::rde](tcllib/files/modules/pt/pt\_rdengine\.md) &#183; [pt::tclparam::configuration::nx](tcllib/files/modules/pt/pt\_tclparam\_config\_nx\.md) &#183; [pt::tclparam::configuration::snit](tcllib/files/modules/pt/pt\_tclparam\_config\_snit\.md) &#183; [pt::tclparam::configuration::tcloo](tcllib/files/modules/pt/pt\_tclparam\_config\_tcloo\.md) &#183; [pt::util](tcllib/files/modules/pt/pt\_util\.md) &#183; [pt\_export\_api](tcllib/files/modules/pt/pt\_to\_api\.md) &#183; [pt\_import\_api](tcllib/files/modules/pt/pt\_from\_api\.md) &#183; [pt\_introduction](tcllib/files/modules/pt/pt\_introduction\.md) &#183; [pt\_parse\_peg](tcllib/files/modules/pt/pt\_parse\_peg\.md) &#183; [pt\_parser\_api](tcllib/files/modules/pt/pt\_parser\_api\.md) &#183; [pt\_peg\_op](tcllib/files/modules/pt/pt\_peg\_op\.md)|


#### <a name='cQ'></a>Keywords: Q

|||
|---|---|

|<a name='queue'></a>queue|[csv](tcllib/files/modules/csv/csv\.md) &#183; [htmlparse](tcllib/files/modules/htmlparse/htmlparse\.md) &#183; [struct::stack](tcllib/files/modules/struct/stack\.md) &#183; [transfer::copy::queue](tcllib/files/modules/transfer/tqueue\.md)|
|<a name='quoting'></a>quoting|[page\_util\_quote](tcllib/files/modules/page/page\_util\_quote\.md)|


#### <a name='cR'></a>Keywords: R

|||







>







688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
|<a name='push\_down\_automaton'></a>push down automaton|[grammar::me\_intro](tcllib/files/modules/grammar\_me/me\_intro\.md) &#183; [grammar::peg](tcllib/files/modules/grammar\_peg/peg\.md) &#183; [grammar::peg::interp](tcllib/files/modules/grammar\_peg/peg\_interp\.md) &#183; [pt](tcllib/files/apps/pt\.md) &#183; [pt::ast](tcllib/files/modules/pt/pt\_astree\.md) &#183; [pt::cparam::configuration::critcl](tcllib/files/modules/pt/pt\_cparam\_config\_critcl\.md) &#183; [pt::cparam::configuration::tea](tcllib/files/modules/pt/pt\_cparam\_config\_tea\.md) &#183; [pt::json\_language](tcllib/files/modules/pt/pt\_json\_language\.md) &#183; [pt::param](tcllib/files/modules/pt/pt\_param\.md) &#183; [pt::pe](tcllib/files/modules/pt/pt\_pexpression\.md) &#183; [pt::pe::op](tcllib/files/modules/pt/pt\_pexpr\_op\.md) &#183; [pt::peg](tcllib/files/modules/pt/pt\_pegrammar\.md) &#183; [pt::peg::container](tcllib/files/modules/pt/pt\_peg\_container\.md) &#183; [pt::peg::container::peg](tcllib/files/modules/pt/pt\_peg\_container\_peg\.md) &#183; [pt::peg::export](tcllib/files/modules/pt/pt\_peg\_export\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::container](tcllib/files/modules/pt/pt\_peg\_from\_container\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import](tcllib/files/modules/pt/pt\_peg\_import\.md) &#183; [pt::peg::import::container](tcllib/files/modules/pt/pt\_peg\_import\_container\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::interp](tcllib/files/modules/pt/pt\_peg\_interp\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [pt::peg\_language](tcllib/files/modules/pt/pt\_peg\_language\.md) &#183; [pt::pegrammar](tcllib/files/modules/pt/pt\_peg\_introduction\.md) &#183; [pt::pgen](tcllib/files/modules/pt/pt\_pgen\.md) &#183; [pt::rde](tcllib/files/modules/pt/pt\_rdengine\.md) &#183; [pt::tclparam::configuration::nx](tcllib/files/modules/pt/pt\_tclparam\_config\_nx\.md) &#183; [pt::tclparam::configuration::snit](tcllib/files/modules/pt/pt\_tclparam\_config\_snit\.md) &#183; [pt::tclparam::configuration::tcloo](tcllib/files/modules/pt/pt\_tclparam\_config\_tcloo\.md) &#183; [pt::util](tcllib/files/modules/pt/pt\_util\.md) &#183; [pt\_export\_api](tcllib/files/modules/pt/pt\_to\_api\.md) &#183; [pt\_import\_api](tcllib/files/modules/pt/pt\_from\_api\.md) &#183; [pt\_introduction](tcllib/files/modules/pt/pt\_introduction\.md) &#183; [pt\_parse\_peg](tcllib/files/modules/pt/pt\_parse\_peg\.md) &#183; [pt\_parser\_api](tcllib/files/modules/pt/pt\_parser\_api\.md) &#183; [pt\_peg\_op](tcllib/files/modules/pt/pt\_peg\_op\.md)|


#### <a name='cQ'></a>Keywords: Q

|||
|---|---|
|<a name='quasi\_random'></a>quasi\-random|[math::quasirandom](tcllib/files/modules/math/quasirandom\.md)|
|<a name='queue'></a>queue|[csv](tcllib/files/modules/csv/csv\.md) &#183; [htmlparse](tcllib/files/modules/htmlparse/htmlparse\.md) &#183; [struct::stack](tcllib/files/modules/struct/stack\.md) &#183; [transfer::copy::queue](tcllib/files/modules/transfer/tqueue\.md)|
|<a name='quoting'></a>quoting|[page\_util\_quote](tcllib/files/modules/page/page\_util\_quote\.md)|


#### <a name='cR'></a>Keywords: R

|||
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
|<a name='seed'></a>seed|[tcl::randomseed](tcllib/files/modules/virtchannel\_base/randseed\.md)|
|<a name='selectionbox'></a>selectionbox|[javascript](tcllib/files/modules/javascript/javascript\.md)|
|<a name='semantic\_markup'></a>semantic markup|[docidx\_intro](tcllib/files/modules/doctools/docidx\_intro\.md) &#183; [docidx\_lang\_cmdref](tcllib/files/modules/doctools/docidx\_lang\_cmdref\.md) &#183; [docidx\_lang\_faq](tcllib/files/modules/doctools/docidx\_lang\_faq\.md) &#183; [docidx\_lang\_intro](tcllib/files/modules/doctools/docidx\_lang\_intro\.md) &#183; [docidx\_lang\_syntax](tcllib/files/modules/doctools/docidx\_lang\_syntax\.md) &#183; [docidx\_plugin\_apiref](tcllib/files/modules/doctools/docidx\_plugin\_apiref\.md) &#183; [doctoc\_intro](tcllib/files/modules/doctools/doctoc\_intro\.md) &#183; [doctoc\_lang\_cmdref](tcllib/files/modules/doctools/doctoc\_lang\_cmdref\.md) &#183; [doctoc\_lang\_faq](tcllib/files/modules/doctools/doctoc\_lang\_faq\.md) &#183; [doctoc\_lang\_intro](tcllib/files/modules/doctools/doctoc\_lang\_intro\.md) &#183; [doctoc\_lang\_syntax](tcllib/files/modules/doctools/doctoc\_lang\_syntax\.md) &#183; [doctoc\_plugin\_apiref](tcllib/files/modules/doctools/doctoc\_plugin\_apiref\.md) &#183; [doctools2idx\_introduction](tcllib/files/modules/doctools2idx/idx\_introduction\.md) &#183; [doctools2toc\_introduction](tcllib/files/modules/doctools2toc/toc\_introduction\.md) &#183; [doctools\_intro](tcllib/files/modules/doctools/doctools\_intro\.md) &#183; [doctools\_lang\_cmdref](tcllib/files/modules/doctools/doctools\_lang\_cmdref\.md) &#183; [doctools\_lang\_faq](tcllib/files/modules/doctools/doctools\_lang\_faq\.md) &#183; [doctools\_lang\_intro](tcllib/files/modules/doctools/doctools\_lang\_intro\.md) &#183; [doctools\_lang\_syntax](tcllib/files/modules/doctools/doctools\_lang\_syntax\.md) &#183; [doctools\_plugin\_apiref](tcllib/files/modules/doctools/doctools\_plugin\_apiref\.md)|
|<a name='send'></a>send|[comm](tcllib/files/modules/comm/comm\.md)|
|<a name='serialization'></a>serialization|[bee](tcllib/files/modules/bee/bee\.md) &#183; [doctools::idx::export::docidx](tcllib/files/modules/doctools2idx/export\_docidx\.md) &#183; [doctools::idx::export::html](tcllib/files/modules/doctools2idx/idx\_export\_html\.md) &#183; [doctools::idx::export::json](tcllib/files/modules/doctools2idx/idx\_export\_json\.md) &#183; [doctools::idx::export::nroff](tcllib/files/modules/doctools2idx/idx\_export\_nroff\.md) &#183; [doctools::idx::export::text](tcllib/files/modules/doctools2idx/idx\_export\_text\.md) &#183; [doctools::idx::export::wiki](tcllib/files/modules/doctools2idx/idx\_export\_wiki\.md) &#183; [doctools::idx::structure](tcllib/files/modules/doctools2idx/idx\_structure\.md) &#183; [doctools::toc::export::doctoc](tcllib/files/modules/doctools2toc/export\_doctoc\.md) &#183; [doctools::toc::export::html](tcllib/files/modules/doctools2toc/toc\_export\_html\.md) &#183; [doctools::toc::export::json](tcllib/files/modules/doctools2toc/toc\_export\_json\.md) &#183; [doctools::toc::export::nroff](tcllib/files/modules/doctools2toc/toc\_export\_nroff\.md) &#183; [doctools::toc::export::text](tcllib/files/modules/doctools2toc/toc\_export\_text\.md) &#183; [doctools::toc::export::wiki](tcllib/files/modules/doctools2toc/toc\_export\_wiki\.md) &#183; [doctools::toc::structure](tcllib/files/modules/doctools2toc/toc\_structure\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [struct::graph](tcllib/files/modules/struct/graph\.md) &#183; [struct::tree](tcllib/files/modules/struct/struct\_tree\.md)|
|<a name='server'></a>server|[map::geocode::nominatim](tcllib/files/modules/map/map\_geocode\_nominatim\.md) &#183; [map::slippy::fetcher](tcllib/files/modules/map/map\_slippy\_fetcher\.md) &#183; [nameserv::common](tcllib/files/modules/nns/nns\_common\.md) &#183; [nameserv::server](tcllib/files/modules/nns/nns\_server\.md) &#183; [nns\_intro](tcllib/files/modules/nns/nns\_intro\.md) &#183; [nnsd](tcllib/files/apps/nnsd\.md) &#183; [udpcluster](tcllib/files/modules/udpcluster/udpcluster\.md)|
|<a name='service'></a>service|[logger](tcllib/files/modules/log/logger\.md)|
|<a name='services'></a>services|[ftpd](tcllib/files/modules/ftpd/ftpd\.md) &#183; [smtpd](tcllib/files/modules/smtpd/smtpd\.md) &#183; [tool](tcllib/files/modules/httpd/httpd\.md)|
|<a name='set'></a>set|[struct::queue](tcllib/files/modules/struct/queue\.md) &#183; [struct::set](tcllib/files/modules/struct/struct\_set\.md)|
|<a name='sha1'></a>sha1|[sha1](tcllib/files/modules/sha1/sha1\.md)|
|<a name='sha256'></a>sha256|[sha256](tcllib/files/modules/sha1/sha256\.md)|
|<a name='shell'></a>shell|[string::token::shell](tcllib/files/modules/string/token\_shell\.md)|
|<a name='shortest\_path'></a>shortest path|[struct::graph::op](tcllib/files/modules/struct/graphops\.md)|
|<a name='shuffle'></a>shuffle|[struct::list](tcllib/files/modules/struct/struct\_list\.md)|
|<a name='simulated\_annealing'></a>simulated annealing|[simulation::annealing](tcllib/files/modules/simulation/annealing\.md)|







|







801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
|<a name='seed'></a>seed|[tcl::randomseed](tcllib/files/modules/virtchannel\_base/randseed\.md)|
|<a name='selectionbox'></a>selectionbox|[javascript](tcllib/files/modules/javascript/javascript\.md)|
|<a name='semantic\_markup'></a>semantic markup|[docidx\_intro](tcllib/files/modules/doctools/docidx\_intro\.md) &#183; [docidx\_lang\_cmdref](tcllib/files/modules/doctools/docidx\_lang\_cmdref\.md) &#183; [docidx\_lang\_faq](tcllib/files/modules/doctools/docidx\_lang\_faq\.md) &#183; [docidx\_lang\_intro](tcllib/files/modules/doctools/docidx\_lang\_intro\.md) &#183; [docidx\_lang\_syntax](tcllib/files/modules/doctools/docidx\_lang\_syntax\.md) &#183; [docidx\_plugin\_apiref](tcllib/files/modules/doctools/docidx\_plugin\_apiref\.md) &#183; [doctoc\_intro](tcllib/files/modules/doctools/doctoc\_intro\.md) &#183; [doctoc\_lang\_cmdref](tcllib/files/modules/doctools/doctoc\_lang\_cmdref\.md) &#183; [doctoc\_lang\_faq](tcllib/files/modules/doctools/doctoc\_lang\_faq\.md) &#183; [doctoc\_lang\_intro](tcllib/files/modules/doctools/doctoc\_lang\_intro\.md) &#183; [doctoc\_lang\_syntax](tcllib/files/modules/doctools/doctoc\_lang\_syntax\.md) &#183; [doctoc\_plugin\_apiref](tcllib/files/modules/doctools/doctoc\_plugin\_apiref\.md) &#183; [doctools2idx\_introduction](tcllib/files/modules/doctools2idx/idx\_introduction\.md) &#183; [doctools2toc\_introduction](tcllib/files/modules/doctools2toc/toc\_introduction\.md) &#183; [doctools\_intro](tcllib/files/modules/doctools/doctools\_intro\.md) &#183; [doctools\_lang\_cmdref](tcllib/files/modules/doctools/doctools\_lang\_cmdref\.md) &#183; [doctools\_lang\_faq](tcllib/files/modules/doctools/doctools\_lang\_faq\.md) &#183; [doctools\_lang\_intro](tcllib/files/modules/doctools/doctools\_lang\_intro\.md) &#183; [doctools\_lang\_syntax](tcllib/files/modules/doctools/doctools\_lang\_syntax\.md) &#183; [doctools\_plugin\_apiref](tcllib/files/modules/doctools/doctools\_plugin\_apiref\.md)|
|<a name='send'></a>send|[comm](tcllib/files/modules/comm/comm\.md)|
|<a name='serialization'></a>serialization|[bee](tcllib/files/modules/bee/bee\.md) &#183; [doctools::idx::export::docidx](tcllib/files/modules/doctools2idx/export\_docidx\.md) &#183; [doctools::idx::export::html](tcllib/files/modules/doctools2idx/idx\_export\_html\.md) &#183; [doctools::idx::export::json](tcllib/files/modules/doctools2idx/idx\_export\_json\.md) &#183; [doctools::idx::export::nroff](tcllib/files/modules/doctools2idx/idx\_export\_nroff\.md) &#183; [doctools::idx::export::text](tcllib/files/modules/doctools2idx/idx\_export\_text\.md) &#183; [doctools::idx::export::wiki](tcllib/files/modules/doctools2idx/idx\_export\_wiki\.md) &#183; [doctools::idx::structure](tcllib/files/modules/doctools2idx/idx\_structure\.md) &#183; [doctools::toc::export::doctoc](tcllib/files/modules/doctools2toc/export\_doctoc\.md) &#183; [doctools::toc::export::html](tcllib/files/modules/doctools2toc/toc\_export\_html\.md) &#183; [doctools::toc::export::json](tcllib/files/modules/doctools2toc/toc\_export\_json\.md) &#183; [doctools::toc::export::nroff](tcllib/files/modules/doctools2toc/toc\_export\_nroff\.md) &#183; [doctools::toc::export::text](tcllib/files/modules/doctools2toc/toc\_export\_text\.md) &#183; [doctools::toc::export::wiki](tcllib/files/modules/doctools2toc/toc\_export\_wiki\.md) &#183; [doctools::toc::structure](tcllib/files/modules/doctools2toc/toc\_structure\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [struct::graph](tcllib/files/modules/struct/graph\.md) &#183; [struct::tree](tcllib/files/modules/struct/struct\_tree\.md)|
|<a name='server'></a>server|[map::geocode::nominatim](tcllib/files/modules/map/map\_geocode\_nominatim\.md) &#183; [map::slippy::fetcher](tcllib/files/modules/map/map\_slippy\_fetcher\.md) &#183; [nameserv::common](tcllib/files/modules/nns/nns\_common\.md) &#183; [nameserv::server](tcllib/files/modules/nns/nns\_server\.md) &#183; [nns\_intro](tcllib/files/modules/nns/nns\_intro\.md) &#183; [nnsd](tcllib/files/apps/nnsd\.md) &#183; [udpcluster](tcllib/files/modules/udpcluster/udpcluster\.md)|
|<a name='service'></a>service|[logger](tcllib/files/modules/log/logger\.md)|
|<a name='services'></a>services|[ftpd](tcllib/files/modules/ftpd/ftpd\.md) &#183; [httpd](tcllib/files/modules/httpd/httpd\.md) &#183; [smtpd](tcllib/files/modules/smtpd/smtpd\.md)|
|<a name='set'></a>set|[struct::queue](tcllib/files/modules/struct/queue\.md) &#183; [struct::set](tcllib/files/modules/struct/struct\_set\.md)|
|<a name='sha1'></a>sha1|[sha1](tcllib/files/modules/sha1/sha1\.md)|
|<a name='sha256'></a>sha256|[sha256](tcllib/files/modules/sha1/sha256\.md)|
|<a name='shell'></a>shell|[string::token::shell](tcllib/files/modules/string/token\_shell\.md)|
|<a name='shortest\_path'></a>shortest path|[struct::graph::op](tcllib/files/modules/struct/graphops\.md)|
|<a name='shuffle'></a>shuffle|[struct::list](tcllib/files/modules/struct/struct\_list\.md)|
|<a name='simulated\_annealing'></a>simulated annealing|[simulation::annealing](tcllib/files/modules/simulation/annealing\.md)|
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
|<a name='tape\_archive'></a>tape archive|[tar](tcllib/files/modules/tar/tar\.md)|
|<a name='tar'></a>tar|[tar](tcllib/files/modules/tar/tar\.md)|
|<a name='tcl'></a>tcl|[math::bigfloat](tcllib/files/modules/math/bigfloat\.md) &#183; [math::bignum](tcllib/files/modules/math/bignum\.md) &#183; [math::decimal](tcllib/files/modules/math/decimal\.md) &#183; [math::PCA](tcllib/files/modules/math/pca\.md)|
|<a name='tcl\_module'></a>Tcl module|[docstrip\_util](tcllib/files/modules/docstrip/docstrip\_util\.md)|
|<a name='tcl\_syntax'></a>Tcl syntax|[doctools::tcl::parse](tcllib/files/modules/doctools2base/tcl\_parse\.md)|
|<a name='tcler\_s\_wiki'></a>tcler's wiki|[doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::toc](tcllib/files/modules/doctools2toc/toc\_container\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md)|
|<a name='tcllib'></a>tcllib|[csv](tcllib/files/modules/csv/csv\.md)|
|<a name='tcloo'></a>TclOO|[oo::util](tcllib/files/modules/tool/meta\.md) &#183; [oo::util](tcllib/files/modules/ooutil/ooutil\.md) &#183; [oometa](tcllib/files/modules/oometa/oometa\.md) &#183; [tool](tcllib/files/modules/httpd/httpd\.md) &#183; [tool](tcllib/files/modules/tool/tool\.md) &#183; [tool::dict\_ensemble](tcllib/files/modules/tool/tool\_dict\_ensemble\.md)|
|<a name='tclparam'></a>TCLPARAM|[pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md)|
|<a name='tdpl'></a>TDPL|[grammar::peg](tcllib/files/modules/grammar\_peg/peg\.md) &#183; [grammar::peg::interp](tcllib/files/modules/grammar\_peg/peg\_interp\.md) &#183; [pt](tcllib/files/apps/pt\.md) &#183; [pt::ast](tcllib/files/modules/pt/pt\_astree\.md) &#183; [pt::cparam::configuration::critcl](tcllib/files/modules/pt/pt\_cparam\_config\_critcl\.md) &#183; [pt::cparam::configuration::tea](tcllib/files/modules/pt/pt\_cparam\_config\_tea\.md) &#183; [pt::json\_language](tcllib/files/modules/pt/pt\_json\_language\.md) &#183; [pt::param](tcllib/files/modules/pt/pt\_param\.md) &#183; [pt::pe](tcllib/files/modules/pt/pt\_pexpression\.md) &#183; [pt::pe::op](tcllib/files/modules/pt/pt\_pexpr\_op\.md) &#183; [pt::peg](tcllib/files/modules/pt/pt\_pegrammar\.md) &#183; [pt::peg::container](tcllib/files/modules/pt/pt\_peg\_container\.md) &#183; [pt::peg::container::peg](tcllib/files/modules/pt/pt\_peg\_container\_peg\.md) &#183; [pt::peg::export](tcllib/files/modules/pt/pt\_peg\_export\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::container](tcllib/files/modules/pt/pt\_peg\_from\_container\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import](tcllib/files/modules/pt/pt\_peg\_import\.md) &#183; [pt::peg::import::container](tcllib/files/modules/pt/pt\_peg\_import\_container\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::interp](tcllib/files/modules/pt/pt\_peg\_interp\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [pt::peg\_language](tcllib/files/modules/pt/pt\_peg\_language\.md) &#183; [pt::pegrammar](tcllib/files/modules/pt/pt\_peg\_introduction\.md) &#183; [pt::pgen](tcllib/files/modules/pt/pt\_pgen\.md) &#183; [pt::rde](tcllib/files/modules/pt/pt\_rdengine\.md) &#183; [pt::tclparam::configuration::nx](tcllib/files/modules/pt/pt\_tclparam\_config\_nx\.md) &#183; [pt::tclparam::configuration::snit](tcllib/files/modules/pt/pt\_tclparam\_config\_snit\.md) &#183; [pt::tclparam::configuration::tcloo](tcllib/files/modules/pt/pt\_tclparam\_config\_tcloo\.md) &#183; [pt::util](tcllib/files/modules/pt/pt\_util\.md) &#183; [pt\_export\_api](tcllib/files/modules/pt/pt\_to\_api\.md) &#183; [pt\_import\_api](tcllib/files/modules/pt/pt\_from\_api\.md) &#183; [pt\_introduction](tcllib/files/modules/pt/pt\_introduction\.md) &#183; [pt\_parse\_peg](tcllib/files/modules/pt/pt\_parse\_peg\.md) &#183; [pt\_parser\_api](tcllib/files/modules/pt/pt\_parser\_api\.md) &#183; [pt\_peg\_op](tcllib/files/modules/pt/pt\_peg\_op\.md)|
|<a name='temp\_file'></a>temp file|[fileutil](tcllib/files/modules/fileutil/fileutil\.md)|
|<a name='template\_processing'></a>template processing|[textutil::expander](tcllib/files/modules/textutil/expander\.md)|
|<a name='terminal'></a>terminal|[term](tcllib/files/modules/term/term\.md) &#183; [term::ansi::code](tcllib/files/modules/term/ansi\_code\.md) &#183; [term::ansi::code::attr](tcllib/files/modules/term/ansi\_cattr\.md) &#183; [term::ansi::code::ctrl](tcllib/files/modules/term/ansi\_cctrl\.md) &#183; [term::ansi::code::macros](tcllib/files/modules/term/ansi\_cmacros\.md) &#183; [term::ansi::ctrl::unix](tcllib/files/modules/term/ansi\_ctrlu\.md) &#183; [term::ansi::send](tcllib/files/modules/term/ansi\_send\.md) &#183; [term::interact::menu](tcllib/files/modules/term/imenu\.md) &#183; [term::interact::pager](tcllib/files/modules/term/ipager\.md) &#183; [term::receive](tcllib/files/modules/term/receive\.md) &#183; [term::receive::bind](tcllib/files/modules/term/term\_bind\.md) &#183; [term::send](tcllib/files/modules/term/term\_send\.md)|
|<a name='test'></a>test|[fileutil](tcllib/files/modules/fileutil/fileutil\.md)|
|<a name='testing'></a>Testing|[valtype::common](tcllib/files/modules/valtype/valtype\_common\.md) &#183; [valtype::creditcard::amex](tcllib/files/modules/valtype/cc\_amex\.md) &#183; [valtype::creditcard::discover](tcllib/files/modules/valtype/cc\_discover\.md) &#183; [valtype::creditcard::mastercard](tcllib/files/modules/valtype/cc\_mastercard\.md) &#183; [valtype::creditcard::visa](tcllib/files/modules/valtype/cc\_visa\.md) &#183; [valtype::gs1::ean13](tcllib/files/modules/valtype/ean13\.md) &#183; [valtype::iban](tcllib/files/modules/valtype/iban\.md) &#183; [valtype::imei](tcllib/files/modules/valtype/imei\.md) &#183; [valtype::isbn](tcllib/files/modules/valtype/isbn\.md) &#183; [valtype::luhn](tcllib/files/modules/valtype/luhn\.md) &#183; [valtype::luhn5](tcllib/files/modules/valtype/luhn5\.md) &#183; [valtype::usnpi](tcllib/files/modules/valtype/usnpi\.md) &#183; [valtype::verhoeff](tcllib/files/modules/valtype/verhoeff\.md)|







|







877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
|<a name='tape\_archive'></a>tape archive|[tar](tcllib/files/modules/tar/tar\.md)|
|<a name='tar'></a>tar|[tar](tcllib/files/modules/tar/tar\.md)|
|<a name='tcl'></a>tcl|[math::bigfloat](tcllib/files/modules/math/bigfloat\.md) &#183; [math::bignum](tcllib/files/modules/math/bignum\.md) &#183; [math::decimal](tcllib/files/modules/math/decimal\.md) &#183; [math::PCA](tcllib/files/modules/math/pca\.md)|
|<a name='tcl\_module'></a>Tcl module|[docstrip\_util](tcllib/files/modules/docstrip/docstrip\_util\.md)|
|<a name='tcl\_syntax'></a>Tcl syntax|[doctools::tcl::parse](tcllib/files/modules/doctools2base/tcl\_parse\.md)|
|<a name='tcler\_s\_wiki'></a>tcler's wiki|[doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::toc](tcllib/files/modules/doctools2toc/toc\_container\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md)|
|<a name='tcllib'></a>tcllib|[csv](tcllib/files/modules/csv/csv\.md)|
|<a name='tcloo'></a>TclOO|[clay](tcllib/files/modules/clay/clay\.md) &#183; [httpd](tcllib/files/modules/httpd/httpd\.md) &#183; [oo::util](tcllib/files/modules/tool/meta\.md) &#183; [oo::util](tcllib/files/modules/ooutil/ooutil\.md) &#183; [oometa](tcllib/files/modules/oometa/oometa\.md) &#183; [tool](tcllib/files/modules/tool/tool\.md) &#183; [tool::dict\_ensemble](tcllib/files/modules/tool/tool\_dict\_ensemble\.md)|
|<a name='tclparam'></a>TCLPARAM|[pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md)|
|<a name='tdpl'></a>TDPL|[grammar::peg](tcllib/files/modules/grammar\_peg/peg\.md) &#183; [grammar::peg::interp](tcllib/files/modules/grammar\_peg/peg\_interp\.md) &#183; [pt](tcllib/files/apps/pt\.md) &#183; [pt::ast](tcllib/files/modules/pt/pt\_astree\.md) &#183; [pt::cparam::configuration::critcl](tcllib/files/modules/pt/pt\_cparam\_config\_critcl\.md) &#183; [pt::cparam::configuration::tea](tcllib/files/modules/pt/pt\_cparam\_config\_tea\.md) &#183; [pt::json\_language](tcllib/files/modules/pt/pt\_json\_language\.md) &#183; [pt::param](tcllib/files/modules/pt/pt\_param\.md) &#183; [pt::pe](tcllib/files/modules/pt/pt\_pexpression\.md) &#183; [pt::pe::op](tcllib/files/modules/pt/pt\_pexpr\_op\.md) &#183; [pt::peg](tcllib/files/modules/pt/pt\_pegrammar\.md) &#183; [pt::peg::container](tcllib/files/modules/pt/pt\_peg\_container\.md) &#183; [pt::peg::container::peg](tcllib/files/modules/pt/pt\_peg\_container\_peg\.md) &#183; [pt::peg::export](tcllib/files/modules/pt/pt\_peg\_export\.md) &#183; [pt::peg::export::container](tcllib/files/modules/pt/pt\_peg\_export\_container\.md) &#183; [pt::peg::export::json](tcllib/files/modules/pt/pt\_peg\_export\_json\.md) &#183; [pt::peg::export::peg](tcllib/files/modules/pt/pt\_peg\_export\_peg\.md) &#183; [pt::peg::from::container](tcllib/files/modules/pt/pt\_peg\_from\_container\.md) &#183; [pt::peg::from::json](tcllib/files/modules/pt/pt\_peg\_from\_json\.md) &#183; [pt::peg::from::peg](tcllib/files/modules/pt/pt\_peg\_from\_peg\.md) &#183; [pt::peg::import](tcllib/files/modules/pt/pt\_peg\_import\.md) &#183; [pt::peg::import::container](tcllib/files/modules/pt/pt\_peg\_import\_container\.md) &#183; [pt::peg::import::json](tcllib/files/modules/pt/pt\_peg\_import\_json\.md) &#183; [pt::peg::import::peg](tcllib/files/modules/pt/pt\_peg\_import\_peg\.md) &#183; [pt::peg::interp](tcllib/files/modules/pt/pt\_peg\_interp\.md) &#183; [pt::peg::to::container](tcllib/files/modules/pt/pt\_peg\_to\_container\.md) &#183; [pt::peg::to::cparam](tcllib/files/modules/pt/pt\_peg\_to\_cparam\.md) &#183; [pt::peg::to::json](tcllib/files/modules/pt/pt\_peg\_to\_json\.md) &#183; [pt::peg::to::param](tcllib/files/modules/pt/pt\_peg\_to\_param\.md) &#183; [pt::peg::to::peg](tcllib/files/modules/pt/pt\_peg\_to\_peg\.md) &#183; [pt::peg::to::tclparam](tcllib/files/modules/pt/pt\_peg\_to\_tclparam\.md) &#183; [pt::peg\_language](tcllib/files/modules/pt/pt\_peg\_language\.md) &#183; [pt::pegrammar](tcllib/files/modules/pt/pt\_peg\_introduction\.md) &#183; [pt::pgen](tcllib/files/modules/pt/pt\_pgen\.md) &#183; [pt::rde](tcllib/files/modules/pt/pt\_rdengine\.md) &#183; [pt::tclparam::configuration::nx](tcllib/files/modules/pt/pt\_tclparam\_config\_nx\.md) &#183; [pt::tclparam::configuration::snit](tcllib/files/modules/pt/pt\_tclparam\_config\_snit\.md) &#183; [pt::tclparam::configuration::tcloo](tcllib/files/modules/pt/pt\_tclparam\_config\_tcloo\.md) &#183; [pt::util](tcllib/files/modules/pt/pt\_util\.md) &#183; [pt\_export\_api](tcllib/files/modules/pt/pt\_to\_api\.md) &#183; [pt\_import\_api](tcllib/files/modules/pt/pt\_from\_api\.md) &#183; [pt\_introduction](tcllib/files/modules/pt/pt\_introduction\.md) &#183; [pt\_parse\_peg](tcllib/files/modules/pt/pt\_parse\_peg\.md) &#183; [pt\_parser\_api](tcllib/files/modules/pt/pt\_parser\_api\.md) &#183; [pt\_peg\_op](tcllib/files/modules/pt/pt\_peg\_op\.md)|
|<a name='temp\_file'></a>temp file|[fileutil](tcllib/files/modules/fileutil/fileutil\.md)|
|<a name='template\_processing'></a>template processing|[textutil::expander](tcllib/files/modules/textutil/expander\.md)|
|<a name='terminal'></a>terminal|[term](tcllib/files/modules/term/term\.md) &#183; [term::ansi::code](tcllib/files/modules/term/ansi\_code\.md) &#183; [term::ansi::code::attr](tcllib/files/modules/term/ansi\_cattr\.md) &#183; [term::ansi::code::ctrl](tcllib/files/modules/term/ansi\_cctrl\.md) &#183; [term::ansi::code::macros](tcllib/files/modules/term/ansi\_cmacros\.md) &#183; [term::ansi::ctrl::unix](tcllib/files/modules/term/ansi\_ctrlu\.md) &#183; [term::ansi::send](tcllib/files/modules/term/ansi\_send\.md) &#183; [term::interact::menu](tcllib/files/modules/term/imenu\.md) &#183; [term::interact::pager](tcllib/files/modules/term/ipager\.md) &#183; [term::receive](tcllib/files/modules/term/receive\.md) &#183; [term::receive::bind](tcllib/files/modules/term/term\_bind\.md) &#183; [term::send](tcllib/files/modules/term/term\_send\.md)|
|<a name='test'></a>test|[fileutil](tcllib/files/modules/fileutil/fileutil\.md)|
|<a name='testing'></a>Testing|[valtype::common](tcllib/files/modules/valtype/valtype\_common\.md) &#183; [valtype::creditcard::amex](tcllib/files/modules/valtype/cc\_amex\.md) &#183; [valtype::creditcard::discover](tcllib/files/modules/valtype/cc\_discover\.md) &#183; [valtype::creditcard::mastercard](tcllib/files/modules/valtype/cc\_mastercard\.md) &#183; [valtype::creditcard::visa](tcllib/files/modules/valtype/cc\_visa\.md) &#183; [valtype::gs1::ean13](tcllib/files/modules/valtype/ean13\.md) &#183; [valtype::iban](tcllib/files/modules/valtype/iban\.md) &#183; [valtype::imei](tcllib/files/modules/valtype/imei\.md) &#183; [valtype::isbn](tcllib/files/modules/valtype/isbn\.md) &#183; [valtype::luhn](tcllib/files/modules/valtype/luhn\.md) &#183; [valtype::luhn5](tcllib/files/modules/valtype/luhn5\.md) &#183; [valtype::usnpi](tcllib/files/modules/valtype/usnpi\.md) &#183; [valtype::verhoeff](tcllib/files/modules/valtype/verhoeff\.md)|
942
943
944
945
946
947
948

949
950
951
952
953
954
955
|||
|---|---|
|<a name='uevent'></a>uevent|[hook](tcllib/files/modules/hook/hook\.md)|
|<a name='unbind'></a>unbind|[uevent](tcllib/files/modules/uev/uevent\.md)|
|<a name='uncapitalize'></a>uncapitalize|[textutil::string](tcllib/files/modules/textutil/textutil\_string\.md)|
|<a name='undenting'></a>undenting|[textutil::adjust](tcllib/files/modules/textutil/adjust\.md)|
|<a name='unicode'></a>unicode|[stringprep](tcllib/files/modules/stringprep/stringprep\.md) &#183; [stringprep::data](tcllib/files/modules/stringprep/stringprep\_data\.md) &#183; [unicode](tcllib/files/modules/stringprep/unicode\.md) &#183; [unicode::data](tcllib/files/modules/stringprep/unicode\_data\.md)|

|<a name='union'></a>union|[struct::disjointset](tcllib/files/modules/struct/disjointset\.md) &#183; [struct::set](tcllib/files/modules/struct/struct\_set\.md)|
|<a name='unit'></a>unit|[units](tcllib/files/modules/units/units\.md)|
|<a name='unknown\_hooking'></a>unknown hooking|[namespacex](tcllib/files/modules/namespacex/namespacex\.md)|
|<a name='untie'></a>untie|[tie](tcllib/files/modules/tie/tie\_std\.md) &#183; [tie](tcllib/files/modules/tie/tie\.md)|
|<a name='update'></a>update|[coroutine](tcllib/files/modules/coroutine/tcllib\_coroutine\.md) &#183; [coroutine::auto](tcllib/files/modules/coroutine/coro\_auto\.md)|
|<a name='uri'></a>uri|[uri](tcllib/files/modules/uri/uri\.md) &#183; [uri\_urn](tcllib/files/modules/uri/urn\-scheme\.md)|
|<a name='url'></a>url|[doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::idx::import](tcllib/files/modules/doctools2idx/idx\_import\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md) &#183; [doctools::toc::import](tcllib/files/modules/doctools2toc/toc\_import\.md) &#183; [map::geocode::nominatim](tcllib/files/modules/map/map\_geocode\_nominatim\.md) &#183; [map::slippy::fetcher](tcllib/files/modules/map/map\_slippy\_fetcher\.md) &#183; [uri](tcllib/files/modules/uri/uri\.md) &#183; [uri\_urn](tcllib/files/modules/uri/urn\-scheme\.md)|







>







948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
|||
|---|---|
|<a name='uevent'></a>uevent|[hook](tcllib/files/modules/hook/hook\.md)|
|<a name='unbind'></a>unbind|[uevent](tcllib/files/modules/uev/uevent\.md)|
|<a name='uncapitalize'></a>uncapitalize|[textutil::string](tcllib/files/modules/textutil/textutil\_string\.md)|
|<a name='undenting'></a>undenting|[textutil::adjust](tcllib/files/modules/textutil/adjust\.md)|
|<a name='unicode'></a>unicode|[stringprep](tcllib/files/modules/stringprep/stringprep\.md) &#183; [stringprep::data](tcllib/files/modules/stringprep/stringprep\_data\.md) &#183; [unicode](tcllib/files/modules/stringprep/unicode\.md) &#183; [unicode::data](tcllib/files/modules/stringprep/unicode\_data\.md)|
|<a name='unified\_format\_diff'></a>unified format diff|[textutil::patch](tcllib/files/modules/textutil/patch\.md)|
|<a name='union'></a>union|[struct::disjointset](tcllib/files/modules/struct/disjointset\.md) &#183; [struct::set](tcllib/files/modules/struct/struct\_set\.md)|
|<a name='unit'></a>unit|[units](tcllib/files/modules/units/units\.md)|
|<a name='unknown\_hooking'></a>unknown hooking|[namespacex](tcllib/files/modules/namespacex/namespacex\.md)|
|<a name='untie'></a>untie|[tie](tcllib/files/modules/tie/tie\_std\.md) &#183; [tie](tcllib/files/modules/tie/tie\.md)|
|<a name='update'></a>update|[coroutine](tcllib/files/modules/coroutine/tcllib\_coroutine\.md) &#183; [coroutine::auto](tcllib/files/modules/coroutine/coro\_auto\.md)|
|<a name='uri'></a>uri|[uri](tcllib/files/modules/uri/uri\.md) &#183; [uri\_urn](tcllib/files/modules/uri/urn\-scheme\.md)|
|<a name='url'></a>url|[doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::idx::import](tcllib/files/modules/doctools2idx/idx\_import\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md) &#183; [doctools::toc::import](tcllib/files/modules/doctools2toc/toc\_import\.md) &#183; [map::geocode::nominatim](tcllib/files/modules/map/map\_geocode\_nominatim\.md) &#183; [map::slippy::fetcher](tcllib/files/modules/map/map\_slippy\_fetcher\.md) &#183; [uri](tcllib/files/modules/uri/uri\.md) &#183; [uri\_urn](tcllib/files/modules/uri/urn\-scheme\.md)|
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
|||
|---|---|
|<a name='wais'></a>wais|[uri](tcllib/files/modules/uri/uri\.md)|
|<a name='widget'></a>widget|[snit](tcllib/files/modules/snit/snit\.md) &#183; [snitfaq](tcllib/files/modules/snit/snitfaq\.md)|
|<a name='widget\_adaptors'></a>widget adaptors|[snit](tcllib/files/modules/snit/snit\.md) &#183; [snitfaq](tcllib/files/modules/snit/snitfaq\.md)|
|<a name='wiki'></a>wiki|[doctools::idx](tcllib/files/modules/doctools/docidx\.md) &#183; [doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::idx::export::wiki](tcllib/files/modules/doctools2idx/idx\_export\_wiki\.md) &#183; [doctools::toc](tcllib/files/modules/doctools2toc/toc\_container\.md) &#183; [doctools::toc](tcllib/files/modules/doctools/doctoc\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md) &#183; [doctools::toc::export::wiki](tcllib/files/modules/doctools2toc/toc\_export\_wiki\.md)|
|<a name='word'></a>word|[doctools::tcl::parse](tcllib/files/modules/doctools2base/tcl\_parse\.md) &#183; [wip](tcllib/files/modules/wip/wip\.md)|
|<a name='www'></a>WWW|[tool](tcllib/files/modules/httpd/httpd\.md)|
|<a name='www'></a>www|[uri](tcllib/files/modules/uri/uri\.md)|


#### <a name='cX'></a>Keywords: X

|||
|---|---|







|







988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
|||
|---|---|
|<a name='wais'></a>wais|[uri](tcllib/files/modules/uri/uri\.md)|
|<a name='widget'></a>widget|[snit](tcllib/files/modules/snit/snit\.md) &#183; [snitfaq](tcllib/files/modules/snit/snitfaq\.md)|
|<a name='widget\_adaptors'></a>widget adaptors|[snit](tcllib/files/modules/snit/snit\.md) &#183; [snitfaq](tcllib/files/modules/snit/snitfaq\.md)|
|<a name='wiki'></a>wiki|[doctools::idx](tcllib/files/modules/doctools/docidx\.md) &#183; [doctools::idx](tcllib/files/modules/doctools2idx/idx\_container\.md) &#183; [doctools::idx::export](tcllib/files/modules/doctools2idx/idx\_export\.md) &#183; [doctools::idx::export::wiki](tcllib/files/modules/doctools2idx/idx\_export\_wiki\.md) &#183; [doctools::toc](tcllib/files/modules/doctools2toc/toc\_container\.md) &#183; [doctools::toc](tcllib/files/modules/doctools/doctoc\.md) &#183; [doctools::toc::export](tcllib/files/modules/doctools2toc/toc\_export\.md) &#183; [doctools::toc::export::wiki](tcllib/files/modules/doctools2toc/toc\_export\_wiki\.md)|
|<a name='word'></a>word|[doctools::tcl::parse](tcllib/files/modules/doctools2base/tcl\_parse\.md) &#183; [wip](tcllib/files/modules/wip/wip\.md)|
|<a name='www'></a>WWW|[httpd](tcllib/files/modules/httpd/httpd\.md)|
|<a name='www'></a>www|[uri](tcllib/files/modules/uri/uri\.md)|


#### <a name='cX'></a>Keywords: X

|||
|---|---|

Changes to embedded/md/tcllib/files/apps/dtplite.md.

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
  - \[2\]

    The following directory structure is created when processing a single set of
    input documents\. The file extension used is for output in HTML, but that is
    not relevant to the structure and was just used to have proper file names\.

        output/
            toc\.html
            index\.html
            files/
                path/to/FOO\.html

    The last line in the example shows the document generated for a file FOO
    located at

        inputdirectory/path/to/FOO

  - \[3\]

    When merging many packages into a unified set of documents the generated
    directory structure is a bit deeper:

        output
            \.toc
            \.idx
            \.tocdoc
            \.idxdoc
            \.xrf
            toc\.html
            index\.html
            FOO1/
                \.\.\.
            FOO2/
                toc\.html
                files/
                    path/to/BAR\.html

    Each of the directories FOO1, \.\.\. contains the documents generated for the
    package FOO1, \.\.\. and follows the structure shown for use case \[2\]\. The only
    exception is that there is no per\-package index\.

    The files "\.toc", "\.idx", and "\.xrf" contain the internal status of the
    whole output and will be read and updated by the next invokation\. Their







|
|

|












|
|
|
|
|
|
|

|

|

|







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
  - \[2\]

    The following directory structure is created when processing a single set of
    input documents\. The file extension used is for output in HTML, but that is
    not relevant to the structure and was just used to have proper file names\.

        output/
            toc.html
            index.html
            files/
                path/to/FOO.html

    The last line in the example shows the document generated for a file FOO
    located at

        inputdirectory/path/to/FOO

  - \[3\]

    When merging many packages into a unified set of documents the generated
    directory structure is a bit deeper:

        output
            .toc
            .idx
            .tocdoc
            .idxdoc
            .xrf
            toc.html
            index.html
            FOO1/
                ...
            FOO2/
                toc.html
                files/
                    path/to/BAR.html

    Each of the directories FOO1, \.\.\. contains the documents generated for the
    package FOO1, \.\.\. and follows the structure shown for use case \[2\]\. The only
    exception is that there is no per\-package index\.

    The files "\.toc", "\.idx", and "\.xrf" contain the internal status of the
    whole output and will be read and updated by the next invokation\. Their

Changes to embedded/md/tcllib/files/apps/page.md.

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
the plugin option they are associated with does not understand them, and was not
superceded by a plugin option coming after\.

Default options are used if and only if the command line did not contain any
options at all\. They will set the application up as a PEG\-based parser
generator\. The exact list of options is

    \-c peg

And now the recognized options and their arguments, if they have any:

  - __\-\-help__

  - __\-h__








|







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
the plugin option they are associated with does not understand them, and was not
superceded by a plugin option coming after\.

Default options are used if and only if the command line did not contain any
options at all\. They will set the application up as a PEG\-based parser
generator\. The exact list of options is

    -c peg

And now the recognized options and their arguments, if they have any:

  - __\-\-help__

  - __\-h__

262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281

      * *peg*

        It sets the application up as a parser generator accepting parsing
        expression grammars and writing a packrat parser in Tcl\. The actual
        arguments it specifies are:

    \-\-reset
    \-\-append
    \-\-reader    peg
    \-\-transform reach
    \-\-transform use
    \-\-writer    me

  - __\-r__ *name*

    Readers\. The name of the package for the plugin *name* is
    "page::reader::*name*"\.

    We have five predefined plugins:







|
|
|
|
|
|







262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281

      * *peg*

        It sets the application up as a parser generator accepting parsing
        expression grammars and writing a packrat parser in Tcl\. The actual
        arguments it specifies are:

    --reset
    --append
    --reader    peg
    --transform reach
    --transform use
    --writer    me

  - __\-r__ *name*

    Readers\. The name of the package for the plugin *name* is
    "page::reader::*name*"\.

    We have five predefined plugins:

Changes to embedded/md/tcllib/files/apps/pt.md.

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
In this section we are working a complete example, starting with a PEG grammar
and ending with running the parser generated from it over some input, following
the outline shown in the figure below:

![](\.\./\.\./\.\./image/flow\.png) Our grammar, assumed to the stored in the file
"calculator\.peg" is

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

From this we create a snit\-based parser via

    pt generate snit calculator\.tcl \-class calculator \-name calculator peg calculator\.peg

which leaves us with the parser package and class written to the file
"calculator\.tcl"\. Assuming that this package is then properly installed in a
place where Tcl can find it we can now use this class via a script like

    package require calculator

    lassign $argv input
    set channel \[open $input r\]

    set parser \[calculator\]
    set ast \[$parser parse $channel\]
    $parser destroy
    close $channel

    \.\.\. now process the returned abstract syntax tree \.\.\.

where the abstract syntax tree stored in the variable will look like

    set ast \{Expression 0 4
        \{Factor 0 4
            \{Term 0 2
                \{Number 0 2
                    \{Digit 0 0\}
                    \{Digit 1 1\}
                    \{Digit 2 2\}
                \}
            \}


            \{AddOp 3 3\}
            \{Term 4 4
                \{Number 4 4
                    \{Digit 4 4\}
                \}
            \}
        \}
    \}





assuming that the input file and channel contained the text

    120\+5

A more graphical representation of the tree would be

![](\.\./\.\./\.\./image/expr\_ast\.png) Regardless, at this point it is the user's
responsibility to work with the tree to reach whatever goal she desires\. I\.e\.
analyze it, transform it, etc\. The package
__[pt::ast](\.\./modules/pt/pt\_astree\.md)__ should be of help here,







|
|
|
|
|
|
|
|
|




|








|

|
|



|



|
|
|
|
|
|
|
<
<
>
>
|
|
|
|
<
<
<
<
|
>
>
>
>


|







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
In this section we are working a complete example, starting with a PEG grammar
and ending with running the parser generated from it over some input, following
the outline shown in the figure below:

![](\.\./\.\./\.\./image/flow\.png) Our grammar, assumed to the stored in the file
"calculator\.peg" is

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

From this we create a snit\-based parser via

    pt generate snit calculator.tcl -class calculator -name calculator peg calculator.peg

which leaves us with the parser package and class written to the file
"calculator\.tcl"\. Assuming that this package is then properly installed in a
place where Tcl can find it we can now use this class via a script like

    package require calculator

    lassign $argv input
    set channel [open $input r]

    set parser [calculator]
    set ast [$parser parse $channel]
    $parser destroy
    close $channel

    ... now process the returned abstract syntax tree ...

where the abstract syntax tree stored in the variable will look like

    set ast {Expression 0 4
        {Factor 0 4
            {Term 0 2
                {Number 0 2
                    {Digit 0 0}
                    {Digit 1 1}
                    {Digit 2 2}


                }
            }
            {AddOp 3 3}
            {Term 4 4
                {Number 4 4
                    {Digit 4 4}




                }
            }
        }
    }

assuming that the input file and channel contained the text

    120+5

A more graphical representation of the tree would be

![](\.\./\.\./\.\./image/expr\_ast\.png) Regardless, at this point it is the user's
responsibility to work with the tree to reach whatever goal she desires\. I\.e\.
analyze it, transform it, etc\. The package
__[pt::ast](\.\./modules/pt/pt\_astree\.md)__ should be of help here,

Added embedded/md/tcllib/files/devdoc/tcl_community_communication.md.









































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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

[//000000001]: # (tcl\_community\_communication \- )
[//000000002]: # (Generated from file 'tcl\_community\_communication\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (tcl\_community\_communication\(n\) 1 tcllib "")

<hr> [ <a href="../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../toc.md">Table Of Contents</a> &#124; <a
href="../../../index.md">Keyword Index</a> &#124; <a
href="../../../toc0.md">Categories</a> &#124; <a
href="../../../toc1.md">Modules</a> &#124; <a
href="../../../toc2.md">Applications</a> ] <hr>

# NAME

tcl\_community\_communication \- Tcl Community \- Kind Communication

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Description](#section1)

  - [Signatories](#section2)

  - [Authors](#section3)

# <a name='description'></a>DESCRIPTION

The Tcl Community encourages contributions from anyone who wishes to advance the
development of:

  - The Tcl Language

  - Tcl derived languages

  - Tcl related libraries

  - Tcl extensions

  - External Projects that Integrate Tcl

We welcome those contributions from anyone\. We are blind to gender, race,
religion, cultural background, cybernetic nature, and any other demographic
characteristics, as well as personal political views\.

A community lives and dies by communications\. And occasionally our
communications are peppered with patterns that are harsh, unfriendly,
unwelcoming and/or otherwise unkind\. As a volunteer community, we need all of
the help we can get\. Therefore, we ask all contributors to make a conscious
effort, in Tcl Community discussions, to communicate in ways that are welcoming\.
Ways that are friendly\. Ways that are, in a word: kind\.

These guidelines suggest specific ways to accomplish that goal\.

Please note: for the balance of this document any reference to "People",
"Persons", "anybody" or "somebody" can refer to any sentient being, not merely
corporeal members of the species Homo Sapien\.

  - We are a Sanctuary not a Clubhouse

    The Tcl Community is a collective of amateurs and professionals who code,
    test, and use tools\. Our community is open to all\. There is no velvet rope\.
    There is no bouncer at the door\. There are no secret handshakes\. Any
    sentient being who enters our midst is welcome\. If someone is ever asked to
    leave, it is only because they are being disruptive to the functioning of
    the community\.

  - We Merit Ideas, Not People

    A good idea can come from anyone, regardless of how little time they have
    been with us\. A bad idea can come from anyone, regardless of how much time
    or how little time they have been with us\. We judge a concept by how it
    stands up to scrutiny of logic, implementation, and regression testing\. We
    don’t judge ideas based on who had the idea first, who agrees with the idea,
    or who disagrees with it\.

  - Treat Everyone with Respect

    Everyone is deserving of respect and courtesy at all times\.

  - Refer to people by the names they use\.

    If grammar requires you to state a gender for a person, honor their
    preferences about their gender identity\. If you are unsure as to the gender
    of an individual, ask\. If someone had to guess about your gender and got it
    wrong, please correct them and do not take it personally\.

  - Do not take a harsh tone towards other participants\.

    Do not make personal attacks against anyone \(participant or not\.\)

    Criticize statements and actions, never people\.

  - Don’t Take Things Personally

    When in doubt, assume the best in people\. A criticism of your statements is
    not a personal attack on you\.

  - Persons, not People

    Stereotypes are an unhelpful tool on many accounts\. They are generally
    oversimplified\. They are usually flat out wrong\. And even if "right" they
    are of absolutely no utility in determining the capabilities, motivations,
    or fitness of an individual\.

    Don’t use them in Tcl Community communications\.

  - Mistakes Happen

    The human condition is a series of trials and errors\. Progress is when we
    get one more trial than error\. Being wrong or making a mistake is the
    default state of humanity\. Accept the errors of your fellow sentient beings,
    and be aware that you are also fallible\.

  - Keep it Real

    Please respond to what people actually say\. We are all amazing individuals,
    but none among us are mind readers\. If you find yourself responding to what
    you imagine someone is thinking, odds are you are going to be wrong\.

    If you must criticize someone, stick to things they have actually done\.
    Never criticize for something you speculate they have done\. Or imagine they
    have done\. Or something someone who shares some attribute with them has done
    in the past\.

    Keep discussions about any non\-Tcl subjects to what can be stated factually
    and without emotion or judgement\.

  - When Trouble Arises, Don’t Escalate

    If you feel you are being personally attacked or offended, take the high
    road\. Punching back in a public forum will only makes things worse\. Address
    the matter in a private correspondence\. Be polite\. Express your feelings,
    but note that you are expressing your feelings\. When writing, look for a way
    to calm matters down\. And when in doubt, sleep on your letter before
    pressing send\. And when not in doubt, sleep on it for another day after
    that\.

    If you are a spectator to a fight in progress, politely request the two
    parties take the matter to a more private forum\.

  - Always get the Last Word: I’m Sorry

    If an personal argument does arise, be the first to apologize\. An apology
    does not concede a logical point\. It merely acknowledges that at some point
    the discussion left either logic, community decency, or both\. Return to the
    topic when cooler heads can prevail\.

  - Nobody is Keeping Score

    There is no prize for being right\. There is no cost for being wrong\. A hard
    sell is not going to advance your idea along any more than a logical
    argument\. You aren’t running for office\. This isn’t debate club\. If you find
    yourself continuing a discussion beyond where a topic can be logically
    discussed, stop\.

  - No Evangelizing

    The Tcl Community is not the place to promote your chosen operating system,
    political outlook, religion, marketing scheme, or economic model\. Period\.

    \(And if you do bring it up, be prepared to have your chosen topic discussed
    logically\. And odds are, not favorably\.\)

  - Respect the Community

    If the Community has come to a decision on a course of action, please stop
    arguing\.

    If someone complains about how you are expressing your ideas, listen\.

    If your words are hurting people, stop\. There is no amount of being "right"
    that makes up for someone leaving our midst because they felt insulted,
    threatened, or ignored\.

By following these guidelines, we will build our community, encourage more
contribution to our projects, and our discussions will be friendlier and reach
conclusions more easily\.

Thank You\.

# <a name='section2'></a>Signatories

  - Sean "the Hypnotoad" Woods

  - Andreas Kupries

# <a name='section3'></a>Authors

  - Primary

    Sean "the Hypnotoad" Woods

  - Light editing

    Andreas Kupries

Added embedded/md/tcllib/files/devdoc/tcllib_devguide.md.













































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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

[//000000001]: # (tcllib\_devguide \- )
[//000000002]: # (Generated from file 'tcllib\_devguide\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (tcllib\_devguide\(n\) 1 tcllib "")

<hr> [ <a href="../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../toc.md">Table Of Contents</a> &#124; <a
href="../../../index.md">Keyword Index</a> &#124; <a
href="../../../toc0.md">Categories</a> &#124; <a
href="../../../toc1.md">Modules</a> &#124; <a
href="../../../toc2.md">Applications</a> ] <hr>

# NAME

tcllib\_devguide \- Tcllib \- The Developer's Guide

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Synopsis](#synopsis)

  - [Description](#section1)

  - [Commitments](#section2)

      - [Contributor](#subsection1)

      - [Maintainer](#subsection2)

  - [Branching and Workflow](#section3)

      - [Package Dependencies](#subsection3)

      - [Trunk](#subsection4)

      - [Branches](#subsection5)

      - [Working with Branches](#subsection6)

      - [Version numbers](#subsection7)

  - [Structural Overview](#section4)

      - [Main Directories](#subsection8)

      - [More Directories](#subsection9)

      - [Top Files](#subsection10)

      - [File Types](#subsection11)

  - [Testsuite Tooling](#section5)

      - [Invoke the testsuites of a specific module](#subsection12)

      - [Invoke the testsuites of all modules](#subsection13)

      - [Detailed Test Logs](#subsection14)

      - [Shell Selection](#subsection15)

      - [Help](#subsection16)

  - [Documentation Tooling](#section6)

      - [Generate documentation for a specific module](#subsection17)

      - [Generate documentation for all modules](#subsection18)

      - [Available output formats, help](#subsection19)

      - [Validation without output](#subsection20)

  - [Notes On Writing A Testsuite](#section7)

  - [Installation Tooling](#section8)

# <a name='synopsis'></a>SYNOPSIS

[__[Module](\.\./\.\./\.\./index\.md\#module)__ *name* *code\-action* *doc\-action* *example\-action*](#1)  
[__[Application](\.\./\.\./\.\./index\.md\#application)__ *name*](#2)  
[__Exclude__ *name*](#3)  

# <a name='description'></a>DESCRIPTION

Welcome to Tcllib, the Tcl Standard Library\. Note that Tcllib is not a package
itself\. It is a collection of \(semi\-independent\)
*[Tcl](\.\./\.\./\.\./index\.md\#tcl)* packages that provide utility functions
useful to a large collection of Tcl programmers\.

This document is a guide for developers working on Tcllib, i\.e\. maintainers
fixing bugs, extending the collection's functionality, etc\.

Please read

  1. *[Tcllib \- How To Get The Sources](tcllib\_sources\.md)* and

  1. *[Tcllib \- The Installer's Guide](tcllib\_installer\.md)*

first, if that was not done already\.

Here we assume that the sources are already available in a directory of your
choice, and that you not only know how to build and install them, but also have
all the necessary requisites to actually do so\. The guide to the sources in
particular also explains which source code management system is used, where to
find it, how to set it up, etc\.

# <a name='section2'></a>Commitments

## <a name='subsection1'></a>Contributor

As a contributor to Tcllib you are committing yourself to:

  1. keep the guidelines written down in *[Tcl Community \- Kind
     Communication](tcl\_community\_communication\.md)* in your mind\. The main
     point to take away from there is *to be kind to each other*\.

  1. Your contributions getting distributed under a BSD/MIT license\. For the
     details see *[Tcllib \- License](tcllib\_license\.md)*

Contributions are made by entering tickets into our tracker, providing patches,
bundles or branches of code for inclusion, or posting to the Tcllib related
mailing lists\.

## <a name='subsection2'></a>Maintainer

When contributing one or more packages for full inclusion into Tcllib you are
committing yourself to

  1. Keep the guidelines written down in *[Tcl Community \- Kind
     Communication](tcl\_community\_communication\.md)* \(as any contributor\) in
     your mind\. The main point to take away from there is *to be kind to each
     other*\.

  1. Your packages getting distributed under a BSD/MIT license\. For the details
     see *[Tcllib \- License](tcllib\_license\.md)*

  1. Maintenance of the new packages for a period of two years under the
     following rules, and responsibilities:

       1) A maintainer may step down after the mandatory period as they see fit\.

       1) A maintainer may step down before the end of the mandatory period,
          under the condition that a replacement maintainer is immediately
          available and has agreed to serve the remainder of the period, plus
          their own mandatory period \(see below\)\.

       1) When stepping down without a replacement maintainer taking over the
          relevant packages have to be flagged as __unmaintained__\.

       1) When a replacement mantainer is brought in for a package it is \(kept\)
          marked as __maintained__ \(again\)\.

          A replacement maintainer is bound by the same rules as the original
          maintainer, except that the mandatory period of maintenance is
          shortened to one year\.

       1) For any __unmaintained__ package a contributor interested in
          becoming its maintainer can become so by flagging them as
          __maintained__ with their name and contact information, committing
          themselves to the rules of a replacement maintainer \(see previous
          point\)\.

       1) For any already __maintained__ package a contributor interested in
          becoming a co\-maintainer can become so with the agreement of the
          existing maintainer\(s\), committing themselves to the rules of a
          replacement maintainer \(see two points previous\)\.

     The responsibilities as a maintainer include:

       1) Watching Tcllib's ticket tracker for bugs, bug fixes, and feature
          requests related to the new packages\.

       1) Reviewing the aforementioned tickets, rejecting or applying them

       1) Coordination and discussion with ticket submitter during the
          development and/or application of bug fixes\.

  1. Follow the [Branching and Workflow](#section3) of this guide\.

# <a name='section3'></a>Branching and Workflow

## <a name='subsection3'></a>Package Dependencies

Regarding packages and dependencies between them Tcllib occupies a middle
position between two extremes:

  1. On one side a strongly interdependent set of packages, usually by a single
     author, for a single project\. Looking at my \(Andreas Kupries\) own work
     examples of such are [Marpa](https://core\.tcl\.tk/akupries/marpa/index),
     [CRIMP](https://core\.tcl\.tk/akupries/crimp/index),
     [Kinetcl](https://core\.tcl\.tk/akupries/kinetcl/index), etc\.

     For every change the author of the project handles all the modifications
     cascading from any incompatibilities it introduced to the system\.

  1. On the other side, the world of semi\-independent projects by many different
     authors where authors know what packages their own creations depend on, yet
     usually do not know who else depends on them\.

     The best thing an author making an \(incompatible\) change to their project
     can do is to for one announce such changes in some way, and for two use
     versioning to distinguish the code before and after the change\.

     The world is then responsible for adapting, be it by updating their own
     projects to the new version, or by sticking to the old\.

As mentioned already, Tcllib lives in the middle of that\.

While we as maintainers cannot be aware of all users of Tcllib's packages, and
thus have to rely on the mechanisms touched on in point 2 above for that, the
dependencies between the packages contained in Tcllib are a different matter\.

As we are collectively responsible for the usability of Tcllib in toto to the
outside world, it behooves us to be individually mindful even of Tcllib packages
we are not directly maintaining, when they depend on packages under our
maintainership\. This may be as simple as coordinating with the maintainers of
the affected packages\. It may also require us to choose how to adapt affected
packages which do not have maintainers, i\.e\. modify them to use our changed
package properly, or modify them to properly depend on the unchanged version of
our package\.

Note that the above is not only a chore but an opportunity as well\. Additional
insight can be had by forcing ourselves to look at our package and the planned
change\(s\) from an outside perspective, to consider the ramifications of our
actions on others in general, and on dependent packages in particular\.

## <a name='subsection4'></a>Trunk

The management and use of branches is an important part of working with a
*Distributed Version Control System* \(*DVCS*\) like
[fossil](https://www\.fossil\-scm\.org/)\.

For Tcllib the main branch of the collection is *trunk*\. In
*[git](\.\./\.\./\.\./index\.md\#git)* this branch would be called *master*, and
this is exactly the case in the [github
mirror](https://github\.com/tcltk/tcllib/) of Tcllib\.

To properly support debugging *each commit* on this branch *has to pass the
entire testsuite* of the collection\. Using bisection to determine when an issue
appeared is an example of an action made easier by this constraint\.

This is part of our collective responsibility for the usability of Tcllib in
toto to the outside world\. As *[fossil](\.\./\.\./\.\./index\.md\#fossil)* has no
mechanism to enforce this condition this is handled on the honor system for
developers and maintainers\.

To make the task easier Tcllib comes with a tool \("sak\.tcl"\) providing a number
of commands in support\. These commands are explained in the following sections
of this guide\.

While it is possible and allowed to commit directly to trunk remember the above
constraint regarding the testsuite, and the coming notes about other possible
issues with a commit\.

## <a name='subsection5'></a>Branches

Given the constraints placed on the *trunk* branch of the repository it is
\(strongly\) recommended to perform any development going beyond trivial changes
on a non\-trunk branch\.

Outside of the trunk developers are allowed to commit intermediate broken states
of their work\. Only at the end of a development cycle, when the relevant branch
is considered ready for merging, will it be necessary to perform full the set of
validations ensuring that the merge to come will create a good commit on trunk\.

Note that while a review from a second developer is not a required condition for
merging a branch it is recommended to seek out such an independent opinion as a
means of cross\-checking the work\.

It also recommended to give any new branch a name which aids in determining
additional details about it\. Examples of good things to stick into a branch name
would be

  - Developer \(nick\)name

  - Ticket hash/reference

  - One or two keywords applicable to the work

  - \.\.\.

Further, while most development branches are likely quite short\-lived, no
prohibitions exist against making longer\-lived branches\. Creators should however
be mindful that the longer such a branch exists without merges the more
divergent they will tend to be, with an associated increase in the effort which
will have to be spent on either merging from and merging to trunk\.

## <a name='subsection6'></a>Working with Branches

In the hope of engendering good work practices now a few example operations
which will come up with branches, and their associated fossil command
\(sequences\)\.

  - *Awareness*

    When developing we have to keep ourselves aware of the context of our work\.
    On what branch are we ? What files have we changed ? What new files are not
    yet known to the repository ? What has happened remotely since we used our
    checkout ? The answers to these questions become especially important when
    using a long\-lived checkout and coming back to it after some time away\.

    Commands to answer questions like the above are:

      * __fossil pull__

        Get all changes done on the remote since the last pull or sync from it\.
        This has to be done first, before any of the commands below\.

        Even if the commit in our checkout refers to the branch we want right
        now control operations committed to the remote may have changed that
        from underneath us\.

      * __fossil info &#124; grep tags__

      * __fossil branch list &#124; grep '\\\*'__

        Two different ways of determining the branch our checkout is on\.

      * __fossil timeline__

        What have we \(and others\) done recently ?

        *Attention*, this information is very likely outdated, the more the
        longer we did not use this checkout\. Run __fossil pull__ first to
        get latest information from the remote repository of the project\.

      * __fossil timeline current__

        Place the commit our checkout is based on at the top of the timeline\.

      * __fossil changes__

        Lists the files we have changed compared to the commit the checkout is
        based on\.

      * __fossil extra__

        Lists the files we have in the checkout the repository does not know
        about\. This may be leftover chaff from our work, or something we have
        forgotten to __fossil add__ to the repository yet\.

  - *Clean checkouts*

    Be aware of where you are \(see first definition\)\.

    For pretty much all the operation recipes below a clean checkout is at least
    desired, often required\. To check that a checkout is clean invoke

        fossil changes
        fossil extra

    How to clean up when uncommitted changes of all sorts are found is
    context\-specific and outside of the scope of this guide\.

  - *Starting a new branch*

    Be aware of where you are \(see first definition\)\.

    Ensure that you have clean checkout \(see second definition\)\. It is
    *required*\.

    In most situations you want to be on branch *trunk*, and you want to be on
    the latest commit for it\. To get there use

        fossil pull
        fossil update trunk

    If some other branch is desired as the starting point for the coming work
    replace *trunk* in the commands above with the name of that branch\.

    With the base line established we now have two ways of creating the new
    branch, with differing \(dis\)advantages\. The simpler way is to

        fossil branch new NAME_OF_NEW_BRANCH

    and start developing\. The advantage here is that you cannot forget to create
    the branch\. The disadvantages are that we have a branch commit unchanged
    from where we branched from, and that we have to use high\-handed techniques
    like hiding or shunning to get rid of the commit should we decide to abandon
    the work before the first actual commit on the branch\.

    The other way of creating the branch is to start developing, and then on the
    first commit use the option __\-\-branch__ to tell
    __[fossil](\.\./\.\./\.\./index\.md\#fossil)__ that we are starting a branch
    now\. I\.e\. run

        fossil commit --branch NAME_OF_NEW_BRANCH ...

    where *\.\.\.* are any other options used to supply the commit message, files
    to commit, etc\.

    The \(dis\)advantages are now reversed\.

    We have no superflous commit, only what is actually developed\. The work is
    hidden until we commit to make our first commit\.

    We may forget to use __\-\-branch NAME\_OF\_NEW\_BRANCH__ and then have to
    correct that oversight via the fossil web interface \(I am currently unaware
    of ways of doing such from the command line, although some magic
    incantantion of __fossil tag create__ may work\)\.

    It helps to keep awareness, like checking before any commit that we are on
    the desired branch\.

  - *Merging a branch into trunk*

    Be aware of where you are \(see first definition\)\.

    Ensure that you have clean checkout \(see second definition\)\. In the
    full\-blown sequence \(zig\-zag\) it is *required*, due to the merging from
    trunk\. In the shorter sequence it is only desired\. That said, keeping the
    checkout clean before any major operations is a good habit to have, in my
    opinion\.

    The full\-blown sequencing with checks all the way is to

      1. Validate the checkout, i\.e\. last commit on your branch\. Run the full
         test suite and other validations, fix all the issues which have cropped
         up\.

      1. Merge the latest state of the *trunk* \(see next definition\)\.

      1. Validate the checkout again\. The incoming trunk changes may have broken
         something now\. Do any required fixes\.

      1. Now merge to the trunk using

             fossil update trunk
             fossil merge --integrate YOUR_BRANCH

      1. At this point the checkout should be in the same state as at the end of
         point \(3\) above, because we resolved any issues with the trunk already\.
         Thus a simple

             fossil commit ...

         should be sufficient now to commit the merge back and close the branch
         \(due to the __\-\-integrate__ we used on the merge\)\.

         The more paranoid may validate the checkout a third time before
         commiting\.

    I call this a *zig\-zag merge* because of how the arrows look in the
    timeline, from trunk to feature branch for the first merge, and then back
    for the final merge\.

    A less paranoid can do what I call a *simple merge*, which moves step \(2\)
    after step \(4\) and skips step \(3\) entirely\. The resulting shorter sequence
    is

      1. Validate

      1. Merge to trunk

      1. Validate again

      1. Commit to trunk

    The last step after either zig\-zag or plain merge is to

        fossil sync

    This saves our work to the remote side, and further gives us any other work
    done while we were doing our merge\. It especially allows us to check if we
    raced somebody else, resulting in a split trunk\.

    When that happens we should coordinate with the other developer on who fixes
    the split, to ensure that we do not race each other again\.

  - *Merging from trunk*

    Be aware of where you are \(see first definition\)\.

    Ensure that you have clean checkout \(see second definition\)\. It is
    *required*\.

    In most situations you want to import the latest commit of branch *trunk*
    \(or other origin\)\. To get it use

        fossil pull

    With that done we can now import this commit into our current branch with

        fossil merge trunk

    Even if __[fossil](\.\./\.\./\.\./index\.md\#fossil)__ does not report any
    conflicts it is a good idea to check that the operation has not broken the
    new and/or changed functionality we are working on\.

    With the establishment of a good merge we then save the state with

        fossil commit ...

    before continuing development\.

## <a name='subsection7'></a>Version numbers

In Tcllib all changes to a package have to come with an increment of its version
number\. What part is incremented \(patchlevel, minor, major version\) depends on
the kind of change made\. With multiple changes in a commit the highest "wins"\.

When working in a development branch the version change can be deferred until it
is time to merge, and then has to cover all the changes in the branch\.

Below a list of the kinds of changes and their associated version increments:

  - *D \- documentation*

    No increment

  - *T \- testsuite*

    No increment

  - *B \- bugfix*

    Patchlevel

  - *I \- implementation tweak*

    Patchlevel

  - *P \- performance tweak*

    Patchlevel

  - *E \- backward\-compatible extension*

    Minor

  - *API \- incompatible change*

    Major

Note that a commit containing a version increment has to mention the new version
number in its commit message, as well as the kind of change which caused it\.

Note further that the version number of a package currently exists in three
places\. An increment has to update all of them:

  1. The package implementation\.

  1. The package index \("pkgIndex\.tcl"\)

  1. The package documentation\.

The "sak\.tcl" command __validate version__ helps finding discrepancies
between the first two\. All the other __validate__ methods are also of
interest to any developer\. Invoke it with

    sak.tcl help validate

to see their documentation\.

# <a name='section4'></a>Structural Overview

## <a name='subsection8'></a>Main Directories

The main directories in the Tcllib toplevel directory and of interest to a
developer are:

  - "modules"

    Each child directory represents one or more packages\. In the case of the
    latter the packages are usually related in some way\. Examples are "base64",
    "math", and "struct", with loose \(base64\) to strong \(math\) relations between
    the packages in the directory\.

  - "apps"

    This directory contains all the installable applications, with their
    documentation\. Note that this directory is currently *not* split into
    sub\-directories\.

  - "examples"

    Each child directory "foo" contains one or more example application for the
    packages in "modules/foo"\. These examples are generally not polished enough
    to be considered for installation\.

## <a name='subsection9'></a>More Directories

  - "config"

    This directory contains files supporting the Unix build system, i\.e\.
    "configure" and "Makefile\.in"\.

  - "devdoc"

    This directories contains the doctools sources for the global documentation,
    like this document and its sibling guides\.

  - "embedded"

    This directory contains the entire documentation formatted for
    *[HTML](\.\./\.\./\.\./index\.md\#html)* and styled to properly mix into the
    web site generated by fossil for the repository\.

    This is the documentation accessible from the Tcllib home directory,
    represented in the repository as "embedded/index\.md"\.

  - "idoc"

    This directory contains the entire documentation formatted for
    *[nroff](\.\./\.\./\.\./index\.md\#nroff)* and
    *[HTML](\.\./\.\./\.\./index\.md\#html)*, the latter without any styling\. This
    is the documentation which will be installed\.

  - "support"

    This directory contains the sources of internal packages and utilities used
    in the implementation of the "installer\.tcl" and "sak\.tcl" scripts/tools\.

## <a name='subsection10'></a>Top Files

  - "aclocal\.m4"

  - "configure"

  - "configure\.in"

  - "Makefile\.in"

    These four files comprise the Unix build system layered on top of the
    "installer\.tcl" script\.

  - "installer\.tcl"

    The Tcl\-based installation script/tool\.

  - "project\.shed"

    Configuration file for *Sean Wood*'s
    __[PracTcl](\.\./modules/practcl/practcl\.md)__ buildsystem\.

  - "sak\.tcl"

    This is the main tool for developers and release managers, the *Swiss Army
    Knife* of management operations on the collection\.

  - "ChangeLog"

    The log of changes to the global support, when the sources were held in
    *[CVS](\.\./\.\./\.\./index\.md\#cvs)*\. Not relevant any longer with the
    switch to the *[fossil](\.\./\.\./\.\./index\.md\#fossil)* SCM\.

  - "license\.terms"

    The license in plain ASCII\. See also *[Tcllib \-
    License](tcllib\_license\.md)* for the nicely formatted form\. The text is
    identical\.

  - "README\.md"

  - "\.github/CONTRIBUTING\.md"

  - "\.github/ISSUE\_TEMPLATE\.md"

  - "\.github/PULL\_REQUEST\_TEMPLATE\.md"

    These markdown\-formatted documents are used and shown by the github mirror
    of these sources, pointing people back to the official location and issue
    trackers\.

  - "DESCRIPTION\.txt"

  - "STATUS"

  - "tcllib\.spec"

  - "tcllib\.tap"

  - "tcllib\.yml"

    ????

## <a name='subsection11'></a>File Types

The most common file types, by file extension, are:

  - "\.tcl"

    Tcl code for a package, application, or example\.

  - "\.man"

    Doctools\-formatted documentation, usually for a package\.

  - "\.test"

    Test suite for a package, or part of\. Based on __tcltest__\.

  - "\.bench"

    Performance benchmarks for a package, or part of\. Based on "modules/bench"\.

  - "\.pcx"

    Syntax rules for *TclDevKit*'s __tclchecker__\. Using these rules
    allows the checker to validate the use of commands of a Tcllib package
    __foo__ without having to scan the "\.tcl" files implementing it\.

# <a name='section5'></a>Testsuite Tooling

Testsuites in Tcllib are based on Tcl's standard test package __tcltest__,
plus utilities found in the directory "modules/devtools"

Tcllib developers invoke the suites through the __test run__ method of the
"sak\.tcl" tool, with other methods of __[test](\.\./\.\./\.\./index\.md\#test)__
providing management operations, for example setting a list of standard Tcl
shells to use\.

## <a name='subsection12'></a>Invoke the testsuites of a specific module

Invoke either

    ./sak.tcl test run foo

or

    ./sak.tcl test run modules/foo

to invoke the testsuites found in a specific module "foo"\.

## <a name='subsection13'></a>Invoke the testsuites of all modules

Invoke the tool without a module name, i\.e\.

    ./sak.tcl test run

to invoke the testsuites of all modules\.

## <a name='subsection14'></a>Detailed Test Logs

In all the previous examples the test runner will write a combination of
progress display and testsuite log to the standard output, showing for each
module only the tests that passed or failed and how many of each in a summary at
the end\.

To get a detailed log, it is necessary to invoke the test runner with additional
options\.

For one:

    ./sak.tcl test run --log LOG foo

While this shows the same short log on the terminal as before, it also writes a
detailed log to the file "LOG\.log", and excerpts to other files \("LOG\.summary",
"LOG\.failures", etc\.\)\.

For two:

    ./sak.tcl test run -v foo

This writes the detailed log to the standard output, instead of the short log\.

Regardless of form, the detailed log contains a list of all test cases executed,
which failed, and how they failed \(expected versus actual results\)\.

## <a name='subsection15'></a>Shell Selection

By default the test runner will use all the Tcl shells specified via __test
add__ to invoke the specified testsuites, if any\. If no such are specified it
will fall back to the Tcl shell used to run the tool itself\.

Use option __\-\-shell__ to explicitly specify the Tcl shell to use, like

    ./sak.tcl test run --shell /path/to/tclsh ...

## <a name='subsection16'></a>Help

Invoke the tool as

    ./sak.tcl help test

to see the detailed help for all methods of
__[test](\.\./\.\./\.\./index\.md\#test)__, and the associated options\.

# <a name='section6'></a>Documentation Tooling

The standard format used for documentation of packages and other things in
Tcllib is *[doctools](\.\./\.\./\.\./index\.md\#doctools)*\. Its supporting
packages are a part of Tcllib, see the directories "modules/doctools" and
"modules/dtplite"\. The latter is an application package, with the actual
application "apps/dtplite" a light wrapper around it\.

Tcllib developers gain access to these through the __doc__ method of the
"sak\.tcl" tool, another \(internal\) wrapper around the "modules/dtplite"
application package\.

## <a name='subsection17'></a>Generate documentation for a specific module

Invoke either

    ./sak.tcl doc html foo

or

    ./sak.tcl doc html modules/foo

to generate HTML for the documentation found in the module "foo"\. Instead of
__html__ any other supported format can be used here, of course\.

The generated formatted documentation will be placed into a directory "doc" in
the current working directory\.

## <a name='subsection18'></a>Generate documentation for all modules

Invoke the tool without a module name, i\.e\.

    ./sak.tcl doc html

to generate HTML for the documentation found in all modules\. Instead of
__html__ any other supported format can be used here, of course\.

The generated formatted documentation will be placed into a directory "doc" in
the current working directory\.

## <a name='subsection19'></a>Available output formats, help

Invoke the tool as

    ./sak.tcl help doc

to see the entire set of supported output formats which can be generated\.

## <a name='subsection20'></a>Validation without output

Note the special format __validate__\.

Using this value as the name of the format to generate forces the tool to simply
check that the documentation is syntactically correct, without generating actual
output\.

Invoke it as either

    ./sak.tcl doc validate (modules/)foo

or

    ./sak.tcl doc validate

to either check the packages of a specific module or check all of them\.

# <a name='section7'></a>Notes On Writing A Testsuite

While previous sections talked about running the testsuites for a module and the
packages therein, this has no meaning if the module in question has no
testsuites at all\.

This section gives a very basic overview on possible methodologies for writing
tests and testsuites\.

First there are "drudgery" tests\. Written to check absolutely basic assumptions
which should never fail\.

For example for a command FOO taking two arguments, three tests calling it with
zero, one, and three arguments\. The basic checks that the command fails if it
has not enough arguments, or too many\.

After that come the tests checking things based on our knowledge of the command,
about its properties and assumptions\. Some examples based on the graph
operations added during Google's Summer of Code 2009 are:

  - The BellmanFord command in struct::graph::ops takes a *startnode* as
    argument, and this node should be a node of the graph\. This equals one test
    case checking the behavior when the specified node is not a node of the
    graph\.

    This often gives rise to code in the implementation which explicitly checks
    the assumption and throws an understandable error, instead of letting the
    algorithm fail later in some weird non\-deterministic way\.

    It is not always possible to do such checks\. The graph argument for example
    is just a command in itself, and while we expect it to exhibit a certain
    interface, i\.e\. a set of sub\-commands aka methods, we cannot check that it
    has them, except by actually trying to use them\. That is done by the
    algorithm anyway, so an explicit check is just overhead we can get by
    without\.

  - IIRC one of the distinguishing characteristic of either BellmanFord and/or
    Johnson is that they are able to handle negative weights\. Whereas Dijkstra
    requires positive weights\.

    This induces \(at least\) three testcases \.\.\. Graph with all positive weights,
    all negative, and a mix of positive and negative weights\. Thinking further
    does the algorithm handle the weight __0__ as well ? Another test case,
    or several, if we mix zero with positive and negative weights\.

  - The two algorithms we are currently thinking about are about distances
    between nodes, and distance can be 'Inf'inity, i\.e\. nodes may not be
    connected\. This means that good test cases are

      1. Strongly connected graph

      1. Connected graph

      1. Disconnected graph\.

    At the extremes of strongly connected and disconnected we have the fully
    connected graphs and graphs without edges, only nodes, i\.e\. completely
    disconnected\.

  - IIRC both of the algorithms take weighted arcs, and fill in a default if
    arcs are left unweighted in the input graph\.

    This also induces three test cases:

      1. Graph will all arcs with explicit weights\.

      1. Graph without weights at all\.

      1. Graph with mixture of weighted and unweighted graphs\.

What was described above via examples is called *black\-box* testing\. Test
cases are designed and written based on the developer's knowledge of the
properties of the algorithm and its inputs, without referencing a particular
implementation\.

Going further, a complement to *black\-box* testing is *white\-box*\. For this
we know the implementation of the algorithm, we look at it and design our tests
cases so that they force the code through all possible paths in the
implementation\. Wherever a decision is made we have a test case forcing a
specific direction of the decision, for all possible combinations and
directions\. It is easy to get a combinatorial explosion in the number of needed
test\-cases\.

In practice I often hope that the black\-box tests I have made are enough to
cover all the paths, obviating the need for white\-box tests\.

The above should be enough to make it clear that writing tests for an algorithm
takes at least as much time as coding the algorithm, and often more time\. Much
more time\. See for example also
[http://sqlite\.org/testing\.html](http://sqlite\.org/testing\.html), a writeup
on how the Sqlite database engine is tested\. Another article of interest might
be
[https://www\.researchgate\.net/publication/298896236](https://www\.researchgate\.net/publication/298896236)\.
While geared to a particular numerical algorithm it still shows that even a
simple\-looking algorithm can lead to an incredible number of test cases\.

An interesting connection is to documentation\. In one direction, the properties
checked with black\-box testing are exactly the properties which should be
documented in the algorithm's man page\. And conversely, the documentation of the
properties of an algorithm makes a good reference to base the black\-box tests
on\.

In practice test cases and documentation often get written together,
cross\-influencing each other\. And the actual writing of test cases is a mix of
black and white box, possibly influencing the implementation while writing the
tests\. Like writing a test for a condition like *startnode not in input graph*
serving as reminder to put a check for this condition into the code\.

# <a name='section8'></a>Installation Tooling

A last thing to consider when adding a new package to the collection is
installation\.

How to *use* the "installer\.tcl" script is documented in *[Tcllib \- The
Installer's Guide](tcllib\_installer\.md)*\.

Here we document how to extend said installer so that it may install new
package\(s\) and/or application\(s\)\.

In most cases only a single file has to be modified, the
"support/installation/modules\.tcl" holding one command per module and
application to install\.

The relevant commands are:

  - <a name='1'></a>__[Module](\.\./\.\./\.\./index\.md\#module)__ *name* *code\-action* *doc\-action* *example\-action*

    Install the packages of module *name*, found in "modules/*name*"\.

    The *code\-action* is responsible for installing the packages and their
    index\. The system currently provides

      * __\_tcl__

        Copy all "\.tcl" files found in "modules/*name*" into the installation\.

      * __\_tcr__

        As __\_tcl__, copy the "\.tcl" files found in the subdirectories of
        "modules/*name*" as well\.

      * __\_tci__

        As __\_tcl__, and copy the "tclIndex\.tcl" file as well\.

      * __\_msg__

        As __\_tcl__, and copy the subdirectory "msgs" as well\.

      * __\_doc__

        As __\_tcl__, and copy the subdirectory "mpformats" as well\.

      * __\_tex__

        As __\_tcl__, and copy "\.tex" files as well\.

    The *doc\-action* is responsible for installing the package documentation\.
    The system currently provides

      * __\_null__

        No documentation available, do nothing\.

      * __\_man__

        Process the "\.man" files found in "modules/*name*" and install the
        results \(nroff and/or HTML\) in the proper location, as given to the
        installer\.

        This is actually a fallback, normally the installer uses the pre\-made
        formatted documentation found under "idoc"\.

    The *example\-action* is responsible for installing the examples\. The
    system currently provides

      * __\_null__

        No examples available, do nothing\.

      * __\_exa__

        Copy the the directory "examples/*name*" recursively to the install
        location for examples\.

  - <a name='2'></a>__[Application](\.\./\.\./\.\./index\.md\#application)__ *name*

    Install the application with *name*, found in "apps"\.

  - <a name='3'></a>__Exclude__ *name*

    This command signals to the installer which of the listed modules to *not*
    install\. I\.e\. they name the deprecated modules of Tcllib\.

If, and only if the above actions are not suitable for the new module then a
second file has to be modified, "support/installation/actions\.tcl"\.

This file contains the implementations of the available actions, and is the
place where any custom action needed to handle the special circumstances of
module has to be added\.

Added embedded/md/tcllib/files/devdoc/tcllib_installer.md.







































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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

[//000000001]: # (tcllib\_install\_guide \- )
[//000000002]: # (Generated from file 'tcllib\_installer\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (tcllib\_install\_guide\(n\) 1 tcllib "")

<hr> [ <a href="../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../toc.md">Table Of Contents</a> &#124; <a
href="../../../index.md">Keyword Index</a> &#124; <a
href="../../../toc0.md">Categories</a> &#124; <a
href="../../../toc1.md">Modules</a> &#124; <a
href="../../../toc2.md">Applications</a> ] <hr>

# NAME

tcllib\_install\_guide \- Tcllib \- The Installer's Guide

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Description](#section1)

  - [Requisites](#section2)

      - [Tcl](#subsection1)

      - [Critcl](#subsection2)

  - [Build & Installation Instructions](#section3)

      - [Installing on Unix](#subsection3)

      - [Installing on Windows](#subsection4)

      - [Critcl & Accelerators](#subsection5)

      - [Tooling](#subsection6)

# <a name='description'></a>DESCRIPTION

Welcome to Tcllib, the Tcl Standard Library\. Note that Tcllib is not a package
itself\. It is a collection of \(semi\-independent\)
*[Tcl](\.\./\.\./\.\./index\.md\#tcl)* packages that provide utility functions
useful to a large collection of Tcl programmers\.

The audience of this document is anyone wishing to build and install the
packages found in Tcllib, for either themselves, or others\.

For developers intending to work on the packages themselves we additionally
provide

  1. *[Tcllib \- The Developer's Guide](tcllib\_devguide\.md)*\.

Please read *[Tcllib \- How To Get The Sources](tcllib\_sources\.md)* first,
if that was not done already\. Here we assume that the sources are already
available in a directory of your choice\.

# <a name='section2'></a>Requisites

Before Tcllib can be build and used a number of requisites must be installed\.
These are:

  1. The scripting language Tcl\. For details see [Tcl](#subsection1)\.

  1. Optionally, the __critcl__ package \(C embedding\) for
     __[Tcl](\.\./\.\./\.\./index\.md\#tcl)__\. For details see __CriTcl__\.

This list assumes that the machine where Tcllib is to be installed is
essentially clean\. Of course, if parts of the dependencies listed below are
already installed the associated steps can be skipped\. It is still recommended
to read their sections though, to validate that the dependencies they talk about
are indeed installed\.

## <a name='subsection1'></a>Tcl

As we are installing a number of Tcl packages and applications it should be
pretty much obvious that a working installation of Tcl itself is needed, and I
will not belabor the point\.

Out of the many possibilities use whatever you are comfortable with, as long as
it provides at the very least Tcl 8\.2, or higher\. This may be a Tcl installation
provided by your operating system distribution, from a distribution\-independent
vendor, or built by yourself\.

*Note* that the packages in Tcllib have begun to require 8\.4, 8\.5, and even
8\.6\. Older versions of Tcl will not be able to use such packages\. Trying to use
them will result in *package not found* errors, as their package index files
will not register them in versions of the core unable to use them\.

Myself, I used \(and still use\) [ActiveState's](http://www\.activestate\.com)
ActiveTcl 8\.5 distribution during development, as I am most familiar with it\.

*\(Disclosure: I, Andreas Kupries, worked for ActiveState until 2016,
maintaining ActiveTcl and TclDevKit for them\)\.*\. I am currently working for
SUSE Software Canada ULC, although not in Tcl\-related areas\.

This distribution can be found at
[http://www\.activestate\.com/activetcl](http://www\.activestate\.com/activetcl)\.
Retrieve the archive of ActiveTcl 8\.5 \(or higher\) for your platform and install
it as directed by ActiveState\.

For those wishing to build and install Tcl on their own, the relevant sources
can be found at

  - Tcl

    [http://core\.tcl\-lang\.org/tcl/](http://core\.tcl\-lang\.org/tcl/)

together with the necessary instructions on how to build it\.

If there are problems with building, installing, or using Tcl, please file a
ticket against *[Tcl](\.\./\.\./\.\./index\.md\#tcl)*, or the vendor of your
distribution, and *not* *[Tcllib](\.\./\.\./\.\./index\.md\#tcllib)*\.

## <a name='subsection2'></a>Critcl

The __critcl__ tool is an *optional* dependency\.

It is only required when trying to build the C\-based *accelerators* for a
number of packages, as explained in [Critcl & Accelerators](#subsection5)

Tcllib's build system looks for it in the , using the name __critcl__\. This
is for Unix\. On Windows on the other hand the search is more complex\. First we
look for a proper application __critcl\.exe__\. When that is not found we look
for a combination of interpreter \(__tclkitsh\.exe__, __tclsh\.exe__\) and
starkit \(__critcl\.kit__, __critcl__\) instead\. *Note* that the choice
of starkit can be overriden via the environment variable \.

Tcllib requires Critcl version 2 or higher\.

The github repository providing releases of version 2 and higher, and the
associated sources, can be found at
[http://andreas\-kupries\.github\.com/critcl](http://andreas\-kupries\.github\.com/critcl)\.

Any branch of the repository can be used \(if not using the prebuild starkit or
starpack\), although the use of the stable branch *master* is recommended\.

At the above url is also an explanation on how to build and install Critcl,
including a list of its dependencies\.

Its instructions will not be repeated here\. If there are problems with these
directions please file a ticket against the *Critcl* project, and not Tcllib\.

# <a name='section3'></a>Build & Installation Instructions

As Tcllib is mainly a bundle of packages written in pure Tcl building it is the
same as installing it\. The exceptions to this have their own subsection,
[Critcl & Accelerators](#subsection5), later on\.

Before that however comes the standard case, differentiated by the platforms
with material differences in the instruction, i\.e\. *Unix*\-like, versus
*Windows*\.

Regarding the latter it should also be noted that it is possible set up an
*Unix*\-like environment using projects like *MSYS*, *Cygwin*, and others\.
In that case the user has the choice of which instructions to follow\.

Regardless of environment or platform, a suitable
*[Tcl](\.\./\.\./\.\./index\.md\#tcl)* has to be installed, and its __tclsh__
should be placed on the \(*Unix*\) or associated with "\.tcl" files
\(*Windows*\)\.

## <a name='subsection3'></a>Installing on Unix

For *Unix*\-like environments Tcllib comes with the standard set of files to
make

    ./configure
    make install

a suitable way of installing it\. This is a standard non\-interactive install
automatically figuring out where to place everything, i\.e\. packages,
applications, and the manpages\.

To get a graphical installer invoke

    ./installer.tcl

instead\.

## <a name='subsection4'></a>Installing on Windows

In a Windows environment we have the __installer\.tcl__ script to perform
installation\.

If the desired __tclsh__ is associated "\.tcl" files then double\-clicking /
opening the __installer\.tcl__ is enough to invoke it in graphical mode\. This
assumes that *[Tk](\.\./\.\./\.\./index\.md\#tk)* is installed and available as
well\.

Without *[Tk](\.\./\.\./\.\./index\.md\#tk)* the only way to invoke the installer
are to open a DOS window, i\.e\. __cmd\.exe__, and then to invoke

    ./installer.tcl

inside it\.

## <a name='subsection5'></a>Critcl & Accelerators

While the majority of Tcllib consists of packages written in pure Tcl a number
of packages also have *accelerators* associated with them\. These are
__critcl__\-based C packages whose use will boost the performance of the
packages using them\. These accelerators are optional, and they are not installed
by default\.

To build the accelerators the normally optional dependency on __critcl__
becomes required\.

To build and install Tcllib with the accelerators in a Unix\-like environment
invoke:

    ./configure
    make critcl # This builds the shared library holding
                # the accelerators
    make install

The underlying tool is "sak\.tcl" in the toplevel directory of Tcllib and the
command __make critcl__ is just a wrapper around

    ./sak.tcl critcl

Therefore in a Windows environment instead invoke

    ./sak.tcl critcl
    ./installer.tcl

from within a DOS window, i\.e\. __cmd\.exe__\.

## <a name='subsection6'></a>Tooling

The core of Tcllib's build system is the script "installer\.tcl" found in the
toplevel directory of a checkout or release\.

The

    configure ; make install

setup available to developers on Unix\-like systems is just a wrapper around it\.
To go beyond the standard embodied in the wrapper it is necessary to directly
invoke this script\.

On Windows system using it directly is the only way to invoke it\.

For basic help invoke it as

    ./installer.tcl -help

This will print a short list of all the available options to the standard output
channel\.

The commands associated with the various *install* targets in the
*Makefile\.in* for Unix can be used as additional examples on how to use this
tool as well\.

The installer can operate in GUI and CLI modes\. By default it chooses the mode
automatically, based on if the Tcl package
__[Tk](\.\./\.\./\.\./index\.md\#tk)__ can be used or not\. The option
__\-no\-gui__ can be used to force CLI mode\.

Note that it is possible to specify options on the command line even if the
installer ultimatively selects GUI mode\. In that case the hardwired defaults and
the options determine the data presented to the user for editing\.

The installer will select a number of defaults for the locations of packages,
examples, and documentation, and also the format of the documentation\. The user
can overide these defaults in the GUI, or by specifying additional options\. The
defaults depend on the platform detected \(Unix/Windows\) and on the __tclsh__
executable used to run the installer\.

*Options*

  - __\-help__

    Show the list of options explained here on the standard output channel and
    exit\.

  - __\+excluded__

    Include deprecated packages in the installation\.

  - __\-no\-gui__

    Force command line operation of the installer

  - __\-no\-wait__

    In CLI mode the installer will by default ask the user to confirm that the
    chosen configuration \(destination paths, things to install\) is correct
    before performing any action\. Using this option causes the installer to skip
    this query and immediately jump to installation\.

  - __\-app\-path__ *path*

  - __\-example\-path__ *path*

  - __\-html\-path__ *path*

  - __\-nroff\-path__ *path*

  - __\-pkg\-path__ *path*

    Declare the destination paths for the applications, examples, html
    documentation, nroff manpages, and packages\. The defaults are derived from
    the location of the __tclsh__ used to run the installer\.

  - __\-dry\-run__

  - __\-simulate__

    Run the installer without modifying the destination directories\.

  - __\-apps__

  - __\-no\-apps__

  - __\-examples__

  - __\-no\-examples__

  - __\-pkgs__

  - __\-no\-pkgs__

  - __\-html__

  - __\-no\-html__

  - __\-nroff__

  - __\-no\-nroff__

    \(De\)activate the installation of applications, examples, packages, html
    documentation, and nroff manpages\.

    Applications, examples, and packages are installed by default\.

    On Windows the html documentation is installed by default\.

    On Unix the nroff manpages are installed by default\.

Added embedded/md/tcllib/files/devdoc/tcllib_license.md.











































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

[//000000001]: # (tcllib\_license \- )
[//000000002]: # (Generated from file 'tcllib\_license\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (tcllib\_license\(n\) 1 tcllib "")

<hr> [ <a href="../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../toc.md">Table Of Contents</a> &#124; <a
href="../../../index.md">Keyword Index</a> &#124; <a
href="../../../toc0.md">Categories</a> &#124; <a
href="../../../toc1.md">Modules</a> &#124; <a
href="../../../toc2.md">Applications</a> ] <hr>

# NAME

tcllib\_license \- Tcllib \- License

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Description](#section1)

  - [License](#section2)

# <a name='description'></a>DESCRIPTION

Welcome to Tcllib, the Tcl Standard Library\. Note that Tcllib is not a package
itself\. It is a collection of \(semi\-independent\)
*[Tcl](\.\./\.\./\.\./index\.md\#tcl)* packages that provide utility functions
useful to a large collection of Tcl programmers\.

The collection is under the BSD license\.

# <a name='section2'></a>License

This software is copyrighted by Ajuba Solutions and other parties\. The following
terms apply to all files associated with the software unless explicitly
disclaimed in individual files\.

The authors hereby grant permission to use, copy, modify, distribute, and
license this software and its documentation for any purpose, provided that
existing copyright notices are retained in all copies and that this notice is
included verbatim in any distributions\. No written agreement, license, or
royalty fee is required for any of the authorized uses\. Modifications to this
software may be copyrighted by their authors and need not follow the licensing
terms described here, provided that the new terms are clearly indicated on the
first page of each file where they apply\.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT,
INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE
OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE
AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE\.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON\-INFRINGEMENT\. THIS SOFTWARE IS PROVIDED ON AN "AS
IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS\.

GOVERNMENT USE: If you are acquiring this software on behalf of the U\.S\.
government, the Government shall have only "Restricted Rights" in the software
and related documentation as defined in the Federal Acquisition Regulations
\(FARs\) in Clause 52\.227\.19 \(c\) \(2\)\. If you are acquiring the software on behalf
of the Department of Defense, the software shall be classified as "Commercial
Computer Software" and the Government shall have only "Restricted Rights" as
defined in Clause 252\.227\-7013 \(c\) \(1\) of DFARs\. Notwithstanding the foregoing,
the authors grant the U\.S\. Government and others acting in its behalf permission
to use and distribute the software in accordance with the terms specified in
this license\.

Added embedded/md/tcllib/files/devdoc/tcllib_releasemgr.md.

























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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

[//000000001]: # (tcllib\_releasemgr \- )
[//000000002]: # (Generated from file 'tcllib\_releasemgr\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (tcllib\_releasemgr\(n\) 1 tcllib "")

<hr> [ <a href="../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../toc.md">Table Of Contents</a> &#124; <a
href="../../../index.md">Keyword Index</a> &#124; <a
href="../../../toc0.md">Categories</a> &#124; <a
href="../../../toc1.md">Modules</a> &#124; <a
href="../../../toc2.md">Applications</a> ] <hr>

# NAME

tcllib\_releasemgr \- Tcllib \- The Release Manager's Guide

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Description](#section1)

  - [Tools](#section2)

  - [Tasks](#section3)

      - [Start a release candidate](#subsection1)

      - [Ready the candidate](#subsection2)

      - [Make it official](#subsection3)

      - [Distribute the release](#subsection4)

# <a name='description'></a>DESCRIPTION

Welcome to Tcllib, the Tcl Standard Library\. Note that Tcllib is not a package
itself\. It is a collection of \(semi\-independent\)
*[Tcl](\.\./\.\./\.\./index\.md\#tcl)* packages that provide utility functions
useful to a large collection of Tcl programmers\.

The audience of this document is the release manager for Tcllib, their deputies,
and anybody else interested in the task of creating an official release of
Tcllib for distribution\.

Please read *[Tcllib \- How To Get The Sources](tcllib\_sources\.md)* first,
if that was not done already\. Here we assume that the sources are already
available in a directory of your choice\.

# <a name='section2'></a>Tools

The "sak\.tcl" script in the toplevel directory of a Tcllib checkout is the one
tool used by the release manager to perform its [Tasks](#section3)\.

The main commands to be used are

    sak.tcl validate
    sak.tcl test run
    sak.tcl review
    sak.tcl readme
    sak.tcl localdoc
    sak.tcl release

More detail will be provided in the explanations of the various
[Tasks](#section3)\.

# <a name='section3'></a>Tasks

## <a name='subsection1'></a>Start a release candidate

todo: open a candidate for release

## <a name='subsection2'></a>Ready the candidate

todo: test, validate and check that the candidate is worthy of release fix
testsuites, possibly fix packages, documentation regenerate docs coordinate with
package maintainers wrt fixes big thing: going over the packages, classify
changes since last release to generate a nice readme\.

## <a name='subsection3'></a>Make it official

todo: finalize release, make candidate official

## <a name='subsection4'></a>Distribute the release

With the release made it has to be published and the world notified of its
existence\.

  1. Create a proper fossil event for the release, via
     [http://core\.tcl\-lang\.org/tcllib/eventedit](http://core\.tcl\-lang\.org/tcllib/eventedit)\.

     An [existing
     event](http://core\.tcl\-lang\.org/tcllib/event/dac0ddcd2e990234143196b4dc438fe01e7b9817)
     should be used as template\.

  1. Update a number of web locations:

       1) [Home
          page](http://core\.tcl\-lang\.org/tcllib/doc/trunk/embedded/index\.md)

       1) [Downloads](http://core\.tcl\-lang\.org/tcllib/wiki?name=Downloads)

       1) [Past
          Releases](http://core\.tcl\-lang\.org/tcllib/wiki?name=Past\+Releases)

       1) [http://www\.tcl\-lang\.org/home/release\.txt](http://www\.tcl\-lang\.org/home/release\.txt)

       1) [http://www\.tcl\-lang\.org/software/tcllib/\*\.tml](http://www\.tcl\-lang\.org/software/tcllib/\*\.tml)

       1) [http://wiki\.tcl\-lang\.org/page/Tcllib](http://wiki\.tcl\-lang\.org/page/Tcllib)

     The first location maps to the file "embedded/index\.md" in the repository
     itself, as such it can edited as part of the release process\. This is where
     reference to the new fossil event is added, as the new current release\.

     The next two locations are in the fossil tcllib wiki and require admin or
     wiki write permissions for
     [http://core\.tcl\-lang\.org/tcllib](http://core\.tcl\-lang\.org/tcllib)\.

     The last two locations require ssh access to
     [http://www\.tcl\-lang\.org](http://www\.tcl\-lang\.org) and permission to
     edit files in the web area\.

  1. \*\*\*TODO\*\*\* mailing lists and other places to send notes to\.

Added embedded/md/tcllib/files/devdoc/tcllib_sources.md.











































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

[//000000001]: # (tcllib\_sources \- )
[//000000002]: # (Generated from file 'tcllib\_sources\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (tcllib\_sources\(n\) 1 tcllib "")

<hr> [ <a href="../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../toc.md">Table Of Contents</a> &#124; <a
href="../../../index.md">Keyword Index</a> &#124; <a
href="../../../toc0.md">Categories</a> &#124; <a
href="../../../toc1.md">Modules</a> &#124; <a
href="../../../toc2.md">Applications</a> ] <hr>

# NAME

tcllib\_sources \- Tcllib \- How To Get The Sources

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Description](#section1)

  - [Source Location](#section2)

  - [Retrieval](#section3)

  - [Source Code Management](#section4)

# <a name='description'></a>DESCRIPTION

Welcome to Tcllib, the Tcl Standard Library\. Note that Tcllib is not a package
itself\. It is a collection of \(semi\-independent\)
*[Tcl](\.\./\.\./\.\./index\.md\#tcl)* packages that provide utility functions
useful to a large collection of Tcl programmers\.

The audience of this document is anyone wishing to either have just a look at
Tcllib's source code, or build the packages, or to extend and modify them\.

For builders and developers we additionally provide

  1. *[Tcllib \- The Installer's Guide](tcllib\_installer\.md)*\.

  1. *[Tcllib \- The Developer's Guide](tcllib\_devguide\.md)*\.

respectively\.

# <a name='section2'></a>Source Location

The official repository for Tcllib can be found at
[http://core\.tcl\-lang\.org/tcllib](http://core\.tcl\-lang\.org/tcllib)

# <a name='section3'></a>Retrieval

Assuming that you simply wish to look at the sources, or build a specific
revision, the easiest way of retrieving it is to:

  1. Log into this site, as "anonymous", using the semi\-random password in the
     captcha\.

  1. Go to the "Timeline"\.

  1. Choose the revision you wish to have\.

  1. Follow its link to its detailed information page\.

  1. On that page, choose either the "ZIP" or "Tarball" link to get a copy of
     this revision in the format of your choice\.

# <a name='section4'></a>Source Code Management

For the curious \(or a developer\-to\-be\), the sources are managed by the [Fossil
SCM](http://www\.fossil\-scm\.org)\. Binaries for popular platforms can be found
directly at its [download page](http://www\.fossil\-scm\.org/download\.html)\.

With that tool available the full history can be retrieved via:

    fossil clone  http://core.tcl-lang.org/tcllib  tcllib.fossil

followed by

    mkdir tcllib
    cd tcllib
    fossil open ../tcllib.fossil

to get a checkout of the head of the trunk\.

Changes to embedded/md/tcllib/files/modules/aes/aes.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (aes \- Advanced Encryption Standard \(AES\))
[//000000002]: # (Generated from file 'aes\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2005, Pat Thoyts <patthoyts@users\.sourceforge\.net>  
Copyright &copy; 2012\-2014, Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (aes\(n\) 1\.2\.1 tcllib "Advanced Encryption Standard \(AES\)")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (aes \- Advanced Encryption Standard \(AES\))
[//000000002]: # (Generated from file 'aes\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2005, Pat Thoyts <patthoyts@users\.sourceforge\.net>)
[//000000004]: # (Copyright &copy; 2012\-2014, Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000005]: # (aes\(n\) 1\.2\.1 tcllib "Advanced Encryption Standard \(AES\)")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
    randomly and transmitted as the first block of the output\. Errors in
    encryption affect the current block and the next block after which the
    cipher will correct itself\. CBC is the most commonly used mode in software
    encryption\. This is the default mode of operation for this module\.

# <a name='section5'></a>EXAMPLES

    % set nil\_block \[string repeat \\\\0 16\]
    % aes::aes \-hex \-mode cbc \-dir encrypt \-key $nil\_block $nil\_block
    66e94bd4ef8a2c3b884cfa59ca342b2e

    set Key \[aes::Init cbc $sixteen\_bytes\_key\_data $sixteen\_byte\_iv\]
    append ciphertext \[aes::Encrypt $Key $plaintext\]
    append ciphertext \[aes::Encrypt $Key $additional\_plaintext\]
    aes::Final $Key

# <a name='section6'></a>REFERENCES

  1. "Advanced Encryption Standard", Federal Information Processing Standards
     Publication 197, 2001
     \([http://csrc\.nist\.gov/publications/fips/fips197/fips\-197\.pdf](http://csrc\.nist\.gov/publications/fips/fips197/fips\-197\.pdf)\)







|
|


|
|
|







140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
    randomly and transmitted as the first block of the output\. Errors in
    encryption affect the current block and the next block after which the
    cipher will correct itself\. CBC is the most commonly used mode in software
    encryption\. This is the default mode of operation for this module\.

# <a name='section5'></a>EXAMPLES

    % set nil_block [string repeat \\0 16]
    % aes::aes -hex -mode cbc -dir encrypt -key $nil_block $nil_block
    66e94bd4ef8a2c3b884cfa59ca342b2e

    set Key [aes::Init cbc $sixteen_bytes_key_data $sixteen_byte_iv]
    append ciphertext [aes::Encrypt $Key $plaintext]
    append ciphertext [aes::Encrypt $Key $additional_plaintext]
    aes::Final $Key

# <a name='section6'></a>REFERENCES

  1. "Advanced Encryption Standard", Federal Information Processing Standards
     Publication 197, 2001
     \([http://csrc\.nist\.gov/publications/fips/fips197/fips\-197\.pdf](http://csrc\.nist\.gov/publications/fips/fips197/fips\-197\.pdf)\)

Changes to embedded/md/tcllib/files/modules/amazon-s3/S3.md.

1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
      * __\-prefix__

        This names the prefix that will be added to all resources\. That is, it
        is the remote equivalent of __\-directory__\. If it is not specified,
        the root of the bucket will be treated as the remote directory\. An
        example may clarify\.

            S3::Push \-bucket test \-directory /tmp/xyz \-prefix hello/world

        In this example, /tmp/xyz/pdq\.html will be stored as
        http://s3\.amazonaws\.com/test/hello/world/pdq\.html in Amazon's servers\.
        Also, /tmp/xyz/abc/def/Hello will be stored as
        http://s3\.amazonaws\.com/test/hello/world/abc/def/Hello in Amazon's
        servers\. Without the __\-prefix__ option, /tmp/xyz/pdq\.html would be
        stored as http://s3\.amazonaws\.com/test/pdq\.html\.







|







1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
      * __\-prefix__

        This names the prefix that will be added to all resources\. That is, it
        is the remote equivalent of __\-directory__\. If it is not specified,
        the root of the bucket will be treated as the remote directory\. An
        example may clarify\.

            S3::Push -bucket test -directory /tmp/xyz -prefix hello/world

        In this example, /tmp/xyz/pdq\.html will be stored as
        http://s3\.amazonaws\.com/test/hello/world/pdq\.html in Amazon's servers\.
        Also, /tmp/xyz/abc/def/Hello will be stored as
        http://s3\.amazonaws\.com/test/hello/world/abc/def/Hello in Amazon's
        servers\. Without the __\-prefix__ option, /tmp/xyz/pdq\.html would be
        stored as http://s3\.amazonaws\.com/test/pdq\.html\.
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
    delete files that have been deleted from one place but not the other yet not
    copying changed files is untested\.

# <a name='section7'></a>USAGE SUGGESTIONS

To fetch a "directory" out of a bucket, make changes, and store it back:

    file mkdir \./tempfiles
    S3::Pull \-bucket sample \-prefix of/interest \-directory \./tempfiles \\
      \-timestamp aws
    do\_my\_process \./tempfiles other arguments
    S3::Push \-bucket sample \-prefix of/interest \-directory \./tempfiles \\
      \-compare newer \-delete true

To delete files locally that were deleted off of S3 but not otherwise update
files:

    S3::Pull \-bucket sample \-prefix of/interest \-directory \./myfiles \\
      \-compare never \-delete true

# <a name='section8'></a>FUTURE DEVELOPMENTS

The author intends to work on several additional projects related to this
package, in addition to finishing the unfinished features\.

First, a command\-line program allowing browsing of buckets and transfer of files







|
|
|
|
|
|




|
|







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
    delete files that have been deleted from one place but not the other yet not
    copying changed files is untested\.

# <a name='section7'></a>USAGE SUGGESTIONS

To fetch a "directory" out of a bucket, make changes, and store it back:

    file mkdir ./tempfiles
    S3::Pull -bucket sample -prefix of/interest -directory ./tempfiles \
      -timestamp aws
    do_my_process ./tempfiles other arguments
    S3::Push -bucket sample -prefix of/interest -directory ./tempfiles \
      -compare newer -delete true

To delete files locally that were deleted off of S3 but not otherwise update
files:

    S3::Pull -bucket sample -prefix of/interest -directory ./myfiles \
      -compare never -delete true

# <a name='section8'></a>FUTURE DEVELOPMENTS

The author intends to work on several additional projects related to this
package, in addition to finishing the unfinished features\.

First, a command\-line program allowing browsing of buckets and transfer of files
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init \-tls1 1 ;\# forcibly activate support for the TLS1 protocol

    \.\.\. your own application code \.\.\.

# <a name='section10'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *amazon\-s3* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|

|







1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol

    ... your own application code ...

# <a name='section10'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *amazon\-s3* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/amazon-s3/xsxp.md.

139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
      * %PCDATA?

        is like %PCDATA, but returns an empty string if no PCDATA is found\.

    For example, to fetch the first bold text from the fifth paragraph of the
    body of your HTML file,

        xsxp::fetch $pxml \{body p\#4 b\} %PCDATA

  - <a name='3'></a>__xsxp::fetchall__ *pxml\_list* *path* ?*part*?

    This iterates over each PXML in *pxml\_list* \(which must be a list of
    pxmls\) selecting the indicated path from it, building a new list with the
    selected data, and returning that new list\.








|







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
      * %PCDATA?

        is like %PCDATA, but returns an empty string if no PCDATA is found\.

    For example, to fetch the first bold text from the fifth paragraph of the
    body of your HTML file,

        xsxp::fetch $pxml {body p#4 b} %PCDATA

  - <a name='3'></a>__xsxp::fetchall__ *pxml\_list* *path* ?*part*?

    This iterates over each PXML in *pxml\_list* \(which must be a list of
    pxmls\) selecting the indicated path from it, building a new list with the
    selected data, and returning that new list\.

Changes to embedded/md/tcllib/files/modules/asn/asn.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

[//000000001]: # (asn \- ASN\.1 processing)
[//000000002]: # (Generated from file 'asn\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>  
Copyright &copy; 2004 Jochen Loewer <loewerj@web\.de>  
Copyright &copy; 2004\-2011 Michael Schlenker <mic42@users\.sourceforge\.net>)
[//000000004]: # (asn\(n\) 0\.8 tcllib "ASN\.1 processing")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14

[//000000001]: # (asn \- ASN\.1 processing)
[//000000002]: # (Generated from file 'asn\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (Copyright &copy; 2004 Jochen Loewer <loewerj@web\.de>)
[//000000005]: # (Copyright &copy; 2004\-2011 Michael Schlenker <mic42@users\.sourceforge\.net>)
[//000000006]: # (asn\(n\) 0\.8 tcllib "ASN\.1 processing")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

Changes to embedded/md/tcllib/files/modules/base64/ascii85.md.

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

    Ascii85 decodes the given *string* and returns the binary data\. The
    decoder ignores whitespace in the string, as well as tabs and newlines\.

# <a name='section2'></a>EXAMPLES

    % ascii85::encode "Hello, world"
    87cURD\_\*\#TDfTZ\)

    % ascii85::encode \[string repeat xyz 24\]
    G^4U\[H$X^\\H?a^\]G^4U\[H$X^\\H?a^\]G^4U\[H$X^\\H?a^\]G^4U\[H$X^\\H?a^\]G^4U\[H$X^\\H?a^\]G
    ^4U\[H$X^\\H?a^\]
    % ascii85::encode \-wrapchar "" \[string repeat xyz 24\]
    G^4U\[H$X^\\H?a^\]G^4U\[H$X^\\H?a^\]G^4U\[H$X^\\H?a^\]G^4U\[H$X^\\H?a^\]G^4U\[H$X^\\H?a^\]G^4U\[H$X^\\H?a^\]

    \# NOTE: ascii85 encodes BINARY strings\.
    % set chemical \[encoding convertto utf\-8 "C\\u2088H\\u2081\\u2080N\\u2084O\\u2082"\]
    % set encoded \[ascii85::encode $chemical\]
    6fN\]R8E,5Pidu\\UiduhZidua
    % set caffeine \[encoding convertfrom utf\-8 \[ascii85::decode $encoded\]\]

# <a name='section3'></a>References

  1. [http://en\.wikipedia\.org/wiki/Ascii85](http://en\.wikipedia\.org/wiki/Ascii85)

  1. Postscript Language Reference Manual, 3rd Edition, page 131\.
     [http://www\.adobe\.com/devnet/postscript/pdfs/PLRM\.pdf](http://www\.adobe\.com/devnet/postscript/pdfs/PLRM\.pdf)







|

|
|
|
|
|

|
|
|
|
|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

    Ascii85 decodes the given *string* and returns the binary data\. The
    decoder ignores whitespace in the string, as well as tabs and newlines\.

# <a name='section2'></a>EXAMPLES

    % ascii85::encode "Hello, world"
    87cURD_*#TDfTZ)

    % ascii85::encode [string repeat xyz 24]
    G^4U[H$X^\H?a^]G^4U[H$X^\H?a^]G^4U[H$X^\H?a^]G^4U[H$X^\H?a^]G^4U[H$X^\H?a^]G
    ^4U[H$X^\H?a^]
    % ascii85::encode -wrapchar "" [string repeat xyz 24]
    G^4U[H$X^\H?a^]G^4U[H$X^\H?a^]G^4U[H$X^\H?a^]G^4U[H$X^\H?a^]G^4U[H$X^\H?a^]G^4U[H$X^\H?a^]

    # NOTE: ascii85 encodes BINARY strings.
    % set chemical [encoding convertto utf-8 "C\u2088H\u2081\u2080N\u2084O\u2082"]
    % set encoded [ascii85::encode $chemical]
    6fN]R8E,5Pidu\UiduhZidua
    % set caffeine [encoding convertfrom utf-8 [ascii85::decode $encoded]]

# <a name='section3'></a>References

  1. [http://en\.wikipedia\.org/wiki/Ascii85](http://en\.wikipedia\.org/wiki/Ascii85)

  1. Postscript Language Reference Manual, 3rd Edition, page 131\.
     [http://www\.adobe\.com/devnet/postscript/pdfs/PLRM\.pdf](http://www\.adobe\.com/devnet/postscript/pdfs/PLRM\.pdf)

Changes to embedded/md/tcllib/files/modules/base64/base64.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (base64 \- Text encoding & decoding binary data)
[//000000002]: # (Generated from file 'base64\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2000, Eric Melski  
Copyright &copy; 2001, Miguel Sofer)
[//000000004]: # (base64\(n\) 2\.4\.2 tcllib "Text encoding & decoding binary data")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (base64 \- Text encoding & decoding binary data)
[//000000002]: # (Generated from file 'base64\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2000, Eric Melski)
[//000000004]: # (Copyright &copy; 2001, Miguel Sofer)
[//000000005]: # (base64\(n\) 2\.4\.2 tcllib "Text encoding & decoding binary data")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
    ignores whitespace in the string\.

# <a name='section2'></a>EXAMPLES

    % base64::encode "Hello, world"
    SGVsbG8sIHdvcmxk

    % base64::encode \[string repeat xyz 20\]
    eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6
    eHl6eHl6eHl6
    % base64::encode \-wrapchar "" \[string repeat xyz 20\]
    eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6

    \# NOTE: base64 encodes BINARY strings\.
    % set chemical \[encoding convertto utf\-8 "C\\u2088H\\u2081\\u2080N\\u2084O\\u2082"\]
    % set encoded \[base64::encode $chemical\]
    Q\+KCiEjigoHigoBO4oKET\+KCgg==
    % set caffeine \[encoding convertfrom utf\-8 \[base64::decode $encoded\]\]

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *base64* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|


|


|
|
|
|
|







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
    ignores whitespace in the string\.

# <a name='section2'></a>EXAMPLES

    % base64::encode "Hello, world"
    SGVsbG8sIHdvcmxk

    % base64::encode [string repeat xyz 20]
    eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6
    eHl6eHl6eHl6
    % base64::encode -wrapchar "" [string repeat xyz 20]
    eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6eHl6

    # NOTE: base64 encodes BINARY strings.
    % set chemical [encoding convertto utf-8 "C\u2088H\u2081\u2080N\u2084O\u2082"]
    % set encoded [base64::encode $chemical]
    Q+KCiEjigoHigoBO4oKET+KCgg==
    % set caffeine [encoding convertfrom utf-8 [base64::decode $encoded]]

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *base64* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/base64/uuencode.md.

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
    The uuencoded data header line contains a suggested permissions bit pattern
    expressed as an octal string\. To change the default of 0644 you can set this
    option\. For instance, 0755 would be suitable for an executable\. See
    __chmod\(1\)__\.

# <a name='section3'></a>EXAMPLES

    % set d \[uuencode::encode "Hello World\!"\]
    2&5L;&\\\\@5V\]R;&0A

    % uuencode::uudecode $d
    Hello World\!

    % set d \[uuencode::uuencode \-name hello\.txt "Hello World"\]
    begin 644 hello\.txt
    \+2&5L;&\\@5V\]R;&0\`
    \`

    end

    % uuencode::uudecode $d
    \{hello\.txt 644 \{Hello World\}\}

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *base64* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|
|


|

|
|
|
<
>



|







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
    The uuencoded data header line contains a suggested permissions bit pattern
    expressed as an octal string\. To change the default of 0644 you can set this
    option\. For instance, 0755 would be suitable for an executable\. See
    __chmod\(1\)__\.

# <a name='section3'></a>EXAMPLES

    % set d [uuencode::encode "Hello World!"]
    2&5L;&\\@5V]R;&0A

    % uuencode::uudecode $d
    Hello World!

    % set d [uuencode::uuencode -name hello.txt "Hello World"]
    begin 644 hello.txt
    +2&5L;&\@5V]R;&0`

    `
    end

    % uuencode::uudecode $d
    {hello.txt 644 {Hello World}}

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *base64* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/base64/yencode.md.

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

  - \-crc32 boolean

    The yEnc specification recommends the inclusion of a cyclic redundancy check
    value in the footer\. Use this option to change the default from *true* to
    *false*\.

    % set d \[yencode::yencode \-file testfile\.txt\]
    =ybegin line=128 size=584 name=testfile\.txt
     \-o\- data not shown \-o\-
    =yend size=584 crc32=ded29f4f

# <a name='section3'></a>References

  1. [http://www\.yenc\.org/yenc\-draft\.1\.3\.txt](http://www\.yenc\.org/yenc\-draft\.1\.3\.txt)

# <a name='section4'></a>Bugs, Ideas, Feedback







|
|
|







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

  - \-crc32 boolean

    The yEnc specification recommends the inclusion of a cyclic redundancy check
    value in the footer\. Use this option to change the default from *true* to
    *false*\.

    % set d [yencode::yencode -file testfile.txt]
    =ybegin line=128 size=584 name=testfile.txt
     -o- data not shown -o-
    =yend size=584 crc32=ded29f4f

# <a name='section3'></a>References

  1. [http://www\.yenc\.org/yenc\-draft\.1\.3\.txt](http://www\.yenc\.org/yenc\-draft\.1\.3\.txt)

# <a name='section4'></a>Bugs, Ideas, Feedback

Changes to embedded/md/tcllib/files/modules/bench/bench_lang_intro.md.

55
56
57
58
59
60
61
62
63
64

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
number of commands to support the declaration of benchmarks\. A document written
in this language is a Tcl script and has the same syntax\.

## <a name='subsection2'></a>Basics

One of the most simplest benchmarks which can be written in bench is

    bench \-desc LABEL \-body \{
        set a b
    \}


This code declares a benchmark named __LABEL__ which measures the time it
takes to assign a value to a variable\. The Tcl code doing this assignment is the
__\-body__ of the benchmark\.

## <a name='subsection3'></a>Pre\- and postprocessing

Our next example demonstrates how to declare *initialization* and
*[cleanup](\.\./\.\./\.\./\.\./index\.md\#cleanup)* code, i\.e\. code computing
information for the use of the __\-body__, and for releasing such resources
after the measurement is done\. They are the __\-pre__\- and the
__\-post__\-body, respectively\.

In our example, directly drawn from the benchmark suite of Tcllib's
__[aes](\.\./aes/aes\.md)__ package, the concrete initialization code
constructs the key schedule used by the encryption command whose speed we
measure, and the cleanup code releases any resources bound to that schedule\.

    bench \-desc "AES\-$\{len\} ECB encryption core" __\-pre__ \{
        set key \[aes::Init ecb $k $i\]
    \} \-body \{
        aes::Encrypt $key $p
    \} __\-post__ \{
        aes::Final $key
    \}

## <a name='subsection4'></a>Advanced pre\- and postprocessing

Our last example again deals with initialization and cleanup code\. To see the
difference to the regular initialization and cleanup discussed in the last
section it is necessary to know a bit more about how bench actually measures the
speed of the the __\-body__\.







|

<
>


















|
|
|
|
|
|
|







55
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
number of commands to support the declaration of benchmarks\. A document written
in this language is a Tcl script and has the same syntax\.

## <a name='subsection2'></a>Basics

One of the most simplest benchmarks which can be written in bench is

    bench -desc LABEL -body {
        set a b

    }

This code declares a benchmark named __LABEL__ which measures the time it
takes to assign a value to a variable\. The Tcl code doing this assignment is the
__\-body__ of the benchmark\.

## <a name='subsection3'></a>Pre\- and postprocessing

Our next example demonstrates how to declare *initialization* and
*[cleanup](\.\./\.\./\.\./\.\./index\.md\#cleanup)* code, i\.e\. code computing
information for the use of the __\-body__, and for releasing such resources
after the measurement is done\. They are the __\-pre__\- and the
__\-post__\-body, respectively\.

In our example, directly drawn from the benchmark suite of Tcllib's
__[aes](\.\./aes/aes\.md)__ package, the concrete initialization code
constructs the key schedule used by the encryption command whose speed we
measure, and the cleanup code releases any resources bound to that schedule\.

> bench \-desc "AES\-$\{len\} ECB encryption core" __\-pre__ \{  
> &nbsp;&nbsp;&nbsp;&nbsp;set key \[aes::Init ecb $k $i\]  
> \} \-body \{  
> &nbsp;&nbsp;&nbsp;&nbsp;aes::Encrypt $key $p  
> \} __\-post__ \{  
> &nbsp;&nbsp;&nbsp;&nbsp;aes::Final $key  
> \}

## <a name='subsection4'></a>Advanced pre\- and postprocessing

Our last example again deals with initialization and cleanup code\. To see the
difference to the regular initialization and cleanup discussed in the last
section it is necessary to know a bit more about how bench actually measures the
speed of the the __\-body__\.
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
example we used above to demonstrate the necessity for the advanced
initialization and cleanup\. Its concrete initialization code constructs a
variable refering to a set with specific properties \(The set has a string
representation, which is shared\) affecting the speed of the inclusion command,
and the cleanup code releases the temporary variables created by this
initialization\.

    bench \-desc "set include, missing <SC> x$times $n" __\-ipre__ \{
        set A $sx\($times,$n\)
        set B $A
    \} \-body \{
        struct::set include A x
    \} __\-ipost__ \{
        unset A B
    \}

# <a name='section2'></a>FURTHER READING

Now that this document has been digested the reader, assumed to be a *writer*
of benchmarks, he should be fortified enough to be able to understand the formal
*bench language specfication*\. It will also serve as the detailed
specification and cheat sheet for all available commands and their syntax\.







|
|
|
|
|
|
|
|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
example we used above to demonstrate the necessity for the advanced
initialization and cleanup\. Its concrete initialization code constructs a
variable refering to a set with specific properties \(The set has a string
representation, which is shared\) affecting the speed of the inclusion command,
and the cleanup code releases the temporary variables created by this
initialization\.

> bench \-desc "set include, missing <SC> x$times $n" __\-ipre__ \{  
> &nbsp;&nbsp;&nbsp;&nbsp;set A $sx\($times,$n\)  
> &nbsp;&nbsp;&nbsp;&nbsp;set B $A  
> \} \-body \{  
> &nbsp;&nbsp;&nbsp;&nbsp;struct::set include A x  
> \} __\-ipost__ \{  
> &nbsp;&nbsp;&nbsp;&nbsp;unset A B  
> \}

# <a name='section2'></a>FURTHER READING

Now that this document has been digested the reader, assumed to be a *writer*
of benchmarks, he should be fortified enough to be able to understand the formal
*bench language specfication*\. It will also serve as the detailed
specification and cheat sheet for all available commands and their syntax\.

Changes to embedded/md/tcllib/files/modules/blowfish/blowfish.md.

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
    randomly and transmitted as the first block of the output\. Errors in
    encryption affect the current block and the next block after which the
    cipher will correct itself\. CBC is the most commonly used mode in software
    encryption\.

# <a name='section5'></a>EXAMPLES

    % blowfish::blowfish \-hex \-mode ecb \-dir encrypt \-key secret01 "hello, world\!"
    d0d8f27e7a374b9e2dbd9938dd04195a

    set Key \[blowfish::Init cbc $eight\_bytes\_key\_data $eight\_byte\_iv\]
    append ciphertext \[blowfish::Encrypt $Key $plaintext\]
    append ciphertext \[blowfish::Encrypt $Key $additional\_plaintext\]
    blowfish::Final $Key

# <a name='section6'></a>REFERENCES

  1. Schneier, B\. "Applied Cryptography, 2nd edition", 1996, ISBN 0\-471\-11709\-9,
     pub\. John Wiley & Sons\.








|


|
|
|







141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
    randomly and transmitted as the first block of the output\. Errors in
    encryption affect the current block and the next block after which the
    cipher will correct itself\. CBC is the most commonly used mode in software
    encryption\.

# <a name='section5'></a>EXAMPLES

    % blowfish::blowfish -hex -mode ecb -dir encrypt -key secret01 "hello, world!"
    d0d8f27e7a374b9e2dbd9938dd04195a

    set Key [blowfish::Init cbc $eight_bytes_key_data $eight_byte_iv]
    append ciphertext [blowfish::Encrypt $Key $plaintext]
    append ciphertext [blowfish::Encrypt $Key $additional_plaintext]
    blowfish::Final $Key

# <a name='section6'></a>REFERENCES

  1. Schneier, B\. "Applied Cryptography, 2nd edition", 1996, ISBN 0\-471\-11709\-9,
     pub\. John Wiley & Sons\.

Added embedded/md/tcllib/files/modules/clay/clay.md.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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

[//000000001]: # (clay \- Clay Framework)
[//000000002]: # (Generated from file 'clay\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2018 Sean Woods <yoda@etoyoc\.com>)
[//000000004]: # (clay\(n\) 0\.8\.6 tcllib "Clay Framework")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

# NAME

clay \- A minimalist framework for large scale OO Projects

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Synopsis](#synopsis)

  - [Description](#section1)

      - [Structured Data](#subsection1)

      - [Clay Dialect](#subsection2)

      - [Method Delegation](#subsection3)

  - [Commands](#section2)

  - [Classes](#section3)

      - [Class clay::class](#subsection4)

      - [Class clay::object](#subsection5)

  - [AUTHORS](#section4)

  - [Bugs, Ideas, Feedback](#section5)

  - [Keywords](#keywords)

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.6  
package require uuid  
package require oo::dialect  

[proc __clay::PROC__ *name* *arglist* *body* ?*ninja* ____?](#1)  
[proc __clay::\_ancestors__ *resultvar* *class*](#2)  
[proc __clay::ancestors__ ?*args*?](#3)  
[proc __clay::args\_to\_dict__ ?*args*?](#4)  
[proc __clay::args\_to\_options__ ?*args*?](#5)  
[proc __clay::dynamic\_arguments__ *ensemble* *method* *arglist* ?*args*?](#6)  
[proc __clay::dynamic\_wrongargs\_message__ *arglist*](#7)  
[proc __clay::is\_dict__ *d*](#8)  
[proc __clay::is\_null__ *value*](#9)  
[proc __clay::leaf__ ?*args*?](#10)  
[proc __clay::K__ *a* *b*](#11)  
[proc __clay::noop__ ?*args*?](#12)  
[proc __clay::cleanup__](#13)  
[proc __clay::object\_create__ *objname* ?*class* ____?](#14)  
[proc __clay::object\_rename__ *object* *newname*](#15)  
[proc __clay::object\_destroy__ ?*args*?](#16)  
[proc __clay::path__ ?*args*?](#17)  
[proc __clay::putb__ ?*map*? *text*](#18)  
[proc __clay::script\_path__](#19)  
[proc __clay::NSNormalize__ *qualname*](#20)  
[proc __clay::uuid\_generate__ ?*args*?](#21)  
[proc __clay::uuid::generate\_tcl\_machinfo__](#22)  
[proc __clay::uuid::tostring__ *uuid*](#23)  
[proc __clay::uuid::fromstring__ *uuid*](#24)  
[proc __clay::uuid::equal__ *left* *right*](#25)  
[proc __clay::uuid__ *cmd* ?*args*?](#26)  
[proc __clay::tree::sanitize__ *dict*](#27)  
[proc __clay::tree::\_sanitizeb__ *path* *varname* *dict*](#28)  
[proc __clay::tree::storage__ *rawpath*](#29)  
[proc __clay::tree::dictset__ *varname* ?*args*?](#30)  
[proc __clay::tree::dictmerge__ *varname* ?*args*?](#31)  
[proc __clay::tree::merge__ ?*args*?](#32)  
[proc __dictargs::proc__ *name* *argspec* *body*](#33)  
[proc __dictargs::method__ *name* *argspec* *body*](#34)  
[proc __clay::dialect::Push__ *class*](#35)  
[proc __clay::dialect::Peek__](#36)  
[proc __clay::dialect::Pop__](#37)  
[proc __clay::dialect::create__ *name* ?*parent* ____?](#38)  
[proc __clay::dialect::NSNormalize__ *namespace* *qualname*](#39)  
[proc __clay::dialect::DefineThunk__ *target* ?*args*?](#40)  
[proc __clay::dialect::Canonical__ *namespace* *NSpace* *class*](#41)  
[proc __clay::dialect::Define__ *namespace* *class* ?*args*?](#42)  
[proc __clay::dialect::Aliases__ *namespace* ?*args*?](#43)  
[proc __clay::dialect::SuperClass__ *namespace* ?*args*?](#44)  
[proc __clay::dynamic\_methods__ *class*](#45)  
[proc __clay::dynamic\_methods\_class__ *thisclass*](#46)  
[proc __clay::define::Array__ *name* ?*values* ____?](#47)  
[proc __clay::define::Delegate__ *name* *info*](#48)  
[proc __clay::define::constructor__ *arglist* *rawbody*](#49)  
[proc __clay::define::Class\_Method__ *name* *arglist* *body*](#50)  
[proc __clay::define::class\_method__ *name* *arglist* *body*](#51)  
[proc __clay::define::clay__ ?*args*?](#52)  
[proc __clay::define::destructor__ *rawbody*](#53)  
[proc __clay::define::Dict__ *name* ?*values* ____?](#54)  
[proc __clay::define::Option__ *name* ?*args*?](#55)  
[proc __clay::define::Method__ *name* *argstyle* *argspec* *body*](#56)  
[proc __clay::define::Option\_Class__ *name* ?*args*?](#57)  
[proc __clay::define::Variable__ *name* ?*default* ____?](#58)  
[proc __clay::ensemble\_methodbody__ *ensemble* *einfo*](#59)  
[proc __clay::define::Ensemble__ *rawmethod* ?*args*?](#60)  
[proc __clay::event::cancel__ *self* ?*task* __\*__?](#61)  
[proc __clay::event::generate__ *self* *event* ?*args*?](#62)  
[proc __clay::event::nextid__](#63)  
[proc __clay::event::Notification\_list__ *self* *event* ?*stackvar* ____?](#64)  
[proc __clay::event::notify__ *rcpt* *sender* *event* *eventinfo*](#65)  
[proc __clay::event::process__ *self* *handle* *script*](#66)  
[proc __clay::event::schedule__ *self* *handle* *interval* *script*](#67)  
[proc __clay::event::subscribe__ *self* *who* *event*](#68)  
[proc __clay::event::unsubscribe__ *self* ?*args*?](#69)  
[proc __clay::singleton__ *name* *script*](#70)  
[method __clay ancestors__](#71)  
[method __clay dump__](#72)  
[method __clay find__ *path* ?__path\.\.\.__?](#73)  
[method __clay get__ *path* ?__path\.\.\.__?](#74)  
[method __clay GET__ *path* ?__path\.\.\.__?](#75)  
[method __clay merge__ *dict* ?__dict\.\.\.__?](#76)  
[method __clay replace__ *dictionary*](#77)  
[method __clay search__ *path* ?__path\.\.\.__?](#78)  
[method __clay set__ *path* ?__path\.\.\.__? *value*](#79)  
[method __clay ancestors__](#80)  
[method __clay cache__ *path* *value*](#81)  
[method __clay cget__ *field*](#82)  
[method __clay delegate__ ?*stub*? ?*object*?](#83)  
[method __clay dump__](#84)  
[method __clay ensemble\_map__](#85)  
[method __clay eval__ *script*](#86)  
[method __clay evolve__](#87)  
[method __clay exists__ *path* ?__path\.\.\.__?](#88)  
[method __clay flush__](#89)  
[method __clay forward__ *method* *object*](#90)  
[method __clay get__ *path* ?__path\.\.\.__?](#91)  
[method __clay leaf__ *path* ?__path\.\.\.__?](#92)  
[method __clay merge__ *dict* ?__dict\.\.\.__?](#93)  
[method __clay mixin__ *class* ?__class\.\.\.__?](#94)  
[method __clay mixinmap__ ?*stub*? ?*classes*?](#95)  
[method __clay provenance__ *path* ?__path\.\.\.__?](#96)  
[method __clay replace__ *dictionary*](#97)  
[method __clay search__ *path* *valuevar* *isleafvar*](#98)  
[method __clay source__ *filename*](#99)  
[method __clay set__ *path* ?__path\.\.\.__? *value*](#100)  
[method __InitializePublic__](#101)  

# <a name='description'></a>DESCRIPTION

Clay introduces a method ensemble to both __oo::class__ and
__oo::object__ called clay\. This ensemble handles all of the high level
interactions within the framework\. Clay stores structured data\. Clan manages
method delegation\. Clay has facilities to manage the complex interactions that
come about with mixins\.

The central concept is that inside of every object and class \(which are actually
objects too\) is a dict called clay\. What is stored in that dict is left to the
imagination\. But because this dict is exposed via a public method, we can share
structured data between object, classes, and mixins\.

## <a name='subsection1'></a>Structured Data

Clay uses a standardized set of method interactions and introspection that TclOO
already provides to perform on\-the\-fly searches\. On\-the\-fly searches mean that
the data is never stale, and we avoid many of the sorts of collisions that would
arise when objects start mixing in other classes during operation\.

The __clay__ methods for both classes and objects have a get and a set
method\. For objects, get will search through the local clay dict\. If the
requested leaf is not found, or the query is for a branch, the system will then
begin to poll the clay methods of all of the class that implements the object,
all of that classes’ ancestors, as well as all of the classes that have been
mixed into this object, and all of their ancestors\.

Intended branches on a tree end with a directory slash \(/\)\. Intended leaves are
left unadorned\. This is a guide for the tool that builds the search results to
know what parts of a dict are intended to be branches and which are intended to
be leaves\. For simple cases, branch marking can be ignored:

    ::oo::class create ::foo { }
    ::foo clay set property/ color blue
    ::foo clay set property/ shape round

    set A [::foo new]
    $A clay get property/
    {color blue shape round}

    $A clay set property/ shape square
    $A clay get property/
    {color blue shape square}

But when you start storing blocks of text, guessing what field is a dict and
what isn’t gets messy:

    ::foo clay set description {A generic thing of designated color and shape}

    $A clay get description
    {A generic thing of designated color and shape}

    Without a convention for discerning branches for leaves what should have been a value can be accidentally parsed as a dictionary, and merged with all of the other values that were never intended to be merge. Here is an example of it all going wrong:
    ::oo::class create ::foo { }
    # Add description as a leaf
    ::foo clay set description  {A generic thing of designated color and shape}
    # Add description as a branch
    ::foo clay set description/  {A generic thing of designated color and shape}

    ::oo::class create ::bar {
      superclass foo
    }
    # Add description as a leaf
    ::bar clay set description  {A drinking establishment of designated color and shape and size}
    # Add description as a branch
    ::bar clay set description/  {A drinking establishment of designated color and shape and size}

    set B [::bar new]
    # As a leaf we get the value verbatim from he nearest ancestor
    $B clay get description
      {A drinking establishment of designated color and shape and size}
    # As a branch we get a recursive merge
    $B clay get description/
    {A drinking establishment of designated color and size thing of}

## <a name='subsection2'></a>Clay Dialect

Clay is built using the oo::dialect module from Tcllib\. oo::dialect allows you
to either add keywords directly to clay, or to create your own metaclass and
keyword set using Clay as a foundation\. For details on the keywords and what
they do, consult the functions in the ::clay::define namespace\.

## <a name='subsection3'></a>Method Delegation

Method Delegation It is sometimes useful to have an external object that can be
invoked as if it were a method of the object\. Clay provides a delegate ensemble
method to perform that delegation, as well as introspect which methods are
delegated in that manner\. All delegated methods are marked with html\-like tag
markings \(< >\) around them\.

    ::clay::define counter {
      Variable counter 0
      method incr {{howmuch 1}} {
        my variable counter
        incr counter $howmuch
      }
      method value {} {
        my variable counter
        return $counter
      }
      method reset {} {
        my variable counter
        set counter 0
      }
    }
    ::clay::define example {
      variable buffer
      constructor {} {
        # Build a counter object
        set obj [namespace current]::counter
        ::counter create $obj
        # Delegate the counter
        my delegate <counter> $obj
      }
      method line {text} {
        my <counter> incr
        append buffer $text
      }
    }

    set A [example new]
    $A line {Who’s line is it anyway?}
    $A <counter> value
    1

# <a name='section2'></a>Commands

  - <a name='1'></a>proc __clay::PROC__ *name* *arglist* *body* ?*ninja* ____?

    Because many features in this package may be added as commands to future tcl
    cores, or be provided in binary form by packages, I need a declaritive way
    of saying *Create this command if there isn't one already*\. The *ninja*
    argument is a script to execute if the command is created by this mechanism\.

  - <a name='2'></a>proc __clay::\_ancestors__ *resultvar* *class*

  - <a name='3'></a>proc __clay::ancestors__ ?*args*?

  - <a name='4'></a>proc __clay::args\_to\_dict__ ?*args*?

  - <a name='5'></a>proc __clay::args\_to\_options__ ?*args*?

  - <a name='6'></a>proc __clay::dynamic\_arguments__ *ensemble* *method* *arglist* ?*args*?

  - <a name='7'></a>proc __clay::dynamic\_wrongargs\_message__ *arglist*

  - <a name='8'></a>proc __clay::is\_dict__ *d*

  - <a name='9'></a>proc __clay::is\_null__ *value*

  - <a name='10'></a>proc __clay::leaf__ ?*args*?

  - <a name='11'></a>proc __clay::K__ *a* *b*

  - <a name='12'></a>proc __clay::noop__ ?*args*?

    Perform a noop\. Useful in prototyping for commenting out blocks of code
    without actually having to comment them out\. It also makes a handy default
    for method delegation if a delegate has not been assigned yet\.

  - <a name='13'></a>proc __clay::cleanup__

    Process the queue of objects to be destroyed

  - <a name='14'></a>proc __clay::object\_create__ *objname* ?*class* ____?

  - <a name='15'></a>proc __clay::object\_rename__ *object* *newname*

  - <a name='16'></a>proc __clay::object\_destroy__ ?*args*?

    Mark an objects for destruction on the next cleanup

  - <a name='17'></a>proc __clay::path__ ?*args*?

  - <a name='18'></a>proc __clay::putb__ ?*map*? *text*

    Append a line of text to a variable\. Optionally apply a string mapping\.

  - <a name='19'></a>proc __clay::script\_path__

  - <a name='20'></a>proc __clay::NSNormalize__ *qualname*

  - <a name='21'></a>proc __clay::uuid\_generate__ ?*args*?

  - <a name='22'></a>proc __clay::uuid::generate\_tcl\_machinfo__

  - <a name='23'></a>proc __clay::uuid::tostring__ *uuid*

  - <a name='24'></a>proc __clay::uuid::fromstring__ *uuid*

    Convert a string representation of a uuid into its binary format\.

  - <a name='25'></a>proc __clay::uuid::equal__ *left* *right*

    Compare two uuids for equality\.

  - <a name='26'></a>proc __clay::uuid__ *cmd* ?*args*?

    uuid generate \-> string rep of a new uuid uuid equal uuid1 uuid2

  - <a name='27'></a>proc __clay::tree::sanitize__ *dict*

    Output a dictionary removing any \. entries added by
    __clay::tree::merge__

  - <a name='28'></a>proc __clay::tree::\_sanitizeb__ *path* *varname* *dict*

    Helper function for ::clay::tree::sanitize Formats the string representation
    for a dictionary element within a human readable stream of lines, and
    determines if it needs to call itself with further indentation to express a
    sub\-branch

  - <a name='29'></a>proc __clay::tree::storage__ *rawpath*

    Return the path as a storage path for clay::tree with all branch terminators
    removed\. This command will also break arguments up if they contain /\.

    Example:

    > clay::tree::storage {foo bar baz bang}
    foo bar baz bang
    > clay::tree::storage {foo bar baz bang/}
    foo bar baz bang
    > clay::tree::storage {foo bar baz bang:}
    foo bar baz bang:
    > clay::tree::storage {foo/bar/baz bang:}
    foo bar baz bang:
    > clay::tree::storage {foo/bar/baz/bang}
    foo bar baz bang

  - <a name='30'></a>proc __clay::tree::dictset__ *varname* ?*args*?

    Set an element with a recursive dictionary, marking all branches on the way
    down to the final element\. If the value does not exists in the nested
    dictionary it is added as a leaf\. If the value already exists as a branch
    the value given is merged if the value is a valid dict\. If the incoming
    value is not a valid dict, the value overrides the value stored, and the
    value is treated as a leaf from then on\.

    Example:

    > set r {}
    > ::clay::tree::dictset r option color default Green
    . {} option {. {} color {. {} default Green}}
    > ::clay::tree::dictset r option {Something not dictlike}
    . {} option {Something not dictlike}
    # Note that if the value is not a dict, and you try to force it to be
    # an error with be thrown on the merge
    > ::clay::tree::dictset r option color default Blue
    missing value to go with key

  - <a name='31'></a>proc __clay::tree::dictmerge__ *varname* ?*args*?

    A recursive form of dict merge, intended for modifying variables in place\.

    Example:

    > set mydict {sub/ {sub/ {description {a block of text}}}}
    > ::clay::tree::dictmerge mydict {sub/ {sub/ {field {another block of text}}}}]
    > clay::tree::print $mydict
    sub/ {
      sub/ {
        description {a block of text}
        field {another block of text}
      }
    }

  - <a name='32'></a>proc __clay::tree::merge__ ?*args*?

    A recursive form of dict merge

    A routine to recursively dig through dicts and merge adapted from
    http://stevehavelka\.com/tcl\-dict\-operation\-nested\-merge/

    Example:

    > set mydict {sub/ {sub/ {description {a block of text}}}}
    > set odict [clay::tree::merge $mydict {sub/ {sub/ {field {another block of text}}}}]
    > clay::tree::print $odict
    sub/ {
      sub/ {
        description {a block of text}
        field {another block of text}
      }
    }

  - <a name='33'></a>proc __dictargs::proc__ *name* *argspec* *body*

    Named Procedures as new command

  - <a name='34'></a>proc __dictargs::method__ *name* *argspec* *body*

  - <a name='35'></a>proc __clay::dialect::Push__ *class*

  - <a name='36'></a>proc __clay::dialect::Peek__

  - <a name='37'></a>proc __clay::dialect::Pop__

  - <a name='38'></a>proc __clay::dialect::create__ *name* ?*parent* ____?

    This proc will generate a namespace, a "mother of all classes", and a
    rudimentary set of policies for this dialect\.

  - <a name='39'></a>proc __clay::dialect::NSNormalize__ *namespace* *qualname*

    Support commands; not intended to be called directly\.

  - <a name='40'></a>proc __clay::dialect::DefineThunk__ *target* ?*args*?

  - <a name='41'></a>proc __clay::dialect::Canonical__ *namespace* *NSpace* *class*

  - <a name='42'></a>proc __clay::dialect::Define__ *namespace* *class* ?*args*?

    Implementation of the languages' define command

  - <a name='43'></a>proc __clay::dialect::Aliases__ *namespace* ?*args*?

  - <a name='44'></a>proc __clay::dialect::SuperClass__ *namespace* ?*args*?

  - <a name='45'></a>proc __clay::dynamic\_methods__ *class*

  - <a name='46'></a>proc __clay::dynamic\_methods\_class__ *thisclass*

  - <a name='47'></a>proc __clay::define::Array__ *name* ?*values* ____?

    New OO Keywords for clay

  - <a name='48'></a>proc __clay::define::Delegate__ *name* *info*

    An annotation that objects of this class interact with delegated methods\.
    The annotation is intended to be a dictionary, and the only reserved key is
    *description*, a human readable description\.

  - <a name='49'></a>proc __clay::define::constructor__ *arglist* *rawbody*

  - <a name='50'></a>proc __clay::define::Class\_Method__ *name* *arglist* *body*

    Specify the a method for the class object itself, instead of for objects of
    the class

  - <a name='51'></a>proc __clay::define::class\_method__ *name* *arglist* *body*

    And alias to the new Class\_Method keyword

  - <a name='52'></a>proc __clay::define::clay__ ?*args*?

  - <a name='53'></a>proc __clay::define::destructor__ *rawbody*

  - <a name='54'></a>proc __clay::define::Dict__ *name* ?*values* ____?

  - <a name='55'></a>proc __clay::define::Option__ *name* ?*args*?

    Define an option for the class

  - <a name='56'></a>proc __clay::define::Method__ *name* *argstyle* *argspec* *body*

  - <a name='57'></a>proc __clay::define::Option\_Class__ *name* ?*args*?

    Define a class of options All field / value pairs will be be inherited by an
    option that specify *name* as it class field\.

  - <a name='58'></a>proc __clay::define::Variable__ *name* ?*default* ____?

    This keyword can also be expressed:

    property variable NAME {default DEFAULT}

    Variables registered in the variable property are also initialized \(if
    missing\) when the object changes class via the *morph* method\.

  - <a name='59'></a>proc __clay::ensemble\_methodbody__ *ensemble* *einfo*

    Produce the body of an ensemble's public dispatch method ensemble is the
    name of the the ensemble\. einfo is a dictionary of methods for the ensemble,
    and each value is a script to execute on dispatch

    Example:

    ::clay::ensemble_methodbody foo {
      bar {tailcall my Foo_bar {*}$args}
      baz {tailcall my Foo_baz {*}$args}
      clock {return [clock seconds]}
      default {puts "You gave me $method"}
    }

  - <a name='60'></a>proc __clay::define::Ensemble__ *rawmethod* ?*args*?

  - <a name='61'></a>proc __clay::event::cancel__ *self* ?*task* __\*__?

    Cancel a scheduled event

  - <a name='62'></a>proc __clay::event::generate__ *self* *event* ?*args*?

    Generate an event Adds a subscription mechanism for objects to see who has
    recieved this event and prevent spamming or infinite recursion

  - <a name='63'></a>proc __clay::event::nextid__

  - <a name='64'></a>proc __clay::event::Notification\_list__ *self* *event* ?*stackvar* ____?

    Called recursively to produce a list of who recieves notifications

  - <a name='65'></a>proc __clay::event::notify__ *rcpt* *sender* *event* *eventinfo*

    Final delivery to intended recipient object

  - <a name='66'></a>proc __clay::event::process__ *self* *handle* *script*

    Evaluate an event script in the global namespace

  - <a name='67'></a>proc __clay::event::schedule__ *self* *handle* *interval* *script*

    Schedule an event to occur later

  - <a name='68'></a>proc __clay::event::subscribe__ *self* *who* *event*

    Subscribe an object to an event pattern

  - <a name='69'></a>proc __clay::event::unsubscribe__ *self* ?*args*?

    Unsubscribe an object from an event pattern

  - <a name='70'></a>proc __clay::singleton__ *name* *script*

    An object which is intended to be it's own class\.

# <a name='section3'></a>Classes

## <a name='subsection4'></a>Class  clay::class

__Methods__

  - <a name='71'></a>method __clay ancestors__

    Return this class and all ancestors in search order\.

  - <a name='72'></a>method __clay dump__

    Return a complete dump of this object's clay data, but only this object's
    clay data\.

  - <a name='73'></a>method __clay find__ *path* ?__path\.\.\.__?

    Pull a chunk of data from the clay system\. If the last element of *path*
    is a branch, returns a recursive merge of all data from this object and it's
    constituent classes of the data in that branch\. If the last element is a
    leaf, search this object for a matching leaf, or search all constituent
    classes for a matching leaf and return the first value found\. If no value is
    found, returns an empty string\. If a branch is returned the topmost \. entry
    is omitted\.

  - <a name='74'></a>method __clay get__ *path* ?__path\.\.\.__?

    Pull a chunk of data from the class's clay system\. If no value is found,
    returns an empty string\. If a branch is returned the topmost \. entry is
    omitted\.

  - <a name='75'></a>method __clay GET__ *path* ?__path\.\.\.__?

    Pull a chunk of data from the class's clay system\. If no value is found,
    returns an empty string\.

  - <a name='76'></a>method __clay merge__ *dict* ?__dict\.\.\.__?

    Recursively merge the dictionaries given into the object's local clay
    storage\.

  - <a name='77'></a>method __clay replace__ *dictionary*

    Replace the contents of the internal clay storage with the dictionary given\.

  - <a name='78'></a>method __clay search__ *path* ?__path\.\.\.__?

    Return the first matching value for the path in either this class's clay
    data or one of its ancestors

  - <a name='79'></a>method __clay set__ *path* ?__path\.\.\.__? *value*

    Merge the conents of __value__ with the object's clay storage at
    __path__\.

## <a name='subsection5'></a>Class  clay::object

clay::object This class is inherited by all classes that have options\.

__Methods__

  - <a name='80'></a>method __clay ancestors__

    Return the class this object belongs to, all classes mixed into this object,
    and all ancestors of those classes in search order\.

  - <a name='81'></a>method __clay cache__ *path* *value*

    Store VALUE in such a way that request in SEARCH for PATH will always return
    it until the cache is flushed

  - <a name='82'></a>method __clay cget__ *field*

    Pull a value from either the object's clay structure or one of its
    constituent classes that matches the field name\. The order of search us:

    1\. The as a value in local dict variable config

    2\. The as a value in local dict variable clay

    3\. As a leaf in any ancestor as a root of the clay tree

    4\. As a leaf in any ancestor as __const__ *field*

    5\. As a leaf in any ancestor as __option__ *field* __default__

  - <a name='83'></a>method __clay delegate__ ?*stub*? ?*object*?

    Introspect or control method delegation\. With no arguments, the method will
    return a key/value list of stubs and objects\. With just the *stub*
    argument, the method will return the object \(if any\) attached to the stub\.
    With a *stub* and an *object* this command will forward all calls to the
    method *stub* to the *object*\.

  - <a name='84'></a>method __clay dump__

    Return a complete dump of this object's clay data, as well as the data from
    all constituent classes recursively blended in\.

  - <a name='85'></a>method __clay ensemble\_map__

    Return a dictionary describing the method ensembles to be assembled for this
    object

  - <a name='86'></a>method __clay eval__ *script*

    Evaluated a script in the namespace of this object

  - <a name='87'></a>method __clay evolve__

    Trigger the __InitializePublic__ private method

  - <a name='88'></a>method __clay exists__ *path* ?__path\.\.\.__?

    Returns 1 if *path* exists in either the object's clay data\. Values
    greater than one indicate the element exists in one of the object's
    constituent classes\. A value of zero indicates the path could not be found\.

  - <a name='89'></a>method __clay flush__

    Wipe any caches built by the clay implementation

  - <a name='90'></a>method __clay forward__ *method* *object*

    A convenience wrapper for

    oo::objdefine [self] forward {*}$args

  - <a name='91'></a>method __clay get__ *path* ?__path\.\.\.__?

    Pull a chunk of data from the clay system\. If the last element of *path*
    is a branch \(ends in a slash /\), returns a recursive merge of all data from
    this object and it's constituent classes of the data in that branch\. If the
    last element is a leaf, search this object for a matching leaf, or search
    all constituent classes for a matching leaf and return the first value
    found\. If no value is found, returns an empty string\.

  - <a name='92'></a>method __clay leaf__ *path* ?__path\.\.\.__?

    A modified get which is tailored to pull only leaf elements

  - <a name='93'></a>method __clay merge__ *dict* ?__dict\.\.\.__?

    Recursively merge the dictionaries given into the object's local clay
    storage\.

  - <a name='94'></a>method __clay mixin__ *class* ?__class\.\.\.__?

    Perform \[oo::objdefine \[self\] mixin\] on this object, with a few additional
    rules: Prior to the call, for any class was previously mixed in, but not in
    the new result, execute the script registered to mixin/ unmap\-script \(if
    given\.\) For all new classes, that were not present prior to this call, after
    the native TclOO mixin is invoked, execute the script registered to mixin/
    map\-script \(if given\.\) Fall all classes that are now present and “mixed in”,
    execute the script registered to mixin/ react\-script \(if given\.\)

  - <a name='95'></a>method __clay mixinmap__ ?*stub*? ?*classes*?

    With no arguments returns the map of stubs and classes mixed into the
    current object\. When only stub is given, returns the classes mixed in on
    that stub\. When stub and classlist given, replace the classes currently on
    that stub with the given classes and invoke clay mixin on the new matrix of
    mixed in classes\.

  - <a name='96'></a>method __clay provenance__ *path* ?__path\.\.\.__?

    Return either __self__ if that path exists in the current object, or
    return the first class \(if any\) along the clay search path which contains
    that element\.

  - <a name='97'></a>method __clay replace__ *dictionary*

    Replace the contents of the internal clay storage with the dictionary given\.

  - <a name='98'></a>method __clay search__ *path* *valuevar* *isleafvar*

    Return true, and set valuevar to the value and isleafar to true for false if
    PATH was found in the cache\.

  - <a name='99'></a>method __clay source__ *filename*

    Source the given filename within the object's namespace

  - <a name='100'></a>method __clay set__ *path* ?__path\.\.\.__? *value*

    Merge the conents of __value__ with the object's clay storage at
    __path__\.

  - <a name='101'></a>method __InitializePublic__

    Instantiate variables\. Called on object creation and during clay mixin\.

# <a name='section4'></a>AUTHORS

Sean Woods

[mailto:<yoda@etoyoc\.com>](mailto:<yoda@etoyoc\.com>)

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *oo* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

When proposing code changes, please provide *unified diffs*, i\.e the output of
__diff \-u__\.

Note further that *attachments* are strongly preferred over inlined patches\.
Attachments can be made by going to the __Edit__ form of the ticket
immediately after its creation, and then using the left\-most button in the
secondary navigation bar\.

# <a name='keywords'></a>KEYWORDS

[TclOO](\.\./\.\./\.\./\.\./index\.md\#tcloo), [oo](\.\./\.\./\.\./\.\./index\.md\#oo)

# <a name='category'></a>CATEGORY

Programming tools

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2018 Sean Woods <yoda@etoyoc\.com>

Changes to embedded/md/tcllib/files/modules/cmdline/cmdline.md.

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

Starting with version 1\.5 all errors thrown by the package have a proper
__::errorCode__ for use with Tcl's __[try](\.\./try/tcllib\_try\.md)__
command\. This code always has the word __CMDLINE__ as its first element\.

# <a name='section4'></a>EXAMPLES

            package require Tcl 8\.5
            package require try         ;\# Tcllib\.
            package require cmdline 1\.5 ;\# First version with proper error\-codes\.

            \# Notes:
            \# \- Tcl 8\.6\+ has 'try' as a builtin command and therefore does not
            \#   need the 'try' package\.
            \# \- Before Tcl 8\.5 we cannot support 'try' and have to use 'catch'\.
            \#   This then requires a dedicated test \(if\) on the contents of
            \#   ::errorCode to separate the CMDLINE USAGE signal from actual errors\.

            set options \{
                \{a          "set the atime only"\}
                \{m          "set the mtime only"\}
                \{c          "do not create non\-existent files"\}
                \{r\.arg  ""  "use time from ref\_file"\}
                \{t\.arg  \-1  "use specified time"\}
            \}

            set usage ": MyCommandName \\\[options\] filename \.\.\.\\noptions:"

            try \{
                array set params \[::cmdline::getoptions argv $options $usage\]
            \} trap \{CMDLINE USAGE\} \{msg o\} \{
                \# Trap the usage signal, print the message, and exit the application\.
                \# Note: Other errors are not caught and passed through to higher levels\!
    	    puts $msg
    	    exit 1
            \}

            if \{  $params\(a\) \} \{ set set\_atime "true" \}

            set has\_t \[expr \{$params\(t\) \!= \-1\}\]
            set has\_r \[expr \{\[string length $params\(r\)\] > 0\}\]
            if \{$has\_t && $has\_r\} \{
                return \-code error "Cannot specify both \-r and \-t"
            \} elseif \{$has\_t\} \{
    	    \.\.\.
            \}


This example, taken \(and slightly modified\) from the package
__[fileutil](\.\./fileutil/fileutil\.md)__, shows how to use cmdline\.
First, a list of options is created, then the 'args' list is passed to cmdline
for processing\. Subsequently, different options are checked to see if they have
been passed to the script, and what their value is\.








|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
<
>
|

|
|
|
|
|


<
|
|
>
|
|
|
|
|
|
<
>







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

Starting with version 1\.5 all errors thrown by the package have a proper
__::errorCode__ for use with Tcl's __[try](\.\./try/tcllib\_try\.md)__
command\. This code always has the word __CMDLINE__ as its first element\.

# <a name='section4'></a>EXAMPLES

            package require Tcl 8.5
            package require try         ;# Tcllib.
            package require cmdline 1.5 ;# First version with proper error-codes.

            # Notes:
            # - Tcl 8.6+ has 'try' as a builtin command and therefore does not
            #   need the 'try' package.
            # - Before Tcl 8.5 we cannot support 'try' and have to use 'catch'.
            #   This then requires a dedicated test (if) on the contents of
            #   ::errorCode to separate the CMDLINE USAGE signal from actual errors.

            set options {
                {a          "set the atime only"}
                {m          "set the mtime only"}
                {c          "do not create non-existent files"}
                {r.arg  ""  "use time from ref_file"}
                {t.arg  -1  "use specified time"}

            }
            set usage ": MyCommandName \[options] filename ...\noptions:"

            try {
                array set params [::cmdline::getoptions argv $options $usage]
            } trap {CMDLINE USAGE} {msg o} {
                # Trap the usage signal, print the message, and exit the application.
                # Note: Other errors are not caught and passed through to higher levels!
    	    puts $msg
    	    exit 1

            }

            if {  $params(a) } { set set_atime "true" }
            set has_t [expr {$params(t) != -1}]
            set has_r [expr {[string length $params(r)] > 0}]
            if {$has_t && $has_r} {
                return -code error "Cannot specify both -r and -t"
            } elseif {$has_t} {
    	    ...

            }

This example, taken \(and slightly modified\) from the package
__[fileutil](\.\./fileutil/fileutil\.md)__, shows how to use cmdline\.
First, a list of options is created, then the 'args' list is passed to cmdline
for processing\. Subsequently, different options are checked to see if they have
been passed to the script, and what their value is\.

Changes to embedded/md/tcllib/files/modules/comm/comm.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

[//000000001]: # (comm \- Remote communication)
[//000000002]: # (Generated from file 'comm\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 1995\-1998 The Open Group\. All Rights Reserved\.  
Copyright &copy; 2003\-2004 ActiveState Corporation\.  
Copyright &copy; 2006\-2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (comm\(n\) 4\.6\.3 tcllib "Remote communication")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14

[//000000001]: # (comm \- Remote communication)
[//000000002]: # (Generated from file 'comm\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 1995\-1998 The Open Group\. All Rights Reserved\.)
[//000000004]: # (Copyright &copy; 2003\-2004 ActiveState Corporation\.)
[//000000005]: # (Copyright &copy; 2006\-2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000006]: # (comm\(n\) 4\.6\.3 tcllib "Remote communication")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
server for the communication path\. As a result, __comm__ works with multiple
interpreters, works on Windows and Macintosh systems, and provides control over
the remote execution path\.

These commands work just like __[send](\.\./\.\./\.\./\.\./index\.md\#send)__ and
__winfo interps__ :

    ::comm::comm send ?\-async? id cmd ?arg arg \.\.\.?
    ::comm::comm interps

This is all that is really needed to know in order to use __comm__

## <a name='subsection1'></a>Commands

The package initializes __::comm::comm__ as the default *chan*\.







|







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
server for the communication path\. As a result, __comm__ works with multiple
interpreters, works on Windows and Macintosh systems, and provides control over
the remote execution path\.

These commands work just like __[send](\.\./\.\./\.\./\.\./index\.md\#send)__ and
__winfo interps__ :

    ::comm::comm send ?-async? id cmd ?arg arg ...?
    ::comm::comm interps

This is all that is really needed to know in order to use __comm__

## <a name='subsection1'></a>Commands

The package initializes __::comm::comm__ as the default *chan*\.
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
If you find that __::comm::comm send__ doesn't work for a particular
command, try the same thing with Tk's send and see if the result is different\.
If there is a problem, please report it\. For instance, there was had one report
that this command produced an error\. Note that the equivalent
__[send](\.\./\.\./\.\./\.\./index\.md\#send)__ command also produces the same
error\.

    % ::comm::comm send id llength \{a b c\}
    wrong \# args: should be "llength list"
    % send name llength \{a b c\}
    wrong \# args: should be "llength list"

The __eval__ hook \(described below\) can be used to change from
__[send](\.\./\.\./\.\./\.\./index\.md\#send)__'s double eval semantics to single
eval semantics\.

## <a name='subsection3'></a>Multiple Channels








|
|
|
|







172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
If you find that __::comm::comm send__ doesn't work for a particular
command, try the same thing with Tk's send and see if the result is different\.
If there is a problem, please report it\. For instance, there was had one report
that this command produced an error\. Note that the equivalent
__[send](\.\./\.\./\.\./\.\./index\.md\#send)__ command also produces the same
error\.

    % ::comm::comm send id llength {a b c}
    wrong # args: should be "llength list"
    % send name llength {a b c}
    wrong # args: should be "llength list"

The __eval__ hook \(described below\) can be used to change from
__[send](\.\./\.\./\.\./\.\./index\.md\#send)__'s double eval semantics to single
eval semantics\.

## <a name='subsection3'></a>Multiple Channels

201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219

  - <a name='6'></a>__::comm::comm channels__

    This lists all the channels allocated in this Tcl interpreter\.

The default configuration parameters for a new channel are:

    "\-port 0 \-local 1 \-listen 0 \-silent 0"

The default channel __::comm::comm__ is created with:

    "::comm::comm new ::comm::comm \-port 0 \-local 1 \-listen 1 \-silent 0"

## <a name='subsection4'></a>Channel Configuration

The __config__ method acts similar to __fconfigure__ in that it sets or
queries configuration variables associated with a channel\.

  - <a name='7'></a>__::comm::comm config__







|



|







201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219

  - <a name='6'></a>__::comm::comm channels__

    This lists all the channels allocated in this Tcl interpreter\.

The default configuration parameters for a new channel are:

    "-port 0 -local 1 -listen 0 -silent 0"

The default channel __::comm::comm__ is created with:

    "::comm::comm new ::comm::comm -port 0 -local 1 -listen 1 -silent 0"

## <a name='subsection4'></a>Channel Configuration

The __config__ method acts similar to __fconfigure__ in that it sets or
queries configuration variables associated with a channel\.

  - <a name='7'></a>__::comm::comm config__
389
390
391
392
393
394
395
396
397
398
399
400


401
402
403
404
405
406
407
    Variables: __chan__, __id__

    This hook is invoked before making a connection to the remote named in
    *id*\. An error return \(via
    __[error](\.\./\.\./\.\./\.\./index\.md\#error)__\) will abort the connection
    attempt with the error\. Example:

    % ::comm::comm hook connecting \{
        if \{\[string match \{\*\[02468\]\} $id\]\} \{
            error "Can't connect to even ids"
        \}
    \}


    % ::comm::comm send 10000 puts ok
    Connect to remote failed: Can't connect to even ids
    %

  - __connected__

    Variables: __chan__, __fid__, __id__, __host__, and







|
|

<
<
>
>







389
390
391
392
393
394
395
396
397
398


399
400
401
402
403
404
405
406
407
    Variables: __chan__, __id__

    This hook is invoked before making a connection to the remote named in
    *id*\. An error return \(via
    __[error](\.\./\.\./\.\./\.\./index\.md\#error)__\) will abort the connection
    attempt with the error\. Example:

    % ::comm::comm hook connecting {
        if {[string match {*[02468]} $id]} {
            error "Can't connect to even ids"


        }
    }
    % ::comm::comm send 10000 puts ok
    Connect to remote failed: Can't connect to even ids
    %

  - __connected__

    Variables: __chan__, __fid__, __id__, __host__, and
420
421
422
423
424
425
426
427
428
429
430
431


432
433
434
435
436
437
438

    Hook invoked when receiving an incoming connection, allowing arbitrary
    authentication over socket named by *fid*\. An error return \(via
    __[error](\.\./\.\./\.\./\.\./index\.md\#error)__\) will close the connection
    with the error\. Note that the peer is named by *remport* and *addr* but
    that the remote *id* is still unknown\. Example:

    ::comm::comm hook incoming \{
        if \{\[string match 127\.0\.0\.1 $addr\]\} \{
            error "I don't talk to myself"
        \}
    \}



  - __eval__

    Variables: __chan__, __id__, __cmd__, and __buffer__\.

    This hook is invoked after collecting a complete script from a remote but
    *before* evaluating it\. This allows complete control over the processing







|
|

<
<
>
>







420
421
422
423
424
425
426
427
428
429


430
431
432
433
434
435
436
437
438

    Hook invoked when receiving an incoming connection, allowing arbitrary
    authentication over socket named by *fid*\. An error return \(via
    __[error](\.\./\.\./\.\./\.\./index\.md\#error)__\) will close the connection
    with the error\. Note that the peer is named by *remport* and *addr* but
    that the remote *id* is still unknown\. Example:

    ::comm::comm hook incoming {
        if {[string match 127.0.0.1 $addr]} {
            error "I don't talk to myself"


        }
    }

  - __eval__

    Variables: __chan__, __id__, __cmd__, and __buffer__\.

    This hook is invoked after collecting a complete script from a remote but
    *before* evaluating it\. This allows complete control over the processing
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
    __break__ and __return \-code break__ *result* is supported, acting
    similarly to __return \{\}__ and __return \-code return__ *result*\.

    Examples:

      1. augmenting a command

    % ::comm::comm send \[::comm::comm self\] pid
    5013
    % ::comm::comm hook eval \{puts "going to execute $buffer"\}
    % ::comm::comm send \[::comm::comm self\] pid
    going to execute pid
    5013

      1. short circuiting a command

    % ::comm::comm hook eval \{puts "would have executed $buffer"; return 0\}
    % ::comm::comm send \[::comm::comm self\] pid
    would have executed pid
    0

      1. Replacing double eval semantics

    % ::comm::comm send \[::comm::comm self\] llength \{a b c\}
    wrong \# args: should be "llength list"
    % ::comm::comm hook eval \{return \[uplevel \#0 $buffer\]\}
    return \[uplevel \#0 $buffer\]
    % ::comm::comm send \[::comm::comm self\] llength \{a b c\}
    3

      1. Using a slave interpreter

    % interp create foo
    % ::comm::comm hook eval \{return \[foo eval $buffer\]\}
    % ::comm::comm send \[::comm::comm self\] set myvar 123
    123
    % set myvar
    can't read "myvar": no such variable
    % foo eval set myvar
    123

      1. Using a slave interpreter \(double eval\)

    % ::comm::comm hook eval \{return \[eval foo eval $buffer\]\}

      1. Subverting the script to execute

    % ::comm::comm hook eval \{
        switch \-\- $buffer \{
            a \{return A\-OK\}
            b \{return B\-OK\}
            default \{error "$buffer is a no\-no"\}
        \}
    \}


    % ::comm::comm send \[::comm::comm self\] pid
    pid is a no\-no
    % ::comm::comm send \[::comm::comm self\] a
    A\-OK

  - __reply__

    Variables: __chan__, __id__, __buffer__, __ret__, and
    __return\(\)__\.

    This hook is invoked after collecting a complete reply script from a remote







|

|
|





|
|





|
|
|
|
|





|
|








|



|
|
|
|
|
<
<
>
>
|
|
|
|







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
    __break__ and __return \-code break__ *result* is supported, acting
    similarly to __return \{\}__ and __return \-code return__ *result*\.

    Examples:

      1. augmenting a command

    % ::comm::comm send [::comm::comm self] pid
    5013
    % ::comm::comm hook eval {puts "going to execute $buffer"}
    % ::comm::comm send [::comm::comm self] pid
    going to execute pid
    5013

      1. short circuiting a command

    % ::comm::comm hook eval {puts "would have executed $buffer"; return 0}
    % ::comm::comm send [::comm::comm self] pid
    would have executed pid
    0

      1. Replacing double eval semantics

    % ::comm::comm send [::comm::comm self] llength {a b c}
    wrong # args: should be "llength list"
    % ::comm::comm hook eval {return [uplevel #0 $buffer]}
    return [uplevel #0 $buffer]
    % ::comm::comm send [::comm::comm self] llength {a b c}
    3

      1. Using a slave interpreter

    % interp create foo
    % ::comm::comm hook eval {return [foo eval $buffer]}
    % ::comm::comm send [::comm::comm self] set myvar 123
    123
    % set myvar
    can't read "myvar": no such variable
    % foo eval set myvar
    123

      1. Using a slave interpreter \(double eval\)

    % ::comm::comm hook eval {return [eval foo eval $buffer]}

      1. Subverting the script to execute

    % ::comm::comm hook eval {
        switch -- $buffer {
            a {return A-OK}
            b {return B-OK}
            default {error "$buffer is a no-no"}


        }
    }
    % ::comm::comm send [::comm::comm self] pid
    pid is a no-no
    % ::comm::comm send [::comm::comm self] a
    A-OK

  - __reply__

    Variables: __chan__, __id__, __buffer__, __ret__, and
    __return\(\)__\.

    This hook is invoked after collecting a complete reply script from a remote
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

    Variables: __chan__, __id__, and __reason__\.

    This hook is invoked when the connection to __id__ is lost\. Return value
    \(or thrown error\) is ignored\. *reason* is an explanatory string indicating
    why the connection was lost\. Example:

    ::comm::comm hook lost \{
        global myvar
        if \{$myvar\(id\) == $id\} \{
            myfunc
            return
        \}
    \}



## <a name='subsection10'></a>Unsupported

These interfaces may change or go away in subsequence releases\.

  - <a name='14'></a>__::comm::comm remoteid__

    Returns the *id* of the sender of the last remote command executed on this
    channel\. If used by a proc being invoked remotely, it must be called before
    any events are processed\. Otherwise, another command may get invoked and
    change the value\.

  - <a name='15'></a>__::comm::comm\_send__

    Invoking this procedure will substitute the Tk
    __[send](\.\./\.\./\.\./\.\./index\.md\#send)__ and __winfo interps__
    commands with these equivalents that use __::comm::comm__\.

    proc send \{args\} \{
        eval ::comm::comm send $args
    \}

    rename winfo tk\_winfo
    proc winfo \{cmd args\} \{
        if \{\!\[string match in\* $cmd\]\} \{
            return \[eval \[list tk\_winfo $cmd\] $args\]
        \}

        return \[::comm::comm interps\]
    \}


## <a name='subsection11'></a>Security

Starting with version 4\.6 of the package an option __\-socketcmd__ is
supported, allowing the user of a comm channel to specify which command to use
when opening a socket\. Anything which is API\-compatible with the builtin
__::socket__ \(the default\) can be used\.

The envisioned main use is the specification of the __tls::socket__ command,
see package __[tls](\.\./\.\./\.\./\.\./index\.md\#tls)__, to secure the
communication\.

    \# Load and initialize tls
    package require tls
    tls::init  \-cafile /path/to/ca/cert \-keyfile \.\.\.

    \# Create secured comm channel
    ::comm::comm new SECURE \-socketcmd tls::socket \-listen 1
    \.\.\.

The sections [Execution Environment](#subsection6) and
[Callbacks](#subsection9) are also relevant to the security of the system,
providing means to restrict the execution to a specific environment, perform
additional authentication, and the like\.

## <a name='subsection12'></a>Blocking Semantics







|

|


<
<
>
>


















|

<
>
|
|
|
|
<
>
|
<
>












|

|

|
|
|







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

    Variables: __chan__, __id__, and __reason__\.

    This hook is invoked when the connection to __id__ is lost\. Return value
    \(or thrown error\) is ignored\. *reason* is an explanatory string indicating
    why the connection was lost\. Example:

    ::comm::comm hook lost {
        global myvar
        if {$myvar(id) == $id} {
            myfunc
            return


        }
    }

## <a name='subsection10'></a>Unsupported

These interfaces may change or go away in subsequence releases\.

  - <a name='14'></a>__::comm::comm remoteid__

    Returns the *id* of the sender of the last remote command executed on this
    channel\. If used by a proc being invoked remotely, it must be called before
    any events are processed\. Otherwise, another command may get invoked and
    change the value\.

  - <a name='15'></a>__::comm::comm\_send__

    Invoking this procedure will substitute the Tk
    __[send](\.\./\.\./\.\./\.\./index\.md\#send)__ and __winfo interps__
    commands with these equivalents that use __::comm::comm__\.

    proc send {args} {
        eval ::comm::comm send $args

    }
    rename winfo tk_winfo
    proc winfo {cmd args} {
        if {![string match in* $cmd]} {
            return [eval [list tk_winfo $cmd] $args]

        }
        return [::comm::comm interps]

    }

## <a name='subsection11'></a>Security

Starting with version 4\.6 of the package an option __\-socketcmd__ is
supported, allowing the user of a comm channel to specify which command to use
when opening a socket\. Anything which is API\-compatible with the builtin
__::socket__ \(the default\) can be used\.

The envisioned main use is the specification of the __tls::socket__ command,
see package __[tls](\.\./\.\./\.\./\.\./index\.md\#tls)__, to secure the
communication\.

    # Load and initialize tls
    package require tls
    tls::init  -cafile /path/to/ca/cert -keyfile ...

    # Create secured comm channel
    ::comm::comm new SECURE -socketcmd tls::socket -listen 1
    ...

The sections [Execution Environment](#subsection6) and
[Callbacks](#subsection9) are also relevant to the security of the system,
providing means to restrict the execution to a specific environment, perform
additional authentication, and the like\.

## <a name='subsection12'></a>Blocking Semantics
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
    being computed the future will not try to deliver the result it got, but
    just destroy itself\. The future can be configured with a command to call
    when the invoker is lost\. This enables the user to implement an early abort
    of the long\-running operation, should this be supported by it\.

    An example:

    \# Procedure invoked by remote clients to run database operations\.
    proc select \{sql\} \{
        \# Signal the async generation of the result

        set future \[::comm::comm return\_async\]

        \# Generate an async db operation and tell it where to deliver the result\.

        set query \[db query \-command \[list $future return\] $sql\]

        \# Tell the database system which query to cancel if the connection
        \# goes away while it is running\.

        $future configure \-command \[list db cancel $query\]

        \# Note: The above will work without problem only if the async
        \# query will nover run its completion callback immediately, but
        \# only from the eventloop\. Because otherwise the future we wish to
        \# configure may already be gone\. If that is possible use 'catch'
        \# to prevent the error from propagating\.
        return
    \}


    The API of a future object is:

      * <a name='17'></a>__$future__ __return__ ?__\-code__ *code*? ?*value*?

        Use this method to tell the future that long\-running operation has
        completed\. Arguments are an optional return value \(defaults to the empty







|
|
|

|

|

|

|
|

|

|
|
|
|
|

<
>







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
    being computed the future will not try to deliver the result it got, but
    just destroy itself\. The future can be configured with a command to call
    when the invoker is lost\. This enables the user to implement an early abort
    of the long\-running operation, should this be supported by it\.

    An example:

    # Procedure invoked by remote clients to run database operations.
    proc select {sql} {
        # Signal the async generation of the result

        set future [::comm::comm return_async]

        # Generate an async db operation and tell it where to deliver the result.

        set query [db query -command [list $future return] $sql]

        # Tell the database system which query to cancel if the connection
        # goes away while it is running.

        $future configure -command [list db cancel $query]

        # Note: The above will work without problem only if the async
        # query will nover run its completion callback immediately, but
        # only from the eventloop. Because otherwise the future we wish to
        # configure may already be gone. If that is possible use 'catch'
        # to prevent the error from propagating.
        return

    }

    The API of a future object is:

      * <a name='17'></a>__$future__ __return__ ?__\-code__ *code*? ?*value*?

        Use this method to tell the future that long\-running operation has
        completed\. Arguments are an optional return value \(defaults to the empty
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
    being returned correctly from __comm send__\. This has been fixed by
    removing the extra level of indirection into the internal procedure
    __commSend__\. Also added propagation of the *errorCode* variable\. This
    means that these commands return exactly as they would with
    __[send](\.\./\.\./\.\./\.\./index\.md\#send)__:

    comm send id break
    catch \{comm send id break\}
    comm send id expr 1 / 0

    Added a new hook for reply messages\. Reworked method invocation to avoid the
    use of comm:\* procedures; this also cut the invocation time down by 40%\.
    Documented __comm config__ \(as this manual page still listed the defunct
    __comm init__\!\)








|







902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
    being returned correctly from __comm send__\. This has been fixed by
    removing the extra level of indirection into the internal procedure
    __commSend__\. Also added propagation of the *errorCode* variable\. This
    means that these commands return exactly as they would with
    __[send](\.\./\.\./\.\./\.\./index\.md\#send)__:

    comm send id break
    catch {comm send id break}
    comm send id expr 1 / 0

    Added a new hook for reply messages\. Reworked method invocation to avoid the
    use of comm:\* procedures; this also cut the invocation time down by 40%\.
    Documented __comm config__ \(as this manual page still listed the defunct
    __comm init__\!\)

984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init \-tls1 1 ;\# forcibly activate support for the TLS1 protocol

    \.\.\. your own application code \.\.\.

# <a name='section3'></a>Author

John LoVerso, John@LoVerso\.Southborough\.MA\.US

*http://www\.opengroup\.org/~loverso/tcl\-tk/\#comm*








|

|







984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol

    ... your own application code ...

# <a name='section3'></a>Author

John LoVerso, John@LoVerso\.Southborough\.MA\.US

*http://www\.opengroup\.org/~loverso/tcl\-tk/\#comm*

Changes to embedded/md/tcllib/files/modules/comm/comm_wire.md.

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
    __concat__enated together by the server to form the full script to
    execute on the server side\. This emulates the Tcl "eval" semantics\. In most
    cases it is best to have only one word in the list, a list containing the
    exact command\.

    Examples:

        \(a\)     \{send 1 \{\{array get tcl\_platform\}\}\}
        \(b\)     \{send 1 \{array get tcl\_platform\}\}
        \(c\)     \{send 1 \{array \{get tcl\_platform\}\}\}

        are all valid representations of the same command\. They are
        generated via

        \(a'\)    send \{array get tcl\_platform\}
        \(b'\)    send array get tcl\_platform
        \(c'\)    send array \{get tcl\_platform\}

        respectively

    Note that \(a\), generated by \(a'\), is the usual form, if only single commands
    are sent by the client\. For example constructed using
    __[list](\.\./\.\./\.\./\.\./index\.md\#list)__, if the command contains
    variable arguments\. Like

        send \[list array get $the\_variable\]

    These three instructions all invoke the script on the server side\. Their
    difference is in the treatment of result values, and thus determines if a
    reply is expected\.

      * __send__








|
|
|

|


|
|
|








|







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
    __concat__enated together by the server to form the full script to
    execute on the server side\. This emulates the Tcl "eval" semantics\. In most
    cases it is best to have only one word in the list, a list containing the
    exact command\.

    Examples:

        (a)     {send 1 {{array get tcl_platform}}}
        (b)     {send 1 {array get tcl_platform}}
        (c)     {send 1 {array {get tcl_platform}}}

        are all valid representations of the same command. They are
        generated via

        (a')    send {array get tcl_platform}
        (b')    send array get tcl_platform
        (c')    send array {get tcl_platform}

        respectively

    Note that \(a\), generated by \(a'\), is the usual form, if only single commands
    are sent by the client\. For example constructed using
    __[list](\.\./\.\./\.\./\.\./index\.md\#list)__, if the command contains
    variable arguments\. Like

        send [list array get $the_variable]

    These three instructions all invoke the script on the server side\. Their
    difference is in the treatment of result values, and thus determines if a
    reply is expected\.

      * __send__

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
    Like the previous three command, however the tcl script in the payload is
    highly restricted\. It has to be a syntactically valid Tcl
    __[return](\.\./\.\./\.\./\.\./index\.md\#return)__ command\. This contains
    result code, value, error code, and error info\.

    Examples:

        \{reply 1 \{return \-code 0 \{\}\}\}
        \{reply 1 \{return \-code 0 \{osVersion 2\.4\.21\-99\-default byteOrder littleEndian machine i686 platform unix os Linux user andreask wordSize 4\}\}\}

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *comm* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|
|







171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
    Like the previous three command, however the tcl script in the payload is
    highly restricted\. It has to be a syntactically valid Tcl
    __[return](\.\./\.\./\.\./\.\./index\.md\#return)__ command\. This contains
    result code, value, error code, and error info\.

    Examples:

        {reply 1 {return -code 0 {}}}
        {reply 1 {return -code 0 {osVersion 2.4.21-99-default byteOrder littleEndian machine i686 platform unix os Linux user andreask wordSize 4}}}

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *comm* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/control/control.md.

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
    that debugging efforts can be independently controlled module by module\.

        % package require control
        % control::control assert enabled 1
        % namespace eval one namespace import ::control::assert
        % control::control assert enabled 0
        % namespace eval two namespace import ::control::assert
        % one::assert \{1 == 0\}
        assertion failed: 1 == 0
        % two::assert \{1 == 0\}

  - <a name='3'></a>__control::do__ *body* ?*option test*?

    The __[do](\.\./\.\./\.\./\.\./index\.md\#do)__ command evaluates the script
    *body* repeatedly *until* the expression *test* becomes true or as
    long as \(*while*\) *test* is true, depending on the value of *option*
    being __until__ or __while__\. If *option* and *test* are omitted







|

|







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
    that debugging efforts can be independently controlled module by module\.

        % package require control
        % control::control assert enabled 1
        % namespace eval one namespace import ::control::assert
        % control::control assert enabled 0
        % namespace eval two namespace import ::control::assert
        % one::assert {1 == 0}
        assertion failed: 1 == 0
        % two::assert {1 == 0}

  - <a name='3'></a>__control::do__ *body* ?*option test*?

    The __[do](\.\./\.\./\.\./\.\./index\.md\#do)__ command evaluates the script
    *body* repeatedly *until* the expression *test* becomes true or as
    long as \(*while*\) *test* is true, depending on the value of *option*
    being __until__ or __while__\. If *option* and *test* are omitted
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
\-code $code__\] within one of those script arguments for any value of *$code*
other than *ok*\. In this way, the commands of the __control__ package are
limited as compared to Tcl's built\-in control flow commands \(such as __if__,
__while__, etc\.\) and those control flow commands that can be provided by
packages coded in C\. An example of this difference:

    % package require control
    % proc a \{\} \{while 1 \{return \-code error a\}\}
    % proc b \{\} \{control::do \{return \-code error b\} while 1\}
    % catch a
    1
    % catch b
    0

# <a name='section4'></a>Bugs, Ideas, Feedback








|
|







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
\-code $code__\] within one of those script arguments for any value of *$code*
other than *ok*\. In this way, the commands of the __control__ package are
limited as compared to Tcl's built\-in control flow commands \(such as __if__,
__while__, etc\.\) and those control flow commands that can be provided by
packages coded in C\. An example of this difference:

    % package require control
    % proc a {} {while 1 {return -code error a}}
    % proc b {} {control::do {return -code error b} while 1}
    % catch a
    1
    % catch b
    0

# <a name='section4'></a>Bugs, Ideas, Feedback

Changes to embedded/md/tcllib/files/modules/crc/cksum.md.

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

    Returns the checksum value and releases any resources held by this token\.
    Once this command completes the token will be invalid\. The result is a 32
    bit integer value\.

# <a name='section5'></a>EXAMPLES

    % crc::cksum "Hello, World\!"
    2609532967

    % crc::cksum \-format 0x%X "Hello, World\!"
    0x9B8A5027

    % crc::cksum \-file cksum\.tcl
    1828321145

    % set tok \[crc::CksumInit\]
    % crc::CksumUpdate $tok "Hello, "
    % crc::CksumUpdate $tok "World\!"
    % crc::CksumFinal $tok
    2609532967

# <a name='section6'></a>AUTHORS

Pat Thoyts








|


|


|


|

|







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

    Returns the checksum value and releases any resources held by this token\.
    Once this command completes the token will be invalid\. The result is a 32
    bit integer value\.

# <a name='section5'></a>EXAMPLES

    % crc::cksum "Hello, World!"
    2609532967

    % crc::cksum -format 0x%X "Hello, World!"
    0x9B8A5027

    % crc::cksum -file cksum.tcl
    1828321145

    % set tok [crc::CksumInit]
    % crc::CksumUpdate $tok "Hello, "
    % crc::CksumUpdate $tok "World!"
    % crc::CksumFinal $tok
    2609532967

# <a name='section6'></a>AUTHORS

Pat Thoyts

Changes to embedded/md/tcllib/files/modules/crc/crc16.md.

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
    flag is important when processing data from parameters\. If the binary data
    looks like one of the options given above then the data will be read as an
    option if this marker is not included\. Always use the *\-\-* option
    termination flag before giving the data argument\.

# <a name='section4'></a>EXAMPLES

    % crc::crc16 \-\- "Hello, World\!"
    64077

    % crc::crc\-ccitt \-\- "Hello, World\!"
    26586

    % crc::crc16 \-format 0x%X \-\- "Hello, World\!"
    0xFA4D

    % crc::crc16 \-file crc16\.tcl
    51675

# <a name='section5'></a>AUTHORS

Pat Thoyts

# <a name='section6'></a>Bugs, Ideas, Feedback







|


|


|


|







126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
    flag is important when processing data from parameters\. If the binary data
    looks like one of the options given above then the data will be read as an
    option if this marker is not included\. Always use the *\-\-* option
    termination flag before giving the data argument\.

# <a name='section4'></a>EXAMPLES

    % crc::crc16 -- "Hello, World!"
    64077

    % crc::crc-ccitt -- "Hello, World!"
    26586

    % crc::crc16 -format 0x%X -- "Hello, World!"
    0xFA4D

    % crc::crc16 -file crc16.tcl
    51675

# <a name='section5'></a>AUTHORS

Pat Thoyts

# <a name='section6'></a>Bugs, Ideas, Feedback

Changes to embedded/md/tcllib/files/modules/crc/crc32.md.

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

    Returns the checksum value and releases any resources held by this token\.
    Once this command completes the token will be invalid\. The result is a 32
    bit integer value\.

# <a name='section5'></a>EXAMPLES

    % crc::crc32 "Hello, World\!"
    3964322768

    % crc::crc32 \-format 0x%X "Hello, World\!"
    0xEC4AC3D0

    % crc::crc32 \-file crc32\.tcl
    483919716

    % set tok \[crc::Crc32Init\]
    % crc::Crc32Update $tok "Hello, "
    % crc::Crc32Update $tok "World\!"
    % crc::Crc32Final $tok
    3964322768

# <a name='section6'></a>AUTHORS

Pat Thoyts








|


|


|


|

|







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

    Returns the checksum value and releases any resources held by this token\.
    Once this command completes the token will be invalid\. The result is a 32
    bit integer value\.

# <a name='section5'></a>EXAMPLES

    % crc::crc32 "Hello, World!"
    3964322768

    % crc::crc32 -format 0x%X "Hello, World!"
    0xEC4AC3D0

    % crc::crc32 -file crc32.tcl
    483919716

    % set tok [crc::Crc32Init]
    % crc::Crc32Update $tok "Hello, "
    % crc::Crc32Update $tok "World!"
    % crc::Crc32Final $tok
    3964322768

# <a name='section6'></a>AUTHORS

Pat Thoyts

Changes to embedded/md/tcllib/files/modules/crc/sum.md.

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

  - \-format *string*

    Return the checksum using an alternative format template\.

# <a name='section4'></a>EXAMPLES

    % crc::sum "Hello, World\!"
    37287

    % crc::sum \-format 0x%X "Hello, World\!"
    0x91A7

    % crc::sum \-file sum\.tcl
    13392

# <a name='section5'></a>AUTHORS

Pat Thoyts

# <a name='section6'></a>Bugs, Ideas, Feedback







|


|


|







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

  - \-format *string*

    Return the checksum using an alternative format template\.

# <a name='section4'></a>EXAMPLES

    % crc::sum "Hello, World!"
    37287

    % crc::sum -format 0x%X "Hello, World!"
    0x91A7

    % crc::sum -file sum.tcl
    13392

# <a name='section5'></a>AUTHORS

Pat Thoyts

# <a name='section6'></a>Bugs, Ideas, Feedback

Changes to embedded/md/tcllib/files/modules/cron/cron.md.

79
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
    *timecode*\. If *timecode* is expressed as an integer, the timecode is
    assumed to be in unixtime\. All other inputs will be interpreted by __clock
    scan__ and converted to unix time\. This task can be modified by subsequent
    calls to this package's commands by referencing *processname*\. If
    *processname* exists, it will be replaced\. If *processname* is not
    given, one is generated and returned by the command\.

        ::cron::at start\_coffee \{Tomorrow at 9:00am\}  \{remote::exec::coffeepot power on\}
        ::cron::at shutdown\_coffee \{Tomorrow at 12:00pm\}  \{remote::exec::coffeepot power off\}

  - <a name='2'></a>__::cron::cancel__ *processname*

    This command unregisters the process *processname* and cancels any pending
    commands\. Note: processname can be a process created by either
    __::cron::at__ or __::cron::every__\.

        ::cron::cancel check\_mail

  - <a name='3'></a>__::cron::every__ *processname* *frequency* *command*

    This command registers a *command* to be called at the interval of
    *frequency*\. *frequency* is given in seconds\. This task can be modified
    by subsequent calls to this package's commands by referencing
    *processname*\. If *processname* exists, it will be replaced\.

        ::cron::every check\_mail 900  ::imap\_client::check\_mail
        ::cron::every backup\_db  3600 \{::backup\_procedure ::mydb\}

  - <a name='4'></a>__::cron::in__ *?processname?* *timecode* *command*

    This command registers a *command* to be called after a delay of time
    specified by *timecode*\. *timecode* is expressed as an seconds\. This
    task can be modified by subsequent calls to this package's commands by
    referencing *processname*\. If *processname* exists, it will be replaced\.







|
|







|








|
|







79
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
    *timecode*\. If *timecode* is expressed as an integer, the timecode is
    assumed to be in unixtime\. All other inputs will be interpreted by __clock
    scan__ and converted to unix time\. This task can be modified by subsequent
    calls to this package's commands by referencing *processname*\. If
    *processname* exists, it will be replaced\. If *processname* is not
    given, one is generated and returned by the command\.

        ::cron::at start_coffee {Tomorrow at 9:00am}  {remote::exec::coffeepot power on}
        ::cron::at shutdown_coffee {Tomorrow at 12:00pm}  {remote::exec::coffeepot power off}

  - <a name='2'></a>__::cron::cancel__ *processname*

    This command unregisters the process *processname* and cancels any pending
    commands\. Note: processname can be a process created by either
    __::cron::at__ or __::cron::every__\.

        ::cron::cancel check_mail

  - <a name='3'></a>__::cron::every__ *processname* *frequency* *command*

    This command registers a *command* to be called at the interval of
    *frequency*\. *frequency* is given in seconds\. This task can be modified
    by subsequent calls to this package's commands by referencing
    *processname*\. If *processname* exists, it will be replaced\.

        ::cron::every check_mail 900  ::imap_client::check_mail
        ::cron::every backup_db  3600 {::backup_procedure ::mydb}

  - <a name='4'></a>__::cron::in__ *?processname?* *timecode* *command*

    This command registers a *command* to be called after a delay of time
    specified by *timecode*\. *timecode* is expressed as an seconds\. This
    task can be modified by subsequent calls to this package's commands by
    referencing *processname*\. If *processname* exists, it will be replaced\.
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

    If the ::cron::time variable is > 0 this command will advance the internal
    time, 100ms at a time\.

    In all other cases this command will generate a fictious variable, generate
    an after call, and vwait the variable:

        set eventid \[incr ::cron::eventcount\]
        set var ::cron::event\_\#$eventid
        set $var 0
        ::after $ms "set $var 1"
        ::vwait $var
        ::unset $var

    Usage:








|
|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

    If the ::cron::time variable is > 0 this command will advance the internal
    time, 100ms at a time\.

    In all other cases this command will generate a fictious variable, generate
    an after call, and vwait the variable:

        set eventid [incr ::cron::eventcount]
        set var ::cron::event_#$eventid
        set $var 0
        ::after $ms "set $var 1"
        ::vwait $var
        ::unset $var

    Usage:

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
        does so\.

  - <a name='11'></a>__::cron::wake__ *?who?*

    Wake up cron, and arrange for its event loop to be run during the next Idle
    cycle\.

        ::cron::wake \{I just did something important\}

Several utility commands are provided that are used internally within cron and
for testing cron, but may or may not be useful in the general cases\.

  - <a name='12'></a>__::cron::clock\_step__ *milliseconds*

    Return a clock time absolute to the epoch which falls on the next border







|







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
        does so\.

  - <a name='11'></a>__::cron::wake__ *?who?*

    Wake up cron, and arrange for its event loop to be run during the next Idle
    cycle\.

        ::cron::wake {I just did something important}

Several utility commands are provided that are used internally within cron and
for testing cron, but may or may not be useful in the general cases\.

  - <a name='12'></a>__::cron::clock\_step__ *milliseconds*

    Return a clock time absolute to the epoch which falls on the next border

Changes to embedded/md/tcllib/files/modules/csv/csv.md.

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
The alternate format is activated through specification of the option
__\-alternate__ to the various split commands\.

# <a name='section4'></a>EXAMPLE

Using the regular format the record

    123,"123,521\.2","Mary says ""Hello, I am Mary""",""

is parsed into the items

    a\) 123
    b\) 123,521\.2
    c\) Mary says "Hello, I am Mary"
    d\) "

Using the alternate format the result is

    a\) 123
    b\) 123,521\.2
    c\) Mary says "Hello, I am Mary"
    d\) \(the empty string\)

instead\. As can be seen only item \(d\) is different, now the empty string instead
of a "\.

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and







|



|
|
|
|



|
|
|
|







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
The alternate format is activated through specification of the option
__\-alternate__ to the various split commands\.

# <a name='section4'></a>EXAMPLE

Using the regular format the record

    123,"123,521.2","Mary says ""Hello, I am Mary""",""

is parsed into the items

    a) 123
    b) 123,521.2
    c) Mary says "Hello, I am Mary"
    d) "

Using the alternate format the result is

    a) 123
    b) 123,521.2
    c) Mary says "Hello, I am Mary"
    d) (the empty string)

instead\. As can be seen only item \(d\) is different, now the empty string instead
of a "\.

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and

Changes to embedded/md/tcllib/files/modules/debug/debug.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (debug \- debug narrative)
[//000000002]: # (Generated from file 'debug\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 200?, Colin McCormack, Wub Server Utilities  
Copyright &copy; 2012\-2014, Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (debug\(n\) 1\.0\.6 tcllib "debug narrative")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (debug \- debug narrative)
[//000000002]: # (Generated from file 'debug\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 200?, Colin McCormack, Wub Server Utilities)
[//000000004]: # (Copyright &copy; 2012\-2014, Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000005]: # (debug\(n\) 1\.0\.6 tcllib "debug narrative")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

Changes to embedded/md/tcllib/files/modules/debug/debug_heartbeat.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (debug::heartbeat \- debug narrative)
[//000000002]: # (Generated from file 'debug\_heartbeat\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 200?, Colin McCormack, Wub Server Utilities  
Copyright &copy; 2012, Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (debug::heartbeat\(n\) 1 tcllib "debug narrative")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (debug::heartbeat \- debug narrative)
[//000000002]: # (Generated from file 'debug\_heartbeat\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 200?, Colin McCormack, Wub Server Utilities)
[//000000004]: # (Copyright &copy; 2012, Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000005]: # (debug::heartbeat\(n\) 1\.0\.1 tcllib "debug narrative")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require debug::heartbeat ?1?  
package require debug ?1?  

[__[debug](debug\.md)__ __heartbeat__ ?*delta*?](#1)  

# <a name='description'></a>DESCRIPTION

# <a name='section2'></a>API







|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require debug::heartbeat ?1\.0\.1?  
package require debug ?1?  

[__[debug](debug\.md)__ __heartbeat__ ?*delta*?](#1)  

# <a name='description'></a>DESCRIPTION

# <a name='section2'></a>API

Changes to embedded/md/tcllib/files/modules/debug/debug_timestamp.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (debug::timestamp \- debug narrative)
[//000000002]: # (Generated from file 'debug\_timestamp\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 200?, Colin McCormack, Wub Server Utilities  
Copyright &copy; 2012, Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (debug::timestamp\(n\) 1 tcllib "debug narrative")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (debug::timestamp \- debug narrative)
[//000000002]: # (Generated from file 'debug\_timestamp\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 200?, Colin McCormack, Wub Server Utilities)
[//000000004]: # (Copyright &copy; 2012, Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000005]: # (debug::timestamp\(n\) 1 tcllib "debug narrative")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

Changes to embedded/md/tcllib/files/modules/defer/defer.md.

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
    identifier returned by __::defer::defer__, __::defer::with__, or
    __::defer::autowith__\. Any number of arguments may be supplied, and all
    of the IDs supplied will be cancelled\.

# <a name='section3'></a>EXAMPLES

    package require defer 1
    apply \{\{\} \{
    	set fd \[open /dev/null\]
    	defer::defer close $fd
    \}\}

# <a name='section4'></a>REFERENCES

# <a name='section5'></a>AUTHORS

Roy Keene








|
|

|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
    identifier returned by __::defer::defer__, __::defer::with__, or
    __::defer::autowith__\. Any number of arguments may be supplied, and all
    of the IDs supplied will be cancelled\.

# <a name='section3'></a>EXAMPLES

    package require defer 1
    apply {{} {
    	set fd [open /dev/null]
    	defer::defer close $fd
    }}

# <a name='section4'></a>REFERENCES

# <a name='section5'></a>AUTHORS

Roy Keene

Changes to embedded/md/tcllib/files/modules/des/des.md.

167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

    OFB is similar to CFB except that the output of the cipher is fed back into
    the next round and not the xor'd plain text\. This means that errors only
    affect a single block but the cipher is more vulnerable to attack\.

# <a name='section5'></a>EXAMPLES

    % set ciphertext \[DES::des \-mode cbc \-dir encrypt \-key $secret $plaintext\]
    % set plaintext \[DES::des \-mode cbc \-dir decrypt \-key $secret $ciphertext\]

    set iv \[string repeat \\\\0 8\]
    set Key \[DES::Init cbc \\\\0\\\\1\\\\2\\\\3\\\\4\\\\5\\\\6\\\\7 $iv\]
    set ciphertext \[DES::Encrypt $Key "somedata"\]
    append ciphertext \[DES::Encrypt $Key "moredata"\]
    DES::Reset $Key $iv
    set plaintext \[DES::Decrypt $Key $ciphertext\]
    DES::Final $Key

# <a name='section6'></a>REFERENCES

  1. "Data Encryption Standard", Federal Information Processing Standards
     Publication 46\-3, 1999,
     \([http://csrc\.nist\.gov/publications/fips/fips46\-3/fips46\-3\.pdf](http://csrc\.nist\.gov/publications/fips/fips46\-3/fips46\-3\.pdf)\)







|
|

|
|
|
|

|







167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

    OFB is similar to CFB except that the output of the cipher is fed back into
    the next round and not the xor'd plain text\. This means that errors only
    affect a single block but the cipher is more vulnerable to attack\.

# <a name='section5'></a>EXAMPLES

    % set ciphertext [DES::des -mode cbc -dir encrypt -key $secret $plaintext]
    % set plaintext [DES::des -mode cbc -dir decrypt -key $secret $ciphertext]

    set iv [string repeat \\0 8]
    set Key [DES::Init cbc \\0\\1\\2\\3\\4\\5\\6\\7 $iv]
    set ciphertext [DES::Encrypt $Key "somedata"]
    append ciphertext [DES::Encrypt $Key "moredata"]
    DES::Reset $Key $iv
    set plaintext [DES::Decrypt $Key $ciphertext]
    DES::Final $Key

# <a name='section6'></a>REFERENCES

  1. "Data Encryption Standard", Federal Information Processing Standards
     Publication 46\-3, 1999,
     \([http://csrc\.nist\.gov/publications/fips/fips46\-3/fips46\-3\.pdf](http://csrc\.nist\.gov/publications/fips/fips46\-3/fips46\-3\.pdf)\)

Changes to embedded/md/tcllib/files/modules/dicttool/dicttool.md.

30
31
32
33
34
35
36

37
38
39
40
41
42
43
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  


[__ladd__ *varname* *args*](#1)  
[__ldelete__ *varname* *args*](#2)  
[__dict getnull__ *args*](#3)  
[__dict print__ *dict*](#4)  
[__dict is\_dict__ *value*](#5)  
[__rmerge__ *args*](#6)  







>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require dicttool ?1\.0?  

[__ladd__ *varname* *args*](#1)  
[__ldelete__ *varname* *args*](#2)  
[__dict getnull__ *args*](#3)  
[__dict print__ *dict*](#4)  
[__dict is\_dict__ *value*](#5)  
[__rmerge__ *args*](#6)  
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  - <a name='1'></a>__ladd__ *varname* *args*

    This command will add a new instance of each element in *args* to
    *varname*, but only if that element is not already present\.

  - <a name='2'></a>__ldelete__ *varname* *args*

    This command will add a delete all instances of each element in *args*
    from *varname*\.

  - <a name='3'></a>__dict getnull__ *args*

    Operates like __dict get__, however if the key *args* does not exist,
    it returns an empty list instead of throwing an error\.

  - <a name='4'></a>__dict print__ *dict*







|
|







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  - <a name='1'></a>__ladd__ *varname* *args*

    This command will add a new instance of each element in *args* to
    *varname*, but only if that element is not already present\.

  - <a name='2'></a>__ldelete__ *varname* *args*

    This command will delete all instances of each element in *args* from
    *varname*\.

  - <a name='3'></a>__dict getnull__ *args*

    Operates like __dict get__, however if the key *args* does not exist,
    it returns an empty list instead of throwing an error\.

  - <a name='4'></a>__dict print__ *dict*
79
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
  - <a name='6'></a>__rmerge__ *args*

    Return a dict which is the product of a recursive merge of all of the
    arguments\. Unlike __dict merge__, this command descends into all of the
    levels of a dict\. Dict keys which end in a : indicate a leaf, which will be
    interpreted as a literal value, and not descended into further\.

        set items \[dict merge \{
          option \{color \{default: green\}\}
        \} \{
          option \{fruit \{default: mango\}\}
        \} \{
          option \{color \{default: blue\} fruit \{widget: select values: \{mango apple cherry grape\}\}\}
        \}\]
        puts \[dict print $items\]

    Prints the following result:

        option \{
          color \{
            default: blue
          \}

          fruit \{
            widget: select
            values: \{mango apple cherry grape\}
          \}
        \}



# <a name='section2'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *dict* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|
|
|
|
|
|
|
|



|
|

<
>
|

|
<
<
>
>







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
  - <a name='6'></a>__rmerge__ *args*

    Return a dict which is the product of a recursive merge of all of the
    arguments\. Unlike __dict merge__, this command descends into all of the
    levels of a dict\. Dict keys which end in a : indicate a leaf, which will be
    interpreted as a literal value, and not descended into further\.

        set items [dict merge {
          option {color {default: green}}
        } {
          option {fruit {default: mango}}
        } {
          option {color {default: blue} fruit {widget: select values: {mango apple cherry grape}}}
        }]
        puts [dict print $items]

    Prints the following result:

        option {
          color {
            default: blue

          }
          fruit {
            widget: select
            values: {mango apple cherry grape}


          }
        }

# <a name='section2'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *dict* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/dns/tcllib_dns.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (dns \- Domain Name Service)
[//000000002]: # (Generated from file 'tcllib\_dns\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2002, Pat Thoyts)
[//000000004]: # (dns\(n\) 1\.4\.0 tcllib "Domain Name Service")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>




|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (dns \- Domain Name Service)
[//000000002]: # (Generated from file 'tcllib\_dns\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2002, Pat Thoyts)
[//000000004]: # (dns\(n\) 1\.4\.1 tcllib "Domain Name Service")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require dns ?1\.4\.0?  

[__::dns::resolve__ *query* ?*options*?](#1)  
[__::dns::configure__ ?*options*?](#2)  
[__::dns::name__ *token*](#3)  
[__::dns::address__ *token*](#4)  
[__::dns::cname__ *token*](#5)  
[__::dns::result__ *token*](#6)  







|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require dns ?1\.4\.1?  

[__::dns::resolve__ *query* ?*options*?](#1)  
[__::dns::configure__ ?*options*?](#2)  
[__::dns::name__ *token*](#3)  
[__::dns::address__ *token*](#4)  
[__::dns::cname__ *token*](#5)  
[__::dns::result__ *token*](#6)  
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
    users system\. On a unix machine this parses the /etc/resolv\.conf file for
    nameservers \(if it exists\) and on Windows systems we examine certain parts
    of the registry\. If no nameserver can be found then the loopback address
    \(127\.0\.0\.1\) is used as a default\.

# <a name='section3'></a>EXAMPLES

    % set tok \[dns::resolve www\.tcl\.tk\]
    ::dns::1
    % dns::status $tok
    ok
    % dns::address $tok
    199\.175\.6\.239
    % dns::name $tok
    www\.tcl\.tk
    % dns::cleanup $tok

Using DNS URIs as queries:

    % set tok \[dns::resolve "dns:tcl\.tk;type=MX"\]
    % set tok \[dns::resolve "dns://l\.root\-servers\.net/www\.tcl\.tk"\]

Reverse address lookup:

    % set tok \[dns::resolve 127\.0\.0\.1\]
    ::dns::1
    % dns::name $tok
    localhost
    % dns::cleanup $tok

Using DNS over TLS \(RFC 7858\):

    % set tok \[dns::resolve www\.tcl\.tk \-nameserver dns\-tls\.bitwiseshift\.net  \-usetls 1 \-cafile /etc/ssl/certs/ca\-certificates\.crt\]
    ::dns::12
    % dns::wait $tok
    ok
    % dns::address $tok
    104\.25\.119\.118 104\.25\.120\.118

# <a name='section4'></a>REFERENCES

  1. Mockapetris, P\., "Domain Names \- Concepts and Facilities", RFC 1034,
     November 1987\.
     \([http://www\.ietf\.org/rfc/rfc1034\.txt](http://www\.ietf\.org/rfc/rfc1034\.txt)\)








|




|

|




|
|



|







|




|







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
    users system\. On a unix machine this parses the /etc/resolv\.conf file for
    nameservers \(if it exists\) and on Windows systems we examine certain parts
    of the registry\. If no nameserver can be found then the loopback address
    \(127\.0\.0\.1\) is used as a default\.

# <a name='section3'></a>EXAMPLES

    % set tok [dns::resolve www.tcl.tk]
    ::dns::1
    % dns::status $tok
    ok
    % dns::address $tok
    199.175.6.239
    % dns::name $tok
    www.tcl.tk
    % dns::cleanup $tok

Using DNS URIs as queries:

    % set tok [dns::resolve "dns:tcl.tk;type=MX"]
    % set tok [dns::resolve "dns://l.root-servers.net/www.tcl.tk"]

Reverse address lookup:

    % set tok [dns::resolve 127.0.0.1]
    ::dns::1
    % dns::name $tok
    localhost
    % dns::cleanup $tok

Using DNS over TLS \(RFC 7858\):

    % set tok [dns::resolve www.tcl.tk -nameserver dns-tls.bitwiseshift.net  -usetls 1 -cafile /etc/ssl/certs/ca-certificates.crt]
    ::dns::12
    % dns::wait $tok
    ok
    % dns::address $tok
    104.25.119.118 104.25.120.118

# <a name='section4'></a>REFERENCES

  1. Mockapetris, P\., "Domain Names \- Concepts and Facilities", RFC 1034,
     November 1987\.
     \([http://www\.ietf\.org/rfc/rfc1034\.txt](http://www\.ietf\.org/rfc/rfc1034\.txt)\)

Changes to embedded/md/tcllib/files/modules/dns/tcllib_ip.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (tcllib\_ip \- Domain Name Service)
[//000000002]: # (Generated from file 'tcllib\_ip\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004, Pat Thoyts  
Copyright &copy; 2005 Aamer Akhter <aakhter@cisco\.com>)
[//000000004]: # (tcllib\_ip\(n\) 1\.4 tcllib "Domain Name Service")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (tcllib\_ip \- Domain Name Service)
[//000000002]: # (Generated from file 'tcllib\_ip\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004, Pat Thoyts)
[//000000004]: # (Copyright &copy; 2005 Aamer Akhter <aakhter@cisco\.com>)
[//000000005]: # (tcllib\_ip\(n\) 1\.4 tcllib "Domain Name Service")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
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
    suitable for displaying to users\.

  - <a name='6'></a>__::ip::distance__ *ipaddr1* *ipaddr2*

    This command computes the \(integer\) distance from IPv4 address *ipaddr1*
    to IPv4 address *ipaddr2*, i\.e\. "ipaddr2 \- ipaddr1"

        % ::ip::distance 1\.1\.1\.1  1\.1\.1\.5
        4

  - <a name='7'></a>__::ip::nextIp__ *ipaddr* ?*offset*?

    This command adds the integer *offset* to the IPv4 address *ipaddr* and
    returns the new IPv4 address\.

        % ::ip::distance 1\.1\.1\.1  4
        1\.1\.1\.5

  - <a name='8'></a>__::ip::prefix__ *address*

    Returns the address prefix generated by masking the address part with the
    mask if provided\. If there is no mask then it is equivalent to calling
    __normalize__

  - <a name='9'></a>__::ip::type__ *address*

  - <a name='10'></a>__::ip::mask__ *address*

    If the address supplied includes a mask then this is returned otherwise
    returns an empty string\.

  - <a name='11'></a>__::ip::prefixToNative__ *prefix*

    This command converts the string *prefix* from dotted form
    \(<ipaddr>/<mask> format\) to native \(hex\) form\. Returns a list containing two
    elements, ipaddress and mask, in this order, in hexadecimal notation\.

        % ip::prefixToNative 1\.1\.1\.0/24
        0x01010100 0xffffff00

  - <a name='12'></a>__::ip::nativeToPrefix__ *nativeList*&#124;*native* ?__\-ipv4__?

    This command converts from native \(hex\) form to dotted form\. It is the
    complement of __::ip::prefixToNative__\.

      * list *nativeList* \(in\)

        List of several ip addresses in native form\. The native form is a list
        as returned by __::ip::prefixToNative__\.

      * list *native* \(in\)

        A list as returned by __::ip::prefixToNative__\.

    The command returns a list of addresses in dotted form if it was called with
    a list of addresses\. Otherwise a single address in dotted form is returned\.

        % ip::nativeToPrefix \{0x01010100 0xffffff00\} \-ipv4
        1\.1\.1\.0/24

  - <a name='13'></a>__::ip::intToString__ *number* ?__\-ipv4__?

    This command converts from an ip address specified as integer number to
    dotted form\.

        ip::intToString 4294967295
        255\.255\.255\.255

  - <a name='14'></a>__::ip::toInteger__ *ipaddr*

    This command converts a dotted form ip into an integer number\.

        % ::ip::toInteger 1\.1\.1\.0
        16843008

  - <a name='15'></a>__::ip::toHex__ *ipaddr*

    This command converts dotted form ip into a hexadecimal number\.

        % ::ip::toHex 1\.1\.1\.0
        0x01010100

  - <a name='16'></a>__::ip::maskToInt__ *ipmask*

    This command convert an ipmask in either dotted \(255\.255\.255\.0\) form or mask
    length form \(24\) into an integer number\.

        ::ip::maskToInt 24
        4294967040

  - <a name='17'></a>__::ip::broadcastAddress__ *prefix* ?__\-ipv4__?

    This commands returns a broadcast address in dotted form for the given route
    *prefix*, either in the form "addr/mask", or in native form\. The result is
    in dotted form\.

        ::ip::broadcastAddress 1\.1\.1\.0/24
        1\.1\.1\.255

        ::ip::broadcastAddress \{0x01010100 0xffffff00\}
        0x010101ff

  - <a name='18'></a>__::ip::maskToLength__ *dottedMask*&#124;*integerMask*&#124;*hexMask* ?__\-ipv4__?

    This command converts the dotted or integer form of an ipmask to the mask
    length form\.

        ::ip::maskToLength 0xffffff00 \-ipv4
        24

        % ::ip::maskToLength 255\.255\.255\.0
        24

  - <a name='19'></a>__::ip::lengthToMask__ *maskLength* ?__\-ipv4__?

    This command converts an ipmask in mask length form to its dotted form\.

        ::ip::lengthToMask 24
        255\.255\.255\.0

  - <a name='20'></a>__::ip::nextNet__ *ipaddr* *ipmask* ?*count*? ?__\-ipv4__?

    This command returns an ipaddress in the same position in the *count* next
    network\. The default value for *count* is __1__\.

    The address can be specified as either integer number or in dotted form\. The
    mask can be specified as either integer number, dotted form, or mask length
    form\.

    The result is in hex form\.

  - <a name='21'></a>__::ip::isOverlap__ *prefix* *prefix*\.\.\.

    This command checks if the given ip prefixes overlap\. All arguments are in
    dotted "addr/mask" form\. All arguments after the first prefix are compared
    against the first prefix\. The result is a boolean value\. It is true if an
    overlap was found for any of the prefixes\.

        % ::ip::isOverlap 1\.1\.1\.0/24 2\.1\.0\.1/32
        0

        ::ip::isOverlap 1\.1\.1\.0/24 2\.1\.0\.1/32 1\.1\.1\.1/32
        1

  - <a name='22'></a>__::ip::isOverlapNative__ ?__\-all__? ?__\-inline__? ?__\-ipv4__? *hexipaddr* *hexipmask* *hexiplist*

    This command is similar to __::ip::isOverlap__, however the arguments
    are in the native form, and the form of the result is under greater control
    of the caller\. If the option __\-all__ is specified it checks all







|







|
|




















|



















|
|







|





|






|
















|
|

|







|


|







|



















|


|







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
    suitable for displaying to users\.

  - <a name='6'></a>__::ip::distance__ *ipaddr1* *ipaddr2*

    This command computes the \(integer\) distance from IPv4 address *ipaddr1*
    to IPv4 address *ipaddr2*, i\.e\. "ipaddr2 \- ipaddr1"

        % ::ip::distance 1.1.1.1  1.1.1.5
        4

  - <a name='7'></a>__::ip::nextIp__ *ipaddr* ?*offset*?

    This command adds the integer *offset* to the IPv4 address *ipaddr* and
    returns the new IPv4 address\.

        % ::ip::distance 1.1.1.1  4
        1.1.1.5

  - <a name='8'></a>__::ip::prefix__ *address*

    Returns the address prefix generated by masking the address part with the
    mask if provided\. If there is no mask then it is equivalent to calling
    __normalize__

  - <a name='9'></a>__::ip::type__ *address*

  - <a name='10'></a>__::ip::mask__ *address*

    If the address supplied includes a mask then this is returned otherwise
    returns an empty string\.

  - <a name='11'></a>__::ip::prefixToNative__ *prefix*

    This command converts the string *prefix* from dotted form
    \(<ipaddr>/<mask> format\) to native \(hex\) form\. Returns a list containing two
    elements, ipaddress and mask, in this order, in hexadecimal notation\.

        % ip::prefixToNative 1.1.1.0/24
        0x01010100 0xffffff00

  - <a name='12'></a>__::ip::nativeToPrefix__ *nativeList*&#124;*native* ?__\-ipv4__?

    This command converts from native \(hex\) form to dotted form\. It is the
    complement of __::ip::prefixToNative__\.

      * list *nativeList* \(in\)

        List of several ip addresses in native form\. The native form is a list
        as returned by __::ip::prefixToNative__\.

      * list *native* \(in\)

        A list as returned by __::ip::prefixToNative__\.

    The command returns a list of addresses in dotted form if it was called with
    a list of addresses\. Otherwise a single address in dotted form is returned\.

        % ip::nativeToPrefix {0x01010100 0xffffff00} -ipv4
        1.1.1.0/24

  - <a name='13'></a>__::ip::intToString__ *number* ?__\-ipv4__?

    This command converts from an ip address specified as integer number to
    dotted form\.

        ip::intToString 4294967295
        255.255.255.255

  - <a name='14'></a>__::ip::toInteger__ *ipaddr*

    This command converts a dotted form ip into an integer number\.

        % ::ip::toInteger 1.1.1.0
        16843008

  - <a name='15'></a>__::ip::toHex__ *ipaddr*

    This command converts dotted form ip into a hexadecimal number\.

        % ::ip::toHex 1.1.1.0
        0x01010100

  - <a name='16'></a>__::ip::maskToInt__ *ipmask*

    This command convert an ipmask in either dotted \(255\.255\.255\.0\) form or mask
    length form \(24\) into an integer number\.

        ::ip::maskToInt 24
        4294967040

  - <a name='17'></a>__::ip::broadcastAddress__ *prefix* ?__\-ipv4__?

    This commands returns a broadcast address in dotted form for the given route
    *prefix*, either in the form "addr/mask", or in native form\. The result is
    in dotted form\.

        ::ip::broadcastAddress 1.1.1.0/24
        1.1.1.255

        ::ip::broadcastAddress {0x01010100 0xffffff00}
        0x010101ff

  - <a name='18'></a>__::ip::maskToLength__ *dottedMask*&#124;*integerMask*&#124;*hexMask* ?__\-ipv4__?

    This command converts the dotted or integer form of an ipmask to the mask
    length form\.

        ::ip::maskToLength 0xffffff00 -ipv4
        24

        % ::ip::maskToLength 255.255.255.0
        24

  - <a name='19'></a>__::ip::lengthToMask__ *maskLength* ?__\-ipv4__?

    This command converts an ipmask in mask length form to its dotted form\.

        ::ip::lengthToMask 24
        255.255.255.0

  - <a name='20'></a>__::ip::nextNet__ *ipaddr* *ipmask* ?*count*? ?__\-ipv4__?

    This command returns an ipaddress in the same position in the *count* next
    network\. The default value for *count* is __1__\.

    The address can be specified as either integer number or in dotted form\. The
    mask can be specified as either integer number, dotted form, or mask length
    form\.

    The result is in hex form\.

  - <a name='21'></a>__::ip::isOverlap__ *prefix* *prefix*\.\.\.

    This command checks if the given ip prefixes overlap\. All arguments are in
    dotted "addr/mask" form\. All arguments after the first prefix are compared
    against the first prefix\. The result is a boolean value\. It is true if an
    overlap was found for any of the prefixes\.

        % ::ip::isOverlap 1.1.1.0/24 2.1.0.1/32
        0

        ::ip::isOverlap 1.1.1.0/24 2.1.0.1/32 1.1.1.1/32
        1

  - <a name='22'></a>__::ip::isOverlapNative__ ?__\-all__? ?__\-inline__? ?__\-ipv4__? *hexipaddr* *hexipmask* *hexiplist*

    This command is similar to __::ip::isOverlap__, however the arguments
    are in the native form, and the form of the result is under greater control
    of the caller\. If the option __\-all__ is specified it checks all
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
        The first overlapping prefix, or an empoty string if there is none\.

      * \-all \-inline

        A list containing the prefixes of all overlaps found, or an empty list
        if there are none\.

        % ::ip::isOverlapNative 0x01010100 0xffffff00 \{\{0x02010001 0xffffffff\}\}
        0

        % ::ip::isOverlapNative 0x01010100 0xffffff00 \{\{0x02010001 0xffffffff\} \{0x01010101 0xffffffff\}\}
        2

  - <a name='23'></a>__::ip::ipToLayer2Multicast__ *ipaddr*

    This command an converts ipv4 address in dotted form into a layer 2
    multicast address, also in dotted form\.

        % ::ip::ipToLayer2Multicast 224\.0\.0\.2
        01\.00\.5e\.00\.00\.02

  - <a name='24'></a>__::ip::ipHostFromPrefix__ *prefix* ?__\-exclude__ *prefixExcludeList*?

    This command returns a host address from a prefix in the form
    "ipaddr/masklen", also making sure that the result is not an address found
    in the *prefixExcludeList*\. The result is an ip address in dotted form\.

        %::ip::ipHostFromPrefix  1\.1\.1\.5/24
        1\.1\.1\.1

        %::ip::ipHostFromPrefix  1\.1\.1\.1/32
        1\.1\.1\.1

  - <a name='25'></a>__::ip::reduceToAggregates__ *prefixlist*

    This command finds nets that overlap and filters out the more specific nets\.
    The prefixes are in either addr/mask form or in native format\. The result is
    a list containing the non\-overlapping ip prefixes from the input\.

        % ::ip::reduceToAggregates \{1\.1\.1\.0/24 1\.1\.0\.0/8  2\.1\.1\.0/24 1\.1\.1\.1/32 \}
        1\.0\.0\.0/8 2\.1\.1\.0/24

  - <a name='26'></a>__::ip::longestPrefixMatch__ *ipaddr* *prefixlist* ?__\-ipv4__?

    This command finds longest prefix match from set of prefixes, given a
    specific host address\. The prefixes in the list are in either native or
    dotted form, whereas the host address is in either ipprefix format, dotted
    form, or integer form\. The result is the prefix which is the most specific
    match to the host address\.

        % ::ip::longestPrefixMatch 1\.1\.1\.1 \{1\.1\.1\.0/24 1\.0\.0\.0/8  2\.1\.1\.0/24 1\.1\.1\.0/28 \}
        1\.1\.1\.0/28

  - <a name='27'></a>__::ip::collapse__ *prefixlist*

    This commands takes a list of prefixes and returns a list prefixes with the
    largest possible subnet masks covering the input, in this manner collapsing
    adjacent prefixes into larger ranges\.

    This is different from __::ip::reduceToAggregates__ in that the latter
    only removes specific nets from a list when they are covered by other
    elements of the input whereas this command actively merges nets into larger
    ranges when they are adjacent to each other\.

        % ::ip::collapse \{1\.2\.2\.0/24 1\.2\.3\.0/24\}
        1\.2\.2\.0/23

  - <a name='28'></a>__::ip::subtract__ *prefixlist*

    This command takes a list of prefixes, some of which are prefixed by a dash\.
    These latter *negative* prefixes are used to punch holes into the ranges
    described by the other, *positive*, prefixes\. I\.e\. the negative prefixes
    are subtracted frrom the positive ones, resulting in a larger list of
    describes describing the covered ranges only as positives\.

# <a name='section3'></a>EXAMPLES

    % ip::version ::1
    6
    % ip::version 127\.0\.0\.1
    4

    % ip::normalize 127/8
    127\.0\.0\.0/8
    % ip::contract 192\.168\.0\.0
    192\.168
    %
    % ip::normalize fec0::1
    fec0:0000:0000:0000:0000:0000:0000:0001
    % ip::contract fec0:0000:0000:0000:0000:0000:0000:0001
    fec0::1

    % ip::equal 192\.168\.0\.4/16 192\.168\.0\.0/16
    1
    % ip::equal fec0::1/10 fec0::fe01/10
    1

# <a name='section4'></a>REFERENCES

  1. Postel, J\. "Internet Protocol\." RFC 791, September 1981,







|


|







|
|







|
|

|
|







|
|









|
|












|
|













|



|
|
|






|







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
        The first overlapping prefix, or an empoty string if there is none\.

      * \-all \-inline

        A list containing the prefixes of all overlaps found, or an empty list
        if there are none\.

        % ::ip::isOverlapNative 0x01010100 0xffffff00 {{0x02010001 0xffffffff}}
        0

        % ::ip::isOverlapNative 0x01010100 0xffffff00 {{0x02010001 0xffffffff} {0x01010101 0xffffffff}}
        2

  - <a name='23'></a>__::ip::ipToLayer2Multicast__ *ipaddr*

    This command an converts ipv4 address in dotted form into a layer 2
    multicast address, also in dotted form\.

        % ::ip::ipToLayer2Multicast 224.0.0.2
        01.00.5e.00.00.02

  - <a name='24'></a>__::ip::ipHostFromPrefix__ *prefix* ?__\-exclude__ *prefixExcludeList*?

    This command returns a host address from a prefix in the form
    "ipaddr/masklen", also making sure that the result is not an address found
    in the *prefixExcludeList*\. The result is an ip address in dotted form\.

        %::ip::ipHostFromPrefix  1.1.1.5/24
        1.1.1.1

        %::ip::ipHostFromPrefix  1.1.1.1/32
        1.1.1.1

  - <a name='25'></a>__::ip::reduceToAggregates__ *prefixlist*

    This command finds nets that overlap and filters out the more specific nets\.
    The prefixes are in either addr/mask form or in native format\. The result is
    a list containing the non\-overlapping ip prefixes from the input\.

        % ::ip::reduceToAggregates {1.1.1.0/24 1.1.0.0/8  2.1.1.0/24 1.1.1.1/32 }
        1.0.0.0/8 2.1.1.0/24

  - <a name='26'></a>__::ip::longestPrefixMatch__ *ipaddr* *prefixlist* ?__\-ipv4__?

    This command finds longest prefix match from set of prefixes, given a
    specific host address\. The prefixes in the list are in either native or
    dotted form, whereas the host address is in either ipprefix format, dotted
    form, or integer form\. The result is the prefix which is the most specific
    match to the host address\.

        % ::ip::longestPrefixMatch 1.1.1.1 {1.1.1.0/24 1.0.0.0/8  2.1.1.0/24 1.1.1.0/28 }
        1.1.1.0/28

  - <a name='27'></a>__::ip::collapse__ *prefixlist*

    This commands takes a list of prefixes and returns a list prefixes with the
    largest possible subnet masks covering the input, in this manner collapsing
    adjacent prefixes into larger ranges\.

    This is different from __::ip::reduceToAggregates__ in that the latter
    only removes specific nets from a list when they are covered by other
    elements of the input whereas this command actively merges nets into larger
    ranges when they are adjacent to each other\.

        % ::ip::collapse {1.2.2.0/24 1.2.3.0/24}
        1.2.2.0/23

  - <a name='28'></a>__::ip::subtract__ *prefixlist*

    This command takes a list of prefixes, some of which are prefixed by a dash\.
    These latter *negative* prefixes are used to punch holes into the ranges
    described by the other, *positive*, prefixes\. I\.e\. the negative prefixes
    are subtracted frrom the positive ones, resulting in a larger list of
    describes describing the covered ranges only as positives\.

# <a name='section3'></a>EXAMPLES

    % ip::version ::1
    6
    % ip::version 127.0.0.1
    4

    % ip::normalize 127/8
    127.0.0.0/8
    % ip::contract 192.168.0.0
    192.168
    %
    % ip::normalize fec0::1
    fec0:0000:0000:0000:0000:0000:0000:0001
    % ip::contract fec0:0000:0000:0000:0000:0000:0000:0001
    fec0::1

    % ip::equal 192.168.0.4/16 192.168.0.0/16
    1
    % ip::equal fec0::1/10 fec0::fe01/10
    1

# <a name='section4'></a>REFERENCES

  1. Postel, J\. "Internet Protocol\." RFC 791, September 1981,

Changes to embedded/md/tcllib/files/modules/docstrip/docstrip.md.

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

The basic unit __docstrip__ operates on are the *lines* of a master source
file\. Extraction consists of selecting some of these lines to be copied from
input text to output text\. The basic distinction is that between *code lines*
\(which are copied and do not begin with a percent character\) and *comment
lines* \(which begin with a percent character and are not copied\)\.

    docstrip::extract \[join \{
      \{% comment\}
      \{% more comment \!"\#$%&/\(\}
      \{some command\}
      \{ % blah $blah "Not a comment\."\}
      \{% abc; this is comment\}
      \{\# def; this is code\}
      \{ghi\}
      \{% jkl\}
    \} \\n\] \{\}

returns the same sequence of lines as

    join \{
      \{some command\}
      \{ % blah $blah "Not a comment\."\}
      \{\# def; this is code\}
      \{ghi\} ""
    \} \\n

It does not matter to __docstrip__ what format is used for the documentation
in the comment lines, but in order to do better than plain text comments, one
typically uses some markup language\. Most commonly LaTeX is used, as that is a
very established standard and also provides the best support for mathematical
formulae, but the __docstrip::util__ package also gives some support for
*[doctools](\.\./\.\./\.\./\.\./index\.md\#doctools)*\-like markup\.







|
|
|
|
|
|
|
|
|
|



|
|
|
|
|
|







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

The basic unit __docstrip__ operates on are the *lines* of a master source
file\. Extraction consists of selecting some of these lines to be copied from
input text to output text\. The basic distinction is that between *code lines*
\(which are copied and do not begin with a percent character\) and *comment
lines* \(which begin with a percent character and are not copied\)\.

    docstrip::extract [join {
      {% comment}
      {% more comment !"#$%&/(}
      {some command}
      { % blah $blah "Not a comment."}
      {% abc; this is comment}
      {# def; this is code}
      {ghi}
      {% jkl}
    } \n] {}

returns the same sequence of lines as

    join {
      {some command}
      { % blah $blah "Not a comment."}
      {# def; this is code}
      {ghi} ""
    } \n

It does not matter to __docstrip__ what format is used for the documentation
in the comment lines, but in order to do better than plain text comments, one
typically uses some markup language\. Most commonly LaTeX is used, as that is a
very established standard and also provides the best support for mathematical
formulae, but the __docstrip::util__ package also gives some support for
*[doctools](\.\./\.\./\.\./\.\./index\.md\#doctools)*\-like markup\.
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
line is one of

    '%' '<' STARSLASH EXPRESSION '>'
    '%' '<' PLUSMINUS EXPRESSION '>' CODE

where

    STARSLASH  ::=  '\*' &#124; '/'
    PLUSMINUS  ::=  &#124; '\+' &#124; '\-'
    EXPRESSION ::= SECONDARY &#124; SECONDARY ',' EXPRESSION
                 &#124; SECONDARY '&#124;' EXPRESSION
    SECONDARY  ::= PRIMARY &#124; PRIMARY '&' SECONDARY
    PRIMARY    ::= TERMINAL &#124; '\!' PRIMARY &#124; '\(' EXPRESSION '\)'
    CODE       ::= \{ any character except end\-of\-line \}

Comma and vertical bar both denote 'or'\. Ampersand denotes 'and'\. Exclamation
mark denotes 'not'\. A TERMINAL can be any nonempty string of characters not
containing '>', '&', '&#124;', comma, '\(', or '\)', although the __docstrip__
manual is a bit restrictive and only guarantees proper operation for strings of
letters \(although even the LaTeX core sources make heavy use also of digits in
TERMINALs\)\. The second argument of __docstrip::extract__ is the list of
those TERMINALs that should count as having the value 'true'; all other
TERMINALs count as being 'false' when guard expressions are evaluated\.

In the case of a '%<\**EXPRESSION*>' guard, the lines guarded are all lines up
to the next '%</*EXPRESSION*>' guard with the same *EXPRESSION* \(compared as
strings\)\. The blocks of code delimited by such '\*' and '/' guard lines must be
properly nested\.

    set text \[join \{
       \{begin\}
       \{%<\*foo>\}
       \{1\}
       \{%<\*bar>\}
       \{2\}
       \{%</bar>\}
       \{%<\*\!bar>\}
       \{3\}
       \{%</\!bar>\}
       \{4\}
       \{%</foo>\}
       \{5\}
       \{%<\*bar>\}
       \{6\}
       \{%</bar>\}
       \{end\}
    \} \\n\]
    set res \[docstrip::extract $text foo\]
    append res \[docstrip::extract $text \{foo bar\}\]
    append res \[docstrip::extract $text bar\]

sets $res to the result of

    join \{
       \{begin\}
       \{1\}
       \{3\}
       \{4\}
       \{5\}
       \{end\}
       \{begin\}
       \{1\}
       \{2\}
       \{4\}
       \{5\}
       \{6\}
       \{end\}
       \{begin\}
       \{5\}
       \{6\}
       \{end\} ""
    \} \\n

In guard lines without a '\*', '/', '\+', or '\-' modifier after the '%<', the
guard applies only to the CODE following the '>' on that single line\. A '\+'
modifier is equivalent to no modifier\. A '\-' modifier is like the case with no
modifier, but the expression is implicitly negated, i\.e\., the CODE of a '%<\-'
guard line is only included if the expression evaluates to false\.

Metacomment lines are "comment lines which should not be stripped away", but be
extracted like code lines; these are sometimes used for copyright notices and
similar material\. The '%%' prefix is however not kept, but substituted by the
current __\-metaprefix__, which is customarily set to some "comment until end
of line" character \(or character sequence\) of the language of the code being
extracted\.

    set text \[join \{
       \{begin\}
       \{%<foo> foo\}
       \{%<\+foo>plusfoo\}
       \{%<\-foo>minusfoo\}
       \{middle\}
       \{%% some metacomment\}
       \{%<\*foo>\}
       \{%%another metacomment\}
       \{%</foo>\}
       \{end\}
    \} \\n\]
    set res \[docstrip::extract $text foo \-metaprefix \{\# \}\]
    append res \[docstrip::extract $text bar \-metaprefix \{\#\}\]

sets $res to the result of

    join \{
       \{begin\}
       \{ foo\}
       \{plusfoo\}
       \{middle\}
       \{\#  some metacomment\}
       \{\# another metacomment\}
       \{end\}
       \{begin\}
       \{minusfoo\}
       \{middle\}
       \{\# some metacomment\}
       \{end\} ""
    \} \\n

Verbatim guards can be used to force code line interpretation of a block of
lines even if some of them happen to look like any other type of lines to
docstrip\. A verbatim guard has the form '%<<*END\-TAG*' and the verbatim block
is terminated by the first line that is exactly '%*END\-TAG*'\.

    set text \[join \{
       \{begin\}
       \{%<\*myblock>\}
       \{some stupid\(\)\}
       \{   \#computer<program>\}
       \{%<<QQQ\-98765\}
       \{% These three lines are copied verbatim \(including percents\}
       \{%% even if \-metaprefix is something different than %%\)\.\}
       \{%</myblock>\}
       \{%QQQ\-98765\}
       \{   using\*strange@programming<language>\}
       \{%</myblock>\}
       \{end\}
    \} \\n\]
    set res \[docstrip::extract $text myblock \-metaprefix \{\# \}\]
    append res \[docstrip::extract $text \{\}\]

sets $res to the result of

    join \{
       \{begin\}
       \{some stupid\(\)\}
       \{   \#computer<program>\}
       \{% These three lines are copied verbatim \(including percents\}
       \{%% even if \-metaprefix is something different than %%\)\.\}
       \{%</myblock>\}
       \{   using\*strange@programming<language>\}
       \{end\}
       \{begin\}
       \{end\} ""
    \} \\n

The processing of verbatim guards takes place also inside blocks of lines which
due to some outer block guard will not be copied\.

The final piece of __docstrip__ syntax is that extraction stops at a line
that is exactly "\\endinput"; this is often used to avoid copying random
whitespace at the end of a file\. In the unlikely case that one wants such a code







|
|
|
|
|
|
|















|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|



|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|














|
|
|
|
|
|
|
|
|
|
|
|
|
|



|
|
|
|
|
|
|
|
|
|
|
|
|
|






|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|



|
|
|
|
|
|
|
|
|
|
|
|







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
line is one of

    '%' '<' STARSLASH EXPRESSION '>'
    '%' '<' PLUSMINUS EXPRESSION '>' CODE

where

    STARSLASH  ::=  '*' | '/'
    PLUSMINUS  ::=  | '+' | '-'
    EXPRESSION ::= SECONDARY | SECONDARY ',' EXPRESSION
                 | SECONDARY '|' EXPRESSION
    SECONDARY  ::= PRIMARY | PRIMARY '&' SECONDARY
    PRIMARY    ::= TERMINAL | '!' PRIMARY | '(' EXPRESSION ')'
    CODE       ::= { any character except end-of-line }

Comma and vertical bar both denote 'or'\. Ampersand denotes 'and'\. Exclamation
mark denotes 'not'\. A TERMINAL can be any nonempty string of characters not
containing '>', '&', '&#124;', comma, '\(', or '\)', although the __docstrip__
manual is a bit restrictive and only guarantees proper operation for strings of
letters \(although even the LaTeX core sources make heavy use also of digits in
TERMINALs\)\. The second argument of __docstrip::extract__ is the list of
those TERMINALs that should count as having the value 'true'; all other
TERMINALs count as being 'false' when guard expressions are evaluated\.

In the case of a '%<\**EXPRESSION*>' guard, the lines guarded are all lines up
to the next '%</*EXPRESSION*>' guard with the same *EXPRESSION* \(compared as
strings\)\. The blocks of code delimited by such '\*' and '/' guard lines must be
properly nested\.

    set text [join {
       {begin}
       {%<*foo>}
       {1}
       {%<*bar>}
       {2}
       {%</bar>}
       {%<*!bar>}
       {3}
       {%</!bar>}
       {4}
       {%</foo>}
       {5}
       {%<*bar>}
       {6}
       {%</bar>}
       {end}
    } \n]
    set res [docstrip::extract $text foo]
    append res [docstrip::extract $text {foo bar}]
    append res [docstrip::extract $text bar]

sets $res to the result of

    join {
       {begin}
       {1}
       {3}
       {4}
       {5}
       {end}
       {begin}
       {1}
       {2}
       {4}
       {5}
       {6}
       {end}
       {begin}
       {5}
       {6}
       {end} ""
    } \n

In guard lines without a '\*', '/', '\+', or '\-' modifier after the '%<', the
guard applies only to the CODE following the '>' on that single line\. A '\+'
modifier is equivalent to no modifier\. A '\-' modifier is like the case with no
modifier, but the expression is implicitly negated, i\.e\., the CODE of a '%<\-'
guard line is only included if the expression evaluates to false\.

Metacomment lines are "comment lines which should not be stripped away", but be
extracted like code lines; these are sometimes used for copyright notices and
similar material\. The '%%' prefix is however not kept, but substituted by the
current __\-metaprefix__, which is customarily set to some "comment until end
of line" character \(or character sequence\) of the language of the code being
extracted\.

    set text [join {
       {begin}
       {%<foo> foo}
       {%<+foo>plusfoo}
       {%<-foo>minusfoo}
       {middle}
       {%% some metacomment}
       {%<*foo>}
       {%%another metacomment}
       {%</foo>}
       {end}
    } \n]
    set res [docstrip::extract $text foo -metaprefix {# }]
    append res [docstrip::extract $text bar -metaprefix {#}]

sets $res to the result of

    join {
       {begin}
       { foo}
       {plusfoo}
       {middle}
       {#  some metacomment}
       {# another metacomment}
       {end}
       {begin}
       {minusfoo}
       {middle}
       {# some metacomment}
       {end} ""
    } \n

Verbatim guards can be used to force code line interpretation of a block of
lines even if some of them happen to look like any other type of lines to
docstrip\. A verbatim guard has the form '%<<*END\-TAG*' and the verbatim block
is terminated by the first line that is exactly '%*END\-TAG*'\.

    set text [join {
       {begin}
       {%<*myblock>}
       {some stupid()}
       {   #computer<program>}
       {%<<QQQ-98765}
       {% These three lines are copied verbatim (including percents}
       {%% even if -metaprefix is something different than %%).}
       {%</myblock>}
       {%QQQ-98765}
       {   using*strange@programming<language>}
       {%</myblock>}
       {end}
    } \n]
    set res [docstrip::extract $text myblock -metaprefix {# }]
    append res [docstrip::extract $text {}]

sets $res to the result of

    join {
       {begin}
       {some stupid()}
       {   #computer<program>}
       {% These three lines are copied verbatim (including percents}
       {%% even if -metaprefix is something different than %%).}
       {%</myblock>}
       {   using*strange@programming<language>}
       {end}
       {begin}
       {end} ""
    } \n

The processing of verbatim guards takes place also inside blocks of lines which
due to some outer block guard will not be copied\.

The final piece of __docstrip__ syntax is that extraction stops at a line
that is exactly "\\endinput"; this is often used to avoid copying random
whitespace at the end of a file\. In the unlikely case that one wants such a code
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
that files employing that document format are given the suffix "\.ddt", to
distinguish them from the more traditional LaTeX\-based "\.dtx" files\.

Master source files with "\.dtx" extension are usually set up so that they can be
typeset directly by __[latex](\.\./\.\./\.\./\.\./index\.md\#latex)__ without any
support from other files\. This is achieved by beginning the file with the lines

    % \\iffalse
    %<\*driver>
    \\documentclass\{tclldoc\}
    \\begin\{document\}
    \\DocInput\{*filename\.dtx*\}
    \\end\{document\}
    %</driver>
    % \\fi

or some variation thereof\. The trick is that the file gets read twice\. With
normal LaTeX reading rules, the first two lines are comments and therefore
ignored\. The third line is the document preamble, the fourth line begins the
document body, and the sixth line ends the document, so LaTeX stops there —
non\-comments below that point in the file are never subjected to the normal
LaTeX reading rules\. Before that, however, the \\DocInput command on the fifth







|
|
|
|
|
|
|
|







391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
that files employing that document format are given the suffix "\.ddt", to
distinguish them from the more traditional LaTeX\-based "\.dtx" files\.

Master source files with "\.dtx" extension are usually set up so that they can be
typeset directly by __[latex](\.\./\.\./\.\./\.\./index\.md\#latex)__ without any
support from other files\. This is achieved by beginning the file with the lines

> &nbsp;&nbsp;&nbsp;% \\iffalse  
> &nbsp;&nbsp;&nbsp;%<\*driver>  
> &nbsp;&nbsp;&nbsp;\\documentclass\{tclldoc\}  
> &nbsp;&nbsp;&nbsp;\\begin\{document\}  
> &nbsp;&nbsp;&nbsp;\\DocInput\{*filename\.dtx*\}  
> &nbsp;&nbsp;&nbsp;\\end\{document\}  
> &nbsp;&nbsp;&nbsp;%</driver>  
> &nbsp;&nbsp;&nbsp;% \\fi

or some variation thereof\. The trick is that the file gets read twice\. With
normal LaTeX reading rules, the first two lines are comments and therefore
ignored\. The third line is the document preamble, the fourth line begins the
document body, and the sixth line ends the document, so LaTeX stops there —
non\-comments below that point in the file are never subjected to the normal
LaTeX reading rules\. Before that, however, the \\DocInput command on the fifth

Changes to embedded/md/tcllib/files/modules/docstrip/docstrip_util.md.

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
terminal '__docstrip\.tcl::catalogue__'\. This supports both the style of
collecting all catalogue lines in one place and the style of putting each
catalogue line in close proximity of the code that it declares\.

Putting catalogue entries next to the code they declare may look as follows

    %    First there's the catalogue entry
    %    \\begin\{tcl\}
    %<docstrip\.tcl::catalogue>pkgProvide foo::bar 1\.0 \{foobar load\}
    %    \\end\{tcl\}
    %    second a metacomment used to include a copyright message
    %    \\begin\{macrocode\}
    %<\*foobar>
    %% This file is placed in the public domain\.
    %    \\end\{macrocode\}
    %    third the package implementation
    %    \\begin\{tcl\}
    namespace eval foo::bar \{
       \# \.\.\. some clever piece of Tcl code elided \.\.\.
    %    \\end\{tcl\}
    %    which at some point may have variant code to make use of a
    %    &#124;load&#124;able extension
    %    \\begin\{tcl\}
    %<\*load>
       load \[file rootname \[info script\]\]\[info sharedlibextension\]
    %</load>
    %<\*\!load>
       \# \.\.\. even more clever scripted counterpart of the extension
       \# also elided \.\.\.
    %</\!load>
    \}

    %</foobar>
    %    \\end\{tcl\}
    %    and that's it\!

The corresponding set\-up with __pkgIndex__ would be

    %    First there's the catalogue entry
    %    \\begin\{tcl\}
    %<docstrip\.tcl::catalogue>pkgIndex foobar load
    %    \\end\{tcl\}
    %    second a metacomment used to include a copyright message
    %    \\begin\{tcl\}
    %<\*foobar>
    %% This file is placed in the public domain\.
    %    \\end\{tcl\}
    %    third the package implementation
    %    \\begin\{tcl\}
    package provide foo::bar 1\.0
    namespace eval foo::bar \{
       \# \.\.\. some clever piece of Tcl code elided \.\.\.
    %    \\end\{tcl\}
    %    which at some point may have variant code to make use of a
    %    &#124;load&#124;able extension
    %    \\begin\{tcl\}
    %<\*load>
       load \[file rootname \[info script\]\]\[info sharedlibextension\]
    %</load>
    %<\*\!load>
       \# \.\.\. even more clever scripted counterpart of the extension
       \# also elided \.\.\.
    %</\!load>
    \}

    %</foobar>
    %    \\end\{tcl\}
    %    and that's it\!

  - <a name='4'></a>__docstrip::util::index\_from\_catalogue__ *dir* *pattern* ?*option* *value* \.\.\.?

    This command is a sibling of the standard __pkg\_mkIndex__ command, in
    that it adds package entries to "pkgIndex\.tcl" files\. The difference is that
    it indexes __[docstrip](docstrip\.md)__\-style source files rather
    than raw "\.tcl" or loadable library files\. Only packages listed in the







|
|
|

|
|
|
|

|
|
|
|

|
|
|
|

|
|
|
|
<
>

|
|




|
|
|

|
|
|
|

|
|
|
|
|

|
|
|
|

|
|
|
|
<
>

|
|







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
terminal '__docstrip\.tcl::catalogue__'\. This supports both the style of
collecting all catalogue lines in one place and the style of putting each
catalogue line in close proximity of the code that it declares\.

Putting catalogue entries next to the code they declare may look as follows

    %    First there's the catalogue entry
    %    \begin{tcl}
    %<docstrip.tcl::catalogue>pkgProvide foo::bar 1.0 {foobar load}
    %    \end{tcl}
    %    second a metacomment used to include a copyright message
    %    \begin{macrocode}
    %<*foobar>
    %% This file is placed in the public domain.
    %    \end{macrocode}
    %    third the package implementation
    %    \begin{tcl}
    namespace eval foo::bar {
       # ... some clever piece of Tcl code elided ...
    %    \end{tcl}
    %    which at some point may have variant code to make use of a
    %    |load|able extension
    %    \begin{tcl}
    %<*load>
       load [file rootname [info script]][info sharedlibextension]
    %</load>
    %<*!load>
       # ... even more clever scripted counterpart of the extension
       # also elided ...
    %</!load>

    }
    %</foobar>
    %    \end{tcl}
    %    and that's it!

The corresponding set\-up with __pkgIndex__ would be

    %    First there's the catalogue entry
    %    \begin{tcl}
    %<docstrip.tcl::catalogue>pkgIndex foobar load
    %    \end{tcl}
    %    second a metacomment used to include a copyright message
    %    \begin{tcl}
    %<*foobar>
    %% This file is placed in the public domain.
    %    \end{tcl}
    %    third the package implementation
    %    \begin{tcl}
    package provide foo::bar 1.0
    namespace eval foo::bar {
       # ... some clever piece of Tcl code elided ...
    %    \end{tcl}
    %    which at some point may have variant code to make use of a
    %    |load|able extension
    %    \begin{tcl}
    %<*load>
       load [file rootname [info script]][info sharedlibextension]
    %</load>
    %<*!load>
       # ... even more clever scripted counterpart of the extension
       # also elided ...
    %</!load>

    }
    %</foobar>
    %    \end{tcl}
    %    and that's it!

  - <a name='4'></a>__docstrip::util::index\_from\_catalogue__ *dir* *pattern* ?*option* *value* \.\.\.?

    This command is a sibling of the standard __pkg\_mkIndex__ command, in
    that it adds package entries to "pkgIndex\.tcl" files\. The difference is that
    it indexes __[docstrip](docstrip\.md)__\-style source files rather
    than raw "\.tcl" or loadable library files\. Only packages listed in the
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
    An existing file of the same name as one to be created will be overwritten\.

  - <a name='6'></a>__docstrip::util::classical\_preamble__ *metaprefix* *message* *target* ?*source* *terminals* \.\.\.?

    This command returns a preamble in the classical
    __[docstrip](docstrip\.md)__ style

    \#\#
    \#\# This is \`TARGET',
    \#\# generated by the docstrip::util package\.
    \#\#
    \#\# The original source files were:
    \#\#
    \#\# SOURCE \(with options: \`foo,bar'\)
    \#\#
    \#\# Some message line 1
    \#\# line2
    \#\# line3

    if called as

    docstrip::util::classical\_preamble \{\#\#\}\\
      "\\nSome message line 1\\nline2\\nline3" TARGET SOURCE \{foo bar\}

    The command supports preambles for files generated from multiple sources,
    even though __modules\_from\_catalogue__ at present does not need that\.

  - <a name='7'></a>__docstrip::util::classical\_postamble__ *metaprefix* *message* *target* ?*source* *terminals* \.\.\.?

    This command returns a postamble in the classical
    __[docstrip](docstrip\.md)__ style

    \#\# Some message line 1
    \#\# line2
    \#\# line3
    \#\#
    \#\# End of file \`TARGET'\.

    if called as

    docstrip::util::classical\_postamble \{\#\#\}\\
      "Some message line 1\\nline2\\nline3" TARGET SOURCE \{foo bar\}

    In other words, the *source* and *terminals* arguments are ignored, but
    supported for symmetry with __classical\_preamble__\.

  - <a name='8'></a>__docstrip::util::packages\_provided__ *text* ?*setup\-script*?

    This command returns a list where every even index element is the name of a







|
|
|
|
|
|
|
|
|
|
|



|
|









|
|
|
|
|



|
|







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
    An existing file of the same name as one to be created will be overwritten\.

  - <a name='6'></a>__docstrip::util::classical\_preamble__ *metaprefix* *message* *target* ?*source* *terminals* \.\.\.?

    This command returns a preamble in the classical
    __[docstrip](docstrip\.md)__ style

    ##
    ## This is `TARGET',
    ## generated by the docstrip::util package.
    ##
    ## The original source files were:
    ##
    ## SOURCE (with options: `foo,bar')
    ##
    ## Some message line 1
    ## line2
    ## line3

    if called as

    docstrip::util::classical_preamble {##}\
      "\nSome message line 1\nline2\nline3" TARGET SOURCE {foo bar}

    The command supports preambles for files generated from multiple sources,
    even though __modules\_from\_catalogue__ at present does not need that\.

  - <a name='7'></a>__docstrip::util::classical\_postamble__ *metaprefix* *message* *target* ?*source* *terminals* \.\.\.?

    This command returns a postamble in the classical
    __[docstrip](docstrip\.md)__ style

    ## Some message line 1
    ## line2
    ## line3
    ##
    ## End of file `TARGET'.

    if called as

    docstrip::util::classical_postamble {##}\
      "Some message line 1\nline2\nline3" TARGET SOURCE {foo bar}

    In other words, the *source* and *terminals* arguments are ignored, but
    supported for symmetry with __classical\_preamble__\.

  - <a name='8'></a>__docstrip::util::packages\_provided__ *text* ?*setup\-script*?

    This command returns a list where every even index element is the name of a
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
    *setup\-script* is evaluated in the local context of the
    __packages\_provided__ procedure just before the *text* is processed\.
    At that time, the name of the slave command for the safe interpreter that
    will do this processing is kept in the local variable __c__\. To for
    example copy the contents of the __::env__ array to the safe
    interpreter, one might use a *setup\-script* of

    $c eval \[list array set env \[array get ::env\]\]

# <a name='section3'></a>Source processing commands

Unlike the previous group of commands, which would use __docstrip::extract__
to extract some code lines and then process those further, the following
commands operate on text consisting of all types of lines\.








|







383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
    *setup\-script* is evaluated in the local context of the
    __packages\_provided__ procedure just before the *text* is processed\.
    At that time, the name of the slave command for the safe interpreter that
    will do this processing is kept in the local variable __c__\. To for
    example copy the contents of the __::env__ array to the safe
    interpreter, one might use a *setup\-script* of

    $c eval [list array set env [array get ::env]]

# <a name='section3'></a>Source processing commands

Unlike the previous group of commands, which would use __docstrip::extract__
to extract some code lines and then process those further, the following
commands operate on text consisting of all types of lines\.

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
        __emph__asised\.

    At the time of writing, no project has employed
    __[doctools](\.\./doctools/doctools\.md)__ markup in master source
    files, so experience of what works well is not available\. A source file
    could however look as follows

    % \[manpage\_begin gcd n 1\.0\]
    % \[keywords divisor\]
    % \[keywords math\]
    % \[moddesc \{Greatest Common Divisor\}\]
    % \[require gcd \[opt 1\.0\]\]
    % \[description\]
    %
    % \[list\_begin definitions\]
    % \[call \[cmd gcd\] \[arg a\] \[arg b\]\]
    %   The \[cmd gcd\] procedure takes two arguments \[arg a\] and \[arg b\] which
    %   must be integers and returns their greatest common divisor\.
    proc gcd \{a b\} \{
    %   The first step is to take the absolute values of the arguments\.
    %   This relieves us of having to worry about how signs will be treated
    %   by the remainder operation\.
       set a \[expr \{abs\($a\)\}\]
       set b \[expr \{abs\($b\)\}\]
    %   The next line does all of Euclid's algorithm\! We can make do
    %   without a temporary variable, since $a is substituted before the
    %   \[lb\]set a $b\[rb\] and thus continues to hold a reference to the
    %   "old" value of \[var a\]\.
       while \{$b>0\} \{ set b \[expr \{ $a % \[set a $b\] \}\] \}
    %   In Tcl 8\.3 we might want to use \[cmd set\] instead of \[cmd return\]
    %   to get the slight advantage of byte\-compilation\.
    %<tcl83>  set a
    %<\!tcl83>   return $a
    \}

    % \[list\_end\]
    %
    % \[manpage\_end\]

    If the above text is fed through __docstrip::util::ddt2man__ then the
    result will be a syntactically correct
    __[doctools](\.\./doctools/doctools\.md)__ manpage, even though its
    purpose is a bit different\.

    It is suggested that master source code files with







|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|

|
|
|
|
|

|
<
>
|

|







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
        __emph__asised\.

    At the time of writing, no project has employed
    __[doctools](\.\./doctools/doctools\.md)__ markup in master source
    files, so experience of what works well is not available\. A source file
    could however look as follows

    % [manpage_begin gcd n 1.0]
    % [keywords divisor]
    % [keywords math]
    % [moddesc {Greatest Common Divisor}]
    % [require gcd [opt 1.0]]
    % [description]
    %
    % [list_begin definitions]
    % [call [cmd gcd] [arg a] [arg b]]
    %   The [cmd gcd] procedure takes two arguments [arg a] and [arg b] which
    %   must be integers and returns their greatest common divisor.
    proc gcd {a b} {
    %   The first step is to take the absolute values of the arguments.
    %   This relieves us of having to worry about how signs will be treated
    %   by the remainder operation.
       set a [expr {abs($a)}]
       set b [expr {abs($b)}]
    %   The next line does all of Euclid's algorithm! We can make do
    %   without a temporary variable, since $a is substituted before the
    %   [lb]set a $b[rb] and thus continues to hold a reference to the
    %   "old" value of [var a].
       while {$b>0} { set b [expr { $a % [set a $b] }] }
    %   In Tcl 8.3 we might want to use [cmd set] instead of [cmd return]
    %   to get the slight advantage of byte-compilation.
    %<tcl83>  set a
    %<!tcl83>   return $a

    }
    % [list_end]
    %
    % [manpage_end]

    If the above text is fed through __docstrip::util::ddt2man__ then the
    result will be a syntactically correct
    __[doctools](\.\./doctools/doctools\.md)__ manpage, even though its
    purpose is a bit different\.

    It is suggested that master source code files with
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
    the header of each hunk specifies which case is at hand\. It is normally
    necessary to manually review both the return value from
    __[patch](\.\./\.\./\.\./\.\./index\.md\#patch)__ and the patched text itself,
    as this command cannot adjust comment lines to match new content\.

    An example use would look like

    set sourceL \[split \[docstrip::util::thefile from\.dtx\] \\n\]
    set terminals \{foo bar baz\}
    set fromtext \[docstrip::util::thefile from\.tcl\]
    set difftext \[exec diff \-\-unified from\.tcl to\.tcl\]
    set leftover \[docstrip::util::patch sourceL $terminals $fromtext\\
      \[docstrip::util::import\_unidiff $difftext\] \-metaprefix \{\#\}\]
    set F \[open to\.dtx w\]; puts $F \[join $sourceL \\n\]; close $F
    return $leftover

    Here, "from\.dtx" was used as source for "from\.tcl", which someone modified
    into "to\.tcl"\. We're trying to construct a "to\.dtx" which can be used as
    source for "to\.tcl"\.

  - <a name='12'></a>__docstrip::util::thefile__ *filename* ?*option* *value* \.\.\.?







|
|
|
|
|
|
|







599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
    the header of each hunk specifies which case is at hand\. It is normally
    necessary to manually review both the return value from
    __[patch](\.\./\.\./\.\./\.\./index\.md\#patch)__ and the patched text itself,
    as this command cannot adjust comment lines to match new content\.

    An example use would look like

    set sourceL [split [docstrip::util::thefile from.dtx] \n]
    set terminals {foo bar baz}
    set fromtext [docstrip::util::thefile from.tcl]
    set difftext [exec diff --unified from.tcl to.tcl]
    set leftover [docstrip::util::patch sourceL $terminals $fromtext\
      [docstrip::util::import_unidiff $difftext] -metaprefix {#}]
    set F [open to.dtx w]; puts $F [join $sourceL \n]; close $F
    return $leftover

    Here, "from\.dtx" was used as source for "from\.tcl", which someone modified
    into "to\.tcl"\. We're trying to construct a "to\.dtx" which can be used as
    source for "to\.tcl"\.

  - <a name='12'></a>__docstrip::util::thefile__ *filename* ?*option* *value* \.\.\.?

Changes to embedded/md/tcllib/files/modules/doctools/changelog.md.

63
64
65
66
67
68
69
70
71


72
73
74
75


76
77
78

79
80
81


82
83

84
85
86
87
88
89
90
    ChangeLog\. Each element/entry is then a list of three elements describing
    the date of the entry, its author, and the comments made, in this order\. The
    last item in each element/entry, the comments, is a list of sections\. Each
    section is described by a list containing two elements, a list of file
    names, and a string containing the true comment associated with the files of
    the section\.

            \{
        	\{


        	    date
        	    author
        	    \{
        		\{


        		    \{file \.\.\.\}
        		    commenttext
        		\}

        		\.\.\.
        	    \}
        	\}


        	\{\.\.\.\}
            \}


  - <a name='2'></a>__::doctools::changelog::flatten__ *entries*

    This command converts a list of entries as generated by __change::scan__
    above into a simpler list of plain text blocks each containing all the
    information of a single entry\.








<
<
>
>


<
<
>
>
|

<
>
|
<
<
>
>
|
<
>







63
64
65
66
67
68
69


70
71
72
73


74
75
76
77

78
79


80
81
82

83
84
85
86
87
88
89
90
    ChangeLog\. Each element/entry is then a list of three elements describing
    the date of the entry, its author, and the comments made, in this order\. The
    last item in each element/entry, the comments, is a list of sections\. Each
    section is described by a list containing two elements, a list of file
    names, and a string containing the true comment associated with the files of
    the section\.



            {
        	{
        	    date
        	    author


        	    {
        		{
        		    {file ...}
        		    commenttext

        		}
        		...


        	    }
        	}
        	{...}

            }

  - <a name='2'></a>__::doctools::changelog::flatten__ *entries*

    This command converts a list of entries as generated by __change::scan__
    above into a simpler list of plain text blocks each containing all the
    information of a single entry\.

Changes to embedded/md/tcllib/files/modules/doctools/docidx_lang_intro.md.

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
interspersed between them, except for whitespace\.

Each markup command is a Tcl command surrounded by a matching pair of __\[__
and __\]__\. Inside of these delimiters the usual rules for a Tcl command
apply with regard to word quotation, nested commands, continuation lines, etc\.
I\.e\.

    \.\.\. \[key \{markup language\}\] \.\.\.

    \.\.\. \[manpage thefile \\\\
            \{file description\}\] \.\.\.

## <a name='subsection2'></a>Basic structure

The most simple document which can be written in docidx is

    \[index\_begin GROUPTITLE TITLE\]
    \[index\_end\]

Not very useful, but valid\. This also shows us that all docidx documents consist
of only one part where we will list all keys and their references\.

A more useful index will contain at least keywords, or short 'keys', i\.e\. the
phrases which were indexed\. So:

    \[index\_begin GROUPTITLE TITLE\]
    \[__key markup__\]
    \[__key \{semantic markup\}\]__\]
    \[__key \{docidx markup\}__\]
    \[__key \{docidx language\}__\]
    \[__key \{docidx commands\}__\]
    \[index\_end\]

In the above example the command __key__ is used to declare the keyword
phrases we wish to be part of the index\.

However a truly useful index does not only list the keyword phrases, but will
also contain references to documents associated with the keywords\. Here is a
made\-up index for all the manpages in the module
*[base64](\.\./\.\./\.\./\.\./index\.md\#base64)*:

    \[index\_begin tcllib/base64 \{De\- & Encoding\}\]
    \[key base64\]
    \[__manpage base64__\]
    \[key encoding\]
    \[__manpage base64__\]
    \[__manpage uuencode__\]
    \[__manpage yencode__\]
    \[key uuencode\]
    \[__manpage uuencode__\]
    \[key yEnc\]
    \[__manpage yencode__\]
    \[key ydecode\]
    \[__manpage yencode__\]
    \[key yencode\]
    \[__manpage yencode__\]
    \[index\_end\]

In the above example the command
__[manpage](\.\./\.\./\.\./\.\./index\.md\#manpage)__ is used to insert references
to documents, using symbolic file names, with each command belonging to the last
__key__ command coming before it\.

The other command to insert references is







|

|
|





|
|







|
|
|
|
|
|
|









|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
interspersed between them, except for whitespace\.

Each markup command is a Tcl command surrounded by a matching pair of __\[__
and __\]__\. Inside of these delimiters the usual rules for a Tcl command
apply with regard to word quotation, nested commands, continuation lines, etc\.
I\.e\.

    ... [key {markup language}] ...

    ... [manpage thefile \
            {file description}] ...

## <a name='subsection2'></a>Basic structure

The most simple document which can be written in docidx is

    [index_begin GROUPTITLE TITLE]
    [index_end]

Not very useful, but valid\. This also shows us that all docidx documents consist
of only one part where we will list all keys and their references\.

A more useful index will contain at least keywords, or short 'keys', i\.e\. the
phrases which were indexed\. So:

> \[index\_begin GROUPTITLE TITLE\]  
> \[__key markup__\]  
> \[__key \{semantic markup\}\]__\]  
> \[__key \{docidx markup\}__\]  
> \[__key \{docidx language\}__\]  
> \[__key \{docidx commands\}__\]  
> \[index\_end\]

In the above example the command __key__ is used to declare the keyword
phrases we wish to be part of the index\.

However a truly useful index does not only list the keyword phrases, but will
also contain references to documents associated with the keywords\. Here is a
made\-up index for all the manpages in the module
*[base64](\.\./\.\./\.\./\.\./index\.md\#base64)*:

> \[index\_begin tcllib/base64 \{De\- & Encoding\}\]  
> \[key base64\]  
> \[__manpage base64__\]  
> \[key encoding\]  
> \[__manpage base64__\]  
> \[__manpage uuencode__\]  
> \[__manpage yencode__\]  
> \[key uuencode\]  
> \[__manpage uuencode__\]  
> \[key yEnc\]  
> \[__manpage yencode__\]  
> \[key ydecode\]  
> \[__manpage yencode__\]  
> \[key yencode\]  
> \[__manpage yencode__\]  
> \[index\_end\]

In the above example the command
__[manpage](\.\./\.\./\.\./\.\./index\.md\#manpage)__ is used to insert references
to documents, using symbolic file names, with each command belonging to the last
__key__ command coming before it\.

The other command to insert references is
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
to be used before the __index\_begin__ command opening the document\.

Instead of only whitespace the two templating commands __include__ and
__vset__ are also allowed, to enable the writer to either set and/or import
configuration settings relevant to the table of contents\. I\.e\. it is possible to
write

    \[__include FILE__\]
    \[__vset VAR VALUE__\]
    \[index\_begin GROUPTITLE TITLE\]
    \.\.\.
    \[index\_end\]

Even more important, these two commands are allowed anywhere where a markup
command is allowed, without regard for any other structure\.

    \[index\_begin GROUPTITLE TITLE\]
    \[__include FILE__\]
    \[__vset VAR VALUE__\]
    \.\.\.
    \[index\_end\]

The only restriction __include__ has to obey is that the contents of the
included file must be valid at the place of the inclusion\. I\.e\. a file included
before __index\_begin__ may contain only the templating commands __vset__
and __include__, a file included after a key may contain only manape or url
references, and other keys, etc\.

## <a name='subsection4'></a>Escapes

Beyond the 6 commands shown so far we have two more available\. However their
function is not the marking up of index structure, but the insertion of
characters, namely __\[__ and __\]__\. These commands, __lb__ and
__rb__ respectively, are required because our use of \[ and \] to bracket
markup commands makes it impossible to directly use \[ and \] within the text\.

Our example of their use are the sources of the last sentence in the previous
paragraph, with some highlighting added\.

    \.\.\.
    These commands, \[cmd lb\] and \[cmd lb\] respectively, are required
    because our use of \[__lb__\] and \[__rb__\] to bracket markup commands makes it
    impossible to directly use \[__lb__\] and \[__rb__\] within the text\.
    \.\.\.

# <a name='section2'></a>FURTHER READING

Now that this document has been digested the reader, assumed to be a *writer*
of documentation should be fortified enough to be able to understand the formal
*[docidx language syntax](docidx\_lang\_syntax\.md)* specification as well\.
From here on out the *[docidx language command







|
|
|
|
|




|
|
|
|
|


















|
|
|
|
|







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
to be used before the __index\_begin__ command opening the document\.

Instead of only whitespace the two templating commands __include__ and
__vset__ are also allowed, to enable the writer to either set and/or import
configuration settings relevant to the table of contents\. I\.e\. it is possible to
write

> \[__include FILE__\]  
> \[__vset VAR VALUE__\]  
> \[index\_begin GROUPTITLE TITLE\]  
> \.\.\.  
> \[index\_end\]

Even more important, these two commands are allowed anywhere where a markup
command is allowed, without regard for any other structure\.

> \[index\_begin GROUPTITLE TITLE\]  
> \[__include FILE__\]  
> \[__vset VAR VALUE__\]  
> \.\.\.  
> \[index\_end\]

The only restriction __include__ has to obey is that the contents of the
included file must be valid at the place of the inclusion\. I\.e\. a file included
before __index\_begin__ may contain only the templating commands __vset__
and __include__, a file included after a key may contain only manape or url
references, and other keys, etc\.

## <a name='subsection4'></a>Escapes

Beyond the 6 commands shown so far we have two more available\. However their
function is not the marking up of index structure, but the insertion of
characters, namely __\[__ and __\]__\. These commands, __lb__ and
__rb__ respectively, are required because our use of \[ and \] to bracket
markup commands makes it impossible to directly use \[ and \] within the text\.

Our example of their use are the sources of the last sentence in the previous
paragraph, with some highlighting added\.

> &nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;These commands, \[cmd lb\] and \[cmd lb\] respectively, are required  
> &nbsp;&nbsp;because our use of \[__lb__\] and \[__rb__\] to bracket markup commands makes it  
> &nbsp;&nbsp;impossible to directly use \[__lb__\] and \[__rb__\] within the text\.  
> &nbsp;&nbsp;\.\.\.

# <a name='section2'></a>FURTHER READING

Now that this document has been digested the reader, assumed to be a *writer*
of documentation should be fortified enough to be able to understand the formal
*[docidx language syntax](docidx\_lang\_syntax\.md)* specification as well\.
From here on out the *[docidx language command

Changes to embedded/md/tcllib/files/modules/doctools/docidx_lang_syntax.md.

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  1. The construct \{ X \} stands for zero or more occurrences of X\.

  1. The construct \[ X \] stands for zero or one occurrence of X\.

The syntax:

    index     = defs
                INDEX\_BEGIN
                \[ contents \]
                INDEX\_END
                \{ <WHITE> \}

    defs      = \{ INCLUDE &#124; VSET &#124; <WHITE> \}
    contents  = keyword \{ keyword \}

    keyword   = defs KEY ref \{ ref \}
    ref       = MANPAGE &#124; URL &#124; defs

At last a rule we were unable to capture in the EBNF syntax, as it is about the
arguments of the markup commands, something which is not modeled here\.

  1. The arguments of all markup commands have to be plain text, and/or text
     markup commands, i\.e\. one of








|
|
|
|

|
|

|
|







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  1. The construct \{ X \} stands for zero or more occurrences of X\.

  1. The construct \[ X \] stands for zero or one occurrence of X\.

The syntax:

    index     = defs
                INDEX_BEGIN
                [ contents ]
                INDEX_END
                { <WHITE> }

    defs      = { INCLUDE | VSET | <WHITE> }
    contents  = keyword { keyword }

    keyword   = defs KEY ref { ref }
    ref       = MANPAGE | URL | defs

At last a rule we were unable to capture in the EBNF syntax, as it is about the
arguments of the markup commands, something which is not modeled here\.

  1. The arguments of all markup commands have to be plain text, and/or text
     markup commands, i\.e\. one of

Changes to embedded/md/tcllib/files/modules/doctools/docidx_plugin_apiref.md.

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
  1. initialize and shutdown each pass

  1. query and initialize engine parameters

After the plugin has been loaded and the frontend commands are established the
commands will be called in the following sequence:

    idx\_numpasses \-> n
    idx\_listvariables \-> vars

    idx\_varset var1 value1
    idx\_varset var2 value2
    \.\.\.
    idx\_varset varK valueK
    idx\_initialize
    idx\_setup 1
    \.\.\.
    idx\_setup 2
    \.\.\.
    \.\.\.
    idx\_setup n
    \.\.\.
    idx\_postprocess
    idx\_shutdown
    \.\.\.

I\.e\. first the number of passes and the set of available engine parameters is
established, followed by calls setting the parameters\. That second part is
optional\.

After that the plugin is initialized, the specified number of passes executed,
the final result run through a global post processing step and at last the







|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







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
  1. initialize and shutdown each pass

  1. query and initialize engine parameters

After the plugin has been loaded and the frontend commands are established the
commands will be called in the following sequence:

    idx_numpasses -> n
    idx_listvariables -> vars

    idx_varset var1 value1
    idx_varset var2 value2
    ...
    idx_varset varK valueK
    idx_initialize
    idx_setup 1
    ...
    idx_setup 2
    ...
    ...
    idx_setup n
    ...
    idx_postprocess
    idx_shutdown
    ...

I\.e\. first the number of passes and the set of available engine parameters is
established, followed by calls setting the parameters\. That second part is
optional\.

After that the plugin is initialized, the specified number of passes executed,
the final result run through a global post processing step and at last the

Changes to embedded/md/tcllib/files/modules/doctools/doctoc_lang_intro.md.

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
interspersed between them, except for whitespace\.

Each markup command is a Tcl command surrounded by a matching pair of __\[__
and __\]__\. Inside of these delimiters the usual rules for a Tcl command
apply with regard to word quotation, nested commands, continuation lines, etc\.
I\.e\.

    \.\.\. \[division\_start \{Appendix 1\}\] \.\.\.

    \.\.\. \[item thefile \\\\
            label \{file description\}\] \.\.\.

## <a name='subsection2'></a>Basic structure

The most simple document which can be written in doctoc is

    \[toc\_begin GROUPTITLE TITLE\]
    \[toc\_end\]

This also shows us that all doctoc documents consist of only one part where we
will list *items* and *divisions*\.

The user is free to mix these as she sees fit\. This is a change from version 1
of the language, which did not allow this mixing, but only the use of either a
series of items or a series of divisions\.







|

|
|





|
|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
interspersed between them, except for whitespace\.

Each markup command is a Tcl command surrounded by a matching pair of __\[__
and __\]__\. Inside of these delimiters the usual rules for a Tcl command
apply with regard to word quotation, nested commands, continuation lines, etc\.
I\.e\.

    ... [division_start {Appendix 1}] ...

    ... [item thefile \
            label {file description}] ...

## <a name='subsection2'></a>Basic structure

The most simple document which can be written in doctoc is

    [toc_begin GROUPTITLE TITLE]
    [toc_end]

This also shows us that all doctoc documents consist of only one part where we
will list *items* and *divisions*\.

The user is free to mix these as she sees fit\. This is a change from version 1
of the language, which did not allow this mixing, but only the use of either a
series of items or a series of divisions\.
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
Symbolic names are used to preserve the convertibility of this format to any
output format\. The actual name of any file will be inserted by the chosen
formatting engine when converting the input, based on a mapping from symbolic to
actual names given to the engine\.

Here a made up example for a table of contents of this document:

    \[toc\_begin Doctoc \{Language Introduction\}\]
    \[__item 1 DESCRIPTION__\]
    \[__item 1\.1 \{Basic structure\}__\]
    \[__item 1\.2 Items__\]
    \[__item 1\.3 Divisions__\]
    \[__item 2 \{FURTHER READING\}__\]
    \[toc\_end\]

## <a name='subsection4'></a>Divisions

One thing of notice in the last example in the previous section is that the
referenced sections actually had a nested structure, something which was
expressed in the item labels, by using a common prefix for all the sections
nested under section 1\.







|
|
|
|
|
|
|







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
Symbolic names are used to preserve the convertibility of this format to any
output format\. The actual name of any file will be inserted by the chosen
formatting engine when converting the input, based on a mapping from symbolic to
actual names given to the engine\.

Here a made up example for a table of contents of this document:

> \[toc\_begin Doctoc \{Language Introduction\}\]  
> \[__item 1 DESCRIPTION__\]  
> \[__item 1\.1 \{Basic structure\}__\]  
> \[__item 1\.2 Items__\]  
> \[__item 1\.3 Divisions__\]  
> \[__item 2 \{FURTHER READING\}__\]  
> \[toc\_end\]

## <a name='subsection4'></a>Divisions

One thing of notice in the last example in the previous section is that the
referenced sections actually had a nested structure, something which was
expressed in the item labels, by using a common prefix for all the sections
nested under section 1\.
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

  - __division\_end__

    This command closes the last opened and not yet closed division\.

Using this we can recast the last example like this

    \[toc\_begin Doctoc \{Language Introduction\}\]
    \[__division\_start DESCRIPTION__\]
    \[item 1 \{Basic structure\}\]
    \[item 2 Items\]
    \[item 3 Divisions\]
    \[__division\_end__\]
    \[__division\_start \{FURTHER READING\}__\]
    \[__division\_end__\]
    \[toc\_end\]

Or, to demonstrate deeper nesting

    \[toc\_begin Doctoc \{Language Introduction\}\]
    \[__division\_start DESCRIPTION__\]
    \[__division\_start \{Basic structure\}__\]
    \[item 1 Do\]
    \[item 2 Re\]
    \[__division\_end__\]
    \[__division\_start Items__\]
    \[item a Fi\]
    \[item b Fo\]
    \[item c Fa\]
    \[__division\_end__\]
    \[__division\_start Divisions__\]
    \[item 1 Sub\]
    \[item 1 Zero\]
    \[__division\_end__\]
    \[__division\_end__\]
    \[__division\_start \{FURTHER READING\}__\]
    \[__division\_end__\]
    \[toc\_end\]

And do not forget, it is possible to freely mix items and divisions, and to have
empty divisions\.

    \[toc\_begin Doctoc \{Language Introduction\}\]
    \[item 1 Do\]
    \[__division\_start DESCRIPTION__\]
    \[__division\_start \{Basic structure\}__\]
    \[item 2 Re\]
    \[__division\_end__\]
    \[item a Fi\]
    \[__division\_start Items__\]
    \[item b Fo\]
    \[item c Fa\]
    \[__division\_end__\]
    \[__division\_start Divisions__\]
    \[__division\_end__\]
    \[__division\_end__\]
    \[__division\_start \{FURTHER READING\}__\]
    \[__division\_end__\]
    \[toc\_end\]

## <a name='subsection5'></a>Advanced structure

In all previous examples we fudged a bit regarding the markup actually allowed
to be used before the __toc\_begin__ command opening the document\.

Instead of only whitespace the two templating commands __include__ and
__vset__ are also allowed, to enable the writer to either set and/or import
configuration settings relevant to the table of contents\. I\.e\. it is possible to
write

    \[__include FILE__\]
    \[__vset VAR VALUE__\]
    \[toc\_begin GROUPTITLE TITLE\]
    \.\.\.
    \[toc\_end\]

Even more important, these two commands are allowed anywhere where a markup
command is allowed, without regard for any other structure\.

    \[toc\_begin GROUPTITLE TITLE\]
    \[__include FILE__\]
    \[__vset VAR VALUE__\]
    \.\.\.
    \[toc\_end\]

The only restriction __include__ has to obey is that the contents of the
included file must be valid at the place of the inclusion\. I\.e\. a file included
before __toc\_begin__ may contain only the templating commands __vset__
and __include__, a file included in a division may contain only items or
divisions commands, etc\.

## <a name='subsection6'></a>Escapes

Beyond the 6 commands shown so far we have two more available\. However their
function is not the marking up of toc structure, but the insertion of
characters, namely __\[__ and __\]__\. These commands, __lb__ and
__rb__ respectively, are required because our use of \[ and \] to bracket
markup commands makes it impossible to directly use \[ and \] within the text\.

Our example of their use are the sources of the last sentence in the previous
paragraph, with some highlighting added\.

    \.\.\.
    These commands, \[cmd lb\] and \[cmd lb\] respectively, are required
    because our use of \[__lb__\] and \[__rb__\] to bracket markup commands makes it
    impossible to directly use \[__lb__\] and \[__rb__\] within the text\.
    \.\.\.

# <a name='section2'></a>FURTHER READING

Now that this document has been digested the reader, assumed to be a *writer*
of documentation should be fortified enough to be able to understand the formal
*[doctoc language syntax](doctoc\_lang\_syntax\.md)* specification as well\.
From here on out the *[doctoc language command







|
|
|
|
|
|
|
|
|



|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|











|
|
|
|
|




|
|
|
|
|


















|
|
|
|
|







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

  - __division\_end__

    This command closes the last opened and not yet closed division\.

Using this we can recast the last example like this

> \[toc\_begin Doctoc \{Language Introduction\}\]  
> \[__division\_start DESCRIPTION__\]  
> \[item 1 \{Basic structure\}\]  
> \[item 2 Items\]  
> \[item 3 Divisions\]  
> \[__division\_end__\]  
> \[__division\_start \{FURTHER READING\}__\]  
> \[__division\_end__\]  
> \[toc\_end\]

Or, to demonstrate deeper nesting

> \[toc\_begin Doctoc \{Language Introduction\}\]  
> \[__division\_start DESCRIPTION__\]  
> \[__division\_start \{Basic structure\}__\]  
> \[item 1 Do\]  
> \[item 2 Re\]  
> \[__division\_end__\]  
> \[__division\_start Items__\]  
> \[item a Fi\]  
> \[item b Fo\]  
> \[item c Fa\]  
> \[__division\_end__\]  
> \[__division\_start Divisions__\]  
> \[item 1 Sub\]  
> \[item 1 Zero\]  
> \[__division\_end__\]  
> \[__division\_end__\]  
> \[__division\_start \{FURTHER READING\}__\]  
> \[__division\_end__\]  
> \[toc\_end\]

And do not forget, it is possible to freely mix items and divisions, and to have
empty divisions\.

> \[toc\_begin Doctoc \{Language Introduction\}\]  
> \[item 1 Do\]  
> \[__division\_start DESCRIPTION__\]  
> \[__division\_start \{Basic structure\}__\]  
> \[item 2 Re\]  
> \[__division\_end__\]  
> \[item a Fi\]  
> \[__division\_start Items__\]  
> \[item b Fo\]  
> \[item c Fa\]  
> \[__division\_end__\]  
> \[__division\_start Divisions__\]  
> \[__division\_end__\]  
> \[__division\_end__\]  
> \[__division\_start \{FURTHER READING\}__\]  
> \[__division\_end__\]  
> \[toc\_end\]

## <a name='subsection5'></a>Advanced structure

In all previous examples we fudged a bit regarding the markup actually allowed
to be used before the __toc\_begin__ command opening the document\.

Instead of only whitespace the two templating commands __include__ and
__vset__ are also allowed, to enable the writer to either set and/or import
configuration settings relevant to the table of contents\. I\.e\. it is possible to
write

> \[__include FILE__\]  
> \[__vset VAR VALUE__\]  
> \[toc\_begin GROUPTITLE TITLE\]  
> \.\.\.  
> \[toc\_end\]

Even more important, these two commands are allowed anywhere where a markup
command is allowed, without regard for any other structure\.

> \[toc\_begin GROUPTITLE TITLE\]  
> \[__include FILE__\]  
> \[__vset VAR VALUE__\]  
> \.\.\.  
> \[toc\_end\]

The only restriction __include__ has to obey is that the contents of the
included file must be valid at the place of the inclusion\. I\.e\. a file included
before __toc\_begin__ may contain only the templating commands __vset__
and __include__, a file included in a division may contain only items or
divisions commands, etc\.

## <a name='subsection6'></a>Escapes

Beyond the 6 commands shown so far we have two more available\. However their
function is not the marking up of toc structure, but the insertion of
characters, namely __\[__ and __\]__\. These commands, __lb__ and
__rb__ respectively, are required because our use of \[ and \] to bracket
markup commands makes it impossible to directly use \[ and \] within the text\.

Our example of their use are the sources of the last sentence in the previous
paragraph, with some highlighting added\.

> &nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;These commands, \[cmd lb\] and \[cmd lb\] respectively, are required  
> &nbsp;&nbsp;because our use of \[__lb__\] and \[__rb__\] to bracket markup commands makes it  
> &nbsp;&nbsp;impossible to directly use \[__lb__\] and \[__rb__\] within the text\.  
> &nbsp;&nbsp;\.\.\.

# <a name='section2'></a>FURTHER READING

Now that this document has been digested the reader, assumed to be a *writer*
of documentation should be fortified enough to be able to understand the formal
*[doctoc language syntax](doctoc\_lang\_syntax\.md)* specification as well\.
From here on out the *[doctoc language command

Changes to embedded/md/tcllib/files/modules/doctools/doctoc_lang_syntax.md.

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
  1. The construct \{ X \} stands for zero or more occurrences of X\.

  1. The construct \[ X \] stands for zero or one occurrence of X\.

The syntax:

    toc       = defs
                TOC\_BEGIN
                contents
                TOC\_END
                \{ <WHITE> \}

    defs      = \{ INCLUDE &#124; VSET &#124; <WHITE> \}
    contents  = \{ defs entry \} \[ defs \]

    entry     = ITEM &#124; division

    division  = DIVISION\_START
                contents
                DIVISION\_END

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *doctools* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|

|
|

|
|

|

|

|







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
  1. The construct \{ X \} stands for zero or more occurrences of X\.

  1. The construct \[ X \] stands for zero or one occurrence of X\.

The syntax:

    toc       = defs
                TOC_BEGIN
                contents
                TOC_END
                { <WHITE> }

    defs      = { INCLUDE | VSET | <WHITE> }
    contents  = { defs entry } [ defs ]

    entry     = ITEM | division

    division  = DIVISION_START
                contents
                DIVISION_END

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *doctools* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/doctools/doctoc_plugin_apiref.md.

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
  1. initialize and shutdown each pass

  1. query and initialize engine parameters

After the plugin has been loaded and the frontend commands are established the
commands will be called in the following sequence:

    toc\_numpasses \-> n
    toc\_listvariables \-> vars

    toc\_varset var1 value1
    toc\_varset var2 value2
    \.\.\.
    toc\_varset varK valueK
    toc\_initialize
    toc\_setup 1
    \.\.\.
    toc\_setup 2
    \.\.\.
    \.\.\.
    toc\_setup n
    \.\.\.
    toc\_postprocess
    toc\_shutdown
    \.\.\.

I\.e\. first the number of passes and the set of available engine parameters is
established, followed by calls setting the parameters\. That second part is
optional\.

After that the plugin is initialized, the specified number of passes executed,
the final result run through a global post processing step and at last the







|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







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
  1. initialize and shutdown each pass

  1. query and initialize engine parameters

After the plugin has been loaded and the frontend commands are established the
commands will be called in the following sequence:

    toc_numpasses -> n
    toc_listvariables -> vars

    toc_varset var1 value1
    toc_varset var2 value2
    ...
    toc_varset varK valueK
    toc_initialize
    toc_setup 1
    ...
    toc_setup 2
    ...
    ...
    toc_setup n
    ...
    toc_postprocess
    toc_shutdown
    ...

I\.e\. first the number of passes and the set of available engine parameters is
established, followed by calls setting the parameters\. That second part is
optional\.

After that the plugin is initialized, the specified number of passes executed,
the final result run through a global post processing step and at last the

Changes to embedded/md/tcllib/files/modules/doctools/doctools.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools \- Documentation tools)
[//000000002]: # (Generated from file 'doctools\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2003\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools\(n\) 1\.5\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>




|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools \- Documentation tools)
[//000000002]: # (Generated from file 'doctools\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2003\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools\(n\) 1\.5\.6 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require doctools ?1\.5\.1?  

[__::doctools::new__ *objectName* ?*option value*\.\.\.?](#1)  
[__::doctools::help__](#2)  
[__::doctools::search__ *path*](#3)  
[__objectName__ __method__ ?*arg arg \.\.\.*?](#4)  
[*objectName* __configure__](#5)  
[*objectName* __configure__ *option*](#6)  







|







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require doctools ?1\.5\.6?  

[__::doctools::new__ *objectName* ?*option value*\.\.\.?](#1)  
[__::doctools::help__](#2)  
[__::doctools::search__ *path*](#3)  
[__objectName__ __method__ ?*arg arg \.\.\.*?](#4)  
[*objectName* __configure__](#5)  
[*objectName* __configure__ *option*](#6)  

Changes to embedded/md/tcllib/files/modules/doctools/doctools_lang_intro.md.

66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
consists primarily of text, with markup commands embedded into it\.

Each markup command is a Tcl command surrounded by a matching pair of __\[__
and __\]__\. Inside of these delimiters the usual rules for a Tcl command
apply with regard to word quotation, nested commands, continuation lines, etc\.
I\.e\.

    \.\.\. \[list\_begin enumerated\] \.\.\.

    \.\.\. \[call \[cmd foo\] \\\\
            \[arg bar\]\] \.\.\.

    \.\.\. \[term \{complex concept\}\] \.\.\.

    \.\.\. \[opt "\[arg key\] \[arg value\]"\] \.\.\.

## <a name='subsection2'></a>Basic structure

The most simple document which can be written in doctools is

        \[manpage\_begin NAME SECTION VERSION\]
    \[see\_also doctools\_intro\]
    \[see\_also doctools\_lang\_cmdref\]
    \[see\_also doctools\_lang\_faq\]
    \[see\_also doctools\_lang\_syntax\]
    \[keywords \{doctools commands\}\]
    \[keywords \{doctools language\}\]
    \[keywords \{doctools markup\}\]
    \[keywords \{doctools syntax\}\]
    \[keywords markup\]
    \[keywords \{semantic markup\}\]
        \[description\]
        \[vset CATEGORY doctools\]
    \[include \.\./doctools2base/include/feedback\.inc\]
    \[manpage\_end\]

This also shows us that all doctools documents are split into two parts, the
*header* and the *body*\. Everything coming before \[__description__\]
belongs to the header, and everything coming after belongs to the body, with the
whole document bracketed by the two __manpage\_\*__ commands\. Before and after
these opening and closing commands we have only *whitespace*\.








|

|
|

|

|





|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
consists primarily of text, with markup commands embedded into it\.

Each markup command is a Tcl command surrounded by a matching pair of __\[__
and __\]__\. Inside of these delimiters the usual rules for a Tcl command
apply with regard to word quotation, nested commands, continuation lines, etc\.
I\.e\.

    ... [list_begin enumerated] ...

    ... [call [cmd foo] \
            [arg bar]] ...

    ... [term {complex concept}] ...

    ... [opt "[arg key] [arg value]"] ...

## <a name='subsection2'></a>Basic structure

The most simple document which can be written in doctools is

        [manpage_begin NAME SECTION VERSION]
    [see_also doctools_intro]
    [see_also doctools_lang_cmdref]
    [see_also doctools_lang_faq]
    [see_also doctools_lang_syntax]
    [keywords {doctools commands}]
    [keywords {doctools language}]
    [keywords {doctools markup}]
    [keywords {doctools syntax}]
    [keywords markup]
    [keywords {semantic markup}]
        [description]
        [vset CATEGORY doctools]
    [include ../common-text/feedback.inc]
    [manpage_end]

This also shows us that all doctools documents are split into two parts, the
*header* and the *body*\. Everything coming before \[__description__\]
belongs to the header, and everything coming after belongs to the body, with the
whole document bracketed by the two __manpage\_\*__ commands\. Before and after
these opening and closing commands we have only *whitespace*\.

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
and they can be used in any order\. However for __titledesc__ and
__moddesc__ only the last occurrence is taken\. For the other two the
specified information is accumulated, in the given order\. Regular text is not
allowed within the header\.

Given the above a less minimal example of a document is

    \[manpage\_begin NAME SECTION VERSION\]
    \[__copyright \{YEAR AUTHOR\}__\]
    \[__titledesc TITLE__\]
    \[__moddesc   MODULE\_TITLE__\]
    \[__require   PACKAGE VERSION__\]
    \[__require   PACKAGE__\]
    \[description\]
    \[manpage\_end\]

Remember that the whitespace is optional\. The document

        \[manpage\_begin NAME SECTION VERSION\]
        \[copyright \{YEAR AUTHOR\}\]\[titledesc TITLE\]\[moddesc MODULE\_TITLE\]
        \[require PACKAGE VERSION\]\[require PACKAGE\]\[description\]
        \[vset CATEGORY doctools\]
    \[include \.\./doctools2base/include/feedback\.inc\]
    \[manpage\_end\]

has the same meaning as the example before\.

On the other hand, if *whitespace* is present it consists not only of any
sequence of characters containing the space character, horizontal and vertical
tabs, carriage return, and newline, but it may contain comment markup as well,
in the form of the __[comment](\.\./\.\./\.\./\.\./index\.md\#comment)__ command\.

    \[__comment \{ \.\.\. \}__\]
    \[manpage\_begin NAME SECTION VERSION\]
    \[copyright \{YEAR AUTHOR\}\]
    \[titledesc TITLE\]
    \[moddesc   MODULE\_TITLE\]\[__comment \{ \.\.\. \}__\]
    \[require   PACKAGE VERSION\]
    \[require   PACKAGE\]
    \[description\]
    \[manpage\_end\]
    \[__comment \{ \.\.\. \}__\]

## <a name='subsection3'></a>Advanced structure

In the simple examples of the last section we fudged a bit regarding the markup
actually allowed to be used before the __manpage\_begin__ command opening the
document\.

Instead of only whitespace the two templating commands __include__ and
__vset__ are also allowed, to enable the writer to either set and/or import
configuration settings relevant to the document\. I\.e\. it is possible to write

    \[__include FILE__\]
    \[__vset VAR VALUE__\]
    \[manpage\_begin NAME SECTION VERSION\]
    \[description\]
    \[manpage\_end\]

Even more important, these two commands are allowed anywhere where a markup
command is allowed, without regard for any other structure\. I\.e\. for example in
the header as well\.

    \[manpage\_begin NAME SECTION VERSION\]
    \[__include FILE__\]
    \[__vset VAR VALUE__\]
    \[description\]
    \[manpage\_end\]

The only restriction __include__ has to obey is that the contents of the
included file must be valid at the place of the inclusion\. I\.e\. a file included
before __manpage\_begin__ may contain only the templating commands
__vset__ and __include__, a file included in the header may contain only
header commands, etc\.








|
|
|
|
|
|
|
|



|
|
|
|
|
|








|
|
|
|
|
|
|
|
|
|











|
|
|
|
|





|
|
|
|
|







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
and they can be used in any order\. However for __titledesc__ and
__moddesc__ only the last occurrence is taken\. For the other two the
specified information is accumulated, in the given order\. Regular text is not
allowed within the header\.

Given the above a less minimal example of a document is

> \[manpage\_begin NAME SECTION VERSION\]  
> \[__copyright \{YEAR AUTHOR\}__\]  
> \[__titledesc TITLE__\]  
> \[__moddesc   MODULE\_TITLE__\]  
> \[__require   PACKAGE VERSION__\]  
> \[__require   PACKAGE__\]  
> \[description\]  
> \[manpage\_end\]

Remember that the whitespace is optional\. The document

        [manpage_begin NAME SECTION VERSION]
        [copyright {YEAR AUTHOR}][titledesc TITLE][moddesc MODULE_TITLE]
        [require PACKAGE VERSION][require PACKAGE][description]
        [vset CATEGORY doctools]
    [include ../common-text/feedback.inc]
    [manpage_end]

has the same meaning as the example before\.

On the other hand, if *whitespace* is present it consists not only of any
sequence of characters containing the space character, horizontal and vertical
tabs, carriage return, and newline, but it may contain comment markup as well,
in the form of the __[comment](\.\./\.\./\.\./\.\./index\.md\#comment)__ command\.

> \[__comment \{ \.\.\. \}__\]  
> \[manpage\_begin NAME SECTION VERSION\]  
> \[copyright \{YEAR AUTHOR\}\]  
> \[titledesc TITLE\]  
> \[moddesc   MODULE\_TITLE\]\[__comment \{ \.\.\. \}__\]  
> \[require   PACKAGE VERSION\]  
> \[require   PACKAGE\]  
> \[description\]  
> \[manpage\_end\]  
> \[__comment \{ \.\.\. \}__\]

## <a name='subsection3'></a>Advanced structure

In the simple examples of the last section we fudged a bit regarding the markup
actually allowed to be used before the __manpage\_begin__ command opening the
document\.

Instead of only whitespace the two templating commands __include__ and
__vset__ are also allowed, to enable the writer to either set and/or import
configuration settings relevant to the document\. I\.e\. it is possible to write

> \[__include FILE__\]  
> \[__vset VAR VALUE__\]  
> \[manpage\_begin NAME SECTION VERSION\]  
> \[description\]  
> \[manpage\_end\]

Even more important, these two commands are allowed anywhere where a markup
command is allowed, without regard for any other structure\. I\.e\. for example in
the header as well\.

> \[manpage\_begin NAME SECTION VERSION\]  
> \[__include FILE__\]  
> \[__vset VAR VALUE__\]  
> \[description\]  
> \[manpage\_end\]

The only restriction __include__ has to obey is that the contents of the
included file must be valid at the place of the inclusion\. I\.e\. a file included
before __manpage\_begin__ may contain only the templating commands
__vset__ and __include__, a file included in the header may contain only
header commands, etc\.

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
The simplest way of structuring the body is through the introduction of
paragraphs\. The command for doing so is __para__\. Each occurrence of this
command closes the previous paragraph and automatically opens the next\. The
first paragraph is automatically opened at the beginning of the body, by
__description__\. In the same manner the last paragraph automatically ends at
__manpage\_end__\.

    \[manpage\_begin NAME SECTION VERSION\]
    \[description\]
     \.\.\.
    \[__para__\]
     \.\.\.
    \[__para__\]
     \.\.\.
    \[manpage\_end\]

Empty paragraphs are ignored\.

A structure coarser than paragraphs are sections, which allow the writer to
split a document into larger, and labeled, pieces\. The command for doing so is
__section__\. Each occurrence of this command closes the previous section and
automatically opens the next, including its first paragraph\. The first section
is automatically opened at the beginning of the body, by __description__
\(This section is labeled "DESCRIPTION"\)\. In the same manner the last section
automatically ends at __manpage\_end__\.

Empty sections are *not* ignored\. We are free to \(not\) use paragraphs within
sections\.

    \[manpage\_begin NAME SECTION VERSION\]
    \[description\]
     \.\.\.
    \[__section \{Section A\}__\]
     \.\.\.
    \[para\]
     \.\.\.
    \[__section \{Section B\}__\]
     \.\.\.
    \[manpage\_end\]

Between sections and paragraphs we have subsections, to split sections\. The
command for doing so is __subsection__\. Each occurrence of this command
closes the previous subsection and automatically opens the next, including its
first paragraph\. A subsection is automatically opened at the beginning of the
body, by __description__, and at the beginning of each section\. In the same
manner the last subsection automatically ends at __manpage\_end__\.

Empty subsections are *not* ignored\. We are free to \(not\) use paragraphs
within subsections\.

    \[manpage\_begin NAME SECTION VERSION\]
    \[description\]
     \.\.\.
    \[section \{Section A\}\]
     \.\.\.
    \[__subsection \{Sub 1\}__\]
     \.\.\.
    \[para\]
     \.\.\.
    \[__subsection \{Sub 2\}__\]
     \.\.\.
    \[section \{Section B\}\]
     \.\.\.
    \[manpage\_end\]

## <a name='subsection5'></a>Text markup

Having handled the overall structure a writer can impose on the document we now
take a closer at the text in a paragraph\.

While most often this is just the unadorned content of the document we do have







|
|
|
|
|
|
|
|














|
|
|
|
|
|
|
|
|
|











|
|
|
|
|
|
|
|
|
|
|
|
|
|







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
The simplest way of structuring the body is through the introduction of
paragraphs\. The command for doing so is __para__\. Each occurrence of this
command closes the previous paragraph and automatically opens the next\. The
first paragraph is automatically opened at the beginning of the body, by
__description__\. In the same manner the last paragraph automatically ends at
__manpage\_end__\.

> \[manpage\_begin NAME SECTION VERSION\]  
> \[description\]  
> &nbsp;\.\.\.  
> \[__para__\]  
> &nbsp;\.\.\.  
> \[__para__\]  
> &nbsp;\.\.\.  
> \[manpage\_end\]

Empty paragraphs are ignored\.

A structure coarser than paragraphs are sections, which allow the writer to
split a document into larger, and labeled, pieces\. The command for doing so is
__section__\. Each occurrence of this command closes the previous section and
automatically opens the next, including its first paragraph\. The first section
is automatically opened at the beginning of the body, by __description__
\(This section is labeled "DESCRIPTION"\)\. In the same manner the last section
automatically ends at __manpage\_end__\.

Empty sections are *not* ignored\. We are free to \(not\) use paragraphs within
sections\.

> \[manpage\_begin NAME SECTION VERSION\]  
> \[description\]  
> &nbsp;\.\.\.  
> \[__section \{Section A\}__\]  
> &nbsp;\.\.\.  
> \[para\]  
> &nbsp;\.\.\.  
> \[__section \{Section B\}__\]  
> &nbsp;\.\.\.  
> \[manpage\_end\]

Between sections and paragraphs we have subsections, to split sections\. The
command for doing so is __subsection__\. Each occurrence of this command
closes the previous subsection and automatically opens the next, including its
first paragraph\. A subsection is automatically opened at the beginning of the
body, by __description__, and at the beginning of each section\. In the same
manner the last subsection automatically ends at __manpage\_end__\.

Empty subsections are *not* ignored\. We are free to \(not\) use paragraphs
within subsections\.

> \[manpage\_begin NAME SECTION VERSION\]  
> \[description\]  
> &nbsp;\.\.\.  
> \[section \{Section A\}\]  
> &nbsp;\.\.\.  
> \[__subsection \{Sub 1\}__\]  
> &nbsp;\.\.\.  
> \[para\]  
> &nbsp;\.\.\.  
> \[__subsection \{Sub 2\}__\]  
> &nbsp;\.\.\.  
> \[section \{Section B\}\]  
> &nbsp;\.\.\.  
> \[manpage\_end\]

## <a name='subsection5'></a>Text markup

Having handled the overall structure a writer can impose on the document we now
take a closer at the text in a paragraph\.

While most often this is just the unadorned content of the document we do have
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
    Its argument is a widget name\.

The example demonstrating the use of text markup is an excerpt from the
*[doctools language command reference](doctools\_lang\_cmdref\.md)*, with
some highlighting added\. It shows their use within a block of text, as the
arguments of a list item command \(__call__\), and our ability to nest them\.

    \.\.\.
    \[call \[__cmd arg\_def__\] \[__arg type__\] \[__arg name__\] \[__opt__ \[__arg mode__\]\]\]

    Text structure\. List element\. Argument list\. Automatically closes the
    previous list element\. Specifies the data\-\[__arg type__\] of the described
    argument of a command, its \[__arg name__\] and its i/o\-\[__arg mode__\]\. The
    latter is optional\.
    \.\.\.

## <a name='subsection6'></a>Escapes

Beyond the 20 commands for simple markup shown in the previous section we have
two more available which are technically simple markup\. However their function
is not the marking up of phrases as specific types of things, but the insertion
of characters, namely __\[__ and __\]__\. These commands, __lb__ and
__rb__ respectively, are required because our use of \[ and \] to bracket
markup commands makes it impossible to directly use \[ and \] within the text\.

Our example of their use are the sources of the last sentence in the previous
paragraph, with some highlighting added\.

    \.\.\.
    These commands, \[cmd lb\] and \[cmd lb\] respectively, are required
    because our use of \[__lb__\] and \[__rb__\] to bracket markup commands makes it
    impossible to directly use \[__lb__\] and \[__rb__\] within the text\.
    \.\.\.

## <a name='subsection7'></a>Cross\-references

The last two commands we have to discuss are for the declaration of
cross\-references between documents, explicit and implicit\. They are
__[keywords](\.\./\.\./\.\./\.\./index\.md\#keywords)__ and __see\_also__\. Both
take an arbitrary number of arguments, all of which have to be plain unmarked







|
|
|
|
|
|
|
|













|
|
|
|
|







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
    Its argument is a widget name\.

The example demonstrating the use of text markup is an excerpt from the
*[doctools language command reference](doctools\_lang\_cmdref\.md)*, with
some highlighting added\. It shows their use within a block of text, as the
arguments of a list item command \(__call__\), and our ability to nest them\.

> &nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;\[call \[__cmd arg\_def__\] \[__arg type__\] \[__arg name__\] \[__opt__ \[__arg mode__\]\]\]  
>   
> &nbsp;&nbsp;Text structure\. List element\. Argument list\. Automatically closes the  
> &nbsp;&nbsp;previous list element\. Specifies the data\-\[__arg type__\] of the described  
> &nbsp;&nbsp;argument of a command, its \[__arg name__\] and its i/o\-\[__arg mode__\]\. The  
> &nbsp;&nbsp;latter is optional\.  
> &nbsp;&nbsp;\.\.\.

## <a name='subsection6'></a>Escapes

Beyond the 20 commands for simple markup shown in the previous section we have
two more available which are technically simple markup\. However their function
is not the marking up of phrases as specific types of things, but the insertion
of characters, namely __\[__ and __\]__\. These commands, __lb__ and
__rb__ respectively, are required because our use of \[ and \] to bracket
markup commands makes it impossible to directly use \[ and \] within the text\.

Our example of their use are the sources of the last sentence in the previous
paragraph, with some highlighting added\.

> &nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;These commands, \[cmd lb\] and \[cmd lb\] respectively, are required  
> &nbsp;&nbsp;because our use of \[__lb__\] and \[__rb__\] to bracket markup commands makes it  
> &nbsp;&nbsp;impossible to directly use \[__lb__\] and \[__rb__\] within the text\.  
> &nbsp;&nbsp;\.\.\.

## <a name='subsection7'></a>Cross\-references

The last two commands we have to discuss are for the declaration of
cross\-references between documents, explicit and implicit\. They are
__[keywords](\.\./\.\./\.\./\.\./index\.md\#keywords)__ and __see\_also__\. Both
take an arbitrary number of arguments, all of which have to be plain unmarked
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
whether she wants to have them at the beginning of the body, or at its end,
maybe near the place a keyword is actually defined by the main content, or
considers them as meta data which should be in the header, etc\.

Our example shows the sources for the cross\-references of this document, with
some highlighting added\. Incidentally they are found at the end of the body\.

    \.\.\.
    \[__see\_also doctools\_intro__\]
    \[__see\_also doctools\_lang\_syntax__\]
    \[__see\_also doctools\_lang\_cmdref__\]
    \[__keywords markup \{semantic markup\}__\]
    \[__keywords \{doctools markup\} \{doctools language\}__\]
    \[__keywords \{doctools syntax\} \{doctools commands\}__\]
    \[manpage\_end\]

## <a name='subsection8'></a>Examples

Where ever we can write plain text we can write examples too\. For simple
examples we have the command __example__ which takes a single argument, the
text of the argument\. The example text must not contain markup\. If we wish to
have markup within an example we have to use the 2\-command combination
__example\_begin__ / __example\_end__ instead\.

The first opens an example block, the other closes it, and in between we can
write plain text and use all the regular text markup commands\. Note that text
structure commands are not allowed\. This also means that it is not possible to
embed examples and lists within an example\. On the other hand, we *can* use
templating commands within example blocks to read their contents from a file
\(Remember section [Advanced structure](#subsection3)\)\.

The source for the very first example in this document \(see section
[Fundamentals](#subsection1)\), with some highlighting added, is

    \[__example__ \{
        \.\.\. \[list\_begin enumerated\] \.\.\.
      \}\]

Using __example\_begin__ / __example\_end__ this would look like

    \[__example\_begin__\]
        \.\.\. \[list\_begin enumerated\] \.\.\.
      \[__example\_end__\]

## <a name='subsection9'></a>Lists

Where ever we can write plain text we can write lists too\. The main commands are
__list\_begin__ to start a list, and __list\_end__ to close one\. The
opening command takes an argument specifying the type of list started it, and
this in turn determines which of the eight existing list item commands are







|
|
|
|
|
|
|
|



















|
|
|



|
|
|







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
whether she wants to have them at the beginning of the body, or at its end,
maybe near the place a keyword is actually defined by the main content, or
considers them as meta data which should be in the header, etc\.

Our example shows the sources for the cross\-references of this document, with
some highlighting added\. Incidentally they are found at the end of the body\.

> &nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;\[__see\_also doctools\_intro__\]  
> &nbsp;&nbsp;\[__see\_also doctools\_lang\_syntax__\]  
> &nbsp;&nbsp;\[__see\_also doctools\_lang\_cmdref__\]  
> &nbsp;&nbsp;\[__keywords markup \{semantic markup\}__\]  
> &nbsp;&nbsp;\[__keywords \{doctools markup\} \{doctools language\}__\]  
> &nbsp;&nbsp;\[__keywords \{doctools syntax\} \{doctools commands\}__\]  
> &nbsp;&nbsp;\[manpage\_end\]

## <a name='subsection8'></a>Examples

Where ever we can write plain text we can write examples too\. For simple
examples we have the command __example__ which takes a single argument, the
text of the argument\. The example text must not contain markup\. If we wish to
have markup within an example we have to use the 2\-command combination
__example\_begin__ / __example\_end__ instead\.

The first opens an example block, the other closes it, and in between we can
write plain text and use all the regular text markup commands\. Note that text
structure commands are not allowed\. This also means that it is not possible to
embed examples and lists within an example\. On the other hand, we *can* use
templating commands within example blocks to read their contents from a file
\(Remember section [Advanced structure](#subsection3)\)\.

The source for the very first example in this document \(see section
[Fundamentals](#subsection1)\), with some highlighting added, is

> \[__example__ \{  
> &nbsp;&nbsp;&nbsp;&nbsp;\.\.\. \[list\_begin enumerated\] \.\.\.  
> &nbsp;&nbsp;\}\]

Using __example\_begin__ / __example\_end__ this would look like

> \[__example\_begin__\]  
> &nbsp;&nbsp;&nbsp;&nbsp;\.\.\. \[list\_begin enumerated\] \.\.\.  
> &nbsp;&nbsp;\[__example\_end__\]

## <a name='subsection9'></a>Lists

Where ever we can write plain text we can write lists too\. The main commands are
__list\_begin__ to start a list, and __list\_end__ to close one\. The
opening command takes an argument specifying the type of list started it, and
this in turn determines which of the eight existing list item commands are
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
    is a specialized form of a term definition list where the term is the name
    of a configuration option for a widget, with its name and class in the
    option database\.

Our example is the source of the definition list in the previous paragraph, with
most of the content in the middle removed\.

    \.\.\.
    \[__list\_begin__ definitions\]
    \[__def__ \[const arg\]\]

    \(\[cmd arg\_def\]\) This opens an argument \(declaration\) list\. It is a
    specialized form of a definition list where the term is an argument
    name, with its type and i/o\-mode\.

    \[__def__ \[const itemized\]\]

    \(\[cmd item\]\)
    This opens a general itemized list\.

    \.\.\.
    \[__def__ \[const tkoption\]\]

    \(\[cmd tkoption\_def\]\) This opens a widget option \(declaration\) list\. It
    is a specialized form of a definition list where the term is the name
    of a configuration option for a widget, with its name and class in the
    option database\.

    \[__list\_end__\]
    \.\.\.

Note that a list cannot begin in one \(sub\)section and end in another\.
Differently said, \(sub\)section breaks are not allowed within lists and list
items\. An example of this *illegal* construct is

    \.\.\.
    \[list\_begin itemized\]
    \[item\]
    \.\.\.
    \[__section \{ILLEGAL WITHIN THE LIST\}__\]
    \.\.\.
    \[list\_end\]
    \.\.\.

# <a name='section2'></a>FURTHER READING

Now that this document has been digested the reader, assumed to be a *writer*
of documentation should be fortified enough to be able to understand the formal
*[doctools language syntax](doctools\_lang\_syntax\.md)* specification as
well\. From here on out the *[doctools language command







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|





|
|
|
|
|
|
|
|







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
    is a specialized form of a term definition list where the term is the name
    of a configuration option for a widget, with its name and class in the
    option database\.

Our example is the source of the definition list in the previous paragraph, with
most of the content in the middle removed\.

> &nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;\[__list\_begin__ definitions\]  
> &nbsp;&nbsp;\[__def__ \[const arg\]\]  
>   
> &nbsp;&nbsp;\(\[cmd arg\_def\]\) This opens an argument \(declaration\) list\. It is a  
> &nbsp;&nbsp;specialized form of a definition list where the term is an argument  
> &nbsp;&nbsp;name, with its type and i/o\-mode\.  
>   
> &nbsp;&nbsp;\[__def__ \[const itemized\]\]  
>   
> &nbsp;&nbsp;\(\[cmd item\]\)  
> &nbsp;&nbsp;This opens a general itemized list\.  
>   
> &nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;\[__def__ \[const tkoption\]\]  
>   
> &nbsp;&nbsp;\(\[cmd tkoption\_def\]\) This opens a widget option \(declaration\) list\. It  
> &nbsp;&nbsp;is a specialized form of a definition list where the term is the name  
> &nbsp;&nbsp;of a configuration option for a widget, with its name and class in the  
> &nbsp;&nbsp;option database\.  
>   
> &nbsp;&nbsp;\[__list\_end__\]  
> &nbsp;&nbsp;\.\.\.

Note that a list cannot begin in one \(sub\)section and end in another\.
Differently said, \(sub\)section breaks are not allowed within lists and list
items\. An example of this *illegal* construct is

> &nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;\[list\_begin itemized\]  
> &nbsp;&nbsp;\[item\]  
> &nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;\[__section \{ILLEGAL WITHIN THE LIST\}__\]  
> &nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;\[list\_end\]  
> &nbsp;&nbsp;\.\.\.

# <a name='section2'></a>FURTHER READING

Now that this document has been digested the reader, assumed to be a *writer*
of documentation should be fortified enough to be able to understand the formal
*[doctools language syntax](doctools\_lang\_syntax\.md)* specification as
well\. From here on out the *[doctools language command

Changes to embedded/md/tcllib/files/modules/doctools/doctools_lang_syntax.md.

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

  1. The construct LIST\_BEGIN<X> stands for the markup command
     __list\_begin__ with __X__ as its type argument\.

The syntax:

    manpage = defs
              MANPAGE\_BEGIN
              header
              DESCRIPTION
              body
              MANPAGE\_END
              \{ <WHITE> \}

    defs    = \{ INCLUDE &#124; VSET &#124; <WHITE> \}

    header  = \{ TITLEDESC &#124; MODDESC &#124; COPYRIGHT &#124; REQUIRE &#124; defs &#124; xref \}

    xref    = KEYWORDS &#124; SEE\_ALSO &#124; CATEGORY

    body    = paras \{ SECTION    sbody  \}
    sbody   = paras \{ SUBSECTION ssbody \}
    ssbody  = paras

    paras   = tblock \{ \(PARA &#124; NL\) tblock \}

    tblock  = \{ <TEXT> &#124; defs &#124; markup &#124; xref &#124; an\_example &#124; a\_list \}

    markup  = ARG     &#124; CLASS &#124; CMD     &#124; CONST     &#124; EMPH   &#124; FILE
            &#124; FUN     &#124; LB    &#124; METHOD  &#124; NAMESPACE &#124; OPT    &#124; OPTION
            &#124; PACKAGE &#124; RB    &#124; SECTREF &#124; STRONG    &#124; SYSCMD &#124; TERM
            &#124; TYPE    &#124; URI   &#124; USAGE   &#124; VAR       &#124; WIDGET

    example = EXAMPLE
            &#124; EXAMPLE\_BEGIN extext EXAMPLE\_END

    extext  = \{ <TEXT> &#124; defs &#124; markup \}

    a\_list  = LIST\_BEGIN<arguments>   argd\_list   LIST\_END
            &#124; LIST\_BEGIN<commands>    cmdd\_list   LIST\_END
            &#124; LIST\_BEGIN<definitions> def\_list    LIST\_END
            &#124; LIST\_BEGIN<enumerated>  enum\_list   LIST\_END
            &#124; LIST\_BEGIN<itemized>    item\_list   LIST\_END
            &#124; LIST\_BEGIN<options>     optd\_list   LIST\_END
            &#124; LIST\_BEGIN<tkoptions>   tkoptd\_list LIST\_END

    argd\_list   = \[ <WHITE> \] \{ ARG\_DEF      paras \}
    cmdd\_list   = \[ <WHITE> \] \{ CMD\_DEF      paras \}
    def\_list    = \[ <WHITE> \] \{ \(DEF&#124;CALL\)   paras \}
    enum\_list   = \[ <WHITE> \] \{ ENUM         paras \}
    item\_list   = \[ <WHITE> \] \{ ITEM         paras \}
    optd\_list   = \[ <WHITE> \] \{ OPT\_DEF      paras \}
    tkoptd\_list = \[ <WHITE> \] \{ TKOPTION\_DEF paras \}

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *doctools* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|
|

|

|

|

|
|


|

|

|
|
|
|


|

|

|
|
|
|
|
|
|

|
|
|
|
|
|
|







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

  1. The construct LIST\_BEGIN<X> stands for the markup command
     __list\_begin__ with __X__ as its type argument\.

The syntax:

    manpage = defs
              MANPAGE_BEGIN
              header
              DESCRIPTION
              body
              MANPAGE_END
              { <WHITE> }

    defs    = { INCLUDE | VSET | <WHITE> }

    header  = { TITLEDESC | MODDESC | COPYRIGHT | REQUIRE | defs | xref }

    xref    = KEYWORDS | SEE_ALSO | CATEGORY

    body    = paras { SECTION    sbody  }
    sbody   = paras { SUBSECTION ssbody }
    ssbody  = paras

    paras   = tblock { (PARA | NL) tblock }

    tblock  = { <TEXT> | defs | markup | xref | an_example | a_list }

    markup  = ARG     | CLASS | CMD     | CONST     | EMPH   | FILE
            | FUN     | LB    | METHOD  | NAMESPACE | OPT    | OPTION
            | PACKAGE | RB    | SECTREF | STRONG    | SYSCMD | TERM
            | TYPE    | URI   | USAGE   | VAR       | WIDGET

    example = EXAMPLE
            | EXAMPLE_BEGIN extext EXAMPLE_END

    extext  = { <TEXT> | defs | markup }

    a_list  = LIST_BEGIN<arguments>   argd_list   LIST_END
            | LIST_BEGIN<commands>    cmdd_list   LIST_END
            | LIST_BEGIN<definitions> def_list    LIST_END
            | LIST_BEGIN<enumerated>  enum_list   LIST_END
            | LIST_BEGIN<itemized>    item_list   LIST_END
            | LIST_BEGIN<options>     optd_list   LIST_END
            | LIST_BEGIN<tkoptions>   tkoptd_list LIST_END

    argd_list   = [ <WHITE> ] { ARG_DEF      paras }
    cmdd_list   = [ <WHITE> ] { CMD_DEF      paras }
    def_list    = [ <WHITE> ] { (DEF|CALL)   paras }
    enum_list   = [ <WHITE> ] { ENUM         paras }
    item_list   = [ <WHITE> ] { ITEM         paras }
    optd_list   = [ <WHITE> ] { OPT_DEF      paras }
    tkoptd_list = [ <WHITE> ] { TKOPTION_DEF paras }

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *doctools* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/doctools/doctools_plugin_apiref.md.

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
  1. initialize and shutdown each pass

  1. query and initialize engine parameters

After the plugin has been loaded and the frontend commands are established the
commands will be called in the following sequence:

    fmt\_numpasses \-> n
    fmt\_listvariables \-> vars

    fmt\_varset var1 value1
    fmt\_varset var2 value2
    \.\.\.
    fmt\_varset varK valueK
    fmt\_initialize
    fmt\_setup 1
    \.\.\.
    fmt\_setup 2
    \.\.\.
    \.\.\.
    fmt\_setup n
    \.\.\.
    fmt\_postprocess
    fmt\_shutdown
    \.\.\.

I\.e\. first the number of passes and the set of available engine parameters is
established, followed by calls setting the parameters\. That second part is
optional\.

After that the plugin is initialized, the specified number of passes executed,
the final result run through a global post processing step and at last the







|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







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
  1. initialize and shutdown each pass

  1. query and initialize engine parameters

After the plugin has been loaded and the frontend commands are established the
commands will be called in the following sequence:

    fmt_numpasses -> n
    fmt_listvariables -> vars

    fmt_varset var1 value1
    fmt_varset var2 value2
    ...
    fmt_varset varK valueK
    fmt_initialize
    fmt_setup 1
    ...
    fmt_setup 2
    ...
    ...
    fmt_setup n
    ...
    fmt_postprocess
    fmt_shutdown
    ...

I\.e\. first the number of passes and the set of available engine parameters is
established, followed by calls setting the parameters\. That second part is
optional\.

After that the plugin is initialized, the specified number of passes executed,
the final result run through a global post processing step and at last the

Changes to embedded/md/tcllib/files/modules/doctools/mpexpand.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (mpexpand \- Documentation toolbox)
[//000000002]: # (Generated from file 'mpexpand\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2002 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>  
Copyright &copy; 2003 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (mpexpand\(n\) 1\.0 tcllib "Documentation toolbox")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (mpexpand \- Documentation toolbox)
[//000000002]: # (Generated from file 'mpexpand\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2002 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (Copyright &copy; 2003 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000005]: # (mpexpand\(n\) 1\.0 tcllib "Documentation toolbox")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

Changes to embedded/md/tcllib/files/modules/doctools2idx/export_docidx.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::idx::export::docidx \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::export::docidx\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::idx::export::docidx \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::export::docidx\(n\) 0\.2\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.4  
package require doctools::idx::export::docidx ?0\.1?  

[__[export](\.\./\.\./\.\./\.\./index\.md\#export)__ *serial* *configuration*](#1)  

# <a name='description'></a>DESCRIPTION

This package implements the doctools keyword index export plugin for the
generation of docidx markup\.







|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.4  
package require doctools::idx::export::docidx ?0\.2\.1?  

[__[export](\.\./\.\./\.\./\.\./index\.md\#export)__ *serial* *configuration*](#1)  

# <a name='description'></a>DESCRIPTION

This package implements the doctools keyword index export plugin for the
generation of docidx markup\.
246
247
248
249
250
251
252
253

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
246
247
248
249
250
251
252
253

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2idx/idx_export.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::idx::export \- Documentation tools)
[//000000002]: # (Generated from file 'idx\_export\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2018 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::export\(n\) 0\.2 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::idx::export \- Documentation tools)
[//000000002]: # (Generated from file 'idx\_export\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::export\(n\) 0\.2\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require doctools::idx::export ?0\.2?  
package require Tcl 8\.4  
package require doctools::config  
package require doctools::idx::structure  
package require snit  
package require pluginmgr  

[__::doctools::idx::export__ *objectName*](#1)  
[__objectName__ __method__ ?*arg arg \.\.\.*?](#2)  
[*objectName* __destroy__](#3)  







|

|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require doctools::idx::export ?0\.2\.1?  
package require Tcl 8\.4  
package require struct::map  
package require doctools::idx::structure  
package require snit  
package require pluginmgr  

[__::doctools::idx::export__ *objectName*](#1)  
[__objectName__ __method__ ?*arg arg \.\.\.*?](#2)  
[*objectName* __destroy__](#3)  
465
466
467
468
469
470
471
472

# <a name='category'></a>CATEGORY

Documentation tools

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2018 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
465
466
467
468
469
470
471
472

# <a name='category'></a>CATEGORY

Documentation tools

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2idx/idx_export_html.md.

1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::idx::export::html \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::export::html\(n\) 0\.2 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a



|







1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::idx::export::html \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::export::html\(n\) 0\.2 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
344
345
346
347
348
349
350
351

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
344
345
346
347
348
349
350
351

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2idx/idx_export_json.md.

1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::idx::export::json \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::export::json\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a



|







1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::idx::export::json \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::export::json\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
76
77
78
79
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

# <a name='section3'></a>JSON notation of keyword indices

The JSON format used for keyword indices is a direct translation of the
[Keyword index serialization format](#section5), mapping Tcl dictionaries
as JSON objects and Tcl lists as JSON arrays\. For example, the Tcl serialization

    doctools::idx \{
    	label \{Keyword Index\}
    	keywords \{
    		changelog  \{changelog\.man cvs\.man\}
    		conversion \{doctools\.man docidx\.man doctoc\.man apps/dtplite\.man mpexpand\.man\}
    		cvs        cvs\.man
    	\}

    	references \{
    		apps/dtplite\.man \{manpage dtplite\}
    		changelog\.man    \{manpage doctools::changelog\}
    		cvs\.man          \{manpage doctools::cvs\}
    		docidx\.man       \{manpage doctools::idx\}
    		doctoc\.man       \{manpage doctools::toc\}
    		doctools\.man     \{manpage doctools\}
    		mpexpand\.man     \{manpage mpexpand\}
    	\}

    	title \{\}
    \}


is equivalent to the JSON string

    \{

        "doctools::idx" : \{
            "label"      : "Keyword Index",
            "keywords"   : \{
                "changelog"  : \["changelog\.man","cvs\.man"\],
                "conversion" : \["doctools\.man","docidx\.man","doctoc\.man","apps\\/dtplite\.man","mpexpand\.man"\],
                "cvs"        : \["cvs\.man"\],
            \},
            "references" : \{
                "apps\\/dtplite\.man" : \["manpage","dtplite"\],
                "changelog\.man"     : \["manpage","doctools::changelog"\],
                "cvs\.man"           : \["manpage","doctools::cvs"\],
                "docidx\.man"        : \["manpage","doctools::idx"\],
                "doctoc\.man"        : \["manpage","doctools::toc"\],
                "doctools\.man"      : \["manpage","doctools"\],
                "mpexpand\.man"      : \["manpage","mpexpand"\]
            \},
            "title"      : ""
        \}
    \}



# <a name='section4'></a>Configuration

The JSON export plugin recognizes the following configuration variables and
changes its behaviour as they specify\.

  - boolean *indented*







|
|
|
|
|
|
<
>
|
|
|
|
|
|
|
|
<
>
|
<
|
>


<
>
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|

<
<
>
>







76
77
78
79
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

# <a name='section3'></a>JSON notation of keyword indices

The JSON format used for keyword indices is a direct translation of the
[Keyword index serialization format](#section5), mapping Tcl dictionaries
as JSON objects and Tcl lists as JSON arrays\. For example, the Tcl serialization

    doctools::idx {
    	label {Keyword Index}
    	keywords {
    		changelog  {changelog.man cvs.man}
    		conversion {doctools.man docidx.man doctoc.man apps/dtplite.man mpexpand.man}
    		cvs        cvs.man

    	}
    	references {
    		apps/dtplite.man {manpage dtplite}
    		changelog.man    {manpage doctools::changelog}
    		cvs.man          {manpage doctools::cvs}
    		docidx.man       {manpage doctools::idx}
    		doctoc.man       {manpage doctools::toc}
    		doctools.man     {manpage doctools}
    		mpexpand.man     {manpage mpexpand}

    	}
    	title {}

    }

is equivalent to the JSON string


    {
        "doctools::idx" : {
            "label"      : "Keyword Index",
            "keywords"   : {
                "changelog"  : ["changelog.man","cvs.man"],
                "conversion" : ["doctools.man","docidx.man","doctoc.man","apps\/dtplite.man","mpexpand.man"],
                "cvs"        : ["cvs.man"],
            },
            "references" : {
                "apps\/dtplite.man" : ["manpage","dtplite"],
                "changelog.man"     : ["manpage","doctools::changelog"],
                "cvs.man"           : ["manpage","doctools::cvs"],
                "docidx.man"        : ["manpage","doctools::idx"],
                "doctoc.man"        : ["manpage","doctools::toc"],
                "doctools.man"      : ["manpage","doctools"],
                "mpexpand.man"      : ["manpage","mpexpand"]
            },
            "title"      : ""


        }
    }

# <a name='section4'></a>Configuration

The JSON export plugin recognizes the following configuration variables and
changes its behaviour as they specify\.

  - boolean *indented*
253
254
255
256
257
258
259
260

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
253
254
255
256
257
258
259
260

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2idx/idx_export_nroff.md.

1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::idx::export::nroff \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::export::nroff\(n\) 0\.3 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a



|







1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::idx::export::nroff \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::export::nroff\(n\) 0\.3 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
208
209
210
211
212
213
214
215

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
208
209
210
211
212
213
214
215

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2idx/idx_export_text.md.

1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::idx::export::text \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::export::text\(n\) 0\.2 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a



|







1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::idx::export::text \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::export::text\(n\) 0\.2 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
192
193
194
195
196
197
198
199

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
192
193
194
195
196
197
198
199

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2idx/idx_export_wiki.md.

1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::idx::export::wiki \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::export::wiki\(n\) 0\.2 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a



|







1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::idx::export::wiki \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::export::wiki\(n\) 0\.2 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
208
209
210
211
212
213
214
215

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
208
209
210
211
212
213
214
215

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2idx/idx_import.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::idx::import \- Documentation tools)
[//000000002]: # (Generated from file 'idx\_import\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2018 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::import\(n\) 0\.2 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::idx::import \- Documentation tools)
[//000000002]: # (Generated from file 'idx\_import\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::import\(n\) 0\.2\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require doctools::idx::import ?0\.2?  
package require Tcl 8\.4  
package require doctools::config  
package require doctools::idx::structure  
package require snit  
package require pluginmgr  

[__::doctools::idx::import__ *objectName*](#1)  
[__objectName__ __method__ ?*arg arg \.\.\.*?](#2)  
[*objectName* __destroy__](#3)  







|

|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require doctools::idx::import ?0\.2\.1?  
package require Tcl 8\.4  
package require struct::map  
package require doctools::idx::structure  
package require snit  
package require pluginmgr  

[__::doctools::idx::import__ *objectName*](#1)  
[__objectName__ __method__ ?*arg arg \.\.\.*?](#2)  
[*objectName* __destroy__](#3)  
522
523
524
525
526
527
528
529

# <a name='category'></a>CATEGORY

Documentation tools

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2018 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
522
523
524
525
526
527
528
529

# <a name='category'></a>CATEGORY

Documentation tools

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2idx/idx_import_json.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::idx::import::json \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::import::json\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::idx::import::json \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::import::json\(n\) 0\.2\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.4  
package require doctools::idx::import::json ?0\.1?  
package require doctools::idx::structure  
package require json  

[__[import](\.\./\.\./\.\./\.\./index\.md\#import)__ *string* *configuration*](#1)  

# <a name='description'></a>DESCRIPTION








|
|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require doctools::idx::import::json ?0\.2\.1?  
package require doctools::idx::structure  
package require json  

[__[import](\.\./\.\./\.\./\.\./index\.md\#import)__ *string* *configuration*](#1)  

# <a name='description'></a>DESCRIPTION

75
76
77
78
79
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

# <a name='section3'></a>JSON notation of keyword indices

The JSON format used for keyword indices is a direct translation of the
[Keyword index serialization format](#section4), mapping Tcl dictionaries
as JSON objects and Tcl lists as JSON arrays\. For example, the Tcl serialization

    doctools::idx \{
    	label \{Keyword Index\}
    	keywords \{
    		changelog  \{changelog\.man cvs\.man\}
    		conversion \{doctools\.man docidx\.man doctoc\.man apps/dtplite\.man mpexpand\.man\}
    		cvs        cvs\.man
    	\}

    	references \{
    		apps/dtplite\.man \{manpage dtplite\}
    		changelog\.man    \{manpage doctools::changelog\}
    		cvs\.man          \{manpage doctools::cvs\}
    		docidx\.man       \{manpage doctools::idx\}
    		doctoc\.man       \{manpage doctools::toc\}
    		doctools\.man     \{manpage doctools\}
    		mpexpand\.man     \{manpage mpexpand\}
    	\}

    	title \{\}
    \}


is equivalent to the JSON string

    \{

        "doctools::idx" : \{
            "label"      : "Keyword Index",
            "keywords"   : \{
                "changelog"  : \["changelog\.man","cvs\.man"\],
                "conversion" : \["doctools\.man","docidx\.man","doctoc\.man","apps\\/dtplite\.man","mpexpand\.man"\],
                "cvs"        : \["cvs\.man"\],
            \},
            "references" : \{
                "apps\\/dtplite\.man" : \["manpage","dtplite"\],
                "changelog\.man"     : \["manpage","doctools::changelog"\],
                "cvs\.man"           : \["manpage","doctools::cvs"\],
                "docidx\.man"        : \["manpage","doctools::idx"\],
                "doctoc\.man"        : \["manpage","doctools::toc"\],
                "doctools\.man"      : \["manpage","doctools"\],
                "mpexpand\.man"      : \["manpage","mpexpand"\]
            \},
            "title"      : ""
        \}
    \}



# <a name='section4'></a>Keyword index serialization format

Here we specify the format used by the doctools v2 packages to serialize keyword
indices as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
<
>
|
|
|
|
|
|
|
|
<
>
|
<
|
>


<
>
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|

<
<
>
>







75
76
77
78
79
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

# <a name='section3'></a>JSON notation of keyword indices

The JSON format used for keyword indices is a direct translation of the
[Keyword index serialization format](#section4), mapping Tcl dictionaries
as JSON objects and Tcl lists as JSON arrays\. For example, the Tcl serialization

    doctools::idx {
    	label {Keyword Index}
    	keywords {
    		changelog  {changelog.man cvs.man}
    		conversion {doctools.man docidx.man doctoc.man apps/dtplite.man mpexpand.man}
    		cvs        cvs.man

    	}
    	references {
    		apps/dtplite.man {manpage dtplite}
    		changelog.man    {manpage doctools::changelog}
    		cvs.man          {manpage doctools::cvs}
    		docidx.man       {manpage doctools::idx}
    		doctoc.man       {manpage doctools::toc}
    		doctools.man     {manpage doctools}
    		mpexpand.man     {manpage mpexpand}

    	}
    	title {}

    }

is equivalent to the JSON string


    {
        "doctools::idx" : {
            "label"      : "Keyword Index",
            "keywords"   : {
                "changelog"  : ["changelog.man","cvs.man"],
                "conversion" : ["doctools.man","docidx.man","doctoc.man","apps\/dtplite.man","mpexpand.man"],
                "cvs"        : ["cvs.man"],
            },
            "references" : {
                "apps\/dtplite.man" : ["manpage","dtplite"],
                "changelog.man"     : ["manpage","doctools::changelog"],
                "cvs.man"           : ["manpage","doctools::cvs"],
                "docidx.man"        : ["manpage","doctools::idx"],
                "doctoc.man"        : ["manpage","doctools::toc"],
                "doctools.man"      : ["manpage","doctools"],
                "mpexpand.man"      : ["manpage","mpexpand"]
            },
            "title"      : ""


        }
    }

# <a name='section4'></a>Keyword index serialization format

Here we specify the format used by the doctools v2 packages to serialize keyword
indices as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
225
226
227
228
229
230
231
232

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
225
226
227
228
229
230
231
232

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2idx/idx_introduction.md.

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
markup of *tables of contents*, and of general documentation, respectively\.
They are described in their own sets of documents, starting at the *DocTools \-
Tables Of Contents* and the *DocTools \- General*, respectively\.

# <a name='section3'></a>Package Overview

                                        ~~~~~~~~~~~ doctools::idx ~~~~~~~~~~~
                                       ~~                   &#124;               ~~
                    doctools::idx::export ~~~~~~~~~~~~~~~~~ &#124; ~~~~~~~~~~~~~ doctools::idx::import
                            &#124;                               &#124;                       &#124;
            \+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+     &#124;    \+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+
            &#124;               &#124;                         &#124;     &#124;    &#124;                  &#124;               &#124;                       &#124;               &#124;
    doctools::config        =                         &#124;     &#124;    &#124;                  =       doctools::include       doctools::config doctools::paths
                            &#124;                         &#124;     &#124;    &#124;                  &#124;
                    doctools::idx::export::<\*>        &#124;     &#124;    &#124;          doctools::idx::import::<\*>
                            docidx                    &#124;     &#124;    &#124;                  docidx, json
                            json                      &#124;     &#124;    &#124;                  &#124;           \\\\
                            html                      &#124;     &#124;    &#124;          doctools::idx::parse \\\\
                            nroff                     &#124;     &#124;    &#124;                  &#124;             \\\\
                            wiki                      &#124;     &#124;    &#124;  \+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+              json
                            text                      &#124;     &#124;    &#124;  &#124;               &#124;
                                                    doctools::idx::structure        &#124;
                                                                                    &#124;

                                                                            \+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+
                                                                            &#124;                       &#124;
              doctools::html  doctools::html::cssdefaults           doctools::tcl::parse    doctools::msgcat
                    &#124;                                                                               &#124;
              doctools::text  doctools::nroff::man\_macros                                           =
                                                                                                    &#124;

                                                                                            doctools::msgcat::idx::<\*>
                                                                                                    c, en, de, fr
                                                                                                    \(fr == en for now\)
            ~~      Interoperable objects, without actual package dependencies
            \-\-      Package dependency, higher requires lower package
            =       Dynamic dependency through plugin system
            <\*>     Multiple packages following the given form of naming\.

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *doctools* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
>
|
|

|
|
<
>
|

|

|

|







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
markup of *tables of contents*, and of general documentation, respectively\.
They are described in their own sets of documents, starting at the *DocTools \-
Tables Of Contents* and the *DocTools \- General*, respectively\.

# <a name='section3'></a>Package Overview

                                        ~~~~~~~~~~~ doctools::idx ~~~~~~~~~~~
                                       ~~                   |               ~~
                    doctools::idx::export ~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ doctools::idx::import
                            |                               |                       |
            +---------------+-------------------------+     |    +------------------+---------------+-----------------------+---------------+
            |               |                         |     |    |                  |               |                       |               |
    struct::map             =                         |     |    |                  =       doctools::include       struct::map      fileutil::paths
                            |                         |     |    |                  |
                    doctools::idx::export::<*>        |     |    |          doctools::idx::import::<*>
                            docidx                    |     |    |                  docidx, json
                            json                      |     |    |                  |           \
                            html                      |     |    |          doctools::idx::parse \
                            nroff                     |     |    |                  |             \
                            wiki                      |     |    |  +---------------+              json
                            text                      |     |    |  |               |
                                                    doctools::idx::structure        |

                                                                                    |
                                                                            +-------+---------------+
                                                                            |                       |
              doctools::html  doctools::html::cssdefaults           doctools::tcl::parse    doctools::msgcat
                    |                                                                               |
              doctools::text  doctools::nroff::man_macros                                           =

                                                                                                    |
                                                                                            doctools::msgcat::idx::<*>
                                                                                                    c, en, de, fr
                                                                                                    (fr == en for now)
            ~~      Interoperable objects, without actual package dependencies
            --      Package dependency, higher requires lower package
            =       Dynamic dependency through plugin system
            <*>     Multiple packages following the given form of naming.

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *doctools* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/doctools2idx/import_docidx.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::idx::import::docidx \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::import::docidx\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::idx::import::docidx \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::idx::import::docidx\(n\) 0\.2\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.4  
package require doctools::idx::import::docidx ?0\.1?  
package require doctools::idx::parse  
package require doctools::idx::structure  
package require doctools::msgcat  
package require doctools::tcl::parse  
package require fileutil  
package require logger  
package require snit  







|
|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require doctools::idx::import::docidx ?0\.2\.1?  
package require doctools::idx::parse  
package require doctools::idx::structure  
package require doctools::msgcat  
package require doctools::tcl::parse  
package require fileutil  
package require logger  
package require snit  
204
205
206
207
208
209
210
211

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
204
205
206
207
208
209
210
211

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2toc/export_doctoc.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::toc::export::doctoc \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::export::doctoc\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::toc::export::doctoc \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::export::doctoc\(n\) 0\.2\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.4  
package require doctools::toc::export::doctoc ?0\.1?  

[__[export](\.\./\.\./\.\./\.\./index\.md\#export)__ *serial* *configuration*](#1)  

# <a name='description'></a>DESCRIPTION

This package implements the doctools table of contents export plugin for the
generation of doctoc markup\.







|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.4  
package require doctools::toc::export::doctoc ?0\.2\.1?  

[__[export](\.\./\.\./\.\./\.\./index\.md\#export)__ *serial* *configuration*](#1)  

# <a name='description'></a>DESCRIPTION

This package implements the doctools table of contents export plugin for the
generation of doctoc markup\.
274
275
276
277
278
279
280
281

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
274
275
276
277
278
279
280
281

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2toc/import_doctoc.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::toc::import::doctoc \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::import::doctoc\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::toc::import::doctoc \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::import::doctoc\(n\) 0\.2\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.4  
package require doctools::toc::import::doctoc ?0\.1?  
package require doctools::toc::parse  
package require doctools::toc::structure  
package require doctools::msgcat  
package require doctools::tcl::parse  
package require fileutil  
package require logger  
package require snit  







|
|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require doctools::toc::import::doctoc ?0\.2\.1?  
package require doctools::toc::parse  
package require doctools::toc::structure  
package require doctools::msgcat  
package require doctools::tcl::parse  
package require fileutil  
package require logger  
package require snit  
233
234
235
236
237
238
239
240

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
233
234
235
236
237
238
239
240

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2toc/toc_export.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::toc::export \- Documentation tools)
[//000000002]: # (Generated from file 'toc\_export\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2018 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::export\(n\) 0\.2 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::toc::export \- Documentation tools)
[//000000002]: # (Generated from file 'toc\_export\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::export\(n\) 0\.2\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require doctools::toc::export ?0\.2?  
package require Tcl 8\.4  
package require doctools::config  
package require doctools::toc::structure  
package require snit  
package require pluginmgr  

[__::doctools::toc::export__ *objectName*](#1)  
[__objectName__ __method__ ?*arg arg \.\.\.*?](#2)  
[*objectName* __destroy__](#3)  







|

|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require doctools::toc::export ?0\.2\.1?  
package require Tcl 8\.4  
package require struct::map  
package require doctools::toc::structure  
package require snit  
package require pluginmgr  

[__::doctools::toc::export__ *objectName*](#1)  
[__objectName__ __method__ ?*arg arg \.\.\.*?](#2)  
[*objectName* __destroy__](#3)  
479
480
481
482
483
484
485
486

# <a name='category'></a>CATEGORY

Documentation tools

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2018 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
479
480
481
482
483
484
485
486

# <a name='category'></a>CATEGORY

Documentation tools

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2toc/toc_export_html.md.

1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::toc::export::html \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::export::html\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a



|







1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::toc::export::html \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::export::html\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
333
334
335
336
337
338
339
340

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
333
334
335
336
337
338
339
340

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2toc/toc_export_json.md.

1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::toc::export::json \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::export::json\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a



|







1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::toc::export::json \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::export::json\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
76
77
78
79
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

# <a name='section3'></a>JSON notation of tables of contents

The JSON format used for tables of contents is a direct translation of the [ToC
serialization format](#section5), mapping Tcl dictionaries as JSON objects
and Tcl lists as JSON arrays\. For example, the Tcl serialization

    doctools::toc \{
        items \{
            \{reference \{
    	    desc \{DocTools \- Tables of Contents\}
    	     id introduction\.man
    	     label doctools::toc::introduction
    	\}\}
    	\{division \{
    	     id processing\.man
    	     items \{
    	         \{reference \{
    		     desc \{doctoc serialization utilities\}
    		     id structure\.man
    		     label doctools::toc::structure
    		 \}\}
    		 \{reference \{
    		     desc \{Parsing text in doctoc format\}
    		     id parse\.man
    		     label doctools::toc::parse
    		 \}\}
    	     \}

                 label Processing
            \}\}
        \}

        label \{Table of Contents\}
        title TOC
    \}


is equivalent to the JSON string

    \{

        "doctools::toc" : \{
            "items" : \[\{
                "reference" : \{
                    "desc"  : "DocTools \- Tables of Contents",
                    "id"    : "introduction\.man",
                    "label" : "doctools::toc::introduction"

                \}
            \},\{
                "division" : \{
                    "id"    : "processing\.man",
                    "items" : \[\{
                        "reference" : \{
                            "desc"  : "doctoc serialization utilities",
                            "id"    : "structure\.man",
                            "label" : "doctools::toc::structure"

                        \}
                    \},\{
                        "reference" : \{
                            "desc"  : "Parsing text in doctoc format",
                            "id"    : "parse\.man",
                            "label" : "doctools::toc::parse"

                        \}
                    \}\],
                    "label" : "Processing"

                \}
            \}\],
            "label" : "Table of Contents",
            "title" : "TOC"
        \}
    \}



# <a name='section4'></a>Configuration

The JSON export plugin recognizes the following configuration variables and
changes its behaviour as they specify\.

  - boolean *indented*







|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|

<
|
>

<
|
>
|

<
>



<
>
|
|
|
|
|

>
|
<
|
|
|
|

|

>
|
<
|

|

>
|
<

>
|
<


<
<
>
>







76
77
78
79
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

# <a name='section3'></a>JSON notation of tables of contents

The JSON format used for tables of contents is a direct translation of the [ToC
serialization format](#section5), mapping Tcl dictionaries as JSON objects
and Tcl lists as JSON arrays\. For example, the Tcl serialization

    doctools::toc {
        items {
            {reference {
    	    desc {DocTools - Tables of Contents}
    	     id introduction.man
    	     label doctools::toc::introduction
    	}}
    	{division {
    	     id processing.man
    	     items {
    	         {reference {
    		     desc {doctoc serialization utilities}
    		     id structure.man
    		     label doctools::toc::structure
    		 }}
    		 {reference {
    		     desc {Parsing text in doctoc format}
    		     id parse.man
    		     label doctools::toc::parse

    		 }}
    	     }
                 label Processing

            }}
        }
        label {Table of Contents}
        title TOC

    }

is equivalent to the JSON string


    {
        "doctools::toc" : {
            "items" : [{
                "reference" : {
                    "desc"  : "DocTools - Tables of Contents",
                    "id"    : "introduction.man",
                    "label" : "doctools::toc::introduction"
                }
            },{

                "division" : {
                    "id"    : "processing.man",
                    "items" : [{
                        "reference" : {
                            "desc"  : "doctoc serialization utilities",
                            "id"    : "structure.man",
                            "label" : "doctools::toc::structure"
                        }
                    },{

                        "reference" : {
                            "desc"  : "Parsing text in doctoc format",
                            "id"    : "parse.man",
                            "label" : "doctools::toc::parse"
                        }
                    }],

                    "label" : "Processing"
                }
            }],

            "label" : "Table of Contents",
            "title" : "TOC"


        }
    }

# <a name='section4'></a>Configuration

The JSON export plugin recognizes the following configuration variables and
changes its behaviour as they specify\.

  - boolean *indented*
302
303
304
305
306
307
308
309

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
302
303
304
305
306
307
308
309

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2toc/toc_export_nroff.md.

1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::toc::export::nroff \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::export::nroff\(n\) 0\.2 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a



|







1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::toc::export::nroff \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::export::nroff\(n\) 0\.2 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
238
239
240
241
242
243
244
245

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
238
239
240
241
242
243
244
245

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2toc/toc_export_text.md.

1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::toc::export::text \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::export::text\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a



|







1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::toc::export::text \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::export::text\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
221
222
223
224
225
226
227
228

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
221
222
223
224
225
226
227
228

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2toc/toc_export_wiki.md.

1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::toc::export::wiki \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::export::wiki\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a



|







1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (doctools::toc::export::wiki \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::export::wiki\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
230
231
232
233
234
235
236
237

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
230
231
232
233
234
235
236
237

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2toc/toc_import.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::toc::import \- Documentation tools)
[//000000002]: # (Generated from file 'toc\_import\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2018 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::import\(n\) 0\.2 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::toc::import \- Documentation tools)
[//000000002]: # (Generated from file 'toc\_import\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::import\(n\) 0\.2\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require doctools::toc::import ?0\.2?  
package require Tcl 8\.4  
package require doctools::config  
package require doctools::toc::structure  
package require snit  
package require pluginmgr  

[__::doctools::toc::import__ *objectName*](#1)  
[__objectName__ __method__ ?*arg arg \.\.\.*?](#2)  
[*objectName* __destroy__](#3)  







|

|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require doctools::toc::import ?0\.2\.1?  
package require Tcl 8\.4  
package require struct::map  
package require doctools::toc::structure  
package require snit  
package require pluginmgr  

[__::doctools::toc::import__ *objectName*](#1)  
[__objectName__ __method__ ?*arg arg \.\.\.*?](#2)  
[*objectName* __destroy__](#3)  
539
540
541
542
543
544
545
546

# <a name='category'></a>CATEGORY

Documentation tools

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2018 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
539
540
541
542
543
544
545
546

# <a name='category'></a>CATEGORY

Documentation tools

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2toc/toc_import_json.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::toc::import::json \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::import::json\(n\) 0\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (doctools::toc::import::json \- Documentation tools)
[//000000002]: # (Generated from file 'plugin\.inc' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (doctools::toc::import::json\(n\) 0\.2\.1 tcllib "Documentation tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.4  
package require doctools::toc::import::json ?0\.1?  
package require doctools::toc::structure  
package require json  

[__[import](\.\./\.\./\.\./\.\./index\.md\#import)__ *string* *configuration*](#1)  

# <a name='description'></a>DESCRIPTION








|
|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require doctools::toc::import::json ?0\.2\.1?  
package require doctools::toc::structure  
package require json  

[__[import](\.\./\.\./\.\./\.\./index\.md\#import)__ *string* *configuration*](#1)  

# <a name='description'></a>DESCRIPTION

75
76
77
78
79
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

# <a name='section3'></a>JSON notation of tables of contents

The JSON format used for tables of contents is a direct translation of the [ToC
serialization format](#section4), mapping Tcl dictionaries as JSON objects
and Tcl lists as JSON arrays\. For example, the Tcl serialization

    doctools::toc \{
        items \{
            \{reference \{
    	    desc \{DocTools \- Tables of Contents\}
    	     id introduction\.man
    	     label doctools::toc::introduction
    	\}\}
    	\{division \{
    	     id processing\.man
    	     items \{
    	         \{reference \{
    		     desc \{doctoc serialization utilities\}
    		     id structure\.man
    		     label doctools::toc::structure
    		 \}\}
    		 \{reference \{
    		     desc \{Parsing text in doctoc format\}
    		     id parse\.man
    		     label doctools::toc::parse
    		 \}\}
    	     \}

                 label Processing
            \}\}
        \}

        label \{Table of Contents\}
        title TOC
    \}


is equivalent to the JSON string

    \{

        "doctools::toc" : \{
            "items" : \[\{
                "reference" : \{
                    "desc"  : "DocTools \- Tables of Contents",
                    "id"    : "introduction\.man",
                    "label" : "doctools::toc::introduction"

                \}
            \},\{
                "division" : \{
                    "id"    : "processing\.man",
                    "items" : \[\{
                        "reference" : \{
                            "desc"  : "doctoc serialization utilities",
                            "id"    : "structure\.man",
                            "label" : "doctools::toc::structure"

                        \}
                    \},\{
                        "reference" : \{
                            "desc"  : "Parsing text in doctoc format",
                            "id"    : "parse\.man",
                            "label" : "doctools::toc::parse"

                        \}
                    \}\],
                    "label" : "Processing"

                \}
            \}\],
            "label" : "Table of Contents",
            "title" : "TOC"
        \}
    \}



# <a name='section4'></a>ToC serialization format

Here we specify the format used by the doctools v2 packages to serialize tables
of contents as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|

<
|
>

<
|
>
|

<
>



<
>
|
|
|
|
|

>
|
<
|
|
|
|

|

>
|
<
|

|

>
|
<

>
|
<


<
<
>
>







75
76
77
78
79
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

# <a name='section3'></a>JSON notation of tables of contents

The JSON format used for tables of contents is a direct translation of the [ToC
serialization format](#section4), mapping Tcl dictionaries as JSON objects
and Tcl lists as JSON arrays\. For example, the Tcl serialization

    doctools::toc {
        items {
            {reference {
    	    desc {DocTools - Tables of Contents}
    	     id introduction.man
    	     label doctools::toc::introduction
    	}}
    	{division {
    	     id processing.man
    	     items {
    	         {reference {
    		     desc {doctoc serialization utilities}
    		     id structure.man
    		     label doctools::toc::structure
    		 }}
    		 {reference {
    		     desc {Parsing text in doctoc format}
    		     id parse.man
    		     label doctools::toc::parse

    		 }}
    	     }
                 label Processing

            }}
        }
        label {Table of Contents}
        title TOC

    }

is equivalent to the JSON string


    {
        "doctools::toc" : {
            "items" : [{
                "reference" : {
                    "desc"  : "DocTools - Tables of Contents",
                    "id"    : "introduction.man",
                    "label" : "doctools::toc::introduction"
                }
            },{

                "division" : {
                    "id"    : "processing.man",
                    "items" : [{
                        "reference" : {
                            "desc"  : "doctoc serialization utilities",
                            "id"    : "structure.man",
                            "label" : "doctools::toc::structure"
                        }
                    },{

                        "reference" : {
                            "desc"  : "Parsing text in doctoc format",
                            "id"    : "parse.man",
                            "label" : "doctools::toc::parse"
                        }
                    }],

                    "label" : "Processing"
                }
            }],

            "label" : "Table of Contents",
            "title" : "TOC"


        }
    }

# <a name='section4'></a>ToC serialization format

Here we specify the format used by the doctools v2 packages to serialize tables
of contents as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
274
275
276
277
278
279
280
281

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
274
275
276
277
278
279
280
281

# <a name='category'></a>CATEGORY

Text formatter plugin

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009\-2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/doctools2toc/toc_introduction.md.

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
markup of *keyword indices*, and of general documentation, respectively\. They
are described in their own sets of documents, starting at the *DocTools \-
Keyword Indices* and the *DocTools \- General*, respectively\.

# <a name='section3'></a>Package Overview

                                        ~~~~~~~~~~~ doctools::toc ~~~~~~~~~~~
                                       ~~                   &#124;               ~~
                    doctools::toc::export ~~~~~~~~~~~~~~~~~ &#124; ~~~~~~~~~~~~~ doctools::toc::import
                            &#124;                               &#124;                       &#124;
            \+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+     &#124;    \+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+
            &#124;               &#124;                         &#124;     &#124;    &#124;                  &#124;               &#124;                       &#124;               &#124;
    doctools::config        =                         &#124;     &#124;    &#124;                  =       doctools::include       doctools::config doctools::paths
                            &#124;                         &#124;     &#124;    &#124;                  &#124;
                    doctools::toc::export::<\*>        &#124;     &#124;    &#124;          doctools::toc::import::<\*>
                            doctoc                    &#124;     &#124;    &#124;                  doctoc, json
                            json                      &#124;     &#124;    &#124;                  &#124;           \\\\
                            html                      &#124;     &#124;    &#124;          doctools::toc::parse \\\\
                            nroff                     &#124;     &#124;    &#124;                  &#124;             \\\\
                            wiki                      &#124;     &#124;    &#124;  \+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+              json
                            text                      &#124;     &#124;    &#124;  &#124;               &#124;
                                                    doctools::toc::structure        &#124;
                                                                                    &#124;

                                                                            \+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+
                                                                            &#124;                       &#124;
              doctools::html  doctools::html::cssdefaults           doctools::tcl::parse    doctools::msgcat
                    &#124;                                                                               &#124;
              doctools::text  doctools::nroff::man\_macros                                           =
                                                                                                    &#124;

                                                                                            doctools::msgcat::toc::<\*>
                                                                                                    c, en, de, fr
                                                                                                    \(fr == en for now\)
            ~~      Interoperable objects, without actual package dependencies
            \-\-      Package dependency, higher requires lower package
            =       Dynamic dependency through plugin system
            <\*>     Multiple packages following the given form of naming\.

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *doctools* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
>
|
|

|
|
<
>
|

|

|

|







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
markup of *keyword indices*, and of general documentation, respectively\. They
are described in their own sets of documents, starting at the *DocTools \-
Keyword Indices* and the *DocTools \- General*, respectively\.

# <a name='section3'></a>Package Overview

                                        ~~~~~~~~~~~ doctools::toc ~~~~~~~~~~~
                                       ~~                   |               ~~
                    doctools::toc::export ~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ doctools::toc::import
                            |                               |                       |
            +---------------+-------------------------+     |    +------------------+---------------+-----------------------+---------------+
            |               |                         |     |    |                  |               |                       |               |
    struct:map              =                         |     |    |                  =       doctools::include       struct::map      fileutil::paths
                            |                         |     |    |                  |
                    doctools::toc::export::<*>        |     |    |          doctools::toc::import::<*>
                            doctoc                    |     |    |                  doctoc, json
                            json                      |     |    |                  |           \
                            html                      |     |    |          doctools::toc::parse \
                            nroff                     |     |    |                  |             \
                            wiki                      |     |    |  +---------------+              json
                            text                      |     |    |  |               |
                                                    doctools::toc::structure        |

                                                                                    |
                                                                            +-------+---------------+
                                                                            |                       |
              doctools::html  doctools::html::cssdefaults           doctools::tcl::parse    doctools::msgcat
                    |                                                                               |
              doctools::text  doctools::nroff::man_macros                                           =

                                                                                                    |
                                                                                            doctools::msgcat::toc::<*>
                                                                                                    c, en, de, fr
                                                                                                    (fr == en for now)
            ~~      Interoperable objects, without actual package dependencies
            --      Package dependency, higher requires lower package
            =       Dynamic dependency through plugin system
            <*>     Multiple packages following the given form of naming.

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *doctools* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/dtplite/pkg_dtplite.md.

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
  - \[2\]

    The following directory structure is created when processing a single set of
    input documents\. The file extension used is for output in HTML, but that is
    not relevant to the structure and was just used to have proper file names\.

        output/
            toc\.html
            index\.html
            files/
                path/to/FOO\.html

    The last line in the example shows the document generated for a file FOO
    located at

        inputdirectory/path/to/FOO

  - \[3\]

    When merging many packages into a unified set of documents the generated
    directory structure is a bit deeper:

        output
            \.toc
            \.idx
            \.tocdoc
            \.idxdoc
            \.xrf
            toc\.html
            index\.html
            FOO1/
                \.\.\.
            FOO2/
                toc\.html
                files/
                    path/to/BAR\.html

    Each of the directories FOO1, \.\.\. contains the documents generated for the
    package FOO1, \.\.\. and follows the structure shown for use case \[2\]\. The only
    exception is that there is no per\-package index\.

    The files "\.toc", "\.idx", and "\.xrf" contain the internal status of the
    whole output and will be read and updated by the next invokation\. Their







|
|

|












|
|
|
|
|
|
|

|

|

|







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
  - \[2\]

    The following directory structure is created when processing a single set of
    input documents\. The file extension used is for output in HTML, but that is
    not relevant to the structure and was just used to have proper file names\.

        output/
            toc.html
            index.html
            files/
                path/to/FOO.html

    The last line in the example shows the document generated for a file FOO
    located at

        inputdirectory/path/to/FOO

  - \[3\]

    When merging many packages into a unified set of documents the generated
    directory structure is a bit deeper:

        output
            .toc
            .idx
            .tocdoc
            .idxdoc
            .xrf
            toc.html
            index.html
            FOO1/
                ...
            FOO2/
                toc.html
                files/
                    path/to/BAR.html

    Each of the directories FOO1, \.\.\. contains the documents generated for the
    package FOO1, \.\.\. and follows the structure shown for use case \[2\]\. The only
    exception is that there is no per\-package index\.

    The files "\.toc", "\.idx", and "\.xrf" contain the internal status of the
    whole output and will be read and updated by the next invokation\. Their

Changes to embedded/md/tcllib/files/modules/fileutil/fileutil.md.

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

    This command performs purely lexical normalization on the *path* and
    returns the changed path as its result\. Symbolic links in the path are
    *not* resolved\.

    Examples:

        fileutil::lexnormalize /foo/\./bar
        => /foo/bar

        fileutil::lexnormalize /foo/\.\./bar
        => /bar

  - <a name='2'></a>__::fileutil::fullnormalize__ *path*

    This command resolves all symbolic links in the *path* and returns the
    changed path as its result\. In contrast to the builtin __file
    normalize__ this command resolves a symbolic link in the last element of







|


|







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

    This command performs purely lexical normalization on the *path* and
    returns the changed path as its result\. Symbolic links in the path are
    *not* resolved\.

    Examples:

        fileutil::lexnormalize /foo/./bar
        => /foo/bar

        fileutil::lexnormalize /foo/../bar
        => /bar

  - <a name='2'></a>__::fileutil::fullnormalize__ *path*

    This command resolves all symbolic links in the *path* and returns the
    changed path as its result\. In contrast to the builtin __file
    normalize__ this command resolves a symbolic link in the last element of
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    joined it with the result of __pwd__ to get an absolute filename\.

    The result of *filtercmd* is a boolean value that indicates if the current
    file should be included in the list of interesting files\.

    Example:

        \# find \.tcl files
        package require fileutil
        proc is\_tcl \{name\} \{return \[string match \*\.tcl $name\]\}
        set tcl\_files \[fileutil::find \. is\_tcl\]

  - <a name='13'></a>__::fileutil::findByPattern__ *basedir* ?__\-regexp__&#124;__\-glob__? ?__\-\-__? *patterns*

    This command is based upon the __TclX__ command __recursive\_glob__,
    except that it doesn't allow recursion over more than one directory at a
    time\. It uses __::fileutil::find__ internally and is thus able to and
    does follow symbolic links, something the __TclX__ command does not do\.







|

|
|







248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    joined it with the result of __pwd__ to get an absolute filename\.

    The result of *filtercmd* is a boolean value that indicates if the current
    file should be included in the list of interesting files\.

    Example:

        # find .tcl files
        package require fileutil
        proc is_tcl {name} {return [string match *.tcl $name]}
        set tcl_files [fileutil::find . is_tcl]

  - <a name='13'></a>__::fileutil::findByPattern__ *basedir* ?__\-regexp__&#124;__\-glob__? ?__\-\-__? *patterns*

    This command is based upon the __TclX__ command __recursive\_glob__,
    except that it doesn't allow recursion over more than one directory at a
    time\. It uses __::fileutil::find__ internally and is thus able to and
    does follow symbolic links, something the __TclX__ command does not do\.
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

    A concrete example and extreme case is the "/sys" hierarchy under Linux
    where some hundred devices exist under both "/sys/devices" and "/sys/class"
    with the two sub\-hierarchies linking to the other, generating millions of
    legal paths to enumerate\. The structure, reduced to three devices, roughly
    looks like

        /sys/class/tty/tty0 \-\-> \.\./\.\./dev/tty0
        /sys/class/tty/tty1 \-\-> \.\./\.\./dev/tty1
        /sys/class/tty/tty2 \-\-> \.\./\.\./dev/tty1

        /sys/dev/tty0/bus
        /sys/dev/tty0/subsystem \-\-> \.\./\.\./class/tty
        /sys/dev/tty1/bus
        /sys/dev/tty1/subsystem \-\-> \.\./\.\./class/tty
        /sys/dev/tty2/bus
        /sys/dev/tty2/subsystem \-\-> \.\./\.\./class/tty

    The command __fileutil::find__ currently has no way to escape this\. When
    having to handle such a pathological hierarchy It is recommended to switch
    to package __fileutil::traverse__ and the same\-named command it
    provides, and then use the __\-prefilter__ option to prevent the
    traverser from following symbolic links, like so:

        package require fileutil::traverse

        proc NoLinks \{fileName\} \{
            if \{\[string equal \[file type $fileName\] link\]\} \{
                return 0
            \}

            return 1
        \}


        fileutil::traverse T /sys/devices \-prefilter NoLinks
        T foreach p \{
            puts $p
        \}

        T destroy

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *fileutil* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas







|
|
|


|

|

|









|
|

<
>

<
|
>
|
|

<
>







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

    A concrete example and extreme case is the "/sys" hierarchy under Linux
    where some hundred devices exist under both "/sys/devices" and "/sys/class"
    with the two sub\-hierarchies linking to the other, generating millions of
    legal paths to enumerate\. The structure, reduced to three devices, roughly
    looks like

        /sys/class/tty/tty0 --> ../../dev/tty0
        /sys/class/tty/tty1 --> ../../dev/tty1
        /sys/class/tty/tty2 --> ../../dev/tty1

        /sys/dev/tty0/bus
        /sys/dev/tty0/subsystem --> ../../class/tty
        /sys/dev/tty1/bus
        /sys/dev/tty1/subsystem --> ../../class/tty
        /sys/dev/tty2/bus
        /sys/dev/tty2/subsystem --> ../../class/tty

    The command __fileutil::find__ currently has no way to escape this\. When
    having to handle such a pathological hierarchy It is recommended to switch
    to package __fileutil::traverse__ and the same\-named command it
    provides, and then use the __\-prefilter__ option to prevent the
    traverser from following symbolic links, like so:

        package require fileutil::traverse

        proc NoLinks {fileName} {
            if {[string equal [file type $fileName] link]} {
                return 0

            }
            return 1

        }

        fileutil::traverse T /sys/devices -prefilter NoLinks
        T foreach p {
            puts $p

        }
        T destroy

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *fileutil* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas

Changes to embedded/md/tcllib/files/modules/fileutil/multiop.md.

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
    Returns the current path type limiter\.

# <a name='section5'></a>EXAMPLES

The following examples assume that the variable __F__ contains a reference
to a multi\-file operation object\.

        $F do copy                       \\\\
    	the  \*\.dll                    \\\\
    	from c:/TDK/PrivateOpenSSL/bin \\\\
    	to   \[installdir\_of tls\]

        $F do move      \\\\
    	the  \*       \\\\
    	from /sources \\\\
    	into /scratch  \\\\
    	but not \*\.html

        \# Alternatively use 'except for \*\.html'\.

        $F do           \\\\
    	move         \\\\
    	the  index    \\\\
    	from /sources  \\\\
    	into /scratch   \\\\
    	as   pkgIndex\.tcl

        $F do         \\\\
    	remove     \\\\
    	the \*\.txt  \\\\
    	in /scratch

Note that the fact that most commands just modify the object state allows us to
use more off forms as specifications instead of just nearly\-natural language
sentences\. For example the second example in this section can re\-arranged into:

        $F do            \\\\
    	from /sources \\\\
    	into /scratch  \\\\
    	but not \*\.html \\\\
    	move           \\\\
    	the  \*

and the result is not only still a valid specification, but even stays
relatively readable\.

Further note that the information collected by the commands __but__,
__except__, and __as__ is automatically reset after the associated
__the__ was executed\. However no other state is reset in that manner,
allowing the user to avoid repetitions of unchanging information\. For example
the second and third examples of this section can be merged and rewritten into
the equivalent:

    $F do                   \\\\
        move                 \\\\
        the  \*                \\\\
        from /sources          \\\\
        into /scratch           \\\\
        but not \*\.html not index \\\\
        the  index               \\\\
        as   pkgIndex\.tcl

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *fileutil* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|
|
|
|

|
|
|
|
|

|

|
|
|
|
|
|

|
|
|






|
|
|
|
|
|











|
|
|
|
|
|
|
|







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
    Returns the current path type limiter\.

# <a name='section5'></a>EXAMPLES

The following examples assume that the variable __F__ contains a reference
to a multi\-file operation object\.

        $F do copy                       \
    	the  *.dll                    \
    	from c:/TDK/PrivateOpenSSL/bin \
    	to   [installdir_of tls]

        $F do move      \
    	the  *       \
    	from /sources \
    	into /scratch  \
    	but not *.html

        # Alternatively use 'except for *.html'.

        $F do           \
    	move         \
    	the  index    \
    	from /sources  \
    	into /scratch   \
    	as   pkgIndex.tcl

        $F do         \
    	remove     \
    	the *.txt  \
    	in /scratch

Note that the fact that most commands just modify the object state allows us to
use more off forms as specifications instead of just nearly\-natural language
sentences\. For example the second example in this section can re\-arranged into:

        $F do            \
    	from /sources \
    	into /scratch  \
    	but not *.html \
    	move           \
    	the  *

and the result is not only still a valid specification, but even stays
relatively readable\.

Further note that the information collected by the commands __but__,
__except__, and __as__ is automatically reset after the associated
__the__ was executed\. However no other state is reset in that manner,
allowing the user to avoid repetitions of unchanging information\. For example
the second and third examples of this section can be merged and rewritten into
the equivalent:

    $F do                   \
        move                 \
        the  *                \
        from /sources          \
        into /scratch           \
        but not *.html not index \
        the  index               \
        as   pkgIndex.tcl

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *fileutil* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Added embedded/md/tcllib/files/modules/fileutil/paths.md.









































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

[//000000001]: # (fileutil::paths \- )
[//000000002]: # (Generated from file 'paths\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (fileutil::paths\(n\) 1 tcllib "")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

# NAME

fileutil::paths \- Manage search path pools

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Synopsis](#synopsis)

  - [Description](#section1)

  - [API](#section2)

  - [Bugs, Ideas, Feedback](#section3)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.4  
package require fileutil::paths ?1?  

[__::fileutil::paths__ *poolName*](#1)  
[__poolName__ __method__ ?*arg arg \.\.\.*?](#2)  
[*poolName* __add__ *path*](#3)  
[*poolName* __clear__](#4)  
[*poolName* __paths__](#5)  
[*poolName* __remove__ *path*](#6)  

# <a name='description'></a>DESCRIPTION

Provides a snit class whose instances manage a pool of \(search\) paths\.

# <a name='section2'></a>API

The main command provides construction of search path pools:

  - <a name='1'></a>__::fileutil::paths__ *poolName*

    Creates a new, empty pool of search paths with an associated global Tcl
    command whose name is *poolName*\. It may be used to invoke various
    operations on the pool\. It has the following general form:

      * <a name='2'></a>__poolName__ __method__ ?*arg arg \.\.\.*?

        __method__ and *arg*uments determine the exact behavior of the
        command\.

    If *poolName* is specified as __%AUTO%__ a unique name will be
    generated by the package itself\. The result of the command is the
    fully\-qualified name of the instance command\.

The following commands are possible for pool objects:

  - <a name='3'></a>*poolName* __add__ *path*

    Adds the *path* to the pool\. Nothing is done if the *path* is already
    known to the pool\. The result of the command is the empty string\.

  - <a name='4'></a>*poolName* __clear__

    Clears the entire pool\. In other words, removes all paths from it\. The
    result of the command is the empty string\.

  - <a name='5'></a>*poolName* __paths__

    Returns the list of all paths known to the pool, in the order they were
    added\.

  - <a name='6'></a>*poolName* __remove__ *path*

    Removes the *path* from the pool, if it is known to the pool\. Unknown
    paths are ignored without error\. The result of the command is the empty
    string\.

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *fileutil* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

When proposing code changes, please provide *unified diffs*, i\.e the output of
__diff \-u__\.

Note further that *attachments* are strongly preferred over inlined patches\.
Attachments can be made by going to the __Edit__ form of the ticket
immediately after its creation, and then using the left\-most button in the
secondary navigation bar\.

Changes to embedded/md/tcllib/files/modules/fileutil/traverse.md.

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

    A concrete example and extreme case is the "/sys" hierarchy under Linux
    where some hundred devices exist under both "/sys/devices" and "/sys/class"
    with the two sub\-hierarchies linking to the other, generating millions of
    legal paths to enumerate\. The structure, reduced to three devices, roughly
    looks like

        /sys/class/tty/tty0 \-\-> \.\./\.\./dev/tty0
        /sys/class/tty/tty1 \-\-> \.\./\.\./dev/tty1
        /sys/class/tty/tty2 \-\-> \.\./\.\./dev/tty1

        /sys/dev/tty0/bus
        /sys/dev/tty0/subsystem \-\-> \.\./\.\./class/tty
        /sys/dev/tty1/bus
        /sys/dev/tty1/subsystem \-\-> \.\./\.\./class/tty
        /sys/dev/tty2/bus
        /sys/dev/tty2/subsystem \-\-> \.\./\.\./class/tty

    When having to handle such a pathological hierarchy it is recommended to use
    the __\-prefilter__ option to prevent the traverser from following
    symbolic links, like so:

        package require fileutil::traverse

        proc NoLinks \{fileName\} \{
            if \{\[string equal \[file type $fileName\] link\]\} \{
                return 0
            \}

            return 1
        \}


        fileutil::traverse T /sys/devices \-prefilter NoLinks
        T foreach p \{
            puts $p
        \}

        T destroy

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *fileutil* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas







|
|
|


|

|

|







|
|

<
>

<
|
>
|
|

<
>







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

    A concrete example and extreme case is the "/sys" hierarchy under Linux
    where some hundred devices exist under both "/sys/devices" and "/sys/class"
    with the two sub\-hierarchies linking to the other, generating millions of
    legal paths to enumerate\. The structure, reduced to three devices, roughly
    looks like

        /sys/class/tty/tty0 --> ../../dev/tty0
        /sys/class/tty/tty1 --> ../../dev/tty1
        /sys/class/tty/tty2 --> ../../dev/tty1

        /sys/dev/tty0/bus
        /sys/dev/tty0/subsystem --> ../../class/tty
        /sys/dev/tty1/bus
        /sys/dev/tty1/subsystem --> ../../class/tty
        /sys/dev/tty2/bus
        /sys/dev/tty2/subsystem --> ../../class/tty

    When having to handle such a pathological hierarchy it is recommended to use
    the __\-prefilter__ option to prevent the traverser from following
    symbolic links, like so:

        package require fileutil::traverse

        proc NoLinks {fileName} {
            if {[string equal [file type $fileName] link]} {
                return 0

            }
            return 1

        }

        fileutil::traverse T /sys/devices -prefilter NoLinks
        T foreach p {
            puts $p

        }
        T destroy

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *fileutil* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas

Changes to embedded/md/tcllib/files/modules/fumagic/rtcore.md.

167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
    This command behaves mostly like __::fileutil::magic::rt::Nv__, except
    that it compares the fetched and masked value against *val* as specified
    with *comp* and returns the result of that comparison\.

    The argument *comp* has to contain one of Tcl's comparison operators, and
    the comparison made will be

        <val> <comp> <fetched\-and\-masked\-value>

    The special comparison operator __x__ signals that no comparison should
    be done, or, in other words, that the fetched value will always match
    *val*\.

  - <a name='12'></a>__::fileutil::magic::rt::Nvx__ *type* *offset* ?*qual*?








|







167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
    This command behaves mostly like __::fileutil::magic::rt::Nv__, except
    that it compares the fetched and masked value against *val* as specified
    with *comp* and returns the result of that comparison\.

    The argument *comp* has to contain one of Tcl's comparison operators, and
    the comparison made will be

        <val> <comp> <fetched-and-masked-value>

    The special comparison operator __x__ signals that no comparison should
    be done, or, in other words, that the fetched value will always match
    *val*\.

  - <a name='12'></a>__::fileutil::magic::rt::Nvx__ *type* *offset* ?*qual*?

Changes to embedded/md/tcllib/files/modules/generator/generator.md.

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
multiple return values and looping over multiple generators at once\. Writing a
generator is also a simple task, much like writing a normal procedure: simply
use the __define__ command to define the generator, and then call
__yield__ instead of __[return](\.\./\.\./\.\./\.\./index\.md\#return)__\. For
example, we can define a generator for looping through the integers in a
particular range:

    generator define range \{n m\} \{
        for \{set i $n\} \{$i <= $m\} \{incr i\} \{ generator yield $i \}
    \}

    generator foreach x \[range 1 10\] \{
        puts "x = $x"
    \}


The above example will print the numbers from 1 to 10 in sequence, as you would
expect\. The difference from a normal loop over a list is that the numbers are
only generated as they are needed\. If we insert a break into the loop then any
remaining numbers in the sequence would never be generated\. To illustrate, we
can define a generator that produces the sequence of natural numbers: an
infinite series\. A normal procedure would never return trying to produce this
series as a list\. By using a generator we only have to generate those values
which are actually used:

    generator define nats \{\} \{
        while 1 \{ generator yield \[incr nat\] \}
    \}

    generator foreach n \[nats\] \{
        if \{$n > 100\} \{ break \}
    \}


# <a name='section2'></a>COMMANDS

  - <a name='1'></a>__generator__ __define__ *name* *params* *body*

    Creates a new generator procedure\. The arguments to the command are
    identical to those for __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__: a







|
|
<
>
|

<
>










|
|
<
>
|
|
<
>







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
multiple return values and looping over multiple generators at once\. Writing a
generator is also a simple task, much like writing a normal procedure: simply
use the __define__ command to define the generator, and then call
__yield__ instead of __[return](\.\./\.\./\.\./\.\./index\.md\#return)__\. For
example, we can define a generator for looping through the integers in a
particular range:

    generator define range {n m} {
        for {set i $n} {$i <= $m} {incr i} { generator yield $i }

    }
    generator foreach x [range 1 10] {
        puts "x = $x"

    }

The above example will print the numbers from 1 to 10 in sequence, as you would
expect\. The difference from a normal loop over a list is that the numbers are
only generated as they are needed\. If we insert a break into the loop then any
remaining numbers in the sequence would never be generated\. To illustrate, we
can define a generator that produces the sequence of natural numbers: an
infinite series\. A normal procedure would never return trying to produce this
series as a list\. By using a generator we only have to generate those values
which are actually used:

    generator define nats {} {
        while 1 { generator yield [incr nat] }

    }
    generator foreach n [nats] {
        if {$n > 100} { break }

    }

# <a name='section2'></a>COMMANDS

  - <a name='1'></a>__generator__ __define__ *name* *params* *body*

    Creates a new generator procedure\. The arguments to the command are
    identical to those for __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__: a
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
    be used like a __finally__ block in the
    __[try](\.\./try/tcllib\_try\.md)__ command, except that it is tied to
    the life\-cycle of the generator rather than to a particular scope\. For
    example, if we create a generator to iterate over the lines in a text file,
    we can use __finally__ to ensure that the file is closed whenever the
    generator is destroyed:

    generator define lines file \{
        set in \[open $file\]
        \# Ensure file is always closed
        generator finally close $in
        while \{\[gets $in line\] >= 0\} \{
            generator yield $line
        \}
    \}


    generator foreach line \[lines /etc/passwd\] \{
        puts "\[incr count\]: $line"
        if \{$count > 10\} \{ break \}
    \}

    \# File will be closed even on early exit

    If you create a generator that consumes another generator \(such as the
    standard __map__ and __filter__ generators defined later\), then you
    should use a __finally__ command to ensure that this generator is
    destroyed when its parent is\. For example, the __map__ generator is
    defined as follows:

    generator define map \{f xs\} \{
        generator finally generator destroy $xs
        generator foreach x $xs \{ generator yield \[\{\*\}$f $x\] \}
    \}


  - <a name='9'></a>__generator__ __from__ *format* *value*

    Creates a generator from a data structure\. Currently, supported formats are
    __list__, __dict__, or __string__\. The list format yields each
    element in turn\. For dictionaries, each key and value are yielded
    separately\. Finally, strings are yielded a character at a time\.

  - <a name='10'></a>__generator__ __to__ *format* *generator*

    Converts a generator into a data structure\. This is the reverse operation of
    the __from__ command, and supports the same data structures\. The two
    operations obey the following identity laws \(where __=__ is interpreted
    appropriately\):

    \[generator to $fmt \[generator from $fmt $value\]\] = $value
    \[generator from $fmt \[generator to $fmt $gen\]\]   = $gen

# <a name='section3'></a>PRELUDE

The following commands are provided as a standard library of generator
combinators and functions that perform convenience operations on generators\. The
functions in this section are loosely modelled on the equivalent functions from
the Haskell Prelude\. *Warning:* most of the functions in this prelude destroy
any generator arguments they are passed as a side\-effect\. If you want to have
persistent generators, see the streams library\.

  - <a name='11'></a>__generator__ __map__ *function* *generator*

    Apply a function to every element of a generator, returning a new generator
    of the results\. This is the classic map function from functional
    programming, applied to generators\. For example, we can generate all the
    square numbers using the following code \(where __nats__ is defined as
    earlier\):

    proc square x \{ expr \{$x \* $x\} \}
    generator foreach n \[generator map square \[nats\]\] \{
        puts "n = $n"
        if \{$n > 1000\} \{ break \}
    \}


  - <a name='12'></a>__generator__ __filter__ *predicate* *generator*

    Another classic functional programming gem\. This command returns a generator
    that yields only those items from the argument generator that satisfy the
    predicate \(boolean function\)\. For example, if we had a generator
    __employees__ that returned a stream of dictionaries representing
    people, we could filter all those whose salaries are above 100,000 dollars
    \(or whichever currency you prefer\) using a simple filter:

    proc salary> \{amount person\} \{ expr \{\[dict get $person salary\] > $amount\} \}
    set fat\-cats \[generator filter \{salary> 100000\} $employees\]

  - <a name='13'></a>__generator__ __reduce__ *function* *zero* *generator*

    This is the classic left\-fold operation\. This command takes a function, an
    initial value, and a generator of values\. For each element in the generator
    it applies the function to the current accumulator value \(the *zero*
    argument initially\) and that element, and then uses the result as the new
    accumulator value\. This process is repeated through the entire generator
    \(eagerly\) and the final accumulator value is then returned\. If we consider
    the function to be a binary operator, and the zero argument to be the left
    identity element of that operation, then we can consider the __reduce__
    command as *folding* the operator between each successive pair of values
    in the generator in a left\-associative fashion\. For example, the sum of a
    sequence of numbers can be calculated by folding a __\+__ operator
    between them, with 0 as the identity:

    \# sum xs          = reduce \+ 0 xs
    \# sum \[range 1 5\] = reduce \+ 0 \[range 1 5\]
    \#                 = reduce \+ \[\+ 0 1\] \[range 2 5\]
    \#                 = reduce \+ \[\+ 1 2\] \[range 3 5\]
    \#                 = \.\.\.
    \#                 = reduce \+ \[\+ 10 5\] <empty>
    \#                 = \(\(\(\(0\+1\)\+2\)\+3\)\+4\)\+5
    \#                 = 15
    proc \+ \{a b\} \{ expr \{$a \+ $b\} \}
    proc sum gen \{ generator reduce \+ 0 $gen \}
    puts \[sum \[range 1 10\]\]

    The __reduce__ operation is an extremely useful one, and a great variety
    of different operations can be defined using it\. For example, we can define
    a factorial function as the product of a range using generators\. This
    definition is both very clear and also quite efficient \(in both memory and
    running time\):

    proc \* \{x y\} \{ expr \{$x \* $y\} \}
    proc prod gen \{ generator reduce \* 0 $gen \}
    proc fac n \{ prod \[range 1 $n\] \}

    However, while the __reduce__ operation is efficient for finite
    generators, care should be taken not to apply it to an infinite generator,
    as this will result in an infinite loop:

    sum \[nats\]; \# Never returns

  - <a name='14'></a>__generator__ __foldl__ *function* *zero* *generator*

    This is an alias for the __reduce__ command\.

  - <a name='15'></a>__generator__ __foldr__ *function* *zero* *generator*








|
|
|

|

<
<
>
>
|
|
|
<
>
|







|

|
<
>















|
|


















|
|

|
<
>










|
|
















|
|
|
|
|
|
|
|
|
|
|







|
|
|





|







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
    be used like a __finally__ block in the
    __[try](\.\./try/tcllib\_try\.md)__ command, except that it is tied to
    the life\-cycle of the generator rather than to a particular scope\. For
    example, if we create a generator to iterate over the lines in a text file,
    we can use __finally__ to ensure that the file is closed whenever the
    generator is destroyed:

    generator define lines file {
        set in [open $file]
        # Ensure file is always closed
        generator finally close $in
        while {[gets $in line] >= 0} {
            generator yield $line


        }
    }
    generator foreach line [lines /etc/passwd] {
        puts "[incr count]: $line"
        if {$count > 10} { break }

    }
    # File will be closed even on early exit

    If you create a generator that consumes another generator \(such as the
    standard __map__ and __filter__ generators defined later\), then you
    should use a __finally__ command to ensure that this generator is
    destroyed when its parent is\. For example, the __map__ generator is
    defined as follows:

    generator define map {f xs} {
        generator finally generator destroy $xs
        generator foreach x $xs { generator yield [{*}$f $x] }

    }

  - <a name='9'></a>__generator__ __from__ *format* *value*

    Creates a generator from a data structure\. Currently, supported formats are
    __list__, __dict__, or __string__\. The list format yields each
    element in turn\. For dictionaries, each key and value are yielded
    separately\. Finally, strings are yielded a character at a time\.

  - <a name='10'></a>__generator__ __to__ *format* *generator*

    Converts a generator into a data structure\. This is the reverse operation of
    the __from__ command, and supports the same data structures\. The two
    operations obey the following identity laws \(where __=__ is interpreted
    appropriately\):

    [generator to $fmt [generator from $fmt $value]] = $value
    [generator from $fmt [generator to $fmt $gen]]   = $gen

# <a name='section3'></a>PRELUDE

The following commands are provided as a standard library of generator
combinators and functions that perform convenience operations on generators\. The
functions in this section are loosely modelled on the equivalent functions from
the Haskell Prelude\. *Warning:* most of the functions in this prelude destroy
any generator arguments they are passed as a side\-effect\. If you want to have
persistent generators, see the streams library\.

  - <a name='11'></a>__generator__ __map__ *function* *generator*

    Apply a function to every element of a generator, returning a new generator
    of the results\. This is the classic map function from functional
    programming, applied to generators\. For example, we can generate all the
    square numbers using the following code \(where __nats__ is defined as
    earlier\):

    proc square x { expr {$x * $x} }
    generator foreach n [generator map square [nats]] {
        puts "n = $n"
        if {$n > 1000} { break }

    }

  - <a name='12'></a>__generator__ __filter__ *predicate* *generator*

    Another classic functional programming gem\. This command returns a generator
    that yields only those items from the argument generator that satisfy the
    predicate \(boolean function\)\. For example, if we had a generator
    __employees__ that returned a stream of dictionaries representing
    people, we could filter all those whose salaries are above 100,000 dollars
    \(or whichever currency you prefer\) using a simple filter:

    proc salary> {amount person} { expr {[dict get $person salary] > $amount} }
    set fat-cats [generator filter {salary> 100000} $employees]

  - <a name='13'></a>__generator__ __reduce__ *function* *zero* *generator*

    This is the classic left\-fold operation\. This command takes a function, an
    initial value, and a generator of values\. For each element in the generator
    it applies the function to the current accumulator value \(the *zero*
    argument initially\) and that element, and then uses the result as the new
    accumulator value\. This process is repeated through the entire generator
    \(eagerly\) and the final accumulator value is then returned\. If we consider
    the function to be a binary operator, and the zero argument to be the left
    identity element of that operation, then we can consider the __reduce__
    command as *folding* the operator between each successive pair of values
    in the generator in a left\-associative fashion\. For example, the sum of a
    sequence of numbers can be calculated by folding a __\+__ operator
    between them, with 0 as the identity:

    # sum xs          = reduce + 0 xs
    # sum [range 1 5] = reduce + 0 [range 1 5]
    #                 = reduce + [+ 0 1] [range 2 5]
    #                 = reduce + [+ 1 2] [range 3 5]
    #                 = ...
    #                 = reduce + [+ 10 5] <empty>
    #                 = ((((0+1)+2)+3)+4)+5
    #                 = 15
    proc + {a b} { expr {$a + $b} }
    proc sum gen { generator reduce + 0 $gen }
    puts [sum [range 1 10]]

    The __reduce__ operation is an extremely useful one, and a great variety
    of different operations can be defined using it\. For example, we can define
    a factorial function as the product of a range using generators\. This
    definition is both very clear and also quite efficient \(in both memory and
    running time\):

    proc * {x y} { expr {$x * $y} }
    proc prod gen { generator reduce * 0 $gen }
    proc fac n { prod [range 1 $n] }

    However, while the __reduce__ operation is efficient for finite
    generators, care should be taken not to apply it to an infinite generator,
    as this will result in an infinite loop:

    sum [nats]; # Never returns

  - <a name='14'></a>__generator__ __foldl__ *function* *zero* *generator*

    This is an alias for the __reduce__ command\.

  - <a name='15'></a>__generator__ __foldr__ *function* *zero* *generator*

437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454

  - <a name='32'></a>__generator__ __iterate__ *function* *init*

    Returns an infinite generator formed by repeatedly applying the function to
    the initial argument\. For example, the Fibonacci numbers can be defined as
    follows:

    proc fst pair \{ lindex $pair 0 \}
    proc snd pair \{ lindex $pair 1 \}
    proc nextFib ab \{ list \[snd $ab\] \[expr \{\[fst $ab\] \+ \[snd $ab\]\}\] \}
    proc fibs \{\} \{ generator map fst \[generator iterate nextFib \{0 1\}\] \}

  - <a name='33'></a>__generator__ __last__ *generator*

    Returns the last element of the generator \(if it exists\)\.

  - <a name='34'></a>__generator__ __length__ *generator*








|
|
|
|







437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454

  - <a name='32'></a>__generator__ __iterate__ *function* *init*

    Returns an infinite generator formed by repeatedly applying the function to
    the initial argument\. For example, the Fibonacci numbers can be defined as
    follows:

    proc fst pair { lindex $pair 0 }
    proc snd pair { lindex $pair 1 }
    proc nextFib ab { list [snd $ab] [expr {[fst $ab] + [snd $ab]}] }
    proc fibs {} { generator map fst [generator iterate nextFib {0 1}] }

  - <a name='33'></a>__generator__ __last__ *generator*

    Returns the last element of the generator \(if it exists\)\.

  - <a name='34'></a>__generator__ __length__ *generator*

479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
  - <a name='40'></a>__generator__ __splitWhen__ *predicate* *generator*

    Splits the generator into lists of elements using the predicate to identify
    delimiters\. The resulting lists are returned as a generator\. Elements
    matching the delimiter predicate are discarded\. For example, to split up a
    generator using the string "&#124;" as a delimiter:

    set xs \[generator from list \{a &#124; b &#124; c\}\]
    generator split \{string equal "&#124;"\} $xs ;\# returns a then b then c

  - <a name='41'></a>__generator__ __scanl__ *function* *zero* *generator*

    Similar to __foldl__, but returns a generator of all of the intermediate
    values for the accumulator argument\. The final element of this generator is
    equivalent to __foldl__ called on the same arguments\.








|
|







479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
  - <a name='40'></a>__generator__ __splitWhen__ *predicate* *generator*

    Splits the generator into lists of elements using the predicate to identify
    delimiters\. The resulting lists are returned as a generator\. Elements
    matching the delimiter predicate are discarded\. For example, to split up a
    generator using the string "&#124;" as a delimiter:

    set xs [generator from list {a | b | c}]
    generator split {string equal "|"} $xs ;# returns a then b then c

  - <a name='41'></a>__generator__ __scanl__ *function* *zero* *generator*

    Similar to __foldl__, but returns a generator of all of the intermediate
    values for the accumulator argument\. The final element of this generator is
    equivalent to __foldl__ called on the same arguments\.

Changes to embedded/md/tcllib/files/modules/gpx/gpx.md.

149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
    elements: *latitude*, *longitude* and *metadata dictionary*\.
    *Latitude* and *longitude* are decimal numbers\. The *metadata
    dictionary* format is described above\. For points in a track, typically
    there will always be ele \(elevation\) and time metadata keys\.

# <a name='section4'></a>EXAMPLE

    % set token \[::gpx::Create myGpxFile\.gpx\]
    % set version \[dict get \[::gpx::GetGPXMetadata $token\] version\]
    % set trackCnt \[::gpx::GetTrackCount $token\]
    % set firstPoint \[lindex \[::gpx::GetTrackPoints $token 1\] 0\]
    % lassign $firstPoint lat lon ptMetadata
    % puts "first point in the first track is at $lat, $lon"
    % if \{\[dict exists $ptMetadata ele\]\} \{
         puts "at elevation \[dict get $ptMetadata ele\] meters"
      \}

    % ::gpx::Cleanup $token

# <a name='section5'></a>REFERENCES

  1. GPX: the GPS Exchange Format
     \([http://www\.topografix\.com/gpx\.asp](http://www\.topografix\.com/gpx\.asp)\)








|
|
|
|


|
|
<
>







149
150
151
152
153
154
155
156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
171
    elements: *latitude*, *longitude* and *metadata dictionary*\.
    *Latitude* and *longitude* are decimal numbers\. The *metadata
    dictionary* format is described above\. For points in a track, typically
    there will always be ele \(elevation\) and time metadata keys\.

# <a name='section4'></a>EXAMPLE

    % set token [::gpx::Create myGpxFile.gpx]
    % set version [dict get [::gpx::GetGPXMetadata $token] version]
    % set trackCnt [::gpx::GetTrackCount $token]
    % set firstPoint [lindex [::gpx::GetTrackPoints $token 1] 0]
    % lassign $firstPoint lat lon ptMetadata
    % puts "first point in the first track is at $lat, $lon"
    % if {[dict exists $ptMetadata ele]} {
         puts "at elevation [dict get $ptMetadata ele] meters"

      }
    % ::gpx::Cleanup $token

# <a name='section5'></a>REFERENCES

  1. GPX: the GPS Exchange Format
     \([http://www\.topografix\.com/gpx\.asp](http://www\.topografix\.com/gpx\.asp)\)

Changes to embedded/md/tcllib/files/modules/grammar_aycock/aycock.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (grammar::aycock \- Aycock\-Horspool\-Earley parser generator for Tcl)
[//000000002]: # (Generated from file 'aycock\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2006 by Kevin B\. Kenny <kennykb@acm\.org>
Redistribution permitted under the terms of the Open Publication License <http://www\.opencontent\.org/openpub/>)
[//000000004]: # (grammar::aycock\(n\) 1\.0 tcllib "Aycock\-Horspool\-Earley parser generator for Tcl")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (grammar::aycock \- Aycock\-Horspool\-Earley parser generator for Tcl)
[//000000002]: # (Generated from file 'aycock\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2006 by Kevin B\. Kenny <kennykb@acm\.org>)
[//000000004]: # (Redistribution permitted under the terms of the Open Publication License <http://www\.opencontent\.org/openpub/>)
[//000000005]: # (grammar::aycock\(n\) 1\.0 tcllib "Aycock\-Horspool\-Earley parser generator for Tcl")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# <a name='section5'></a>EXAMPLE

The following code demonstrates a trivial desk calculator, admitting only
__\+__, __\*__ and parentheses as its operators\. It also shows the format
in which the lexical analyzer is expected to present terminal symbols to the
parser\.

    set p \[aycock::parser \{
        start ::= E \{\}
        E ::= E \+ T \{expr \{\[lindex $\_ 0\] \+ \[lindex $\_ 2\]\}\}
        E ::= T \{\}
        T ::= T \* F \{expr \{\[lindex $\_ 0\] \* \[lindex $\_ 2\]\}\}
        T ::= F \{\}
        F ::= NUMBER \{\}
        F ::= \( E \) \{lindex $\_ 1\}
    \}\]
    puts \[$p parse \{\(  NUMBER \+  NUMBER \)  \*  \( NUMBER \+  NUMBER \) \}  \{\{\} 2      \{\} 3      \{\} \{\} \{\} 7     \{\} 1      \{\}\}\]
    $p destroy

The example, when run, prints __40__\.

# <a name='section6'></a>KEYWORDS

Aycock, Earley, Horspool, parser, compiler







|
|
|
|
|
|
|
|
|
|







135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# <a name='section5'></a>EXAMPLE

The following code demonstrates a trivial desk calculator, admitting only
__\+__, __\*__ and parentheses as its operators\. It also shows the format
in which the lexical analyzer is expected to present terminal symbols to the
parser\.

    set p [aycock::parser {
        start ::= E {}
        E ::= E + T {expr {[lindex $_ 0] + [lindex $_ 2]}}
        E ::= T {}
        T ::= T * F {expr {[lindex $_ 0] * [lindex $_ 2]}}
        T ::= F {}
        F ::= NUMBER {}
        F ::= ( E ) {lindex $_ 1}
    }]
    puts [$p parse {(  NUMBER +  NUMBER )  *  ( NUMBER +  NUMBER ) }  {{} 2      {} 3      {} {} {} 7     {} 1      {}}]
    $p destroy

The example, when run, prints __40__\.

# <a name='section6'></a>KEYWORDS

Aycock, Earley, Horspool, parser, compiler

Changes to embedded/md/tcllib/files/modules/grammar_fa/dexec.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (grammar::fa::dexec \- Finite automaton operations and usage)
[//000000002]: # (Generated from file 'dexec\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>  
Copyright &copy; 2007 Bogdan <rftghost@users\.sourceforge\.net>)
[//000000004]: # (grammar::fa::dexec\(n\) 0\.2 tcllib "Finite automaton operations and usage")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (grammar::fa::dexec \- Finite automaton operations and usage)
[//000000002]: # (Generated from file 'dexec\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (Copyright &copy; 2007 Bogdan <rftghost@users\.sourceforge\.net>)
[//000000005]: # (grammar::fa::dexec\(n\) 0\.2 tcllib "Finite automaton operations and usage")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

Changes to embedded/md/tcllib/files/modules/grammar_fa/fa.md.

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
    overwriting any existing definition\. This is the assignment operator for
    automatons\. It copies the automaton contained in the FA object *srcFA*
    over the automaton definition in *faName*\. The old contents of *faName*
    are deleted by this operation\.

    This operation is in effect equivalent to

        *faName* __deserialize__ \[*srcFA* __serialize__\]

  - <a name='6'></a>*faName* __\-\->__ *dstFA*

    This is the reverse assignment operator for automatons\. It copies the
    automation contained in the object *faName* over the automaton definition
    in the object *dstFA*\. The old contents of *dstFA* are deleted by this
    operation\.

    This operation is in effect equivalent to

        *dstFA* __deserialize__ \[*faName* __serialize__\]

  - <a name='7'></a>*faName* __serialize__

    This method serializes the automaton stored in *faName*\. In other words it
    returns a tcl *value* completely describing that automaton\. This allows,
    for example, the transfer of automatons over arbitrary channels,
    persistence, etc\. This method is also the basis for both the copy







|










|







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
    overwriting any existing definition\. This is the assignment operator for
    automatons\. It copies the automaton contained in the FA object *srcFA*
    over the automaton definition in *faName*\. The old contents of *faName*
    are deleted by this operation\.

    This operation is in effect equivalent to

    > *faName* __deserialize__ \[*srcFA* __serialize__\]

  - <a name='6'></a>*faName* __\-\->__ *dstFA*

    This is the reverse assignment operator for automatons\. It copies the
    automation contained in the object *faName* over the automaton definition
    in the object *dstFA*\. The old contents of *dstFA* are deleted by this
    operation\.

    This operation is in effect equivalent to

    > *dstFA* __deserialize__ \[*faName* __serialize__\]

  - <a name='7'></a>*faName* __serialize__

    This method serializes the automaton stored in *faName*\. In other words it
    returns a tcl *value* completely describing that automaton\. This allows,
    for example, the transfer of automatons over arbitrary channels,
    persistence, etc\. This method is also the basis for both the copy
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
           1) The last element is a dictionary describing the transitions for
              the state\. The keys are symbols \(or the empty string\), and the
              values are sets of successor states\.

    Assuming the following FA \(which describes the life of a truck driver in a
    very simple way :\)

        Drive \-\- yellow \-\-> Brake \-\- red \-\-> \(Stop\) \-\- red/yellow \-\-> Attention \-\- green \-\-> Drive
        \(\.\.\.\) is the start state\.

    a possible serialization is

        grammar::fa \\\\
        \{yellow red green red/yellow\} \\\\
        \{Drive     \{0 0 \{yellow     Brake\}\} \\\\
         Brake     \{0 0 \{red        Stop\}\} \\\\
         Stop      \{1 0 \{red/yellow Attention\}\} \\\\
         Attention \{0 0 \{green      Drive\}\}\}

    A possible one, because I did not care about creation order here

  - <a name='8'></a>*faName* __deserialize__ *serialization*

    This is the complement to __serialize__\. It replaces the automaton
    definition in *faName* with the automaton described by the







|
|



|
|
|
|
|
|







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
           1) The last element is a dictionary describing the transitions for
              the state\. The keys are symbols \(or the empty string\), and the
              values are sets of successor states\.

    Assuming the following FA \(which describes the life of a truck driver in a
    very simple way :\)

        Drive -- yellow --> Brake -- red --> (Stop) -- red/yellow --> Attention -- green --> Drive
        (...) is the start state.

    a possible serialization is

        grammar::fa \
        {yellow red green red/yellow} \
        {Drive     {0 0 {yellow     Brake}} \
         Brake     {0 0 {red        Stop}} \
         Stop      {1 0 {red/yellow Attention}} \
         Attention {0 0 {green      Drive}}}

    A possible one, because I did not care about creation order here

  - <a name='8'></a>*faName* __deserialize__ *serialization*

    This is the complement to __serialize__\. It replaces the automaton
    definition in *faName* with the automaton described by the
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
    more transitions\.

  - <a name='39'></a>*faName* __unreachable\_states__

    Returns the set of states which are not reachable from any start state by
    any number of transitions\. This is

        \[faName states\] \- \[faName reachable\_states\]

  - <a name='40'></a>*faName* __reachable__ *s*

    A predicate\. It tests whether the state *s* in the FA *faName* can be
    reached from a start state by one or more transitions\. The result is a
    boolean value\. It will be set to __true__ if the state can be reached,
    and __false__ otherwise\.

  - <a name='41'></a>*faName* __useful\_states__

    Returns the set of states which are able to reach a final state by one or
    more transitions\.

  - <a name='42'></a>*faName* __unuseful\_states__

    Returns the set of states which are not able to reach a final state by any
    number of transitions\. This is

        \[faName states\] \- \[faName useful\_states\]

  - <a name='43'></a>*faName* __useful__ *s*

    A predicate\. It tests whether the state *s* in the FA *faName* is able
    to reach a final state by one or more transitions\. The result is a boolean
    value\. It will be set to __true__ if the state is useful, and
    __false__ otherwise\.







|


















|







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
    more transitions\.

  - <a name='39'></a>*faName* __unreachable\_states__

    Returns the set of states which are not reachable from any start state by
    any number of transitions\. This is

        [faName states] - [faName reachable_states]

  - <a name='40'></a>*faName* __reachable__ *s*

    A predicate\. It tests whether the state *s* in the FA *faName* can be
    reached from a start state by one or more transitions\. The result is a
    boolean value\. It will be set to __true__ if the state can be reached,
    and __false__ otherwise\.

  - <a name='41'></a>*faName* __useful\_states__

    Returns the set of states which are able to reach a final state by one or
    more transitions\.

  - <a name='42'></a>*faName* __unuseful\_states__

    Returns the set of states which are not able to reach a final state by any
    number of transitions\. This is

        [faName states] - [faName useful_states]

  - <a name='43'></a>*faName* __useful__ *s*

    A predicate\. It tests whether the state *s* in the FA *faName* is able
    to reach a final state by one or more transitions\. The result is a boolean
    value\. It will be set to __true__ if the state is useful, and
    __false__ otherwise\.

Changes to embedded/md/tcllib/files/modules/grammar_peg/peg.md.

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
one of the nonterminals N in the expression, and one of the alternative rules R
for N, and then replace the nonterminal in A with the RHS of the chosen rule\.
Here we can see why the terminal symbols are called such\. They cannot be
expanded any further, thus terminate the process of deriving new expressions\. An
example

    Rules
      \(1\)  A <\- a B c
      \(2a\) B <\- d B
      \(2b\) B <\- e

    Some derivations, using starting expression A\.

      A \-/1/\-> a B c \-/2a/\-> a d B c \-/2b/\-> a d e c

A derived expression containing only terminal symbols is a *sentence*\. The set
of all sentences which can be derived from the start expression is the
*language* of the grammar\.

Some definitions for nonterminals and expressions:








|
|
|

|

|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
one of the nonterminals N in the expression, and one of the alternative rules R
for N, and then replace the nonterminal in A with the RHS of the chosen rule\.
Here we can see why the terminal symbols are called such\. They cannot be
expanded any further, thus terminate the process of deriving new expressions\. An
example

    Rules
      (1)  A <- a B c
      (2a) B <- d B
      (2b) B <- e

    Some derivations, using starting expression A.

      A -/1/-> a B c -/2a/-> a d B c -/2b/-> a d e c

A derived expression containing only terminal symbols is a *sentence*\. The set
of all sentences which can be derived from the start expression is the
*language* of the grammar\.

Some definitions for nonterminals and expressions:

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
    overwriting any existing definition\. This is the assignment operator for
    grammars\. It copies the grammar contained in the grammar object *srcPEG*
    over the grammar definition in *pegName*\. The old contents of *pegName*
    are deleted by this operation\.

    This operation is in effect equivalent to

    *pegName* __deserialize__ \[*srcPEG* __serialize__\]

  - <a name='5'></a>*pegName* __\-\->__ *dstPEG*

    This is the reverse assignment operator for grammars\. It copies the
    automation contained in the object *pegName* over the grammar definition
    in the object *dstPEG*\. The old contents of *dstPEG* are deleted by this
    operation\.

    This operation is in effect equivalent to

    *dstPEG* __deserialize__ \[*pegName* __serialize__\]

  - <a name='6'></a>*pegName* __serialize__

    This method serializes the grammar stored in *pegName*\. In other words it
    returns a tcl *value* completely describing that grammar\. This allows, for
    example, the transfer of grammars over arbitrary channels, persistence, etc\.
    This method is also the basis for both the copy constructor and the







|










|







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
    overwriting any existing definition\. This is the assignment operator for
    grammars\. It copies the grammar contained in the grammar object *srcPEG*
    over the grammar definition in *pegName*\. The old contents of *pegName*
    are deleted by this operation\.

    This operation is in effect equivalent to

    > *pegName* __deserialize__ \[*srcPEG* __serialize__\]

  - <a name='5'></a>*pegName* __\-\->__ *dstPEG*

    This is the reverse assignment operator for grammars\. It copies the
    automation contained in the object *pegName* over the grammar definition
    in the object *dstPEG*\. The old contents of *dstPEG* are deleted by this
    operation\.

    This operation is in effect equivalent to

    > *dstPEG* __deserialize__ \[*pegName* __serialize__\]

  - <a name='6'></a>*pegName* __serialize__

    This method serializes the grammar stored in *pegName*\. In other words it
    returns a tcl *value* completely describing that grammar\. This allows, for
    example, the transfer of grammars over arbitrary channels, persistence, etc\.
    This method is also the basis for both the copy constructor and the
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
         values produced by the symbol\.

      1. The last item is a parsing expression, the *start expression* of the
         grammar\.

    Assuming the following PEG for simple mathematical expressions

    Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'
    Sign       <\- '\+' / '\-'
    Number     <\- Sign? Digit\+
    Expression <\- '\(' Expression '\)' / \(Factor \(MulOp Factor\)\*\)
    MulOp      <\- '\*' / '/'
    Factor     <\- Term \(AddOp Term\)\*
    AddOp      <\- '\+'/'\-'
    Term       <\- Number

    a possible serialization is

    grammar::peg \\\\
    \{Expression \{/ \{x \( Expression \)\} \{x Factor \{\* \{x MulOp Factor\}\}\}\} \\\\
     Factor     \{x Term \{\* \{x AddOp Term\}\}\} \\\\
     Term       Number \\\\
     MulOp      \{/ \* /\} \\\\
     AddOp      \{/ \+ \-\} \\\\
     Number     \{x \{? Sign\} \{\+ Digit\}\} \\\\
     Sign       \{/ \+ \-\} \\\\
     Digit      \{/ 0 1 2 3 4 5 6 7 8 9\} \\\\
    \} \\\\
    \{Expression value     Factor     value \\\\
     Term       value     MulOp      value \\\\
     AddOp      value     Number     value \\\\
     Sign       value     Digit      value \\\\
    \}

    Expression

    A possible one, because the order of the nonterminals in the dictionary is
    not relevant\.

  - <a name='7'></a>*pegName* __deserialize__ *serialization*








|
|
|
|
|
|
|
|



|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
>







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
         values produced by the symbol\.

      1. The last item is a parsing expression, the *start expression* of the
         grammar\.

    Assuming the following PEG for simple mathematical expressions

    Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'
    Sign       <- '+' / '-'
    Number     <- Sign? Digit+
    Expression <- '(' Expression ')' / (Factor (MulOp Factor)*)
    MulOp      <- '*' / '/'
    Factor     <- Term (AddOp Term)*
    AddOp      <- '+'/'-'
    Term       <- Number

    a possible serialization is

    grammar::peg \
    {Expression {/ {x ( Expression )} {x Factor {* {x MulOp Factor}}}} \
     Factor     {x Term {* {x AddOp Term}}} \
     Term       Number \
     MulOp      {/ * /} \
     AddOp      {/ + -} \
     Number     {x {? Sign} {+ Digit}} \
     Sign       {/ + -} \
     Digit      {/ 0 1 2 3 4 5 6 7 8 9} \
    } \
    {Expression value     Factor     value \
     Term       value     MulOp      value \
     AddOp      value     Number     value \
     Sign       value     Digit      value \

    }
    Expression

    A possible one, because the order of the nonterminals in the dictionary is
    not relevant\.

  - <a name='7'></a>*pegName* __deserialize__ *serialization*

Changes to embedded/md/tcllib/files/modules/hook/hook.md.

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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 package defines a new command, __hook__, which implements just such a
mechanism\.

## <a name='subsection2'></a>Bindings

The __hook__ command manages a collection of hook bindings\. A hook binding
has four elements:

  1. A *[subject](\.\./\.\./\.\./\.\./index\.md\#subject)*: the name of the entity







|
|
|
|
|







78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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 package defines a new command, __hook__, which implements
just such a mechanism\.

## <a name='subsection2'></a>Bindings

The __hook__ command manages a collection of hook bindings\. A hook binding
has four elements:

  1. A *[subject](\.\./\.\./\.\./\.\./index\.md\#subject)*: the name of the entity
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
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](\.\./\.\./\.\./\.\./index\.md\#hook)* that it no longer exists:

    hook forget \.view

All bindings involving __\.view__ are deleted\.

# <a name='section5'></a>Credits

Hook has been designed and implemented by William H\. Duquette\.








|







|







312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
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](\.\./\.\./\.\./\.\./index\.md\#hook)* that it no longer exists:

    hook forget .view

All bindings involving __\.view__ are deleted\.

# <a name='section5'></a>Credits

Hook has been designed and implemented by William H\. Duquette\.

Changes to embedded/md/tcllib/files/modules/html/html.md.

1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (html \- HTML Generation)
[//000000002]: # (Generated from file 'html\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (html\(n\) 1\.4\.4 tcllib "HTML Generation")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|







1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (html \- HTML Generation)
[//000000002]: # (Generated from file 'html\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (html\(n\) 1\.5 tcllib "HTML Generation")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  - [Keywords](#keywords)

  - [Category](#category)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require html ?1\.4\.4?  

[__::html::author__ *author*](#1)  
[__::html::bodyTag__ *args*](#2)  
[__::html::cell__ *param value* ?*tag*?](#3)  
[__::html::checkbox__ *name value*](#4)  
[__::html::checkSet__ *key sep list*](#5)  
[__::html::checkValue__ *name* ?*value*?](#6)  







|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  - [Keywords](#keywords)

  - [Category](#category)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require html ?1\.5?  

[__::html::author__ *author*](#1)  
[__::html::bodyTag__ *args*](#2)  
[__::html::cell__ *param value* ?*tag*?](#3)  
[__::html::checkbox__ *name value*](#4)  
[__::html::checkSet__ *key sep list*](#5)  
[__::html::checkValue__ *name* ?*value*?](#6)  
65
66
67
68
69
70
71



72
73
74
75
76
77
78
79
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
[__::html::headTag__ *string*](#28)  
[__::html::html\_entities__ *string*](#29)  
[__::html::if__ *expr1 body1* ?__elseif__ *expr2 body2 \.\.\.*? ?__else__ *bodyN*?](#30)  
[__::html::init__ ?*list*?](#31)  
[__::html::keywords__ *args*](#32)  
[__::html::mailto__ *email* ?*subject*?](#33)  
[__::html::meta__ *args*](#34)  



[__::html::css__ *href*](#35)  
[__::html::css\-clear__](#36)  
[__::html::js__ *href*](#37)  
[__::html::js\-clear__](#38)  
[__::html::minorList__ *list* ?*ordered*?](#39)  
[__::html::minorMenu__ *list* ?*sep*?](#40)  
[__::html::nl2br__ *string*](#41)  
[__::html::openTag__ *tag* ?*param*?](#42)  
[__::html::paramRow__ *list* ?*rparam*? ?*cparam*?](#43)  
[__::html::passwordInput__ ?*name*?](#44)  
[__::html::passwordInputRow__ *label* ?*name*?](#45)  
[__::html::quoteFormValue__ *value*](#46)  
[__::html::radioSet__ *key sep list*](#47)  
[__::html::radioValue__ *name value*](#48)  
[__::html::refresh__ *seconds url*](#49)  
[__::html::row__ *args*](#50)  
[__::html::select__ *name param choices* ?*current*?](#51)  
[__::html::selectPlain__ *name param choices* ?*current*?](#52)  
[__::html::set__ *var val*](#53)  
[__::html::submit__ *label* ?*name*?](#54)  
[__::html::tableFromArray__ *arrname* ?*param*? ?*pat*?](#55)  
[__::html::tableFromList__ *querylist* ?*param*?](#56)  
[__::html::textarea__ *name* ?*param*? ?*current*?](#57)  
[__::html::textInput__ *name value args*](#58)  
[__::html::textInputRow__ *label name value args*](#59)  
[__::html::varEmpty__ *name*](#60)  
[__::html::while__ *test body*](#61)  
[__::html::doctype__ *id*](#62)  


# <a name='description'></a>DESCRIPTION

The package __html__ provides commands that generate HTML\. These commands
typically return an HTML string as their result\. In particular, they do not
output their result to __stdout__\.








>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
[__::html::headTag__ *string*](#28)  
[__::html::html\_entities__ *string*](#29)  
[__::html::if__ *expr1 body1* ?__elseif__ *expr2 body2 \.\.\.*? ?__else__ *bodyN*?](#30)  
[__::html::init__ ?*list*?](#31)  
[__::html::keywords__ *args*](#32)  
[__::html::mailto__ *email* ?*subject*?](#33)  
[__::html::meta__ *args*](#34)  
[__::html::meta\_name__ *args*](#35)  
[__::html::meta\_equiv__ *args*](#36)  
[__::html::meta\_charset__ *charset*](#37)  
[__::html::css__ *href*](#38)  
[__::html::css\-clear__](#39)  
[__::html::js__ *href*](#40)  
[__::html::js\-clear__](#41)  
[__::html::minorList__ *list* ?*ordered*?](#42)  
[__::html::minorMenu__ *list* ?*sep*?](#43)  
[__::html::nl2br__ *string*](#44)  
[__::html::openTag__ *tag* ?*param*?](#45)  
[__::html::paramRow__ *list* ?*rparam*? ?*cparam*?](#46)  
[__::html::passwordInput__ ?*name*?](#47)  
[__::html::passwordInputRow__ *label* ?*name*?](#48)  
[__::html::quoteFormValue__ *value*](#49)  
[__::html::radioSet__ *key sep list*](#50)  
[__::html::radioValue__ *name value*](#51)  
[__::html::refresh__ *seconds url*](#52)  
[__::html::row__ *args*](#53)  
[__::html::select__ *name param choices* ?*current*?](#54)  
[__::html::selectPlain__ *name param choices* ?*current*?](#55)  
[__::html::set__ *var val*](#56)  
[__::html::submit__ *label* ?*name*? ?*title*?](#57)  
[__::html::tableFromArray__ *arrname* ?*param*? ?*pat*?](#58)  
[__::html::tableFromList__ *querylist* ?*param*?](#59)  
[__::html::textarea__ *name* ?*param*? ?*current*?](#60)  
[__::html::textInput__ *name value args*](#61)  
[__::html::textInputRow__ *label name value args*](#62)  
[__::html::varEmpty__ *name*](#63)  
[__::html::while__ *test body*](#64)  
[__::html::doctype__ *id*](#65)  
[__::html::wrapTag__ *tag* ?*text*? ?*args*?](#66)  

# <a name='description'></a>DESCRIPTION

The package __html__ provides commands that generate HTML\. These commands
typically return an HTML string as their result\. In particular, they do not
output their result to __stdout__\.

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

  - <a name='33'></a>__::html::mailto__ *email* ?*subject*?

    Generate a hypertext link to a mailto: URL\.

  - <a name='34'></a>__::html::meta__ *args*





    *Side effect only*\. Call this before __::html::head__ to define a
    *meta* tag for the page\. The *args* is a Tcl\-style name, value list that



    is used for the name= and value= parameters for the *meta* tag\. The






    *meta* tag is included in the result of __::html::head__\.








  - <a name='35'></a>__::html::css__ *href*

    *Side effect only*\. Call this before __::html::head__ to define a
    *link* tag for a linked CSS document\. The *href* value is a HTTP URL to
    a CSS document\. The *link* tag is included in the result of
    __::html::head__\.

    Multiple calls of this command are allowed, enabling the use of multiple CSS
    document references\. In other words, the arguments of multiple calls are
    accumulated, and do not overwrite each other\.

  - <a name='36'></a>__::html::css\-clear__

    *Side effect only*\. Call this before __::html::head__ to clear all
    links to CSS documents\.

    Multiple calls of this command are allowed, doing nothing after the first of
    a sequence with no intervening __::html::css__\.

  - <a name='37'></a>__::html::js__ *href*

    *Side effect only*\. Call this before __::html::head__ to define a
    *script* tag for a linked JavaScript document\. The *href* is a HTTP URL
    to a JavaScript document\. The *script* tag is included in the result of
    __::html::head__\.

    Multiple calls of this command are allowed, enabling the use of multiple
    JavaScript document references\. In other words, the arguments of multiple
    calls are accumulated, and do not overwrite each other\.

  - <a name='38'></a>__::html::js\-clear__

    *Side effect only*\. Call this before __::html::head__ to clear all
    links to JavaScript documents\.

    Multiple calls of this command are allowed, doing nothing after the first of
    a sequence with no intervening __::html::js__\.

  - <a name='39'></a>__::html::minorList__ *list* ?*ordered*?

    Generate an ordered or unordered list of links\. The *list* is a Tcl\-style
    name, value list of labels and urls for the links\. *ordered* is a boolean
    used to choose between an ordered or unordered list\. It defaults to
    __false__\.

  - <a name='40'></a>__::html::minorMenu__ *list* ?*sep*?

    Generate a series of hypertext links\. The *list* is a Tcl\-style name,
    value list of labels and urls for the links\. The *sep* is the text to put
    between each link\. It defaults to " &#124; "\.

  - <a name='41'></a>__::html::nl2br__ *string*

    This command replaces all line\-endings in the *string* with a *br* tag
    and returns the modified text\.

  - <a name='42'></a>__::html::openTag__ *tag* ?*param*?

    Push *tag* onto a stack and generate the opening tag for *tag*\. Use
    __::html::closeTag__ to pop the tag from the stack\. The second argument
    provides any tag arguments, as a list whose elements are formatted to be in
    the form "__key__=__value__"\.

  - <a name='43'></a>__::html::paramRow__ *list* ?*rparam*? ?*cparam*?

    Generate a table row, including *tr* and *td* tags\. Each value in
    *list* is placed into its own table cell\. This uses __::html::cell__\.
    The value of *rparam* is used as parameter for the *tr* tag\. The value
    of *cparam* is passed to __::html::cell__ as parameter for the *td*
    tags\.

  - <a name='44'></a>__::html::passwordInput__ ?*name*?

    Generate an *input* tag of type
    *[password](\.\./\.\./\.\./\.\./index\.md\#password)*\. The *name* defaults to
    "password"\.

  - <a name='45'></a>__::html::passwordInputRow__ *label* ?*name*?

    Format a table row containing a label and an *input* tag of type
    *[password](\.\./\.\./\.\./\.\./index\.md\#password)*\. The *name* defaults to
    "password"\.

  - <a name='46'></a>__::html::quoteFormValue__ *value*

    Quote special characters in *value* by replacing them with HTML entities
    for quotes, ampersand, and angle brackets\.

  - <a name='47'></a>__::html::radioSet__ *key sep list*

    Generate a set of *input* tags of type *radio* and an associated text
    label\. All the radio buttons share the same *key* for their name\. The
    *sep* is text used to separate the elements\. The *list* is a Tcl\-style
    label, value list\.

  - <a name='48'></a>__::html::radioValue__ *name value*

    Generate the "name=*name* value=*value*" for a *radio* form element\.
    If the CGI variable *name* has the value *value*, then SELECTED is added
    to the return value\.

  - <a name='49'></a>__::html::refresh__ *seconds url*

    Set up a refresh *meta* tag\. Call this before __::html::head__ and the
    HEAD section will contain a *meta* tag that causes the document to refresh
    in *seconds* seconds\. The *url* is optional\. If specified, it specifies
    a new page to load after the refresh interval\.

  - <a name='50'></a>__::html::row__ *args*

    Generate a table row, including *tr* and *td* tags\. Each value in
    *args* is place into its own table cell\. This uses __::html::cell__\.
    Ignores any default information set up via __::html::init__\.

  - <a name='51'></a>__::html::select__ *name param choices* ?*current*?

    Generate a *select* form element and nested *option* tags\. The *name*
    and *param* are used to generate the *select* tag\. The *choices* list
    is a Tcl\-style name, value list\.

  - <a name='52'></a>__::html::selectPlain__ *name param choices* ?*current*?

    Like __::html::select__ except that *choices* is a Tcl list of values
    used for the *option* tags\. The label and the value for each *option*
    are the same\.

  - <a name='53'></a>__::html::set__ *var val*

    This procedure is similar to the built\-in Tcl
    __[set](\.\./\.\./\.\./\.\./index\.md\#set)__ command\. The main difference is
    that it returns "" so it can be called from an HTML template file without
    appending unwanted results\. The other difference is that it must take two
    arguments\.

  - <a name='54'></a>__::html::submit__ *label* ?*name*?

    Generate an *input* tag of type *submit*\. *name* defaults to "submit"\.



  - <a name='55'></a>__::html::tableFromArray__ *arrname* ?*param*? ?*pat*?

    Generate a two\-column *[table](\.\./\.\./\.\./\.\./index\.md\#table)* and nested
    rows to display a Tcl array\. The table gets a heading that matches the array
    name, and each generated row contains a name, value pair\. The array names
    are sorted \(__lsort__ without special options\)\. The argument *param*
    is for the *[table](\.\./\.\./\.\./\.\./index\.md\#table)* tag and has to
    contain a pre\-formatted string\. The *pat* is a __string match__
    pattern used to select the array elements to show in the table\. It defaults
    to __\*__, i\.e\. the whole array is shown\.

  - <a name='56'></a>__::html::tableFromList__ *querylist* ?*param*?

    Generate a two\-column *[table](\.\./\.\./\.\./\.\./index\.md\#table)* and nested
    rows to display *querylist*, which is a Tcl dictionary\. Each generated row
    contains a name, value pair\. The information is shown in the same order as
    specified in the dictionary\. The argument *param* is for the
    *[table](\.\./\.\./\.\./\.\./index\.md\#table)* tag and has to contain a
    pre\-formatted string\.

  - <a name='57'></a>__::html::textarea__ *name* ?*param*? ?*current*?

    Generate a *textarea* tag wrapped around its current values\.

  - <a name='58'></a>__::html::textInput__ *name value args*

    Generate an *input* form tag with type
    *[text](\.\./\.\./\.\./\.\./index\.md\#text)*\. This uses
    __::html::formValue__\. The args is any additional tag attributes you
    want to put into the *input* tag\.

  - <a name='59'></a>__::html::textInputRow__ *label name value args*

    Generate an *input* form tag with type
    *[text](\.\./\.\./\.\./\.\./index\.md\#text)* formatted into a table row with an
    associated label\. The args is any additional tag attributes you want to put
    into the *input* tag\.

  - <a name='60'></a>__::html::varEmpty__ *name*

    This returns 1 if the named variable either does not exist or has the empty
    string for its value\.

  - <a name='61'></a>__::html::while__ *test body*

    This procedure is similar to the built\-in Tcl __while__ control
    structure\. Rather than evaluating the body, it returns the subst'ed
    *body*\. Each iteration of the loop causes another string to be
    concatenated to the result value\.

  - <a name='62'></a>__::html::doctype__ *id*

    This procedure can be used to build the standard DOCTYPE declaration string\.
    It will return the standard declaration string for the id, or throw an error
    if the id is not known\. The following id's are defined:

      1. HTML32








>
>
>
>

|
>
>
>
|
>
>
>
>
>
>
|

>
>
>
>
>
>
>
|










|







|










|







|






|





|




|






|







|





|





|




|






|





|






|





|





|





|







|

|
>
>

|










|








|



|






|






|




|






|







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

  - <a name='33'></a>__::html::mailto__ *email* ?*subject*?

    Generate a hypertext link to a mailto: URL\.

  - <a name='34'></a>__::html::meta__ *args*

    Compatibility name for __html::meta\_name__\.

  - <a name='35'></a>__::html::meta\_name__ *args*

    *Side effect only*\. Call this before __::html::head__ to define a
    *meta* tag for the page\. The arguments \(*args*\) are a Tcl\-style name,
    value list that is used for the __name=__ and __content=__
    attributes of the *meta* tag\. The *meta* tag is included in the result
    of __::html::head__\.

  - <a name='36'></a>__::html::meta\_equiv__ *args*

    *Side effect only*\. Call this before __::html::head__ to define a
    *meta* tag for the page\. The arguments \(*args*\) are a Tcl\-style name,
    value list that is used for the __http\-equiv=__ and __content=__
    attributes of the *meta* tag\. The *meta* tag is included in the result
    of __::html::head__\.

  - <a name='37'></a>__::html::meta\_charset__ *charset*

    *Side effect only*\. Call this before __::html::head__ to define a
    *meta* tag for the page\. The *charset* is used with the __charset=__
    attribute of the *meta* tag\. The *meta* tag is included in the result of
    __::html::head__\.

  - <a name='38'></a>__::html::css__ *href*

    *Side effect only*\. Call this before __::html::head__ to define a
    *link* tag for a linked CSS document\. The *href* value is a HTTP URL to
    a CSS document\. The *link* tag is included in the result of
    __::html::head__\.

    Multiple calls of this command are allowed, enabling the use of multiple CSS
    document references\. In other words, the arguments of multiple calls are
    accumulated, and do not overwrite each other\.

  - <a name='39'></a>__::html::css\-clear__

    *Side effect only*\. Call this before __::html::head__ to clear all
    links to CSS documents\.

    Multiple calls of this command are allowed, doing nothing after the first of
    a sequence with no intervening __::html::css__\.

  - <a name='40'></a>__::html::js__ *href*

    *Side effect only*\. Call this before __::html::head__ to define a
    *script* tag for a linked JavaScript document\. The *href* is a HTTP URL
    to a JavaScript document\. The *script* tag is included in the result of
    __::html::head__\.

    Multiple calls of this command are allowed, enabling the use of multiple
    JavaScript document references\. In other words, the arguments of multiple
    calls are accumulated, and do not overwrite each other\.

  - <a name='41'></a>__::html::js\-clear__

    *Side effect only*\. Call this before __::html::head__ to clear all
    links to JavaScript documents\.

    Multiple calls of this command are allowed, doing nothing after the first of
    a sequence with no intervening __::html::js__\.

  - <a name='42'></a>__::html::minorList__ *list* ?*ordered*?

    Generate an ordered or unordered list of links\. The *list* is a Tcl\-style
    name, value list of labels and urls for the links\. *ordered* is a boolean
    used to choose between an ordered or unordered list\. It defaults to
    __false__\.

  - <a name='43'></a>__::html::minorMenu__ *list* ?*sep*?

    Generate a series of hypertext links\. The *list* is a Tcl\-style name,
    value list of labels and urls for the links\. The *sep* is the text to put
    between each link\. It defaults to " &#124; "\.

  - <a name='44'></a>__::html::nl2br__ *string*

    This command replaces all line\-endings in the *string* with a *br* tag
    and returns the modified text\.

  - <a name='45'></a>__::html::openTag__ *tag* ?*param*?

    Push *tag* onto a stack and generate the opening tag for *tag*\. Use
    __::html::closeTag__ to pop the tag from the stack\. The second argument
    provides any tag arguments, as a list whose elements are formatted to be in
    the form "__key__=__value__"\.

  - <a name='46'></a>__::html::paramRow__ *list* ?*rparam*? ?*cparam*?

    Generate a table row, including *tr* and *td* tags\. Each value in
    *list* is placed into its own table cell\. This uses __::html::cell__\.
    The value of *rparam* is used as parameter for the *tr* tag\. The value
    of *cparam* is passed to __::html::cell__ as parameter for the *td*
    tags\.

  - <a name='47'></a>__::html::passwordInput__ ?*name*?

    Generate an *input* tag of type
    *[password](\.\./\.\./\.\./\.\./index\.md\#password)*\. The *name* defaults to
    "password"\.

  - <a name='48'></a>__::html::passwordInputRow__ *label* ?*name*?

    Format a table row containing a label and an *input* tag of type
    *[password](\.\./\.\./\.\./\.\./index\.md\#password)*\. The *name* defaults to
    "password"\.

  - <a name='49'></a>__::html::quoteFormValue__ *value*

    Quote special characters in *value* by replacing them with HTML entities
    for quotes, ampersand, and angle brackets\.

  - <a name='50'></a>__::html::radioSet__ *key sep list*

    Generate a set of *input* tags of type *radio* and an associated text
    label\. All the radio buttons share the same *key* for their name\. The
    *sep* is text used to separate the elements\. The *list* is a Tcl\-style
    label, value list\.

  - <a name='51'></a>__::html::radioValue__ *name value*

    Generate the "name=*name* value=*value*" for a *radio* form element\.
    If the CGI variable *name* has the value *value*, then SELECTED is added
    to the return value\.

  - <a name='52'></a>__::html::refresh__ *seconds url*

    Set up a refresh *meta* tag\. Call this before __::html::head__ and the
    HEAD section will contain a *meta* tag that causes the document to refresh
    in *seconds* seconds\. The *url* is optional\. If specified, it specifies
    a new page to load after the refresh interval\.

  - <a name='53'></a>__::html::row__ *args*

    Generate a table row, including *tr* and *td* tags\. Each value in
    *args* is place into its own table cell\. This uses __::html::cell__\.
    Ignores any default information set up via __::html::init__\.

  - <a name='54'></a>__::html::select__ *name param choices* ?*current*?

    Generate a *select* form element and nested *option* tags\. The *name*
    and *param* are used to generate the *select* tag\. The *choices* list
    is a Tcl\-style name, value list\.

  - <a name='55'></a>__::html::selectPlain__ *name param choices* ?*current*?

    Like __::html::select__ except that *choices* is a Tcl list of values
    used for the *option* tags\. The label and the value for each *option*
    are the same\.

  - <a name='56'></a>__::html::set__ *var val*

    This procedure is similar to the built\-in Tcl
    __[set](\.\./\.\./\.\./\.\./index\.md\#set)__ command\. The main difference is
    that it returns "" so it can be called from an HTML template file without
    appending unwanted results\. The other difference is that it must take two
    arguments\.

  - <a name='57'></a>__::html::submit__ *label* ?*name*? ?*title*?

    Generate an *input* tag of type *submit*\. The *name* defaults to
    "submit"\. When a non\-empty *title* string is specified the button gains a
    __title=__ attribute with that value\.

  - <a name='58'></a>__::html::tableFromArray__ *arrname* ?*param*? ?*pat*?

    Generate a two\-column *[table](\.\./\.\./\.\./\.\./index\.md\#table)* and nested
    rows to display a Tcl array\. The table gets a heading that matches the array
    name, and each generated row contains a name, value pair\. The array names
    are sorted \(__lsort__ without special options\)\. The argument *param*
    is for the *[table](\.\./\.\./\.\./\.\./index\.md\#table)* tag and has to
    contain a pre\-formatted string\. The *pat* is a __string match__
    pattern used to select the array elements to show in the table\. It defaults
    to __\*__, i\.e\. the whole array is shown\.

  - <a name='59'></a>__::html::tableFromList__ *querylist* ?*param*?

    Generate a two\-column *[table](\.\./\.\./\.\./\.\./index\.md\#table)* and nested
    rows to display *querylist*, which is a Tcl dictionary\. Each generated row
    contains a name, value pair\. The information is shown in the same order as
    specified in the dictionary\. The argument *param* is for the
    *[table](\.\./\.\./\.\./\.\./index\.md\#table)* tag and has to contain a
    pre\-formatted string\.

  - <a name='60'></a>__::html::textarea__ *name* ?*param*? ?*current*?

    Generate a *textarea* tag wrapped around its current values\.

  - <a name='61'></a>__::html::textInput__ *name value args*

    Generate an *input* form tag with type
    *[text](\.\./\.\./\.\./\.\./index\.md\#text)*\. This uses
    __::html::formValue__\. The args is any additional tag attributes you
    want to put into the *input* tag\.

  - <a name='62'></a>__::html::textInputRow__ *label name value args*

    Generate an *input* form tag with type
    *[text](\.\./\.\./\.\./\.\./index\.md\#text)* formatted into a table row with an
    associated label\. The args is any additional tag attributes you want to put
    into the *input* tag\.

  - <a name='63'></a>__::html::varEmpty__ *name*

    This returns 1 if the named variable either does not exist or has the empty
    string for its value\.

  - <a name='64'></a>__::html::while__ *test body*

    This procedure is similar to the built\-in Tcl __while__ control
    structure\. Rather than evaluating the body, it returns the subst'ed
    *body*\. Each iteration of the loop causes another string to be
    concatenated to the result value\.

  - <a name='65'></a>__::html::doctype__ *id*

    This procedure can be used to build the standard DOCTYPE declaration string\.
    It will return the standard declaration string for the id, or throw an error
    if the id is not known\. The following id's are defined:

      1. HTML32

523
524
525
526
527
528
529








530
531
532
533
534
535
536
      1. XHTML10T

      1. XHTML10F

      1. XHTML11

      1. XHTMLB









# <a name='section2'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *html* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







>
>
>
>
>
>
>
>







549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
      1. XHTML10T

      1. XHTML10F

      1. XHTML11

      1. XHTMLB

  - <a name='66'></a>__::html::wrapTag__ *tag* ?*text*? ?*args*?

    A helper to wrap a *text* in a pair of open/close *tag*s\. The arguments
    \(*args*\) are a Tcl\-style name, value list that is used to provide
    attributes and associated values to the opening tag\. The result is a string
    with the open *tag* along with the optional attributes, the optional text,
    and the closed tag\.

# <a name='section2'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *html* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/http/autoproxy.md.

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init \-tls1 1 ;\# forcibly activate support for the TLS1 protocol

    \.\.\. your own application code \.\.\.

# <a name='section3'></a>COMMANDS

  - <a name='1'></a>__::autoproxy::init__

    Initialize the autoproxy package from system resources\. Under unix this
    means we look for environment variables\. Under windows we look for the same







|

|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol

    ... your own application code ...

# <a name='section3'></a>COMMANDS

  - <a name='1'></a>__::autoproxy::init__

    Initialize the autoproxy package from system resources\. Under unix this
    means we look for environment variables\. Under windows we look for the same
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
    The end\-of\-options indicator may be used alone to unset any authentication
    details currently enabled\.

# <a name='section6'></a>EXAMPLES

    package require autoproxy
    autoproxy::init
    autoproxy::configure \-basic \-username ME \-password SEKRET
    set tok \[http::geturl http://wiki\.tcl\.tk/\]
    http::data $tok

    package require http
    package require tls
    package require autoproxy
    autoproxy::init
    http::register https 443 autoproxy::tls\_socket
    set tok \[http::geturl https://www\.example\.com/\]

# <a name='section7'></a>REFERENCES

  1. Berners\-Lee, T\., Fielding R\. and Frystyk, H\. "Hypertext Transfer Protocol
     \-\- HTTP/1\.0", RFC 1945, May 1996,
     \([http://www\.rfc\-editor\.org/rfc/rfc1945\.txt](http://www\.rfc\-editor\.org/rfc/rfc1945\.txt)\)








|
|






|
|







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
    The end\-of\-options indicator may be used alone to unset any authentication
    details currently enabled\.

# <a name='section6'></a>EXAMPLES

    package require autoproxy
    autoproxy::init
    autoproxy::configure -basic -username ME -password SEKRET
    set tok [http::geturl http://wiki.tcl.tk/]
    http::data $tok

    package require http
    package require tls
    package require autoproxy
    autoproxy::init
    http::register https 443 autoproxy::tls_socket
    set tok [http::geturl https://www.example.com/]

# <a name='section7'></a>REFERENCES

  1. Berners\-Lee, T\., Fielding R\. and Frystyk, H\. "Hypertext Transfer Protocol
     \-\- HTTP/1\.0", RFC 1945, May 1996,
     \([http://www\.rfc\-editor\.org/rfc/rfc1945\.txt](http://www\.rfc\-editor\.org/rfc/rfc1945\.txt)\)

Changes to embedded/md/tcllib/files/modules/httpd/httpd.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

36

37

38

39
40
41
42
43
44
45
46
47
48
49
50
51


52
53

54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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

[//000000001]: # (tool \- Tcl Web Server)
[//000000002]: # (Generated from file 'httpd\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2018 Sean Woods <yoda@etoyoc\.com>)
[//000000004]: # (tool\(n\) 4\.1\.1 tcllib "Tcl Web Server")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

# NAME

tool \- A TclOO and coroutine based web server

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Synopsis](#synopsis)

  - [Description](#section1)

  - [Minimal Example](#section2)

  - [Class ::httpd::server](#section3)

  - [Class ::httpd::reply](#section4)

  - [Reply Method Ensembles](#section5)

  - [Reply Method Ensemble: http\_info](#section6)


  - [Reply Method Ensemble: request](#section7)



  - [Reply Method Ensemble: reply](#section8)


  - [Reply Methods](#section9)

  - [Class ::httpd::content](#section10)

  - [Class ::httpd::content\.cgi](#section11)

  - [Class ::httpd::content\.file](#section12)

  - [Class ::httpd::content\.proxy](#section13)

  - [Class ::httpd::content\.scgi](#section14)



  - [Class ::httpd::content\.websocket](#section15)


  - [SCGI Server Functions](#section16)


  - [Class ::httpd::reply\.scgi](#section17)

  - [Class ::httpd::server\.scgi](#section18)

  - [AUTHORS](#section19)

  - [Bugs, Ideas, Feedback](#section20)

  - [Keywords](#keywords)

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.6  
package require httpd ?4\.1\.1?  
package require sha1  
package require dicttool  
package require oo::meta  
package require oo::dialect  
package require tool  
package require coroutine  
package require fileutil  
package require fileutil::magic::filetype  
package require websocket  
package require mime  
package require cron  
package require uri  
package require Markdown  

[constructor ?port ?port?? ?myaddr ?ipaddr?&#124;all? ?server\_string ?string?? ?server\_name ?string??](#1)  
[method __add\_uri__ *pattern* *dict*](#2)  
[method __connect__ *sock* *ip* *port*](#3)  
[method __Connect__ *uuid* *sock* *ip*](#4)  
[method __[counter](\.\./counter/counter\.md)__ *which*](#5)  
[method __CheckTimeout__](#6)  
[method __dispatch__ *header\_dict*](#7)  
[method __[log](\.\./log/log\.md)__ *args*](#8)  
[method __port\_listening__](#9)  
[method __PrefixNormalize__ *prefix*](#10)  
[method __start__](#11)  
[method __stop__](#12)  
[method __template__ *page*](#13)  
[method __TemplateSearch__ *page*](#14)  
[method __Validate\_Connection__ *sock* *ip*](#15)  
[method __ENSEMBLE::add__ *field* *element*](#16)  
[method __ENSEMBLE::dump__](#17)  
[method __ENSEMBLE::get__ *field*](#18)  
[method __ENSEMBLE::reset__](#19)  
[method __ENSEMBLE::remove__ *field* *element*](#20)  
[method __ENSEMBLE::replace__ *keyvaluelist*](#21)  
[method __ENSEMBLE::reset__](#22)  
[method __ENSEMBLE::set__ *field* *value*](#23)  
[method __http\_info::netstring__](#24)  
[method __request::parse__ *string*](#25)  
[method __reply::output__](#26)  
[method __close__](#27)  
[method __HttpHeaders__ *sock* *?debug?*](#28)  
[method __dispatch__ *newsock* *datastate*](#29)  



[method __[error](\.\./\.\./\.\./\.\./index\.md\#error)__ *code* *?message?* *?errorInfo?*](#30)  
[method __content__](#31)  
[method __EncodeStatus__ *status*](#32)  
[method FormData](#33)  
[method MimeParse *mimetext*](#34)  
[method __DoOutput__](#35)  

[method PostData *length*](#36)  

[method __puts__ *string*](#37)  



[method __reset__](#38)  
[method __timeOutCheck__](#39)  
[method __[timestamp](\.\./\.\./\.\./\.\./index\.md\#timestamp)__](#40)  








[method __TransferComplete__ *args*](#41)  

[method __Url\_Decode__ *string*](#42)  




[method cgi\_info](#43)  


[option __path__](#44)  

[option __[prefix](\.\./\.\./\.\./\.\./index\.md\#prefix)__](#45)  

[method proxy\_info](#46)  





























[method scgi\_info](#47)  














# <a name='description'></a>DESCRIPTION

This module implements a web server, suitable for embedding in an application\.
The server is object oriented, and contains all of the fundamentals needed for a
full service website\.

# <a name='section2'></a>Minimal Example

Starting a web service requires starting a class of type __httpd::server__,
and providing that server with one or more URIs to service, and
__httpd::reply__ derived classes to generate them\.

    tool::define ::reply\.hello \{
      method content \{\} \{
        my puts "<HTML><HEAD><TITLE>IRM Dispatch Server</TITLE></HEAD><BODY>"
        my puts "<h1>Hello World\!</h1>"
        my puts </BODY></HTML>
      \}
    \}
    ::docserver::server create HTTPD port 8015 myaddr 127\.0\.0\.1
    HTTPD add\_uri /\* \[list mixin reply\.hello\]

# <a name='section3'></a>Class ::httpd::server

This class is the root object of the webserver\. It is responsible for opening
the socket and providing the initial connection negotiation\.

  - <a name='1'></a>constructor ?port ?port?? ?myaddr ?ipaddr?&#124;all? ?server\_string ?string?? ?server\_name ?string??

    Build a new server object\. ?port? is the port to listen on

  - <a name='2'></a>method __add\_uri__ *pattern* *dict*

    Set the hander for a URI pattern\. Information given in the *dict* is

    stored in the data structure the __dispatch__ method uses\. If a field
    called *mixin* is given, that class will be mixed into the reply object
    immediately after construction\.

  - <a name='3'></a>method __connect__ *sock* *ip* *port*

    Reply to an open socket\. This method builds a coroutine to manage the





    remainder of the connection\. The coroutine's operations are driven by the
    __Connect__ method\.


  - <a name='4'></a>method __Connect__ *uuid* *sock* *ip*



    This method reads HTTP headers, and then consults the __dispatch__
    method to determine if the request is valid, and/or what kind of reply to
    generate\. Under normal cases, an object of class __::http::reply__ is
    created\. Fields the server are looking for in particular are: class: A class
    to use instead of the server's own *reply\_class* mixin: A class to be
    mixed into the new object after construction\. All other fields are passed
    along to the __http\_info__ structure of the reply object\. After the
    class is created and the mixin is mixed in, the server invokes the reply
    objects __dispatch__ method\. This action passes control of the socket to
    the reply object\. The reply object manages the rest of the transaction,
    including closing the socket\.

  - <a name='5'></a>method __[counter](\.\./counter/counter\.md)__ *which*

    Increment an internal counter\.


  - <a name='6'></a>method __CheckTimeout__

    Check open connections for a time out event\.


  - <a name='7'></a>method __dispatch__ *header\_dict*

    Given a key/value list of information, return a data structure describing
    how the server should reply\.

  - <a name='8'></a>method __[log](\.\./log/log\.md)__ *args*

    Log an event\. The input for args is free form\. This method is intended to be
    replaced by the user, and is a noop for a stock http::server object\.

  - <a name='9'></a>method __port\_listening__

    Return the actual port that httpd is listening on\.

  - <a name='10'></a>method __PrefixNormalize__ *prefix*

    For the stock version, trim trailing /'s and \*'s from a prefix\. This method
    can be replaced by the end user to perform any other transformations needed
    for the application\.

  - <a name='11'></a>method __start__

    Open the socket listener\.



  - <a name='12'></a>method __stop__

    Shut off the socket listener, and destroy any pending replies\.



  - <a name='13'></a>method __template__ *page*

    Return a template for the string *page*

  - <a name='14'></a>method __TemplateSearch__ *page*

    Perform a search for the template that best matches *page*\. This can
    include local file searches, in\-memory structures, or even database lookups\.
    The stock implementation simply looks for files with a \.tml or \.html
    extension in the ?doc\_root? directory\.

  - <a name='15'></a>method __Validate\_Connection__ *sock* *ip*

    Given a socket and an ip address, return true if this connection should be
    terminated, or false if it should be allowed to continue\. The stock
    implementation always returns 0\. This is intended for applications to be
    able to implement black lists and/or provide security based on IP address\.

# <a name='section4'></a>Class ::httpd::reply

A class which shephards a request through the process of generating a reply\. The
socket associated with the reply is available at all times as the *chan*
variable\. The process of generating a reply begins with an __httpd::server__
generating a __http::class__ object, mixing in a set of behaviors and then
invoking the reply object's __dispatch__ method\. In normal operations the
__dispatch__ method:

|


|










|











|

|

|

|

>
|
>

>
|
>

|

|

|

|

|

|

>
>
|

>
|
>

|

|

|

|










|
<
|
<
<
<









<
|
|
|
<
|
|
<
|
|
|
|
|
|
|
<
|
<
|
<
<
|
<
|
|
|
|
|
|
>
>
>
|
|
|
|
|
|
>
|
>
|
>
>
>



>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
|
>
>
|
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>













|
|

|

<
<
<
<
|
<
|
<
<
|
<
|
<
|
<

<
>
|
<
<

<
|
<
>
>
>
>
>
|
|
>

<
>
>

<
<
<
<
<
<
<
<
|
<
<

|

<
>

|

<
>

|

<
<
|
<

|
<

|

<
|
<

|
<
<

|

<
>

>
|
|
<
>
>

|

|

|

<
<
|
<

<
|
<
<
<
<

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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

[//000000001]: # (httpd \- Tcl Web Server)
[//000000002]: # (Generated from file 'httpd\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2018 Sean Woods <yoda@etoyoc\.com>)
[//000000004]: # (httpd\(n\) 4\.3\.4 tcllib "Tcl Web Server")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

# NAME

httpd \- A TclOO and coroutine based web server

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Synopsis](#synopsis)

  - [Description](#section1)

  - [Minimal Example](#section2)

  - [Classes](#section3)

      - [Class httpd::mime](#subsection1)

      - [Class httpd::reply](#subsection2)

      - [Class httpd::server](#subsection3)

      - [Class httpd::server::dispatch](#subsection4)

      - [Class httpd::content\.redirect](#subsection5)

      - [Class httpd::content\.cache](#subsection6)

      - [Class httpd::content\.template](#subsection7)

      - [Class httpd::content\.file](#subsection8)

      - [Class httpd::content\.exec](#subsection9)

      - [Class httpd::content\.proxy](#subsection10)

      - [Class httpd::content\.cgi](#subsection11)

      - [Class httpd::protocol\.scgi](#subsection12)

      - [Class httpd::content\.scgi](#subsection13)

      - [Class httpd::server\.scgi](#subsection14)

      - [Class httpd::content\.websocket](#subsection15)

      - [Class httpd::plugin](#subsection16)

      - [Class httpd::plugin\.dict\_dispatch](#subsection17)

      - [Class httpd::reply\.memchan](#subsection18)

      - [Class httpd::plugin\.local\_memchan](#subsection19)

  - [AUTHORS](#section4)

  - [Bugs, Ideas, Feedback](#section5)

  - [Keywords](#keywords)

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.6  
package require uuid  

package require clay  



package require coroutine  
package require fileutil  
package require fileutil::magic::filetype  
package require websocket  
package require mime  
package require cron  
package require uri  
package require Markdown  


[method __ChannelCopy__ *in* *out* ?*args*?](#1)  
[method __html\_header__ ?*title* ____? ?*args*?](#2)  
[method __html\_footer__ ?*args*?](#3)  

[method __http\_code\_string__ *code*](#4)  
[method __HttpHeaders__ *sock* ?*debug* ____?](#5)  

[method __HttpHeaders\_Default__](#6)  
[method __HttpServerHeaders__](#7)  
[method __MimeParse__ *mimetext*](#8)  
[method __Url\_Decode__ *data*](#9)  
[method __Url\_PathCheck__ *urlsuffix*](#10)  
[method __wait__ *mode* *sock*](#11)  
[variable __ChannelRegister__](#12)  

[variable __reply__](#13)  

[variable __request__](#14)  


[delegate __<server>__](#15)  

[method __constructor__ *ServerObj* ?*args*?](#16)  
[method __destructor__ ?*dictargs*?](#17)  
[method __ChannelRegister__ ?*args*?](#18)  
[method __close__](#19)  
[method __Log\_Dispatched__](#20)  
[method __dispatch__ *newsock* *datastate*](#21)  
[method __Dispatch__](#22)  
[method __html\_header__ *title* ?*args*?](#23)  
[method __html\_footer__ ?*args*?](#24)  
[method __[error](\.\./\.\./\.\./\.\./index\.md\#error)__ *code* ?*msg* ____? ?*errorInfo* ____?](#25)  
[method __content__](#26)  
[method __EncodeStatus__ *status*](#27)  
[method __[log](\.\./log/log\.md)__ *type* ?*info* ____?](#28)  
[method __CoroName__](#29)  
[method __DoOutput__](#30)  
[method __FormData__](#31)  
[method __PostData__ *length*](#32)  
[method __Session\_Load__](#33)  
[method __puts__ *line*](#34)  
[method __RequestFind__ *field*](#35)  
[method __request__ *subcommand* ?*args*?](#36)  
[method __reply__ *subcommand* ?*args*?](#37)  
[method __reset__](#38)  
[method __timeOutCheck__](#39)  
[method __[timestamp](\.\./\.\./\.\./\.\./index\.md\#timestamp)__](#40)  
[variable __template__](#41)  
[variable __url\_patterns__](#42)  
[method __constructor__ *args* ?*port* __auto__? ?*myaddr* __127\.0\.0\.1__? ?*string* __auto__? ?*name* __auto__? ?*doc\_root* ____? ?*reverse\_dns* __0__? ?*configuration\_file* ____? ?*protocol* __HTTP/1\.1__?](#43)  
[method __destructor__ ?*dictargs*?](#44)  
[method __connect__ *sock* *ip* *port*](#45)  
[method __ServerHeaders__ *ip* *http\_request* *mimetxt*](#46)  
[method __Connect__ *uuid* *sock* *ip*](#47)  
[method __[counter](\.\./counter/counter\.md)__ *which*](#48)  
[method __CheckTimeout__](#49)  
[method __[debug](\.\./debug/debug\.md)__ ?*args*?](#50)  
[method __dispatch__ *data*](#51)  
[method __Dispatch\_Default__ *reply*](#52)  
[method __Dispatch\_Local__ *data*](#53)  
[method __Headers\_Local__ *varname*](#54)  
[method __Headers\_Process__ *varname*](#55)  
[method __HostName__ *ipaddr*](#56)  
[method __[log](\.\./log/log\.md)__ ?*args*?](#57)  
[method __[plugin](\.\./\.\./\.\./\.\./index\.md\#plugin)__ *slot* ?*class* ____?](#58)  
[method __port\_listening__](#59)  
[method __PrefixNormalize__ *prefix*](#60)  
[method __[source](\.\./\.\./\.\./\.\./index\.md\#source)__ *filename*](#61)  
[method __start__](#62)  
[method __stop__](#63)  
[method __SubObject \{\} db__](#64)  
[method __SubObject \{\} default__](#65)  
[method __template__ *page*](#66)  
[method __TemplateSearch__ *page*](#67)  
[method __Thread\_start__](#68)  
[method __Uuid\_Generate__](#69)  
[method __Validate\_Connection__ *sock* *ip*](#70)  
[method __reset__](#71)  
[method __content__](#72)  
[method __Dispatch__](#73)  
[method __content__](#74)  
[method __FileName__](#75)  
[method __DirectoryListing__ *local\_file*](#76)  
[method __content__](#77)  
[method __Dispatch__](#78)  
[variable __exename__](#79)  
[method __CgiExec__ *execname* *script* *arglist*](#80)  
[method __Cgi\_Executable__ *script*](#81)  
[method __proxy\_channel__](#82)  
[method __proxy\_path__](#83)  
[method __ProxyRequest__ *chana* *chanb*](#84)  
[method __ProxyReply__ *chana* *chanb* ?*args*?](#85)  
[method __Dispatch__](#86)  
[method __FileName__](#87)  
[method __proxy\_channel__](#88)  
[method __ProxyRequest__ *chana* *chanb*](#89)  
[method __ProxyReply__ *chana* *chanb* ?*args*?](#90)  
[method __DirectoryListing__ *local\_file*](#91)  
[method __EncodeStatus__ *status*](#92)  
[method __scgi\_info__](#93)  
[method __proxy\_channel__](#94)  
[method __ProxyRequest__ *chana* *chanb*](#95)  
[method __ProxyReply__ *chana* *chanb* ?*args*?](#96)  
[method __[debug](\.\./debug/debug\.md)__ ?*args*?](#97)  
[method __Connect__ *uuid* *sock* *ip*](#98)  
[method __Dispatch\_Dict__ *data*](#99)  
[method __uri \{\} add__ *vhosts* *patterns* *info*](#100)  
[method __uri \{\} direct__ *vhosts* *patterns* *info* *body*](#101)  
[method __output__](#102)  
[method __DoOutput__](#103)  
[method __close__](#104)  
[method __local\_memchan__ *command* ?*args*?](#105)  
[method __Connect\_Local__ *uuid* *sock* ?*args*?](#106)  

# <a name='description'></a>DESCRIPTION

This module implements a web server, suitable for embedding in an application\.
The server is object oriented, and contains all of the fundamentals needed for a
full service website\.

# <a name='section2'></a>Minimal Example

Starting a web service requires starting a class of type __httpd::server__,
and providing that server with one or more URIs to service, and
__httpd::reply__ derived classes to generate them\.

    oo::class create ::reply.hello {
      method content {} {
        my puts "<HTML><HEAD><TITLE>IRM Dispatch Server</TITLE></HEAD><BODY>"
        my puts "<h1>Hello World!</h1>"
        my puts </BODY></HTML>




      }

    }


    ::httpd::server create HTTPD port 8015 myaddr 127.0.0.1 doc_root ~/htdocs

    HTTPD plugin dispatch httpd::server::dispatch

    HTTPD uri add * /hello [list mixin reply.hello]



The bare module does have facilities to hose a files from a file system\. Files
that end in a \.tml will be substituted in the style of Tclhttpd:




    <!-- hello.tml -->

    [my html_header {Hello World!}]
    Your Server is running.
    <p>
    The time is now [clock format [clock seconds]]
    [my html_footer]

A complete example of an httpd server is in the /examples directory of Tcllib\.
It also show how to dispatch URIs to other processes via SCGI and HTTP proxies\.


    cd ~/tcl/sandbox/tcllib
    tclsh examples/httpd.tcl









# <a name='section3'></a>Classes



## <a name='subsection1'></a>Class  httpd::mime


A metaclass for MIME handling behavior across a live socket

__Methods__


  - <a name='1'></a>method __ChannelCopy__ *in* *out* ?*args*?

  - <a name='2'></a>method __html\_header__ ?*title* ____? ?*args*?



    Returns a block of HTML


  - <a name='3'></a>method __html\_footer__ ?*args*?


  - <a name='4'></a>method __http\_code\_string__ *code*


  - <a name='5'></a>method __HttpHeaders__ *sock* ?*debug* ____?


  - <a name='6'></a>method __HttpHeaders\_Default__



  - <a name='7'></a>method __HttpServerHeaders__


  - <a name='8'></a>method __MimeParse__ *mimetext*

    Converts a block of mime encoded text to a key/value list\. If an exception
    is encountered, the method will generate its own call to the
    __[error](\.\./\.\./\.\./\.\./index\.md\#error)__ method, and immediately

    invoke the __output__ method to produce an error code and close the
    connection\.

  - <a name='9'></a>method __Url\_Decode__ *data*

    De\-httpizes a string\.

  - <a name='10'></a>method __Url\_PathCheck__ *urlsuffix*



  - <a name='11'></a>method __wait__ *mode* *sock*



## <a name='subsection2'></a>Class  httpd::reply





*ancestors*: __httpd::mime__

A class which shephards a request through the process of generating a reply\. The
socket associated with the reply is available at all times as the *chan*
variable\. The process of generating a reply begins with an __httpd::server__
generating a __http::class__ object, mixing in a set of behaviors and then
invoking the reply object's __dispatch__ method\. In normal operations the
__dispatch__ method:
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

  1. Invokes the __content__ method for the object, generating an call to
     the __[error](\.\./\.\./\.\./\.\./index\.md\#error)__ method if an exception
     is raised\.

  1. Invokes the __output__ method for the object

# <a name='section5'></a>Reply Method Ensembles

The __http::reply__ class and its derivatives maintain several variables as
dictionaries internally\. Access to these dictionaries is managed through a
dedicated ensemble\. The ensemble implements most of the same behaviors as the
__[dict](\.\./\.\./\.\./\.\./index\.md\#dict)__ command\. Each ensemble implements
the following methods above, beyond, or modifying standard dicts:

  - <a name='16'></a>method __ENSEMBLE::add__ *field* *element*

    Add *element* to a list stored in *field*, but only if it is not already
    present om the list\.

  - <a name='17'></a>method __ENSEMBLE::dump__

    Return the current contents of the data structure as a key/value list\.

  - <a name='18'></a>method __ENSEMBLE::get__ *field*

    Return the value of the field *field*, or an empty string if it does not
    exist\.

  - <a name='19'></a>method __ENSEMBLE::reset__

    Return a key/value list of the default contents for this data structure\.

  - <a name='20'></a>method __ENSEMBLE::remove__ *field* *element*

    Remove all instances of *element* from the list stored in *field*\.

  - <a name='21'></a>method __ENSEMBLE::replace__ *keyvaluelist*

    Replace the internal dict with the contents of *keyvaluelist*

  - <a name='22'></a>method __ENSEMBLE::reset__

    Replace the internal dict with the default state\.

  - <a name='23'></a>method __ENSEMBLE::set__ *field* *value*

    Set the value of *field* to *value*\.

# <a name='section6'></a>Reply Method Ensemble: http\_info

Manages HTTP headers passed in by the server\. Ensemble Methods:

  - <a name='24'></a>method __http\_info::netstring__

    Return the contents of this data structure as a netstring encoded block\.

# <a name='section7'></a>Reply Method Ensemble: request

Managed data from MIME headers of the request\.

  - <a name='25'></a>method __request::parse__ *string*

    Replace the contents of the data structure with information encoded in a
    MIME formatted block of text \(*string*\)\.

# <a name='section8'></a>Reply Method Ensemble: reply

Manage the headers sent in the reply\.

  - <a name='26'></a>method __reply::output__

    Return the contents of this data structure as a MIME encoded block
    appropriate for an HTTP response\.

# <a name='section9'></a>Reply Methods

  - <a name='27'></a>method __close__

    Terminate the transaction, and close the socket\.

  - <a name='28'></a>method __HttpHeaders__ *sock* *?debug?*

    Stream MIME headers from the socket *sock*, stopping at an empty line\.
    Returns the stream as a block of text\.

  - <a name='29'></a>method __dispatch__ *newsock* *datastate*

    Take over control of the socket *newsock*, and store that as the *chan*
    variable for the object\. This method runs through all of the steps of
    reading HTTP headers, generating content, and closing the connection\. \(See
    class writetup\)\.

  - <a name='30'></a>method __[error](\.\./\.\./\.\./\.\./index\.md\#error)__ *code* *?message?* *?errorInfo?*

    Generate an error message of the specified *code*, and display the
    *message* as the reason for the exception\. *errorInfo* is passed in from
    calls, but how or if it should be displayed is a prerogative of the
    developer\.

  - <a name='31'></a>method __content__

    Generate the content for the reply\. This method is intended to be replaced
    by the mixin\. Developers have the option of streaming output to a buffer via
    the __puts__ method of the reply, or simply populating the
    *reply\_body* variable of the object\. The information returned by the
    __content__ method is not interpreted in any way\. If an exception is
    thrown \(via the __[error](\.\./\.\./\.\./\.\./index\.md\#error)__ command in
    Tcl, for example\) the caller will auto\-generate a 500 \{Internal Error\}
    message\. A typical implementation of __content__ look like:

    tool::define ::test::content\.file \{
    	superclass ::httpd::content\.file
    	\# Return a file
    	\# Note: this is using the content\.file mixin which looks for the reply\_file variable
    	\# and will auto\-compute the Content\-Type
    	method content \{\} \{
    	  my reset
        set doc\_root \[my http\_info get doc\_root\]
        my variable reply\_file
        set reply\_file \[file join $doc\_root index\.html\]
    	\}
    \}


    tool::define ::test::content\.time \{
      \# return the current system time
    	method content \{\} \{
    		my variable reply\_body
        my reply set Content\-Type text/plain
    		set reply\_body \[clock seconds\]
    	\}
    \}


    tool::define ::test::content\.echo \{
    	method content \{\} \{
    		my variable reply\_body
        my reply set Content\-Type \[my request get CONTENT\_TYPE\]
    		set reply\_body \[my PostData \[my request get CONTENT\_LENGTH\]\]
    	\}
    \}


    tool::define ::test::content\.form\_handler \{
    	method content \{\} \{
    	  set form \[my FormData\]
    	  my reply set Content\-Type \{text/html; charset=UTF\-8\}
        my puts \[my html header \{My Dynamic Page\}\]
        my puts "<BODY>"
        my puts "You Sent<p>"
        my puts "<TABLE>"
        foreach \{f v\} $form \{
          my puts "<TR><TH>$f</TH><TD><verbatim>$v</verbatim></TD>"
        \}

        my puts "</TABLE><p>"
        my puts "Send some info:<p>"
        my puts "<FORM action=/\[my http\_info get REQUEST\_PATH\] method POST>"
        my puts "<TABLE>"
        foreach field \{name rank serial\_number\} \{
          set line "<TR><TH>$field</TH><TD><input name=\\"$field\\" "
          if \{\[dict exists $form $field\]\} \{
            append line " value=\\"\[dict get $form $field\]\\"""
          \}

          append line " /></TD></TR>"
          my puts $line
        \}

        my puts "</TABLE>"
        my puts \[my html footer\]


    	\}

    \}

































































  - <a name='32'></a>method __EncodeStatus__ *status*

    Formulate a standard HTTP status header from he string provided\.


  - <a name='33'></a>method FormData









    For GET requests, converts the QUERY\_DATA header into a key/value list\. For
    POST requests, reads the Post data and converts that information to a
    key/value list for application/x\-www\-form\-urlencoded posts\. For multipart
    posts, it composites all of the MIME headers of the post to a singular
    key/value list, and provides MIME\_\* information as computed by the
    __[mime](\.\./mime/mime\.md)__ package, including the MIME\_TOKEN, which
    can be fed back into the mime package to read out the contents\.

  - <a name='34'></a>method MimeParse *mimetext*

    Converts a block of mime encoded text to a key/value list\. If an exception
    is encountered, the method will generate its own call to the
    __[error](\.\./\.\./\.\./\.\./index\.md\#error)__ method, and immediately
    invoke the __output__ method to produce an error code and close the
    connection\.

  - <a name='35'></a>method __DoOutput__

    Generates the the HTTP reply, and streams that reply back across *chan*\.

  - <a name='36'></a>method PostData *length*

    Stream *length* bytes from the *chan* socket, but only of the request is
    a POST or PUSH\. Returns an empty string otherwise\.





  - <a name='37'></a>method __puts__ *string*

    Appends the value of *string* to the end of *reply\_body*, as well as a
    trailing newline character\.







  - <a name='38'></a>method __reset__

    Clear the contents of the *reply\_body* variable, and reset all headers in
    the __reply__ structure back to the defaults for this object\.

  - <a name='39'></a>method __timeOutCheck__

    Called from the __http::server__ object which spawned this reply\. Checks
    to see if too much time has elapsed while waiting for data or generating a
    reply, and issues a timeout error to the request if it has, as well as
    destroy the object and close the *chan* socket\.

  - <a name='40'></a>method __[timestamp](\.\./\.\./\.\./\.\./index\.md\#timestamp)__

    Return the current system time in the format:

    %a, %d %b %Y %T %Z

  - <a name='41'></a>method __TransferComplete__ *args*


    Intended to be invoked from __chan copy__ as a callback\. This closes

    every channel fed to it on the command line, and then destroys the object\.



    \#\#\#
    \# Output the body
    \#\#\#

    chan configure $sock \-translation binary \-blocking 0 \-buffering full \-buffersize 4096

    chan configure $chan \-translation binary \-blocking 0 \-buffering full \-buffersize 4096

    if \{$length\} \{



      \#\#\#

      \# Send any POST/PUT/etc content

      \#\#\#






      chan copy $sock $chan \-size $SIZE \-command \[info coroutine\]

      yield

    \}

    catch \{close $sock\}
    chan flush $chan



  - <a name='42'></a>method __Url\_Decode__ *string*




    De\-httpizes a string\.





# <a name='section10'></a>Class ::httpd::content






























The httpd module includes several ready to use implementations of content mixins



for common use cases\. Options are passed in to the __add\_uri__ method of the


server\.



# <a name='section11'></a>Class ::httpd::content\.cgi




An implementation to relay requests to process which will accept post data

streamed in vie stdin, and sent a reply streamed to stdout\.












  - <a name='43'></a>method cgi\_info








    Mandatory method to be replaced by the end user\. If needed, activates the

    process to proxy, and then returns a list of three values: *exec* \- The

    arguments to send to exec to fire off the responding process, minus the




    stdin/stdout redirection\.





# <a name='section12'></a>Class ::httpd::content\.file



An implementation to deliver files from the local file system\.


  - <a name='44'></a>option __path__






    The root directory on the local file system to be exposed via http\.



  - <a name='45'></a>option __[prefix](\.\./\.\./\.\./\.\./index\.md\#prefix)__







    The prefix of the URI portion to ignore when calculating relative file

    paths\.



# <a name='section13'></a>Class ::httpd::content\.proxy



An implementation to relay requests to another HTTP server, and relay the

results back across the request channel\.



  - <a name='46'></a>method proxy\_info






















    Mandatory method to be replaced by the end user\. If needed, activates the

    process to proxy, and then returns a list of three values: *proxyhost* \-

    The hostname where the proxy is located *proxyport* \- The port to connect

    to *proxyscript* \- A pre\-amble block of text to send prior to the mirrored

    request



# <a name='section14'></a>Class ::httpd::content\.scgi



An implementation to relay requests to a server listening on a socket expecting

SCGI encoded requests, and relay the results back across the request channel\.








  - <a name='47'></a>method scgi\_info














    Mandatory method to be replaced by the end user\. If needed, activates the

    process to proxy, and then returns a list of three values: *scgihost* \-

    The hostname where the scgi listener is located *scgiport* \- The port to

    connect to *scgiscript* \- The contents of the *SCRIPT\_NAME* header to be

    sent



# <a name='section15'></a>Class ::httpd::content\.websocket



A placeholder for a future implementation to manage requests that can expect to

be promoted to a Websocket\. Currently it is an empty class\.



# <a name='section16'></a>SCGI Server Functions

















The HTTP module also provides an SCGI server implementation, as well as an HTTP

implementation\. To use the SCGI functions, create an object of the

__http::server\.scgi__ class instead of the __http::server__ class\.



# <a name='section17'></a>Class ::httpd::reply\.scgi



An modified __http::reply__ implementation that understands how to deal with

netstring encoded headers\.



# <a name='section18'></a>Class ::httpd::server\.scgi



A modified __http::server__ which is tailored to replying to request

according to the SCGI standard instead of the HTTP standard\.













# <a name='section19'></a>AUTHORS

Sean Woods

# <a name='section20'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *network* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

When proposing code changes, please provide *unified diffs*, i\.e the output of







<
|
<
<
<
<
<
|
<
|
<
<
|
<
|
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|

|
|
|
<
<
>
>
|
|
|
|
|
|
<
<
>
>
|
|
|
|
|
<
<
>
>
|
|
|
|
|



|

<
>


|

|
|
|
|
<
>


<
>

|
>
>
|
>
|
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|



>
|
>
>
>
>
>
>
>
>









<
|
<
<
<
<
<
<
<
<
<
<
<




>
>
>
>
|




>
>
>
>
>
>


















|

>
|
>
|
>

>
|
|
|
>
|
>
|
>
|
>
>
>
|
>
|
>
|
>
>
>
>
>
>
|
>
|
>
|
>
|
<
>

>
|
>

>
>
|
>

>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
|
>
>
|
>

>
|
>
>

>
|
>
|
>

>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>

>
|
>
|
>
|
>
>
>
>
|
>

>
>
>
|
>

>
|

>
|
>

>
>
>
>
|
>

>
|
>
>
>
>
>

>
|
>
|
>

>
|
>

>
|
>
|
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
|
>
|
>
|
>
|
>

>
|
>

>
|
>
|
>

>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
|
>
|
>
|
>
|
>

>
|
>

>
|
>
|
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
|
>
|
>

>
|
>

>
|
>
|
>

>
|
>

>
|
>
|
>

>
>
>
>
>
>
>
>
>
>
>
|



|







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

  1. Invokes the __content__ method for the object, generating an call to
     the __[error](\.\./\.\./\.\./\.\./index\.md\#error)__ method if an exception
     is raised\.

  1. Invokes the __output__ method for the object


Developers have the option of streaming output to a buffer via the __puts__





method of the reply, or simply populating the *reply\_body* variable of the

object\. The information returned by the __content__ method is not


interpreted in any way\. If an exception is thrown \(via the

__[error](\.\./\.\./\.\./\.\./index\.md\#error)__ command in Tcl, for example\) the

caller will auto\-generate a 500 \{Internal Error\} message\. A typical

implementation of __content__ look like:





















































































    clay::define ::test::content.file {
    	superclass ::httpd::content.file
    	# Return a file
    	# Note: this is using the content.file mixin which looks for the reply_file variable
    	# and will auto-compute the Content-Type
    	method content {} {
    	  my reset
        set doc_root [my request get DOCUMENT_ROOT]
        my variable reply_file
        set reply_file [file join $doc_root index.html]


    	}
    }
    clay::define ::test::content.time {
      # return the current system time
    	method content {} {
    		my variable reply_body
        my reply set Content-Type text/plain
    		set reply_body [clock seconds]


    	}
    }
    clay::define ::test::content.echo {
    	method content {} {
    		my variable reply_body
        my reply set Content-Type [my request get CONTENT_TYPE]
    		set reply_body [my PostData [my request get CONTENT_LENGTH]]


    	}
    }
    clay::define ::test::content.form_handler {
    	method content {} {
    	  set form [my FormData]
    	  my reply set Content-Type {text/html; charset=UTF-8}
        my puts [my html_header {My Dynamic Page}]
        my puts "<BODY>"
        my puts "You Sent<p>"
        my puts "<TABLE>"
        foreach {f v} $form {
          my puts "<TR><TH>$f</TH><TD><verbatim>$v</verbatim></TD>"

        }
        my puts "</TABLE><p>"
        my puts "Send some info:<p>"
        my puts "<FORM action=/[my request get REQUEST_PATH] method POST>"
        my puts "<TABLE>"
        foreach field {name rank serial_number} {
          set line "<TR><TH>$field</TH><TD><input name=\"$field\" "
          if {[dict exists $form $field]} {
            append line " value=\"[dict get $form $field]\"""

          }
          append line " /></TD></TR>"
          my puts $line

        }
        my puts "</TABLE>"
        my puts [my html footer]
    	}
    }

__Variable__

  - <a name='12'></a>variable __ChannelRegister__

  - <a name='13'></a>variable __reply__

    A dictionary which will converted into the MIME headers of the reply

  - <a name='14'></a>variable __request__

    A dictionary containing the SCGI transformed HTTP headers for the request

__Delegate__

  - <a name='15'></a>delegate __<server>__

    The server object which spawned this reply

__Methods__

  - <a name='16'></a>method __constructor__ *ServerObj* ?*args*?

  - <a name='17'></a>method __destructor__ ?*dictargs*?

    clean up on exit

  - <a name='18'></a>method __ChannelRegister__ ?*args*?

    Registers a channel to be closed by the close method

  - <a name='19'></a>method __close__

    Close channels opened by this object

  - <a name='20'></a>method __Log\_Dispatched__

    Record a dispatch event

  - <a name='21'></a>method __dispatch__ *newsock* *datastate*

    Accept the handoff from the server object of the socket *newsock* and feed
    it the state *datastate*\. Fields the *datastate* are looking for in
    particular are:

    \* __mixin__ \- A key/value list of slots and classes to be mixed into the
    object prior to invoking __Dispatch__\.

    \* __http__ \- A key/value list of values to populate the object's
    *request* ensemble

    All other fields are passed along to the __clay__ structure of the
    object\.

  - <a name='22'></a>method __Dispatch__

  - <a name='23'></a>method __html\_header__ *title* ?*args*?

  - <a name='24'></a>method __html\_footer__ ?*args*?

  - <a name='25'></a>method __[error](\.\./\.\./\.\./\.\./index\.md\#error)__ *code* ?*msg* ____? ?*errorInfo* ____?

  - <a name='26'></a>method __content__

    REPLACE ME: This method is the "meat" of your application\. It writes to the
    result buffer via the "puts" method and can tweak the headers via "clay put
    header\_reply"

  - <a name='27'></a>method __EncodeStatus__ *status*

    Formulate a standard HTTP status header from he string provided\.

  - <a name='28'></a>method __[log](\.\./log/log\.md)__ *type* ?*info* ____?

  - <a name='29'></a>method __CoroName__

  - <a name='30'></a>method __DoOutput__

    Generates the the HTTP reply, streams that reply back across *chan*, and
    destroys the object\.

  - <a name='31'></a>method __FormData__

    For GET requests, converts the QUERY\_DATA header into a key/value list\. For
    POST requests, reads the Post data and converts that information to a
    key/value list for application/x\-www\-form\-urlencoded posts\. For multipart
    posts, it composites all of the MIME headers of the post to a singular
    key/value list, and provides MIME\_\* information as computed by the
    __[mime](\.\./mime/mime\.md)__ package, including the MIME\_TOKEN, which
    can be fed back into the mime package to read out the contents\.


  - <a name='32'></a>method __PostData__ *length*












    Stream *length* bytes from the *chan* socket, but only of the request is
    a POST or PUSH\. Returns an empty string otherwise\.

  - <a name='33'></a>method __Session\_Load__

    Manage session data

  - <a name='34'></a>method __puts__ *line*

    Appends the value of *string* to the end of *reply\_body*, as well as a
    trailing newline character\.

  - <a name='35'></a>method __RequestFind__ *field*

  - <a name='36'></a>method __request__ *subcommand* ?*args*?

  - <a name='37'></a>method __reply__ *subcommand* ?*args*?

  - <a name='38'></a>method __reset__

    Clear the contents of the *reply\_body* variable, and reset all headers in
    the __reply__ structure back to the defaults for this object\.

  - <a name='39'></a>method __timeOutCheck__

    Called from the __http::server__ object which spawned this reply\. Checks
    to see if too much time has elapsed while waiting for data or generating a
    reply, and issues a timeout error to the request if it has, as well as
    destroy the object and close the *chan* socket\.

  - <a name='40'></a>method __[timestamp](\.\./\.\./\.\./\.\./index\.md\#timestamp)__

    Return the current system time in the format:

    %a, %d %b %Y %T %Z

## <a name='subsection3'></a>Class  httpd::server

*ancestors*: __httpd::mime__

__Variable__

  - <a name='41'></a>variable __template__

  - <a name='42'></a>variable __url\_patterns__

__Methods__

  - <a name='43'></a>method __constructor__ *args* ?*port* __auto__? ?*myaddr* __127\.0\.0\.1__? ?*string* __auto__? ?*name* __auto__? ?*doc\_root* ____? ?*reverse\_dns* __0__? ?*configuration\_file* ____? ?*protocol* __HTTP/1\.1__?

  - <a name='44'></a>method __destructor__ ?*dictargs*?

  - <a name='45'></a>method __connect__ *sock* *ip* *port*

    Reply to an open socket\. This method builds a coroutine to manage the
    remainder of the connection\. The coroutine's operations are driven by the
    __Connect__ method\.

  - <a name='46'></a>method __ServerHeaders__ *ip* *http\_request* *mimetxt*

  - <a name='47'></a>method __Connect__ *uuid* *sock* *ip*

    This method reads HTTP headers, and then consults the __dispatch__
    method to determine if the request is valid, and/or what kind of reply to
    generate\. Under normal cases, an object of class __::http::reply__ is
    created, and that class's __dispatch__ method\. This action passes
    control of the socket to the reply object\. The reply object manages the rest
    of the transaction, including closing the socket\.

  - <a name='48'></a>method __[counter](\.\./counter/counter\.md)__ *which*

    Increment an internal counter\.

  - <a name='49'></a>method __CheckTimeout__


    Check open connections for a time out event\.

  - <a name='50'></a>method __[debug](\.\./debug/debug\.md)__ ?*args*?

  - <a name='51'></a>method __dispatch__ *data*

    Given a key/value list of information, return a data structure describing
    how the server should reply\.

  - <a name='52'></a>method __Dispatch\_Default__ *reply*

    Method dispatch method of last resort before returning a 404 NOT FOUND
    error\. The default behavior is to look for a file in *DOCUMENT\_ROOT* which
    matches the query\.

  - <a name='53'></a>method __Dispatch\_Local__ *data*

    Method dispatch method invoked prior to invoking methods implemented by
    plugins\. If this method returns a non\-empty dictionary, that structure will
    be passed to the reply\. The default is an empty implementation\.

  - <a name='54'></a>method __Headers\_Local__ *varname*

    Introspect and possibly modify a data structure destined for a reply\. This
    method is invoked before invoking Header methods implemented by plugins\. The
    default implementation is empty\.

  - <a name='55'></a>method __Headers\_Process__ *varname*

    Introspect and possibly modify a data structure destined for a reply\. This
    method is built dynamically by the
    __[plugin](\.\./\.\./\.\./\.\./index\.md\#plugin)__ method\.

  - <a name='56'></a>method __HostName__ *ipaddr*

    Convert an ip address to a host name\. If the server/ reverse\_dns flag is
    false, this method simply returns the IP address back\. Internally, this
    method uses the *dns* module from tcllib\.

  - <a name='57'></a>method __[log](\.\./log/log\.md)__ ?*args*?

    Log an event\. The input for args is free form\. This method is intended to be
    replaced by the user, and is a noop for a stock http::server object\.

  - <a name='58'></a>method __[plugin](\.\./\.\./\.\./\.\./index\.md\#plugin)__ *slot* ?*class* ____?

    Incorporate behaviors from a plugin\. This method dynamically rebuilds the
    __Dispatch__ and __Headers__ method\. For every plugin, the server
    looks for the following entries in *clay plugin/*:

    *load* \- A script to invoke in the server's namespace during the
    __[plugin](\.\./\.\./\.\./\.\./index\.md\#plugin)__ method invokation\.

    *dispatch* \- A script to stitch into the server's __Dispatch__ method\.

    *headers* \- A script to stitch into the server's __Headers__ method\.

    *thread* \- A script to stitch into the server's __Thread\_start__
    method\.

  - <a name='59'></a>method __port\_listening__

    Return the actual port that httpd is listening on\.

  - <a name='60'></a>method __PrefixNormalize__ *prefix*

    For the stock version, trim trailing /'s and \*'s from a prefix\. This method
    can be replaced by the end user to perform any other transformations needed
    for the application\.

  - <a name='61'></a>method __[source](\.\./\.\./\.\./\.\./index\.md\#source)__ *filename*

  - <a name='62'></a>method __start__

    Open the socket listener\.

  - <a name='63'></a>method __stop__

    Shut off the socket listener, and destroy any pending replies\.

  - <a name='64'></a>method __SubObject \{\} db__

  - <a name='65'></a>method __SubObject \{\} default__

  - <a name='66'></a>method __template__ *page*

    Return a template for the string *page*

  - <a name='67'></a>method __TemplateSearch__ *page*

    Perform a search for the template that best matches *page*\. This can
    include local file searches, in\-memory structures, or even database lookups\.
    The stock implementation simply looks for files with a \.tml or \.html
    extension in the ?doc\_root? directory\.

  - <a name='68'></a>method __Thread\_start__

    Built by the __[plugin](\.\./\.\./\.\./\.\./index\.md\#plugin)__ method\.
    Called by the __start__ method\. Intended to allow plugins to spawn
    worker threads\.

  - <a name='69'></a>method __Uuid\_Generate__

    Generate a GUUID\. Used to ensure every request has a unique ID\. The default
    implementation is:

    return [::clay::uuid generate]

  - <a name='70'></a>method __Validate\_Connection__ *sock* *ip*

    Given a socket and an ip address, return true if this connection should be
    terminated, or false if it should be allowed to continue\. The stock
    implementation always returns 0\. This is intended for applications to be
    able to implement black lists and/or provide security based on IP address\.

## <a name='subsection4'></a>Class  httpd::server::dispatch

*ancestors*: __httpd::server__

Provide a backward compadible alias

## <a name='subsection5'></a>Class  httpd::content\.redirect

__Methods__

  - <a name='71'></a>method __reset__

  - <a name='72'></a>method __content__

## <a name='subsection6'></a>Class  httpd::content\.cache

__Methods__

  - <a name='73'></a>method __Dispatch__

## <a name='subsection7'></a>Class  httpd::content\.template

__Methods__

  - <a name='74'></a>method __content__

## <a name='subsection8'></a>Class  httpd::content\.file

Class to deliver Static content When utilized, this class is fed a local
filename by the dispatcher

__Methods__

  - <a name='75'></a>method __FileName__

  - <a name='76'></a>method __DirectoryListing__ *local\_file*

  - <a name='77'></a>method __content__

  - <a name='78'></a>method __Dispatch__

## <a name='subsection9'></a>Class  httpd::content\.exec

__Variable__

  - <a name='79'></a>variable __exename__

__Methods__

  - <a name='80'></a>method __CgiExec__ *execname* *script* *arglist*

  - <a name='81'></a>method __Cgi\_Executable__ *script*

## <a name='subsection10'></a>Class  httpd::content\.proxy

*ancestors*: __httpd::content\.exec__

Return data from an proxy process

__Methods__

  - <a name='82'></a>method __proxy\_channel__

  - <a name='83'></a>method __proxy\_path__

  - <a name='84'></a>method __ProxyRequest__ *chana* *chanb*

  - <a name='85'></a>method __ProxyReply__ *chana* *chanb* ?*args*?

  - <a name='86'></a>method __Dispatch__

## <a name='subsection11'></a>Class  httpd::content\.cgi

*ancestors*: __httpd::content\.proxy__

__Methods__

  - <a name='87'></a>method __FileName__

  - <a name='88'></a>method __proxy\_channel__

  - <a name='89'></a>method __ProxyRequest__ *chana* *chanb*

  - <a name='90'></a>method __ProxyReply__ *chana* *chanb* ?*args*?

  - <a name='91'></a>method __DirectoryListing__ *local\_file*

    For most CGI applications a directory list is vorboten

## <a name='subsection12'></a>Class  httpd::protocol\.scgi

Return data from an SCGI process

__Methods__

  - <a name='92'></a>method __EncodeStatus__ *status*

## <a name='subsection13'></a>Class  httpd::content\.scgi

*ancestors*: __httpd::content\.proxy__

__Methods__

  - <a name='93'></a>method __scgi\_info__

  - <a name='94'></a>method __proxy\_channel__

  - <a name='95'></a>method __ProxyRequest__ *chana* *chanb*

  - <a name='96'></a>method __ProxyReply__ *chana* *chanb* ?*args*?

## <a name='subsection14'></a>Class  httpd::server\.scgi

*ancestors*: __httpd::server__

Act as an SCGI Server

__Methods__

  - <a name='97'></a>method __[debug](\.\./debug/debug\.md)__ ?*args*?

  - <a name='98'></a>method __Connect__ *uuid* *sock* *ip*

## <a name='subsection15'></a>Class  httpd::content\.websocket

Upgrade a connection to a websocket

## <a name='subsection16'></a>Class  httpd::plugin

httpd plugin template

## <a name='subsection17'></a>Class  httpd::plugin\.dict\_dispatch

A rudimentary plugin that dispatches URLs from a dict data structure

__Methods__

  - <a name='99'></a>method __Dispatch\_Dict__ *data*

    Implementation of the dispatcher

  - <a name='100'></a>method __uri \{\} add__ *vhosts* *patterns* *info*

  - <a name='101'></a>method __uri \{\} direct__ *vhosts* *patterns* *info* *body*

## <a name='subsection18'></a>Class  httpd::reply\.memchan

*ancestors*: __httpd::reply__

__Methods__

  - <a name='102'></a>method __output__

  - <a name='103'></a>method __DoOutput__

  - <a name='104'></a>method __close__

## <a name='subsection19'></a>Class  httpd::plugin\.local\_memchan

__Methods__

  - <a name='105'></a>method __local\_memchan__ *command* ?*args*?

  - <a name='106'></a>method __Connect\_Local__ *uuid* *sock* ?*args*?

    A modified connection method that passes simple GET request to an object and
    pulls data directly from the reply\_body data variable in the object Needed
    because memchan is bidirectional, and we can't seem to communicate that the
    server is one side of the link and the reply is another

# <a name='section4'></a>AUTHORS

Sean Woods

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *network* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

When proposing code changes, please provide *unified diffs*, i\.e the output of

Changes to embedded/md/tcllib/files/modules/imap4/imap4.md.

31
32
33
34
35
36
37


38
39
40
41
42
43
44
45
46
47
48
49
  - [REFERENCES](#section5)

  - [Bugs, Ideas, Feedback](#section6)

  - [See Also](#seealso)

  - [Keywords](#keywords)



# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require imap4 ?0\.5\.2?  

[__::imap4::open__ *hostname* ?*port*?](#1)  
[__::imap4::starttls__ *chan*](#2)  
[__::imap4::login__ *chan* *user* *pass*](#3)  
[__::imap4::folders__ *chan* ?*\-inline*? ?*mboxref*? ?*mboxname*?](#4)  
[__::imap4::select__ *chan* ?*mailbox*?](#5)  
[__::imap4::examine__ *chan* ?*mailbox*?](#6)  







>
>




|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  - [REFERENCES](#section5)

  - [Bugs, Ideas, Feedback](#section6)

  - [See Also](#seealso)

  - [Keywords](#keywords)

  - [Category](#category)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require imap4 ?0\.5\.3?  

[__::imap4::open__ *hostname* ?*port*?](#1)  
[__::imap4::starttls__ *chan*](#2)  
[__::imap4::login__ *chan* *user* *pass*](#3)  
[__::imap4::folders__ *chan* ?*\-inline*? ?*mboxref*? ?*mboxname*?](#4)  
[__::imap4::select__ *chan* ?*mailbox*?](#5)  
[__::imap4::examine__ *chan* ?*mailbox*?](#6)  
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
    The namespace variable __::imap4::use\_ssl__ can be used to establish to
    a secure connection via TSL/SSL if set to true\. In this case default
    connection port defaults to 993\.

    *Note:* For connecting via SSL the Tcl module *tls* must be already
    loaded otherwise an error is raised\.

        package require tls              ; \# must be loaded for TLS/SSL
        set ::imap4::use\_ssl 1           ; \# request a secure connection
        set chan \[::imap4::open $server\] ; \# default port is now 993

  - <a name='2'></a>__::imap4::starttls__ *chan*

    Use this when tasked with connecting to an unsecure port which must be
    changed to a secure port prior to user login\. This feature is known as
    *STARTTLS*\.








|
|
|







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
    The namespace variable __::imap4::use\_ssl__ can be used to establish to
    a secure connection via TSL/SSL if set to true\. In this case default
    connection port defaults to 993\.

    *Note:* For connecting via SSL the Tcl module *tls* must be already
    loaded otherwise an error is raised\.

        package require tls              ; # must be loaded for TLS/SSL
        set ::imap4::use_ssl 1           ; # request a secure connection
        set chan [::imap4::open $server] ; # default port is now 993

  - <a name='2'></a>__::imap4::starttls__ *chan*

    Use this when tasked with connecting to an unsecure port which must be
    changed to a secure port prior to user login\. This feature is known as
    *STARTTLS*\.

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

    *mboxname* \- mailbox name, defaults to "\*"

    If __\-inline__ is specified a compact folderlist is returned instead of
    the result code\. All flags are converted to lowercase and leading special
    characters are removed\.

        \{\{Arc08 noselect\} \{Arc08/Private \{noinferiors unmarked\}\} \{INBOX noinferiors\}\}

  - <a name='5'></a>__::imap4::select__ *chan* ?*mailbox*?

    Select a mailbox, 0 is returned on success\.

    *chan* \- imap channel








|







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

    *mboxname* \- mailbox name, defaults to "\*"

    If __\-inline__ is specified a compact folderlist is returned instead of
    the result code\. All flags are converted to lowercase and leading special
    characters are removed\.

        {{Arc08 noselect} {Arc08/Private {noinferiors unmarked}} {INBOX noinferiors}}

  - <a name='5'></a>__::imap4::select__ *chan* ?*mailbox*?

    Select a mailbox, 0 is returned on success\.

    *chan* \- imap channel

202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

    Currently supported options: *delim* \- hierarchy delimiter only, *match*
    \- ref and mbox search patterns \(see __::imap4::folders__\), *names* \-
    list of folder names only, *flags* \- list of folder names with flags in
    format *\{ \{name \{flags\}\} \.\.\. \}* \(see also compact format in function
    __::imap4::folders__\)\.

        \{\{Arc08 \{\{\\NoSelect\}\}\} \{Arc08/Private \{\{\\NoInferiors\} \{\\UnMarked\}\}\} \{INBOX \{\\NoInferiors\}\}\}

  - <a name='11'></a>__::imap4::msginfo__ *chan* *msgid* ?*info*? ?*defval*?

    Get information \(from previously collected using fetch\) from a given
    *msgid*\. If the 'info' argument is omitted or a null string, the list of
    available information options for the given message is returned\.








|







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

    Currently supported options: *delim* \- hierarchy delimiter only, *match*
    \- ref and mbox search patterns \(see __::imap4::folders__\), *names* \-
    list of folder names only, *flags* \- list of folder names with flags in
    format *\{ \{name \{flags\}\} \.\.\. \}* \(see also compact format in function
    __::imap4::folders__\)\.

        {{Arc08 {{\NoSelect}}} {Arc08/Private {{\NoInferiors} {\UnMarked}}} {INBOX {\NoInferiors}}}

  - <a name='11'></a>__::imap4::msginfo__ *chan* *msgid* ?*info*? ?*defval*?

    Get information \(from previously collected using fetch\) from a given
    *msgid*\. If the 'info' argument is omitted or a null string, the list of
    available information options for the given message is returned\.

244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
    'recent' flagged msgs\), *FLAGS*

    In conjunction with OK: *PERMFLAGS*, *UIDNEXT*, *UIDVAL*, *UNSEEN*

    Div\. states: *CURRENT*, *FOUND*, *PERM*\.

        ::imap4::select $chan INBOX
        puts "\[::imap4::mboxinfo $chan exists\] mails in INBOX"

  - <a name='13'></a>__::imap4::isableto__ *chan* ?*capability*?

    Test for capability\. It returns 1 if requested capability is supported, 0
    otherwise\. If *capability* is omitted all capability imap codes are
    retured as list\.








|







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
    'recent' flagged msgs\), *FLAGS*

    In conjunction with OK: *PERMFLAGS*, *UIDNEXT*, *UIDVAL*, *UNSEEN*

    Div\. states: *CURRENT*, *FOUND*, *PERM*\.

        ::imap4::select $chan INBOX
        puts "[::imap4::mboxinfo $chan exists] mails in INBOX"

  - <a name='13'></a>__::imap4::isableto__ *chan* ?*capability*?

    Test for capability\. It returns 1 if requested capability is supported, 0
    otherwise\. If *capability* is omitted all capability imap codes are
    retured as list\.

325
326
327
328
329
330
331
332
333
334
335
336
337
338
339

    *Imap conditional search flags:* SMALLER, LARGER, ON, SENTBEFORE, SENTON,
    SENTSINCE, SINCE, BEFORE \(not implemented\), UID \(not implemented\)

    *Logical search conditions:* OR, NOT

        ::imap4::search $chan larger 4000 seen
        puts "Found messages: \[::imap4::mboxinfo $chan found\]"
        Found messages: 1 3 6 7 8 9 13 14 15 19 20

  - <a name='20'></a>__::imap4::close__ *chan*

    Close the mailbox\. Permanently removes \\Deleted messages and return to the
    AUTH state\.








|







327
328
329
330
331
332
333
334
335
336
337
338
339
340
341

    *Imap conditional search flags:* SMALLER, LARGER, ON, SENTBEFORE, SENTON,
    SENTSINCE, SINCE, BEFORE \(not implemented\), UID \(not implemented\)

    *Logical search conditions:* OR, NOT

        ::imap4::search $chan larger 4000 seen
        puts "Found messages: [::imap4::mboxinfo $chan found]"
        Found messages: 1 3 6 7 8 9 13 14 15 19 20

  - <a name='20'></a>__::imap4::close__ *chan*

    Close the mailbox\. Permanently removes \\Deleted messages and return to the
    AUTH state\.

386
387
388
389
390
391
392
393
394
395
396
397
398
399
400

      * \-FLAGS

        Remove the flags in *flaglist* to the existing flags for the message\.

    For example:

        ::imap4::store $chan $start\_msgid:$end\_msgid \+FLAGS "Deleted"

  - <a name='24'></a>__::imap4::expunge__ *chan*

    Permanently removes all messages that have the \\Deleted flag set from the
    currently selected mailbox, without the need to close the connection\.

    *chan* \- imap channel







|







388
389
390
391
392
393
394
395
396
397
398
399
400
401
402

      * \-FLAGS

        Remove the flags in *flaglist* to the existing flags for the message\.

    For example:

        ::imap4::store $chan $start_msgid:$end_msgid +FLAGS "Deleted"

  - <a name='24'></a>__::imap4::expunge__ *chan*

    Permanently removes all messages that have the \\Deleted flag set from the
    currently selected mailbox, without the need to close the connection\.

    *chan* \- imap channel
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

    *chan* \- imap channel

# <a name='section3'></a>EXAMPLES

    set user myusername
    set pass xtremescrt
    set server imap\.test\.tld
    set FOLDER INBOX
    \# Connect to server
    set imap \[::imap4::open $server\]
    ::imap4::login $imap $user $pass
    ::imap4::select $imap $FOLDER
    \# Output all the information about that mailbox
    foreach info \[::imap4::mboxinfo $imap\] \{
        puts "$info \-> \[::imap4::mboxinfo $imap $info\]"
    \}

    \# fetch 3 records inline
    set fields \{from: to: subject: size\}
    foreach rec \[::imap4::fetch $imap :3 \-inline \{\*\}$fields\] \{
        puts \-nonewline "\#\[incr idx\]\)"
        for \{set j 0\} \{$j<\[llength $fields\]\} \{incr j\} \{
            puts "\\t\[lindex $fields $j\] \[lindex $rec $j\]"
        \}
    \}



    \# Show all the information available about the message ID 1
    puts "Available info about message 1: \[::imap4::msginfo $imap 1\]"

    \# Use the capability stuff
    puts "Capabilities: \[::imap4::isableto $imap\]"
    puts "Is able to imap4rev1? \[::imap4::isableto $imap imap4rev1\]"

    \# Cleanup
    ::imap4::cleanup $imap

# <a name='section4'></a>TLS Security Considerations

This package uses the __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ package to
handle the security for __https__ urls and other socket connections\.








|

|
|


|
|
|
<
>
|
|
|
|
|
|
<
<
|
>
>
|
|

|
|
|

|







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

    *chan* \- imap channel

# <a name='section3'></a>EXAMPLES

    set user myusername
    set pass xtremescrt
    set server imap.test.tld
    set FOLDER INBOX
    # Connect to server
    set imap [::imap4::open $server]
    ::imap4::login $imap $user $pass
    ::imap4::select $imap $FOLDER
    # Output all the information about that mailbox
    foreach info [::imap4::mboxinfo $imap] {
        puts "$info -> [::imap4::mboxinfo $imap $info]"

    }
    # fetch 3 records inline
    set fields {from: to: subject: size}
    foreach rec [::imap4::fetch $imap :3 -inline {*}$fields] {
        puts -nonewline "#[incr idx])"
        for {set j 0} {$j<[llength $fields]} {incr j} {
            puts "\t[lindex $fields $j] [lindex $rec $j]"


        }
    }

    # Show all the information available about the message ID 1
    puts "Available info about message 1: [::imap4::msginfo $imap 1]"

    # Use the capability stuff
    puts "Capabilities: [::imap4::isableto $imap]"
    puts "Is able to imap4rev1? [::imap4::isableto $imap imap4rev1]"

    # Cleanup
    ::imap4::cleanup $imap

# <a name='section4'></a>TLS Security Considerations

This package uses the __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ package to
handle the security for __https__ urls and other socket connections\.

469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init \-tls1 1 ;\# forcibly activate support for the TLS1 protocol

    \.\.\. your own application code \.\.\.

# <a name='section5'></a>REFERENCES

Mark R\. Crispin, "INTERNET MESSAGE ACCESS PROTOCOL \- VERSION 4rev1", RFC 3501,
March 2003,
[http://www\.rfc\-editor\.org/rfc/rfc3501\.txt](http://www\.rfc\-editor\.org/rfc/rfc3501\.txt)








|

|







471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol

    ... your own application code ...

# <a name='section5'></a>REFERENCES

Mark R\. Crispin, "INTERNET MESSAGE ACCESS PROTOCOL \- VERSION 4rev1", RFC 3501,
March 2003,
[http://www\.rfc\-editor\.org/rfc/rfc3501\.txt](http://www\.rfc\-editor\.org/rfc/rfc3501\.txt)

509
510
511
512
513
514
515




# <a name='keywords'></a>KEYWORDS

[email](\.\./\.\./\.\./\.\./index\.md\#email), [imap](\.\./\.\./\.\./\.\./index\.md\#imap),
[internet](\.\./\.\./\.\./\.\./index\.md\#internet),
[mail](\.\./\.\./\.\./\.\./index\.md\#mail), [net](\.\./\.\./\.\./\.\./index\.md\#net),
[rfc3501](\.\./\.\./\.\./\.\./index\.md\#rfc3501),
[ssl](\.\./\.\./\.\./\.\./index\.md\#ssl), [tls](\.\./\.\./\.\./\.\./index\.md\#tls)











>
>
>
>
511
512
513
514
515
516
517
518
519
520
521
# <a name='keywords'></a>KEYWORDS

[email](\.\./\.\./\.\./\.\./index\.md\#email), [imap](\.\./\.\./\.\./\.\./index\.md\#imap),
[internet](\.\./\.\./\.\./\.\./index\.md\#internet),
[mail](\.\./\.\./\.\./\.\./index\.md\#mail), [net](\.\./\.\./\.\./\.\./index\.md\#net),
[rfc3501](\.\./\.\./\.\./\.\./index\.md\#rfc3501),
[ssl](\.\./\.\./\.\./\.\./index\.md\#ssl), [tls](\.\./\.\./\.\./\.\./index\.md\#tls)

# <a name='category'></a>CATEGORY

Networking

Changes to embedded/md/tcllib/files/modules/irc/picoirc.md.

87
88
89
90
91
92
93
94
95

96
97
98
99
100
101
102
    break error code to halt further processing\. In this way the application can
    override the default send via the callback procedure\.

# <a name='section3'></a>CALLBACK

The callback must look like:

    proc Callback \{context state args\} \{
    \}


where context is the irc context variable name \(in case you need to pass it back
to a picoirc procedure\)\. state is one of a number of states as described below\.

  - __init__

    called just before the socket is created







|
<
>







87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102
    break error code to halt further processing\. In this way the application can
    override the default send via the callback procedure\.

# <a name='section3'></a>CALLBACK

The callback must look like:

    proc Callback {context state args} {

    }

where context is the irc context variable name \(in case you need to pass it back
to a picoirc procedure\)\. state is one of a number of states as described below\.

  - __init__

    called just before the socket is created

Changes to embedded/md/tcllib/files/modules/jpeg/jpeg.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

[//000000001]: # (jpeg \- JPEG image manipulation)
[//000000002]: # (Generated from file 'jpeg\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004\-2005, Code: Aaron Faupell <afaupell@users\.sourceforge\.net>  
Copyright &copy; 2007, Code:  Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>  
Copyright &copy; 2004\-2009, Doc:  Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>  
Copyright &copy; 2011, Code: Pat Thoyts <patthoyts@users\.sourceforge\.net>)
[//000000004]: # (jpeg\(n\) 0\.5 tcllib "JPEG image manipulation")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

[//000000001]: # (jpeg \- JPEG image manipulation)
[//000000002]: # (Generated from file 'jpeg\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004\-2005, Code: Aaron Faupell <afaupell@users\.sourceforge\.net>)
[//000000004]: # (Copyright &copy; 2007, Code:  Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000005]: # (Copyright &copy; 2004\-2009, Doc:  Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000006]: # (Copyright &copy; 2011, Code: Pat Thoyts <patthoyts@users\.sourceforge\.net>)
[//000000007]: # (jpeg\(n\) 0\.5 tcllib "JPEG image manipulation")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
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
    thumbnail is included in *file*, and the empty string otherwise\. Note that
    it is possible to include thumbnails in formats other than JPEG although
    that is not common\. The command finds thumbnails that are encoded in either
    the JFXX or EXIF segments of the JPEG information\. If both are present the
    EXIF thumbnail will take precedence\. Throws an error if *file* is not a
    JPEG image\.

        set fh \[open thumbnail\.jpg w\+\]
        fconfigure $fh \-translation binary \-encoding binary
        puts \-nonewline $fh \[::jpeg::getThumbnail photo\.jpg\]
        close $fh

  - <a name='5'></a>__::jpeg::getExif__ *file* ?*section*?

    *section* must be one of __main__ or __thumbnail__\. The default is
    __main__\. Returns a dictionary containing the EXIF information for the
    specified section\. For example:

            set exif \{
        	Make     Canon
        	Model    \{Canon DIGITAL IXUS\}
        	DateTime \{2001:06:09 15:17:32\}
            \}


    Throws an error if *file* is not a JPEG image\.

  - <a name='6'></a>__::jpeg::getExifFromChannel__ *channel* ?*section*?

    This command is as per __::jpeg::getExif__ except that it uses a
    previously opened channel\. *channel* should be a seekable channel and







|
|
|








|

|
|
<
>







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
    thumbnail is included in *file*, and the empty string otherwise\. Note that
    it is possible to include thumbnails in formats other than JPEG although
    that is not common\. The command finds thumbnails that are encoded in either
    the JFXX or EXIF segments of the JPEG information\. If both are present the
    EXIF thumbnail will take precedence\. Throws an error if *file* is not a
    JPEG image\.

        set fh [open thumbnail.jpg w+]
        fconfigure $fh -translation binary -encoding binary
        puts -nonewline $fh [::jpeg::getThumbnail photo.jpg]
        close $fh

  - <a name='5'></a>__::jpeg::getExif__ *file* ?*section*?

    *section* must be one of __main__ or __thumbnail__\. The default is
    __main__\. Returns a dictionary containing the EXIF information for the
    specified section\. For example:

            set exif {
        	Make     Canon
        	Model    {Canon DIGITAL IXUS}
        	DateTime {2001:06:09 15:17:32}

            }

    Throws an error if *file* is not a JPEG image\.

  - <a name='6'></a>__::jpeg::getExifFromChannel__ *channel* ?*section*?

    This command is as per __::jpeg::getExif__ except that it uses a
    previously opened channel\. *channel* should be a seekable channel and
129
130
131
132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
147
148

  - <a name='7'></a>__::jpeg::formatExif__ *keys*

    Takes a list of key\-value pairs as returned by __getExif__ and formats
    many of the values into a more human readable form\. As few as one key\-value
    may be passed in, the entire exif is not required\.

        foreach \{key val\} \[::jpeg::formatExif \[::jpeg::getExif photo\.jpg\]\] \{
            puts "$key: $val"
        \}


        array set exif \[::jpeg::getExif photo\.jpg\]
        puts "max f\-stop: \[::jpeg::formatExif \[list MaxAperture $exif\(MaxAperture\)\]\]

  - <a name='8'></a>__::jpeg::exifKeys__

    Returns a list of the EXIF keys which are currently understood\. There may be
    keys present in __getExif__ data that are not understood\. Those keys
    will appear in a 4 digit hexadecimal format\.








|

<
|
>
|
|







129
130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145
146
147
148

  - <a name='7'></a>__::jpeg::formatExif__ *keys*

    Takes a list of key\-value pairs as returned by __getExif__ and formats
    many of the values into a more human readable form\. As few as one key\-value
    may be passed in, the entire exif is not required\.

        foreach {key val} [::jpeg::formatExif [::jpeg::getExif photo.jpg]] {
            puts "$key: $val"

        }

        array set exif [::jpeg::getExif photo.jpg]
        puts "max f-stop: [::jpeg::formatExif [list MaxAperture $exif(MaxAperture)]]

  - <a name='8'></a>__::jpeg::exifKeys__

    Returns a list of the EXIF keys which are currently understood\. There may be
    keys present in __getExif__ data that are not understood\. Those keys
    will appear in a 4 digit hexadecimal format\.

Changes to embedded/md/tcllib/files/modules/json/json.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (json \- JSON)
[//000000002]: # (Generated from file 'json\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2006 ActiveState Software Inc\.  
Copyright &copy; 2009 Thomas Maeder, Glue Software Engineering AG)
[//000000004]: # (json\(n\) 1\.3\.4 tcllib "JSON")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (json \- JSON)
[//000000002]: # (Generated from file 'json\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2006 ActiveState Software Inc\.)
[//000000004]: # (Copyright &copy; 2009 Thomas Maeder, Glue Software Engineering AG)
[//000000005]: # (json\(n\) 1\.3\.4 tcllib "JSON")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
78
79
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
    throw an error\.

# <a name='section3'></a>EXAMPLES

An example of a JSON array converted to Tcl\. A JSON array is returned as a
single item with multiple elements\.

    \[
        \{


           "precision": "zip",
           "Latitude":  37\.7668,
           "Longitude": \-122\.3959,
           "Address":   "",
           "City":      "SAN FRANCISCO",
           "State":     "CA",
           "Zip":       "94107",
           "Country":   "US"
        \},
        \{

           "precision": "zip",
           "Latitude":  37\.371991,
           "Longitude": \-122\.026020,
           "Address":   "",
           "City":      "SUNNYVALE",
           "State":     "CA",
           "Zip":       "94085",
           "Country":   "US"
        \}
    \]


    =>
    \{Country US Latitude 37\.7668 precision zip State CA City \{SAN FRANCISCO\} Address \{\} Zip 94107 Longitude \-122\.3959\} \{Country US Latitude 37\.371991 precision zip State CA City SUNNYVALE Address \{\} Zip 94085 Longitude \-122\.026020\}

An example of a JSON object converted to Tcl\. A JSON object is returned as a
multi\-element list \(a dict\)\.

    \{

        "Image": \{
            "Width":  800,
            "Height": 600,
            "Title":  "View from 15th Floor",
            "Thumbnail": \{
                "Url":    "http://www\.example\.com/image/481989943",
                "Height": 125,
                "Width":  "100"
            \},
            "IDs": \[116, 943, 234, 38793\]
        \}
    \}


    =>
    Image \{IDs \{116 943 234 38793\} Thumbnail \{Width 100 Height 125 Url http://www\.example\.com/image/481989943\} Width 800 Height 600 Title \{View from 15th Floor\}\}

# <a name='section4'></a>RELATED

To write json, instead of parsing it, see package
__[json::write](json\_write\.md)__\.

# <a name='section5'></a>Bugs, Ideas, Feedback







<
<
>
>

|
|





|
<
>

|
|





<
<
>
>

|




<
>
|



|
|


|
|
<
<
>
>

|







78
79
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
    throw an error\.

# <a name='section3'></a>EXAMPLES

An example of a JSON array converted to Tcl\. A JSON array is returned as a
single item with multiple elements\.



    [
        {
           "precision": "zip",
           "Latitude":  37.7668,
           "Longitude": -122.3959,
           "Address":   "",
           "City":      "SAN FRANCISCO",
           "State":     "CA",
           "Zip":       "94107",
           "Country":   "US"
        },

        {
           "precision": "zip",
           "Latitude":  37.371991,
           "Longitude": -122.026020,
           "Address":   "",
           "City":      "SUNNYVALE",
           "State":     "CA",
           "Zip":       "94085",
           "Country":   "US"


        }
    ]
    =>
    {Country US Latitude 37.7668 precision zip State CA City {SAN FRANCISCO} Address {} Zip 94107 Longitude -122.3959} {Country US Latitude 37.371991 precision zip State CA City SUNNYVALE Address {} Zip 94085 Longitude -122.026020}

An example of a JSON object converted to Tcl\. A JSON object is returned as a
multi\-element list \(a dict\)\.


    {
        "Image": {
            "Width":  800,
            "Height": 600,
            "Title":  "View from 15th Floor",
            "Thumbnail": {
                "Url":    "http://www.example.com/image/481989943",
                "Height": 125,
                "Width":  "100"
            },
            "IDs": [116, 943, 234, 38793]


        }
    }
    =>
    Image {IDs {116 943 234 38793} Thumbnail {Width 100 Height 125 Url http://www.example.com/image/481989943} Width 800 Height 600 Title {View from 15th Floor}}

# <a name='section4'></a>RELATED

To write json, instead of parsing it, see package
__[json::write](json\_write\.md)__\.

# <a name='section5'></a>Bugs, Ideas, Feedback

Changes to embedded/md/tcllib/files/modules/lambda/lambda.md.

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# <a name='description'></a>DESCRIPTION

This package provides two convenience commands to make the writing of anonymous
procedures, i\.e\. lambdas more
__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__\-like\. Instead of, for example, to
write

    set f \{::apply \{\{x\} \{
       \.\.\.\.
    \}\}\}

with its deep nesting of braces, or

    set f \[list ::apply \{\{x y\} \{
       \.\.\.\.
    \}\} $value\_for\_x\]

with a list command to insert some of the arguments of a partial application,
just write

    set f \[lambda \{x\} \{
       \.\.\.\.
    \}\]

and

    set f \[lambda \{x y\} \{
       \.\.\.\.
    \} $value\_for\_x\]

# <a name='section2'></a>COMMANDS

  - <a name='1'></a>__::lambda__ *arguments* *body* ?*arg*\.\.\.?

    The command constructs an anonymous procedure from the list of arguments,
    body script and \(optional\) predefined argument values and returns a command







|
|
|



|
|
|




|
|
|



|
|
|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# <a name='description'></a>DESCRIPTION

This package provides two convenience commands to make the writing of anonymous
procedures, i\.e\. lambdas more
__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__\-like\. Instead of, for example, to
write

    set f {::apply {{x} {
       ....
    }}}

with its deep nesting of braces, or

    set f [list ::apply {{x y} {
       ....
    }} $value_for_x]

with a list command to insert some of the arguments of a partial application,
just write

    set f [lambda {x} {
       ....
    }]

and

    set f [lambda {x y} {
       ....
    } $value_for_x]

# <a name='section2'></a>COMMANDS

  - <a name='1'></a>__::lambda__ *arguments* *body* ?*arg*\.\.\.?

    The command constructs an anonymous procedure from the list of arguments,
    body script and \(optional\) predefined argument values and returns a command

Changes to embedded/md/tcllib/files/modules/lazyset/lazyset.md.

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
    boolean* is specified as true, then 2 arguments are appended corresponding
    to the name of the variable and the index, otherwise 1 argument is appended
    containing the name of variable\. The *commandPrefix* code is run in the
    same scope as the variable is read\.

# <a name='section3'></a>EXAMPLES

    ::lazyset::variable page \{apply \{\{name\} \{
    	package require http
    	set token \[http::geturl http://www\.tcl\.tk/\]
    	set data \[http::data $token\]
    	return $data
    \}\}\}

    puts $page

    ::lazyset::variable \-array true page \{apply \{\{name index\} \{
    	package require http
    	set token \[http::geturl $index\]
    	set data \[http::data $token\]
    	return $data
    \}\}\}

    puts $page\(http://www\.tcl\.tk/\)

    ::lazyset::variable \-appendArgs false simple \{
    	return \-level 0 42
    \}


    puts $simple

# <a name='section4'></a>AUTHORS

Roy Keene








|

|
|

|



|

|
|

|

|

|
|
<
>







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98
    boolean* is specified as true, then 2 arguments are appended corresponding
    to the name of the variable and the index, otherwise 1 argument is appended
    containing the name of variable\. The *commandPrefix* code is run in the
    same scope as the variable is read\.

# <a name='section3'></a>EXAMPLES

    ::lazyset::variable page {apply {{name} {
    	package require http
    	set token [http::geturl http://www.tcl.tk/]
    	set data [http::data $token]
    	return $data
    }}}

    puts $page

    ::lazyset::variable -array true page {apply {{name index} {
    	package require http
    	set token [http::geturl $index]
    	set data [http::data $token]
    	return $data
    }}}

    puts $page(http://www.tcl.tk/)

    ::lazyset::variable -appendArgs false simple {
    	return -level 0 42

    }

    puts $simple

# <a name='section4'></a>AUTHORS

Roy Keene

Changes to embedded/md/tcllib/files/modules/ldap/ldap.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

[//000000001]: # (ldap \- LDAP client)
[//000000002]: # (Generated from file 'ldap\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>  
Copyright &copy; 2004 Jochen Loewer <loewerj@web\.de>  
Copyright &copy; 2006 Michael Schlenker <mic42@users\.sourceforge\.net>)
[//000000004]: # (ldap\(n\) 1\.9\.2 tcllib "LDAP client")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14

[//000000001]: # (ldap \- LDAP client)
[//000000002]: # (Generated from file 'ldap\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (Copyright &copy; 2004 Jochen Loewer <loewerj@web\.de>)
[//000000005]: # (Copyright &copy; 2006 Michael Schlenker <mic42@users\.sourceforge\.net>)
[//000000006]: # (ldap\(n\) 1\.9\.2 tcllib "LDAP client")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init \-tls1 1 ;\# forcibly activate support for the TLS1 protocol

    \.\.\. your own application code \.\.\.

# <a name='section3'></a>COMMANDS

  - <a name='1'></a>__::ldap::connect__ *host* ?*port*?

    Opens a LDAPv3 connection to the specified *host*, at the given *port*,
    and returns a token for the connection\. This token is the *handle*







|

|







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol

    ... your own application code ...

# <a name='section3'></a>COMMANDS

  - <a name='1'></a>__::ldap::connect__ *host* ?*port*?

    Opens a LDAPv3 connection to the specified *host*, at the given *port*,
    and returns a token for the connection\. This token is the *handle*
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
    If *verify\_cert* is set to 1, the default, this checks the server
    certificate against the known hosts\. If *sni\_servername* is set, the given
    hostname is used as the hostname for Server Name Indication in the TLS
    handshake\.

    Use __::tls::init__ to setup defaults for trusted certificates\.

    tls::init \-cadir /etc/ssl/certs/ca\-certificates\.crt

    TLS supports different protocol levels\. In common use are the versions 1\.0,
    1\.1 and 1\.2\. By default all those versions are offered\. If you need to
    modify the acceptable protocols, you can change the ::ldap::tlsProtocols
    list\.

  - <a name='3'></a>__::ldap::disconnect__ *handle*







|







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
    If *verify\_cert* is set to 1, the default, this checks the server
    certificate against the known hosts\. If *sni\_servername* is set, the given
    hostname is used as the hostname for Server Name Indication in the TLS
    handshake\.

    Use __::tls::init__ to setup defaults for trusted certificates\.

    tls::init -cadir /etc/ssl/certs/ca-certificates.crt

    TLS supports different protocol levels\. In common use are the versions 1\.0,
    1\.1 and 1\.2\. By default all those versions are offered\. If you need to
    modify the acceptable protocols, you can change the ::ldap::tlsProtocols
    list\.

  - <a name='3'></a>__::ldap::disconnect__ *handle*
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
    *attributes* of all matching objects \(DNs\)\. If the list of *attributes*
    was empty all attributes are returned\. The command blocks until it has
    received all results\. The valid *options* are identical to the options
    listed for __::ldap::searchInit__\.

    An example of a search expression is

    set filterString "&#124;\(cn=Linus\*\)\(sn=Torvalds\*\)"

    The return value of the command is a list of nested dictionaries\. The first
    level keys are object identifiers \(DNs\), second levels keys are attribute
    names\. In other words, it is in the form

    \{dn1 \{attr1 \{val11 val12 \.\.\.\} attr2 \{val21\.\.\.\} \.\.\.\}\} \{dn2 \{a1 \{v11 \.\.\.\} \.\.\.\}\} \.\.\.

  - <a name='9'></a>__::ldap::searchInit__ *handle* *baseObject* *filterString* *attributes* *options*

    This command initiates a LDAP search below the *baseObject* tree using a
    complex LDAP search expression *filterString*\. The search gets the
    specified *attributes* of all matching objects \(DNs\)\. The command itself
    just starts the search, to retrieve the actual results, use
    __::ldap::searchNext__\. A search can be terminated at any time by
    __::ldap::searchEnd__\. This informs the server that no further results
    should be sent by sending and ABANDON message and cleans up the internal
    state of the search\. Only one __::ldap::search__ can be active at a
    given time, this includes the introspection commands __::ldap::info
    saslmechanisms__, __ldap::info control__ and __ldap::info
    extensions__, which invoke a search internally\. Error responses from the
    server due to wrong arguments or similar things are returned with the first
    __::ldap::searchNext__ call and should be checked and dealed with there\.
    If the list of requested *attributes* is empty all attributes will be
    returned\. The parameter *options* specifies the options to be used in the
    search, and has the following format:

    \{\-option1 value1 \-option2 value2 \.\.\. \}

    Following options are available:

      * __\-scope__ base one sub

        Control the scope of the search to be one of __base__, __one__,
        or __sub__, to specify a base object, one\-level or subtree search\.







|





|




















|







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
    *attributes* of all matching objects \(DNs\)\. If the list of *attributes*
    was empty all attributes are returned\. The command blocks until it has
    received all results\. The valid *options* are identical to the options
    listed for __::ldap::searchInit__\.

    An example of a search expression is

    set filterString "|(cn=Linus*)(sn=Torvalds*)"

    The return value of the command is a list of nested dictionaries\. The first
    level keys are object identifiers \(DNs\), second levels keys are attribute
    names\. In other words, it is in the form

    {dn1 {attr1 {val11 val12 ...} attr2 {val21...} ...}} {dn2 {a1 {v11 ...} ...}} ...

  - <a name='9'></a>__::ldap::searchInit__ *handle* *baseObject* *filterString* *attributes* *options*

    This command initiates a LDAP search below the *baseObject* tree using a
    complex LDAP search expression *filterString*\. The search gets the
    specified *attributes* of all matching objects \(DNs\)\. The command itself
    just starts the search, to retrieve the actual results, use
    __::ldap::searchNext__\. A search can be terminated at any time by
    __::ldap::searchEnd__\. This informs the server that no further results
    should be sent by sending and ABANDON message and cleans up the internal
    state of the search\. Only one __::ldap::search__ can be active at a
    given time, this includes the introspection commands __::ldap::info
    saslmechanisms__, __ldap::info control__ and __ldap::info
    extensions__, which invoke a search internally\. Error responses from the
    server due to wrong arguments or similar things are returned with the first
    __::ldap::searchNext__ call and should be checked and dealed with there\.
    If the list of requested *attributes* is empty all attributes will be
    returned\. The parameter *options* specifies the options to be used in the
    search, and has the following format:

    {-option1 value1 -option2 value2 ... }

    Following options are available:

      * __\-scope__ base one sub

        Control the scope of the search to be one of __base__, __one__,
        or __sub__, to specify a base object, one\-level or subtree search\.
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
    This command returns the next entry from a LDAP search initiated by
    __::ldap::searchInit__\. It returns only after a new result is received
    or when no further results are available, but takes care to keep the event
    loop alive\. The returned entry is a list with two elements: the first is the
    DN of the entry, the second is the list of attributes and values, under the
    format:

    dn \{attr1 \{val11 val12 \.\.\.\} attr2 \{val21\.\.\.\} \.\.\.\}

    The __::ldap::searchNext__ command returns an empty list at the end of
    the search\.

  - <a name='11'></a>__::ldap::searchEnd__ *handle*

    This command terminates a LDAP search initiated by







|







269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
    This command returns the next entry from a LDAP search initiated by
    __::ldap::searchInit__\. It returns only after a new result is received
    or when no further results are available, but takes care to keep the event
    loop alive\. The returned entry is a list with two elements: the first is the
    DN of the entry, the second is the list of attributes and values, under the
    format:

    dn {attr1 {val11 val12 ...} attr2 {val21...} ...}

    The __::ldap::searchNext__ command returns an empty list at the end of
    the search\.

  - <a name='11'></a>__::ldap::searchEnd__ *handle*

    This command terminates a LDAP search initiated by
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
  - <a name='13'></a>__::ldap::modifyMulti__ *handle* *dn* *attrValToReplace* ?*attrValToDelete*? ?*attrValToAdd*?

    This command modifies the object *dn* on the ldap server we are connected
    to via *handle*\. It replaces attributes with new values, deletes
    attributes, and adds new attributes with new values\. All arguments are lists
    with the format:

    attr1 \{val11 val12 \.\.\.\} attr2 \{val21\.\.\.\} \.\.\.

    where each value list may be empty for deleting all attributes\. The optional
    arguments default to empty lists of attributes to delete and to add\.

      * list *attrValToReplace* \(in\)

        No attributes will be changed if this argument is empty\. The dictionary







|







320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
  - <a name='13'></a>__::ldap::modifyMulti__ *handle* *dn* *attrValToReplace* ?*attrValToDelete*? ?*attrValToAdd*?

    This command modifies the object *dn* on the ldap server we are connected
    to via *handle*\. It replaces attributes with new values, deletes
    attributes, and adds new attributes with new values\. All arguments are lists
    with the format:

    attr1 {val11 val12 ...} attr2 {val21...} ...

    where each value list may be empty for deleting all attributes\. The optional
    arguments default to empty lists of attributes to delete and to add\.

      * list *attrValToReplace* \(in\)

        No attributes will be changed if this argument is empty\. The dictionary
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

# <a name='section4'></a>EXAMPLES

A small example, extracted from the test application coming with this code\.

        package require ldap

        \# Connect, bind, add a new object, modify it in various ways

        set handle \[ldap::connect localhost 9009\]

        set dn "cn=Manager, o=University of Michigan, c=US"
        set pw secret

        ldap::bind $handle $dn $pw

        set dn "cn=Test User,ou=People,o=University of Michigan,c=US"

        ldap::add $handle $dn \{
    	objectClass     OpenLDAPperson
    	cn              \{Test User\}
    	mail            test\.user@google\.com
    	uid             testuid
    	sn              User
    	telephoneNumber \+31415926535
    	telephoneNumber \+27182818285
        \}


        set dn "cn=Another User,ou=People,o=University of Michigan,c=US"

        ldap::addMulti $handle $dn \{
    	objectClass     \{OpenLDAPperson\}
    	cn              \{\{Anotther User\}\}
    	mail            \{test\.user@google\.com\}
    	uid             \{testuid\}
    	sn              \{User\}
    	telephoneNumber \{\+31415926535 \+27182818285\}
        \}


        \# Replace all attributes
        ldap::modify $handle $dn \[list drink icetea uid JOLO\]

        \# Add some more
        ldap::modify $handle $dn \{\} \{\} \[list drink water  drink orangeJuice pager "\+1 313 555 7671"\]

        \# Delete
        ldap::modify $handle $dn \{\} \[list drink water  pager ""\]

        \# Move
        ldap::modifyDN $handle $dn "cn=Tester"

        \# Kill the test object, and shut the connection down\.
        set dn "cn=Tester,ou=People,o=University of Michigan,c=US"
        ldap::delete $handle $dn

        ldap::unbind     $handle
        ldap::disconnect $handle

And a another example, a simple query, and processing the results\.

        package require ldap
        set handle \[ldap::connect ldap\.acme\.com 389\]
        ldap::bind $handle
        set results \[ldap::search $handle "o=acme,dc=com" "\(uid=jdoe\)" \{\}\]
        foreach result $results \{
    	foreach \{object attributes\} $result break

    	\# The processing here is similar to what 'parray' does\.
    	\# I\.e\. finding the longest attribute name and then
    	\# generating properly aligned output listing all attributes
    	\# and their values\.

    	set width 0
    	set sortedAttribs \{\}
    	foreach \{type values\} $attributes \{
    	    if \{\[string length $type\] > $width\} \{
    		set width \[string length $type\]
    	    \}

    	    lappend sortedAttribs \[list $type $values\]
    	\}


    	puts "object='$object'"

    	foreach sortedAttrib  $sortedAttribs \{
    	    foreach \{type values\} $sortedAttrib break
    	    foreach value $values \{
    		regsub \-all "\\\[\\x01\-\\x1f\\\]" $value ? value
    		puts \[format "  %\-$\{width\}s %s" $type $value\]
    	    \}
    	\}


    	puts ""
        \}

        ldap::unbind $handle
        ldap::disconnect $handle

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *ldap* of the [Tcllib







|

|








|

|
|


|
|
<
|
>


|
|
|
|
|
|
|
<
|
>
|
|

|
|

|
|

|


|









|

|
|
|

|
|
|
|


|
|
|
|
<
>
|
<
|
>


|
|
|
|
|
<
<
>
>

<
>







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

# <a name='section4'></a>EXAMPLES

A small example, extracted from the test application coming with this code\.

        package require ldap

        # Connect, bind, add a new object, modify it in various ways

        set handle [ldap::connect localhost 9009]

        set dn "cn=Manager, o=University of Michigan, c=US"
        set pw secret

        ldap::bind $handle $dn $pw

        set dn "cn=Test User,ou=People,o=University of Michigan,c=US"

        ldap::add $handle $dn {
    	objectClass     OpenLDAPperson
    	cn              {Test User}
    	mail            [email protected]
    	uid             testuid
    	sn              User
    	telephoneNumber +31415926535
    	telephoneNumber +27182818285

        }

        set dn "cn=Another User,ou=People,o=University of Michigan,c=US"

        ldap::addMulti $handle $dn {
    	objectClass     {OpenLDAPperson}
    	cn              {{Anotther User}}
    	mail            {test.user@google.com}
    	uid             {testuid}
    	sn              {User}
    	telephoneNumber {+31415926535 +27182818285}

        }

        # Replace all attributes
        ldap::modify $handle $dn [list drink icetea uid JOLO]

        # Add some more
        ldap::modify $handle $dn {} {} [list drink water  drink orangeJuice pager "+1 313 555 7671"]

        # Delete
        ldap::modify $handle $dn {} [list drink water  pager ""]

        # Move
        ldap::modifyDN $handle $dn "cn=Tester"

        # Kill the test object, and shut the connection down.
        set dn "cn=Tester,ou=People,o=University of Michigan,c=US"
        ldap::delete $handle $dn

        ldap::unbind     $handle
        ldap::disconnect $handle

And a another example, a simple query, and processing the results\.

        package require ldap
        set handle [ldap::connect ldap.acme.com 389]
        ldap::bind $handle
        set results [ldap::search $handle "o=acme,dc=com" "(uid=jdoe)" {}]
        foreach result $results {
    	foreach {object attributes} $result break

    	# The processing here is similar to what 'parray' does.
    	# I.e. finding the longest attribute name and then
    	# generating properly aligned output listing all attributes
    	# and their values.

    	set width 0
    	set sortedAttribs {}
    	foreach {type values} $attributes {
    	    if {[string length $type] > $width} {
    		set width [string length $type]

    	    }
    	    lappend sortedAttribs [list $type $values]

    	}

    	puts "object='$object'"

    	foreach sortedAttrib  $sortedAttribs {
    	    foreach {type values} $sortedAttrib break
    	    foreach value $values {
    		regsub -all "\[\x01-\x1f\]" $value ? value
    		puts [format "  %-${width}s %s" $type $value]


    	    }
    	}
    	puts ""

        }
        ldap::unbind $handle
        ldap::disconnect $handle

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *ldap* of the [Tcllib

Changes to embedded/md/tcllib/files/modules/ldap/ldapx.md.

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
    difference is computed from the entry and its internal backup \(see section
    [OVERVIEW](#section2)\)\. Return value is the computed change list\.

## <a name='subsection6'></a>Entry Example

    package require ldapx

    \#

    \# Create an entry and fill it as a standard entry with
    \# attributes and values
    \#

    ::ldapx::entry create e
    e dn "uid=joe,ou=people,o=mycomp"
    e set1 "uid"             "joe"
    e set  "objectClass"     \{person anotherObjectClass\}
    e set1 "givenName"       "Joe"
    e set1 "sn"              "User"
    e set  "telephoneNumber" \{\+31415926535 \+2182818\}
    e set1 "anotherAttr"     "This is a beautiful day, isn't it?"

    puts stdout "e\\n\[e print\]"

    \#

    \# Create a second entry as a backup of the first, and
    \# make some changes on it\.
    \# Entry is named automatically by snit\.
    \#


    set b \[::ldapx::entry create %AUTO%\]
    e backup $b

    puts stdout "$b\\n\[$b print\]"

    $b del  "anotherAttr"
    $b del1 "objectClass" "anotherObjectClass"

    \#

    \# Create a change entry, a compute differences between first
    \# and second entry\.
    \#


    ::ldapx::entry create c
    c diff e $b

    puts stdout "$c\\n\[$c print\]"

    \#

    \# Apply changes to first entry\. It should be the same as the
    \# second entry, now\.
    \#


    e apply c

    ::ldapx::entry create nc
    nc diff e $b

    puts stdout "nc\\n\[nc print\]"

    \#

    \# Clean\-up
    \#


    e destroy
    $b destroy
    c destroy
    nc destroy

# <a name='section4'></a>LDAP CLASS







<
>
|
|
<
>



|


|


|

<
>
|
|
|
<
|
>
|


|




<
>
|
|
<
>




|

<
>
|
|
<
>






|

<
>
|
<
>







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
    difference is computed from the entry and its internal backup \(see section
    [OVERVIEW](#section2)\)\. Return value is the computed change list\.

## <a name='subsection6'></a>Entry Example

    package require ldapx


    #
    # Create an entry and fill it as a standard entry with
    # attributes and values

    #
    ::ldapx::entry create e
    e dn "uid=joe,ou=people,o=mycomp"
    e set1 "uid"             "joe"
    e set  "objectClass"     {person anotherObjectClass}
    e set1 "givenName"       "Joe"
    e set1 "sn"              "User"
    e set  "telephoneNumber" {+31415926535 +2182818}
    e set1 "anotherAttr"     "This is a beautiful day, isn't it?"

    puts stdout "e\n[e print]"


    #
    # Create a second entry as a backup of the first, and
    # make some changes on it.
    # Entry is named automatically by snit.

    #

    set b [::ldapx::entry create %AUTO%]
    e backup $b

    puts stdout "$b\n[$b print]"

    $b del  "anotherAttr"
    $b del1 "objectClass" "anotherObjectClass"


    #
    # Create a change entry, a compute differences between first
    # and second entry.

    #

    ::ldapx::entry create c
    c diff e $b

    puts stdout "$c\n[$c print]"


    #
    # Apply changes to first entry. It should be the same as the
    # second entry, now.

    #

    e apply c

    ::ldapx::entry create nc
    nc diff e $b

    puts stdout "nc\n[nc print]"


    #
    # Clean-up

    #

    e destroy
    $b destroy
    c destroy
    nc destroy

# <a name='section4'></a>LDAP CLASS
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
    Note: in the future, this method should use the LDAP transaction extension
    provided by OpenLDAP 2\.3 and later\.

## <a name='subsection10'></a>Ldap Example

        package require ldapx

        \#

        \# Connects to the LDAP directory
        \#


        ::ldapx::ldap create l
        set url "ldap://server\.mycomp\.com"
        if \{\! \[l connect $url "cn=admin,o=mycomp" "mypasswd"\]\} then \{
    	puts stderr "error: \[l error\]"
    	exit 1
        \}

        \#

        \# Search all entries matching some criterion
        \#


        l configure \-scope one
        ::ldapx::entry create e
        set n 0
        l traverse "ou=people,o=mycomp" "\(sn=Joe\*\)" \{sn givenName\} e \{
    	puts "dn: \[e dn\]"
    	puts "  sn:        \[e get1 sn\]"
    	puts "  givenName: \[e get1 givenName\]"
    	incr n
        \}

        puts "$n entries found"
        e destroy

        \#

        \# Add a telephone number to some entries
        \# Note this modification cannot be done in the "traverse" operation\.
        \#


        set lent \[l search "ou=people,o=mycomp" "\(sn=Joe\*\)" \{\}\]
        ::ldapx::entry create c
        foreach e $lent \{
    	$e backup
    	$e add1 "telephoneNumber" "\+31415926535"
    	c diff $e
    	if \{\! \[l commit c\]\} then \{
    	    puts stderr "error: \[l error\]"
    	    exit 1
    	\}

    	$e destroy
        \}

        c destroy

        l disconnect
        l destroy

# <a name='section5'></a>LDIF CLASS








<
>
|
<
|
>

|
|
|

<
|
|
>
|
<
|
>
|


|
|
|
|

<
>



<
>
|
|
<
|
>
|

|

|

|
|

<
>

<
>







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
    Note: in the future, this method should use the LDAP transaction extension
    provided by OpenLDAP 2\.3 and later\.

## <a name='subsection10'></a>Ldap Example

        package require ldapx


        #
        # Connects to the LDAP directory

        #

        ::ldapx::ldap create l
        set url "ldap://server.mycomp.com"
        if {! [l connect $url "cn=admin,o=mycomp" "mypasswd"]} then {
    	puts stderr "error: [l error]"
    	exit 1

        }

        #
        # Search all entries matching some criterion

        #

        l configure -scope one
        ::ldapx::entry create e
        set n 0
        l traverse "ou=people,o=mycomp" "(sn=Joe*)" {sn givenName} e {
    	puts "dn: [e dn]"
    	puts "  sn:        [e get1 sn]"
    	puts "  givenName: [e get1 givenName]"
    	incr n

        }
        puts "$n entries found"
        e destroy


        #
        # Add a telephone number to some entries
        # Note this modification cannot be done in the "traverse" operation.

        #

        set lent [l search "ou=people,o=mycomp" "(sn=Joe*)" {}]
        ::ldapx::entry create c
        foreach e $lent {
    	$e backup
    	$e add1 "telephoneNumber" "+31415926535"
    	c diff $e
    	if {! [l commit c]} then {
    	    puts stderr "error: [l error]"
    	    exit 1

    	}
    	$e destroy

        }
        c destroy

        l disconnect
        l destroy

# <a name='section5'></a>LDIF CLASS

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
    This method writes the entry given in the argument *entry* to the LDIF
    file\.

## <a name='subsection14'></a>Ldif Example

        package require ldapx

        \# This examples reads a LDIF file containing entries,
        \# compare them to a LDAP directory, and writes on standard
        \# output an LDIF file containing changes to apply to the
        \# LDAP directory to match exactly the LDIF file\.

        ::ldapx::ldif create liin
        liin channel stdin

        ::ldapx::ldif create liout
        liout channel stdout

        ::ldapx::ldap create la
        if \{\! \[la connect "ldap://server\.mycomp\.com"\]\} then \{
    	puts stderr "error: \[la error\]"
    	exit 1
        \}

        la configure \-scope one

        \# Reads LDIF file

        ::ldapx::entry create e1
        ::ldapx::entry create e2
        ::ldapx::entry create c

        while \{\[liin read e1\] \!= 0\} \{
    	set base \[e1 superior\]
    	set id \[e1 rdn\]
    	if \{\[la read $base "\($id\)" e2\] == 0\} then \{
    	    e2 reset
    	\}


    	c diff e1 e2
    	if \{\[llength \[c change\]\] \!= 0\} then \{
    	    liout write c
    	\}
        \}



        la disconnect
        la destroy
        e1 destroy
        e2 destroy
        c destroy
        liout destroy







|
|
|
|








|
|

<
>
|

|





|
|
|
|

<
|
>

|

<
<
>
>







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
    This method writes the entry given in the argument *entry* to the LDIF
    file\.

## <a name='subsection14'></a>Ldif Example

        package require ldapx

        # This examples reads a LDIF file containing entries,
        # compare them to a LDAP directory, and writes on standard
        # output an LDIF file containing changes to apply to the
        # LDAP directory to match exactly the LDIF file.

        ::ldapx::ldif create liin
        liin channel stdin

        ::ldapx::ldif create liout
        liout channel stdout

        ::ldapx::ldap create la
        if {! [la connect "ldap://server.mycomp.com"]} then {
    	puts stderr "error: [la error]"
    	exit 1

        }
        la configure -scope one

        # Reads LDIF file

        ::ldapx::entry create e1
        ::ldapx::entry create e2
        ::ldapx::entry create c

        while {[liin read e1] != 0} {
    	set base [e1 superior]
    	set id [e1 rdn]
    	if {[la read $base "($id)" e2] == 0} then {
    	    e2 reset

    	}

    	c diff e1 e2
    	if {[llength [c change]] != 0} then {
    	    liout write c


    	}
        }

        la disconnect
        la destroy
        e1 destroy
        e2 destroy
        c destroy
        liout destroy

Changes to embedded/md/tcllib/files/modules/log/log.md.

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
a *level* determining the importance of the message\. The user can then select
which levels to log, what commands to use for the logging of each level and the
channel to write the message to\. In the following example the logging of all
message with level __debug__ is deactivated\.

    package require log
    log::lvSuppress debug
    log::log debug "Unseen message" ; \# No output

By default all messages associated with an error\-level \(__emergency__,
__alert__, __critical__, and __error__\) are written to
__stderr__\. Messages with any other level are written to __stdout__\. In
the following example the log module is reconfigured to write __debug__
messages to __stderr__ too\.








|







78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
a *level* determining the importance of the message\. The user can then select
which levels to log, what commands to use for the logging of each level and the
channel to write the message to\. In the following example the logging of all
message with level __debug__ is deactivated\.

    package require log
    log::lvSuppress debug
    log::log debug "Unseen message" ; # No output

By default all messages associated with an error\-level \(__emergency__,
__alert__, __critical__, and __error__\) are written to
__stderr__\. Messages with any other level are written to __stdout__\. In
the following example the log module is reconfigured to write __debug__
messages to __stderr__ too\.

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
log any message\. In the following example all messages of level __notice__
are given to the non\-standard command __toText__ for logging\. This disables
the channel setting for such messages, assuming that __toText__ does not use
it by itself\.

    package require log
    log::lvCmd notice toText
    log::log notice "Handled by \\"toText\\""

Another database maintained by this facility is a map from message levels to
colors\. The information in this database has *no* influence on the behaviour
of the module\. It is merely provided as a convenience and in anticipation of the
usage of this facility in __tk__\-based application which may want to
colorize message logs\.








|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
log any message\. In the following example all messages of level __notice__
are given to the non\-standard command __toText__ for logging\. This disables
the channel setting for such messages, assuming that __toText__ does not use
it by itself\.

    package require log
    log::lvCmd notice toText
    log::log notice "Handled by \"toText\""

Another database maintained by this facility is a map from message levels to
colors\. The information in this database has *no* influence on the behaviour
of the module\. It is merely provided as a convenience and in anticipation of the
usage of this facility in __tk__\-based application which may want to
colorize message logs\.

239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    Like __::log::log__, but *msg* may contain substitutions and variable
    references, which are evaluated in the caller scope first\. The purpose of
    this command is to avoid overhead in the non\-logging case, if the log
    message building is expensive\. Any substitution errors raise an error in the
    command execution\. The following example shows an xml text representation,
    which is only generated in debug mode:

    log::logsubst debug \{XML of node $node is '\[$node toXml\]'\}

  - <a name='21'></a>__::log::logMsg__ *text*

    Convenience wrapper around __::log::log__\. Equivalent to __::log::log
    info text__\.

  - <a name='22'></a>__::log::logError__ *text*







|







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    Like __::log::log__, but *msg* may contain substitutions and variable
    references, which are evaluated in the caller scope first\. The purpose of
    this command is to avoid overhead in the non\-logging case, if the log
    message building is expensive\. Any substitution errors raise an error in the
    command execution\. The following example shows an xml text representation,
    which is only generated in debug mode:

    log::logsubst debug {XML of node $node is '[$node toXml]'}

  - <a name='21'></a>__::log::logMsg__ *text*

    Convenience wrapper around __::log::log__\. Equivalent to __::log::log
    info text__\.

  - <a name='22'></a>__::log::logError__ *text*

Changes to embedded/md/tcllib/files/modules/log/logger.md.

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

The __logger__ package provides a flexible system for logging messages from
different services, at priority levels, with different commands\.

To begin using the logger package, we do the following:

    package require logger
    set log \[logger::init myservice\]
    $\{log\}::notice "Initialized myservice logging"

    \.\.\. code \.\.\.

    $\{log\}::notice "Ending myservice logging"
    $\{log\}::delete

In the above code, after the package is loaded, the following things happen:

  - <a name='1'></a>__logger::init__ *service*

    Initializes the service *service* for logging\. The service names are
    actually Tcl namespace names, so they are separated with '::'\. The service







|
|

|

|
|







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

The __logger__ package provides a flexible system for logging messages from
different services, at priority levels, with different commands\.

To begin using the logger package, we do the following:

    package require logger
    set log [logger::init myservice]
    ${log}::notice "Initialized myservice logging"

    ... code ...

    ${log}::notice "Ending myservice logging"
    ${log}::delete

In the above code, after the package is loaded, the following things happen:

  - <a name='1'></a>__logger::init__ *service*

    Initializes the service *service* for logging\. The service names are
    actually Tcl namespace names, so they are separated with '::'\. The service
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
    Set the script to call when the log instance in question changes its log
    level\. If called without a command it returns the currently registered
    command\. The command gets two arguments appended, the old and the new
    loglevel\. The callback is invoked after all changes have been done\. If child
    loggers are affected, their callbacks are called before their parents
    callback\.

    proc lvlcallback \{old new\} \{
        puts "Loglevel changed from $old to $new"
    \}

    $\{log\}::lvlchangeproc lvlcallback

  - <a name='23'></a>__$\{log\}::logproc__ *level*

  - <a name='24'></a>__$\{log\}::logproc__ *level* *command*

  - <a name='25'></a>__$\{log\}::logproc__ *level* *argname* *body*

    This command comes in three forms \- the third, older one is deprecated and
    may be removed from future versions of the logger package\. The current set
    version takes one argument, a command to be executed when the level is
    called\. The callback command takes on argument, the text to be logged\. If
    called only with a valid level __logproc__ returns the name of the
    command currently registered as callback command\. __logproc__ specifies
    which command will perform the actual logging for a given level\. The logger
    package ships with default commands for all log levels, but with
    __logproc__ it is possible to replace them with custom code\. This would
    let you send your logs over the network, to a database, or anything else\.
    For example:

    proc logtoserver \{txt\} \{
        variable socket
        puts $socket "Notice: $txt"
    \}


    $\{log\}::logproc notice logtoserver

    Trace logs are slightly different: instead of a plain text argument, the
    argument provided to the logproc is a dictionary consisting of the
    __enter__ or __leave__ keyword along with another dictionary of
    details about the trace\. These include:

      * __proc__ \- Name of the procedure being traced\.







|

<
>
|



















|


<
|
>
|







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
    Set the script to call when the log instance in question changes its log
    level\. If called without a command it returns the currently registered
    command\. The command gets two arguments appended, the old and the new
    loglevel\. The callback is invoked after all changes have been done\. If child
    loggers are affected, their callbacks are called before their parents
    callback\.

    proc lvlcallback {old new} {
        puts "Loglevel changed from $old to $new"

    }
    ${log}::lvlchangeproc lvlcallback

  - <a name='23'></a>__$\{log\}::logproc__ *level*

  - <a name='24'></a>__$\{log\}::logproc__ *level* *command*

  - <a name='25'></a>__$\{log\}::logproc__ *level* *argname* *body*

    This command comes in three forms \- the third, older one is deprecated and
    may be removed from future versions of the logger package\. The current set
    version takes one argument, a command to be executed when the level is
    called\. The callback command takes on argument, the text to be logged\. If
    called only with a valid level __logproc__ returns the name of the
    command currently registered as callback command\. __logproc__ specifies
    which command will perform the actual logging for a given level\. The logger
    package ships with default commands for all log levels, but with
    __logproc__ it is possible to replace them with custom code\. This would
    let you send your logs over the network, to a database, or anything else\.
    For example:

    proc logtoserver {txt} {
        variable socket
        puts $socket "Notice: $txt"

    }

    ${log}::logproc notice logtoserver

    Trace logs are slightly different: instead of a plain text argument, the
    argument provided to the logproc is a dictionary consisting of the
    __enter__ or __leave__ keyword along with another dictionary of
    details about the trace\. These include:

      * __proc__ \- Name of the procedure being traced\.
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

  - <a name='30'></a>__$\{log\}::delproc__

    Set the script to call when the log instance in question is deleted\. If
    called without a command it returns the currently registered command\. For
    example:

    $\{log\}::delproc \[list closesock $logsock\]

  - <a name='31'></a>__$\{log\}::delete__

    This command deletes a particular logging service, and its children\. You
    must call this to clean up the resources used by a service\.

  - <a name='32'></a>__$\{log\}::trace__ *command*

    This command controls logging of enter/leave traces for specified
    procedures\. It is used to enable and disable tracing, query tracing status,
    and specify procedures are to be traced\. Trace handlers are unregistered
    when tracing is disabled\. As a result, there is not performance impact to a
    library when tracing is disabled, just as with other log level commands\.

      proc tracecmd \{ dict \} \{
          puts $dict
      \}


      set log \[::logger::init example\]
      $\{log\}::logproc trace tracecmd

      proc foo \{ args \} \{
          puts "In foo"
          bar 1
          return "foo\_result"
      \}


      proc bar \{ x \} \{
          puts "In bar"
          return "bar\_result"
      \}


      $\{log\}::trace add foo bar
      $\{log\}::trace on

      foo

    \# Output:
    enter \{proc ::foo level 1 script \{\} caller \{\} procargs \{args \{\}\}\}
    In foo
    enter \{proc ::bar level 2 script \{\} caller ::foo procargs \{x 1\}\}
    In bar
    leave \{proc ::bar level 2 script \{\} caller ::foo status ok result bar\_result\}
    leave \{proc ::foo level 1 script \{\} caller \{\} status ok result foo\_result\}

  - <a name='33'></a>__$\{log\}::trace__ __on__

    Turns on trace logging for procedures registered through the
    __[trace](\.\./\.\./\.\./\.\./index\.md\#trace)__ __add__ command\. This is
    similar to the __enable__ command for other logging levels, but allows
    trace logging to take place at any level\. The trace logging mechanism takes







|














|

<
|
>
|
|

|


|
<
|
>
|

|
<
|
>
|
|



|
|

|

|
|







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

  - <a name='30'></a>__$\{log\}::delproc__

    Set the script to call when the log instance in question is deleted\. If
    called without a command it returns the currently registered command\. For
    example:

    ${log}::delproc [list closesock $logsock]

  - <a name='31'></a>__$\{log\}::delete__

    This command deletes a particular logging service, and its children\. You
    must call this to clean up the resources used by a service\.

  - <a name='32'></a>__$\{log\}::trace__ *command*

    This command controls logging of enter/leave traces for specified
    procedures\. It is used to enable and disable tracing, query tracing status,
    and specify procedures are to be traced\. Trace handlers are unregistered
    when tracing is disabled\. As a result, there is not performance impact to a
    library when tracing is disabled, just as with other log level commands\.

      proc tracecmd { dict } {
          puts $dict

      }

      set log [::logger::init example]
      ${log}::logproc trace tracecmd

      proc foo { args } {
          puts "In foo"
          bar 1
          return "foo_result"

      }

      proc bar { x } {
          puts "In bar"
          return "bar_result"

      }

      ${log}::trace add foo bar
      ${log}::trace on

      foo

    # Output:
    enter {proc ::foo level 1 script {} caller {} procargs {args {}}}
    In foo
    enter {proc ::bar level 2 script {} caller ::foo procargs {x 1}}
    In bar
    leave {proc ::bar level 2 script {} caller ::foo status ok result bar_result}
    leave {proc ::foo level 1 script {} caller {} status ok result foo_result}

  - <a name='33'></a>__$\{log\}::trace__ __on__

    Turns on trace logging for procedures registered through the
    __[trace](\.\./\.\./\.\./\.\./index\.md\#trace)__ __add__ command\. This is
    similar to the __enable__ command for other logging levels, but allows
    trace logging to take place at any level\. The trace logging mechanism takes
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
# <a name='section3'></a>Logprocs and Callstack

The logger package takes extra care to keep the logproc out of the call stack\.
This enables logprocs to execute code in the callers scope by using uplevel or
linking to local variables by using upvar\. This may fire traces with all usual
side effects\.

    \# Print caller and current vars in the calling proc
    proc log\_local\_var \{txt\} \{
         set caller \[info level \-1\]
         set vars \[uplevel 1 info vars\]
         foreach var \[lsort $vars\] \{
            if \{\[uplevel 1 \[list array exists $var\]\] == 1\} \{
            	lappend val $var <Array>
            \} else \{
            	lappend val $var \[uplevel 1 \[list set $var\]\]
            \}
         \}


         puts "$txt"
         puts "Caller: $caller"
         puts "Variables in callers scope:"
         foreach \{var value\} $val \{
         	puts "$var = $value"
         \}
    \}



    \# install as logproc
    $\{log\}::logproc debug log\_local\_var

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *logger* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|
|
|
|
|
|

|
|
<
<
>
>



|

<
<
|
>
>
|
|







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
# <a name='section3'></a>Logprocs and Callstack

The logger package takes extra care to keep the logproc out of the call stack\.
This enables logprocs to execute code in the callers scope by using uplevel or
linking to local variables by using upvar\. This may fire traces with all usual
side effects\.

    # Print caller and current vars in the calling proc
    proc log_local_var {txt} {
         set caller [info level -1]
         set vars [uplevel 1 info vars]
         foreach var [lsort $vars] {
            if {[uplevel 1 [list array exists $var]] == 1} {
            	lappend val $var <Array>
            } else {
            	lappend val $var [uplevel 1 [list set $var]]


            }
         }
         puts "$txt"
         puts "Caller: $caller"
         puts "Variables in callers scope:"
         foreach {var value} $val {
         	puts "$var = $value"


         }
    }

    # install as logproc
    ${log}::logproc debug log_local_var

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *logger* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/log/loggerUtils.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (logger::utils \- Object Oriented logging facility)
[//000000002]: # (Generated from file 'loggerUtils\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2005 Aamer Akhter <aakhter@cisco\.com>)
[//000000004]: # (logger::utils\(n\) 1\.3 tcllib "Object Oriented logging facility")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>




|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (logger::utils \- Object Oriented logging facility)
[//000000002]: # (Generated from file 'loggerUtils\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2005 Aamer Akhter <aakhter@cisco\.com>)
[//000000004]: # (logger::utils\(n\) 1\.3\.1 tcllib "Object Oriented logging facility")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.4  
package require logger::utils ?1\.3?  

[__::logger::utils::createFormatCmd__ *formatString*](#1)  
[__::logger::utils::createLogProc__ __\-procName__ *procName* ?*options*\.\.\.?](#2)  
[__::logger::utils::applyAppender__ __\-appender__ *appenderType* ?*options*\.\.\.?](#3)  
[__::logger::utils::autoApplyAppender__ *command* *command\-string* *log* *op* *args*\.\.\.](#4)  

# <a name='description'></a>DESCRIPTION







|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.4  
package require logger::utils ?1\.3\.1?  

[__::logger::utils::createFormatCmd__ *formatString*](#1)  
[__::logger::utils::createLogProc__ __\-procName__ *procName* ?*options*\.\.\.?](#2)  
[__::logger::utils::applyAppender__ __\-appender__ *appenderType* ?*options*\.\.\.?](#3)  
[__::logger::utils::autoApplyAppender__ *command* *command\-string* *log* *op* *args*\.\.\.](#4)  

# <a name='description'></a>DESCRIPTION
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
      * __\-appenderArgs__ appenderArgs

        Additional arguments to apply to the appender\. The argument of the
        option is a list of options and their arguments\.

        For example

            logger::utils::applyAppender \-serviceCmd $log \-appender console \-appenderArgs \{\-conversionPattern \{\\\[%M\\\] \\\[%p\\\] \- %m\}\}

        The usual Tcl quoting rules apply\.

      * __\-levels__ levelList

        The list of levels to apply this appender to\. If not specified all
        levels are assumed\.

    Example of usage:

        % set log \[logger::init testLog\]
        ::logger::tree::testLog
        % logger::utils::applyAppender \-appender console \-serviceCmd $log
        % $\{log\}::error "this is an error"
        \[2005/08/22 10:14:13\] \[testLog\] \[global\] \[error\] this is an error

  - <a name='4'></a>__::logger::utils::autoApplyAppender__ *command* *command\-string* *log* *op* *args*\.\.\.

    This command is designed to be added via __trace leave__ to calls of
    __logger::init__\. It will look at preconfigured state \(via
    __::logger::utils::applyAppender__\) to autocreate appenders for newly
    created logger instances\. It will return its argument *log*\.

    Example of usage:

        logger::utils::applyAppender \-appender console
        set log \[logger::init applyAppender\-3\]
        $\{log\}::error "this is an error"

# <a name='section2'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *logger* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|










|

|
|
|










|
|
|







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
      * __\-appenderArgs__ appenderArgs

        Additional arguments to apply to the appender\. The argument of the
        option is a list of options and their arguments\.

        For example

            logger::utils::applyAppender -serviceCmd $log -appender console -appenderArgs {-conversionPattern {\[%M\] \[%p\] - %m}}

        The usual Tcl quoting rules apply\.

      * __\-levels__ levelList

        The list of levels to apply this appender to\. If not specified all
        levels are assumed\.

    Example of usage:

        % set log [logger::init testLog]
        ::logger::tree::testLog
        % logger::utils::applyAppender -appender console -serviceCmd $log
        % ${log}::error "this is an error"
        [2005/08/22 10:14:13] [testLog] [global] [error] this is an error

  - <a name='4'></a>__::logger::utils::autoApplyAppender__ *command* *command\-string* *log* *op* *args*\.\.\.

    This command is designed to be added via __trace leave__ to calls of
    __logger::init__\. It will look at preconfigured state \(via
    __::logger::utils::applyAppender__\) to autocreate appenders for newly
    created logger instances\. It will return its argument *log*\.

    Example of usage:

        logger::utils::applyAppender -appender console
        set log [logger::init applyAppender-3]
        ${log}::error "this is an error"

# <a name='section2'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *logger* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/map/map_slippy.md.

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# <a name='section2'></a>API

  - <a name='1'></a>__::map::slippy__ __length__ *level*

    This method returns the width/height of a slippy\-based map at the specified
    zoom *level*, in pixels\. This is, in essence, the result of

        expr \{ \[tiles $level\] \* \[tile size\] \}

  - <a name='2'></a>__::map::slippy__ __tiles__ *level*

    This method returns the width/height of a slippy\-based map at the specified
    zoom *level*, in *tiles*\.

  - <a name='3'></a>__::map::slippy__ __tile size__







|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# <a name='section2'></a>API

  - <a name='1'></a>__::map::slippy__ __length__ *level*

    This method returns the width/height of a slippy\-based map at the specified
    zoom *level*, in pixels\. This is, in essence, the result of

        expr { [tiles $level] * [tile size] }

  - <a name='2'></a>__::map::slippy__ __tiles__ *level*

    This method returns the width/height of a slippy\-based map at the specified
    zoom *level*, in *tiles*\.

  - <a name='3'></a>__::map::slippy__ __tile size__

Changes to embedded/md/tcllib/files/modules/markdown/markdown.md.

1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (markdown \- Markdown to HTML Converter)
[//000000002]: # (Generated from file 'markdown\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (markdown\(n\) 1\.1 tcllib "Markdown to HTML Converter")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|







1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (markdown \- Markdown to HTML Converter)
[//000000002]: # (Generated from file 'markdown\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (markdown\(n\) 1\.1\.1 tcllib "Markdown to HTML Converter")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  - [Bugs, Ideas, Feedback](#section2)

  - [Category](#category)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require Markdown 1\.1  
package require textutil ?0\.8?  

[__::Markdown::convert__ *markdown*](#1)  
[__::Markdown::register__ *langspec* *converter*](#2)  
[__::Markdown::get\_lang\_counter__](#3)  
[__::Markdown::reset\_lang\_counter__](#4)  








|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  - [Bugs, Ideas, Feedback](#section2)

  - [Category](#category)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require Markdown 1\.1\.1  
package require textutil ?0\.8?  

[__::Markdown::convert__ *markdown*](#1)  
[__::Markdown::register__ *langspec* *converter*](#2)  
[__::Markdown::get\_lang\_counter__](#3)  
[__::Markdown::reset\_lang\_counter__](#4)  

Changes to embedded/md/tcllib/files/modules/math/bigfloat.md.

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
    eventually a minus sign, it is considered as an integer\. Subsequently, no
    conversion is done at all\.

    *trailingZeros* \- the number of zeros to append at the end of the
    floating\-point number to get more precision\. It cannot be applied to an
    integer\.

        \# x and y are BigFloats : the first string contained a dot, and the second an e sign
        set x \[fromstr \-1\.000000\]
        set y \[fromstr 2000e30\]
        \# let's see how we get integers
        set t 20000000000000
        \# the old way \(package 1\.2\) is still supported for backwards compatibility :
        set m \[fromstr 10000000000\]
        \# but we do not need fromstr for integers anymore
        set n \-39
        \# t, m and n are integers

    The *number*'s last digit is considered by the procedure to be true at
    \+/\-1, For example, 1\.00 is the interval \[0\.99, 1\.01\], and 0\.43 the interval
    \[0\.42, 0\.44\]\. The Pi constant may be approximated by the number "3\.1415"\.
    This string could be considered as the interval \[3\.1414 , 3\.1416\] by
    __fromstr__\. So, when you mean 1\.0 as a double, you may have to write
    1\.000000 to get enough precision\. To learn more about this subject, see
    [PRECISION](#section7)\.

    For example :

        set x \[fromstr 1\.0000000000\]
        \# the next line does the same, but smarter
        set y \[fromstr 1\. 10\]

  - <a name='2'></a>__tostr__ ?__\-nosci__? *number*

    Returns a string form of a BigFloat, in which all digits are exacts\. *All
    exact digits* means a rounding may occur, for example to zero, if the
    uncertainty interval does not clearly show the true digits\. *number* may
    be an integer, causing the command to return exactly the input argument\.
    With the __\-nosci__ option, the number returned is never shown in
    scientific notation, i\.e\. not like '3\.4523e\+5' but like '345230\.'\.

        puts \[tostr \[fromstr 0\.99999\]\] ;\# 1\.0000
        puts \[tostr \[fromstr 1\.00001\]\] ;\# 1\.0000
        puts \[tostr \[fromstr 0\.002\]\] ;\# 0\.e\-2

    See [PRECISION](#section7) for that matter\. See also __iszero__ for
    how to detect zeros, which is useful when performing a division\.

  - <a name='3'></a>__fromdouble__ *double* ?*decimals*?

    Converts a double \(a simple floating\-point value\) to a BigFloat, with
    exactly *decimals* digits\. Without the *decimals* argument, it behaves
    like __fromstr__\. Here, the only important feature you might care of is
    the ability to create BigFloats with a fixed number of *decimals*\.

        tostr \[fromstr 1\.111 4\]
        \# returns : 1\.111000 \(3 zeros\)
        tostr \[fromdouble 1\.111 4\]
        \# returns : 1\.111

  - <a name='4'></a>__todouble__ *number*

    Returns a double, that may be used in *expr*, from a BigFloat\.

  - <a name='5'></a>__isInt__ *number*

    Returns 1 if *number* is an integer, 0 otherwise\.

  - <a name='6'></a>__isFloat__ *number*

    Returns 1 if *number* is a BigFloat, 0 otherwise\.

  - <a name='7'></a>__int2float__ *integer* ?*decimals*?

    Converts an integer to a BigFloat with *decimals* trailing zeros\. The
    default, and minimal, number of *decimals* is 1\. When converting back to
    string, one decimal is lost:

        set n 10
        set x \[int2float $n\]; \# like fromstr 10\.0
        puts \[tostr $x\]; \# prints "10\."
        set x \[int2float $n 3\]; \# like fromstr 10\.000
        puts \[tostr $x\]; \# prints "10\.00"

# <a name='section3'></a>ARITHMETICS

  - <a name='8'></a>__add__ *x* *y*

  - <a name='9'></a>__sub__ *x* *y*








|
|
|
|

|
|
|
|
|











|
|
|










|
|
|











|
|
|
|




















|
|
|
|







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
    eventually a minus sign, it is considered as an integer\. Subsequently, no
    conversion is done at all\.

    *trailingZeros* \- the number of zeros to append at the end of the
    floating\-point number to get more precision\. It cannot be applied to an
    integer\.

        # x and y are BigFloats : the first string contained a dot, and the second an e sign
        set x [fromstr -1.000000]
        set y [fromstr 2000e30]
        # let's see how we get integers
        set t 20000000000000
        # the old way (package 1.2) is still supported for backwards compatibility :
        set m [fromstr 10000000000]
        # but we do not need fromstr for integers anymore
        set n -39
        # t, m and n are integers

    The *number*'s last digit is considered by the procedure to be true at
    \+/\-1, For example, 1\.00 is the interval \[0\.99, 1\.01\], and 0\.43 the interval
    \[0\.42, 0\.44\]\. The Pi constant may be approximated by the number "3\.1415"\.
    This string could be considered as the interval \[3\.1414 , 3\.1416\] by
    __fromstr__\. So, when you mean 1\.0 as a double, you may have to write
    1\.000000 to get enough precision\. To learn more about this subject, see
    [PRECISION](#section7)\.

    For example :

        set x [fromstr 1.0000000000]
        # the next line does the same, but smarter
        set y [fromstr 1. 10]

  - <a name='2'></a>__tostr__ ?__\-nosci__? *number*

    Returns a string form of a BigFloat, in which all digits are exacts\. *All
    exact digits* means a rounding may occur, for example to zero, if the
    uncertainty interval does not clearly show the true digits\. *number* may
    be an integer, causing the command to return exactly the input argument\.
    With the __\-nosci__ option, the number returned is never shown in
    scientific notation, i\.e\. not like '3\.4523e\+5' but like '345230\.'\.

        puts [tostr [fromstr 0.99999]] ;# 1.0000
        puts [tostr [fromstr 1.00001]] ;# 1.0000
        puts [tostr [fromstr 0.002]] ;# 0.e-2

    See [PRECISION](#section7) for that matter\. See also __iszero__ for
    how to detect zeros, which is useful when performing a division\.

  - <a name='3'></a>__fromdouble__ *double* ?*decimals*?

    Converts a double \(a simple floating\-point value\) to a BigFloat, with
    exactly *decimals* digits\. Without the *decimals* argument, it behaves
    like __fromstr__\. Here, the only important feature you might care of is
    the ability to create BigFloats with a fixed number of *decimals*\.

        tostr [fromstr 1.111 4]
        # returns : 1.111000 (3 zeros)
        tostr [fromdouble 1.111 4]
        # returns : 1.111

  - <a name='4'></a>__todouble__ *number*

    Returns a double, that may be used in *expr*, from a BigFloat\.

  - <a name='5'></a>__isInt__ *number*

    Returns 1 if *number* is an integer, 0 otherwise\.

  - <a name='6'></a>__isFloat__ *number*

    Returns 1 if *number* is a BigFloat, 0 otherwise\.

  - <a name='7'></a>__int2float__ *integer* ?*decimals*?

    Converts an integer to a BigFloat with *decimals* trailing zeros\. The
    default, and minimal, number of *decimals* is 1\. When converting back to
    string, one decimal is lost:

        set n 10
        set x [int2float $n]; # like fromstr 10.0
        puts [tostr $x]; # prints "10."
        set x [int2float $n 3]; # like fromstr 10.000
        puts [tostr $x]; # prints "10.00"

# <a name='section3'></a>ARITHMETICS

  - <a name='8'></a>__add__ *x* *y*

  - <a name='9'></a>__sub__ *x* *y*

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

      * a BigFloat close enough to zero to raise "divide by zero"\.

      * the integer 0\.

    See here how numbers that are close to zero are converted to strings:

        tostr \[fromstr 0\.001\] ; \# \-> 0\.e\-2
        tostr \[fromstr 0\.000000\] ; \# \-> 0\.e\-5
        tostr \[fromstr \-0\.000001\] ; \# \-> 0\.e\-5
        tostr \[fromstr 0\.0\] ; \# \-> 0\.
        tostr \[fromstr 0\.002\] ; \# \-> 0\.e\-2

        set a \[fromstr 0\.002\] ; \# uncertainty interval : 0\.001, 0\.003
        tostr  $a ; \# 0\.e\-2
        iszero $a ; \# false

        set a \[fromstr 0\.001\] ; \# uncertainty interval : 0\.000, 0\.002
        tostr  $a ; \# 0\.e\-2
        iszero $a ; \# true

  - <a name='17'></a>__[equal](\.\./\.\./\.\./\.\./index\.md\#equal)__ *x* *y*

    Returns 1 if *x* and *y* are equal, 0 elsewhere\.

  - <a name='18'></a>__compare__ *x* *y*








|
|
|
|
|

|
|
|

|
|
|







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

      * a BigFloat close enough to zero to raise "divide by zero"\.

      * the integer 0\.

    See here how numbers that are close to zero are converted to strings:

        tostr [fromstr 0.001] ; # -> 0.e-2
        tostr [fromstr 0.000000] ; # -> 0.e-5
        tostr [fromstr -0.000001] ; # -> 0.e-5
        tostr [fromstr 0.0] ; # -> 0.
        tostr [fromstr 0.002] ; # -> 0.e-2

        set a [fromstr 0.002] ; # uncertainty interval : 0.001, 0.003
        tostr  $a ; # 0.e-2
        iszero $a ; # false

        set a [fromstr 0.001] ; # uncertainty interval : 0.000, 0.002
        tostr  $a ; # 0.e-2
        iszero $a ; # true

  - <a name='17'></a>__[equal](\.\./\.\./\.\./\.\./index\.md\#equal)__ *x* *y*

    Returns 1 if *x* and *y* are equal, 0 elsewhere\.

  - <a name='18'></a>__compare__ *x* *y*

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
internals of this library, the uncertainty interval may be slightly wider than
expected, but this should not cause false digits\.

Now you may ask this question : What precision am I going to get after calling
add, sub, mul or div? First you set a number from the string representation and,
by the way, its uncertainty is set:

    set a \[fromstr 1\.230\]
    \# $a belongs to \[1\.229, 1\.231\]
    set a \[fromstr 1\.000\]
    \# $a belongs to \[0\.999, 1\.001\]
    \# $a has a relative uncertainty of 0\.1% : 0\.001\(the uncertainty\)/1\.000\(the medium value\)

The uncertainty of the sum, or the difference, of two numbers, is the sum of
their respective uncertainties\.

    set a \[fromstr 1\.230\]
    set b \[fromstr 2\.340\]
    set sum \[add $a $b\]\]
    \# the result is : \[3\.568, 3\.572\] \(the last digit is known with an uncertainty of 2\)
    tostr $sum ; \# 3\.57

But when, for example, we add or substract an integer to a BigFloat, the
relative uncertainty of the result is unchanged\. So it is desirable not to
convert integers to BigFloats:

    set a \[fromstr 0\.999999999\]
    \# now something dangerous
    set b \[fromstr 2\.000\]
    \# the result has only 3 digits
    tostr \[add $a $b\]

    \# how to keep precision at its maximum
    puts \[tostr \[add $a 2\]\]

For multiplication and division, the relative uncertainties of the product or
the quotient, is the sum of the relative uncertainties of the operands\. Take
care of division by zero : check each divider with __iszero__\.

    set num \[fromstr 4\.00\]
    set denom \[fromstr 0\.01\]

    puts \[iszero $denom\];\# true
    set quotient \[div $num $denom\];\# error : divide by zero

    \# opposites of our operands
    puts \[compare $num \[opp $num\]\]; \# 1
    puts \[compare $denom \[opp $denom\]\]; \# 0 \!\!\!
    \# No suprise \! 0 and its opposite are the same\.\.\.

Effects of the precision of a number considered equal to zero to the cos
function:

    puts \[tostr \[cos \[fromstr 0\. 10\]\]\]; \# \-> 1\.000000000
    puts \[tostr \[cos \[fromstr 0\. 5\]\]\]; \# \-> 1\.0000
    puts \[tostr \[cos \[fromstr 0e\-10\]\]\]; \# \-> 1\.000000000
    puts \[tostr \[cos \[fromstr 1e\-10\]\]\]; \# \-> 1\.000000000

BigFloats with different internal representations may be converted to the same
string\.

For most analysis functions \(cosine, square root, logarithm, etc\.\), determining
the precision of the result is difficult\. It seems however that in many cases,
the loss of precision in the result is of one or two digits\. There are some
exceptions : for example,

    tostr \[exp \[fromstr 100\.0 10\]\]
    \# returns : 2\.688117142e\+43 which has only 10 digits of precision, although the entry
    \# has 14 digits of precision\.

# <a name='section8'></a>WHAT ABOUT TCL 8\.4 ?

If your setup do not provide Tcl 8\.5 but supports 8\.4, the package can still be
loaded, switching back to *math::bigfloat* 1\.2\. Indeed, an important function
introduced in Tcl 8\.5 is required \- the ability to handle bignums, that we can
do with __expr__\. Before 8\.5, this ability was provided by several packages,
including the pure\-Tcl *math::bignum* package provided by *tcllib*\. In this
case, all you need to know, is that arguments to the commands explained here,
are expected to be in their internal representation\. So even with integers, you
will need to call __fromstr__ and __tostr__ in order to convert them
between string and internal representations\.

    \#

    \# with Tcl 8\.5
    \# ============
    set a \[pi 20\]
    \# round returns an integer and 'everything is a string' applies to integers
    \# whatever big they are
    puts \[round \[mul $a 10000000000\]\]
    \#

    \# the same with Tcl 8\.4
    \# =====================
    set a \[pi 20\]
    \# bignums \(arbitrary length integers\) need a conversion hook
    set b \[fromstr 10000000000\]
    \# round returns a bignum:
    \# before printing it, we need to convert it with 'tostr'
    puts \[tostr \[round \[mul $a $b\]\]\]

# <a name='section9'></a>NAMESPACES AND OTHER PACKAGES

We have not yet discussed about namespaces because we assumed that you had
imported public commands into the global namespace, like this:

    namespace import ::math::bigfloat::\*

If you matter much about avoiding names conflicts, I considere it should be
resolved by the following :

    package require math::bigfloat
    \# beware: namespace ensembles are not available in Tcl 8\.4
    namespace eval ::math::bigfloat \{namespace ensemble create \-command ::bigfloat\}
    \# from now, the bigfloat command takes as subcommands all original math::bigfloat::\* commands
    set a \[bigfloat sub \[bigfloat fromstr 2\.000\] \[bigfloat fromstr 0\.530\]\]
    puts \[bigfloat tostr $a\]

# <a name='section10'></a>EXAMPLES

Guess what happens when you are doing some astronomy\. Here is an example :

    \# convert acurrate angles with a millisecond\-rated accuracy
    proc degree\-angle \{degrees minutes seconds milliseconds\} \{
        set result 0
        set div 1
        foreach factor \{1 1000 60 60\} var \[list $milliseconds $seconds $minutes $degrees\] \{
            \# we convert each entry var into milliseconds
            set div \[expr \{$div\*$factor\}\]
            incr result \[expr \{$var\*$div\}\]
        \}

        return \[div \[int2float $result\] $div\]
    \}

    \# load the package
    package require math::bigfloat
    namespace import ::math::bigfloat::\*
    \# work with angles : a standard formula for navigation \(taking bearings\)
    set angle1 \[deg2rad \[degree\-angle 20 30 40   0\]\]
    set angle2 \[deg2rad \[degree\-angle 21  0 50 500\]\]
    set opposite3 \[deg2rad \[degree\-angle 51  0 50 500\]\]
    set sinProduct \[mul \[sin $angle1\] \[sin $angle2\]\]
    set cosProduct \[mul \[cos $angle1\] \[cos $angle2\]\]
    set angle3 \[asin \[add \[mul $sinProduct \[cos $opposite3\]\] $cosProduct\]\]
    puts "angle3 : \[tostr \[rad2deg $angle3\]\]"

# <a name='section11'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *math :: bignum :: float*
of the [Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also
report any ideas for enhancements you may have for either package and/or







|
|
|
|
|




|
|
|
|
|





|
|
|
|
|

|
|





|
|

|
|

|
|
|
|




|
|
|
|









|
|
|













<
>
|
|
|
|
|
|
<
>
|
|
|
|
|
|
|
|






|





|
|
|
|
|





|
|


|
|
|
|
<
>
|
<
>
|

|
|
|
|
|
|
|
|
|







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
internals of this library, the uncertainty interval may be slightly wider than
expected, but this should not cause false digits\.

Now you may ask this question : What precision am I going to get after calling
add, sub, mul or div? First you set a number from the string representation and,
by the way, its uncertainty is set:

    set a [fromstr 1.230]
    # $a belongs to [1.229, 1.231]
    set a [fromstr 1.000]
    # $a belongs to [0.999, 1.001]
    # $a has a relative uncertainty of 0.1% : 0.001(the uncertainty)/1.000(the medium value)

The uncertainty of the sum, or the difference, of two numbers, is the sum of
their respective uncertainties\.

    set a [fromstr 1.230]
    set b [fromstr 2.340]
    set sum [add $a $b]]
    # the result is : [3.568, 3.572] (the last digit is known with an uncertainty of 2)
    tostr $sum ; # 3.57

But when, for example, we add or substract an integer to a BigFloat, the
relative uncertainty of the result is unchanged\. So it is desirable not to
convert integers to BigFloats:

    set a [fromstr 0.999999999]
    # now something dangerous
    set b [fromstr 2.000]
    # the result has only 3 digits
    tostr [add $a $b]

    # how to keep precision at its maximum
    puts [tostr [add $a 2]]

For multiplication and division, the relative uncertainties of the product or
the quotient, is the sum of the relative uncertainties of the operands\. Take
care of division by zero : check each divider with __iszero__\.

    set num [fromstr 4.00]
    set denom [fromstr 0.01]

    puts [iszero $denom];# true
    set quotient [div $num $denom];# error : divide by zero

    # opposites of our operands
    puts [compare $num [opp $num]]; # 1
    puts [compare $denom [opp $denom]]; # 0 !!!
    # No suprise ! 0 and its opposite are the same...

Effects of the precision of a number considered equal to zero to the cos
function:

    puts [tostr [cos [fromstr 0. 10]]]; # -> 1.000000000
    puts [tostr [cos [fromstr 0. 5]]]; # -> 1.0000
    puts [tostr [cos [fromstr 0e-10]]]; # -> 1.000000000
    puts [tostr [cos [fromstr 1e-10]]]; # -> 1.000000000

BigFloats with different internal representations may be converted to the same
string\.

For most analysis functions \(cosine, square root, logarithm, etc\.\), determining
the precision of the result is difficult\. It seems however that in many cases,
the loss of precision in the result is of one or two digits\. There are some
exceptions : for example,

    tostr [exp [fromstr 100.0 10]]
    # returns : 2.688117142e+43 which has only 10 digits of precision, although the entry
    # has 14 digits of precision.

# <a name='section8'></a>WHAT ABOUT TCL 8\.4 ?

If your setup do not provide Tcl 8\.5 but supports 8\.4, the package can still be
loaded, switching back to *math::bigfloat* 1\.2\. Indeed, an important function
introduced in Tcl 8\.5 is required \- the ability to handle bignums, that we can
do with __expr__\. Before 8\.5, this ability was provided by several packages,
including the pure\-Tcl *math::bignum* package provided by *tcllib*\. In this
case, all you need to know, is that arguments to the commands explained here,
are expected to be in their internal representation\. So even with integers, you
will need to call __fromstr__ and __tostr__ in order to convert them
between string and internal representations\.


    #
    # with Tcl 8.5
    # ============
    set a [pi 20]
    # round returns an integer and 'everything is a string' applies to integers
    # whatever big they are
    puts [round [mul $a 10000000000]]

    #
    # the same with Tcl 8.4
    # =====================
    set a [pi 20]
    # bignums (arbitrary length integers) need a conversion hook
    set b [fromstr 10000000000]
    # round returns a bignum:
    # before printing it, we need to convert it with 'tostr'
    puts [tostr [round [mul $a $b]]]

# <a name='section9'></a>NAMESPACES AND OTHER PACKAGES

We have not yet discussed about namespaces because we assumed that you had
imported public commands into the global namespace, like this:

    namespace import ::math::bigfloat::*

If you matter much about avoiding names conflicts, I considere it should be
resolved by the following :

    package require math::bigfloat
    # beware: namespace ensembles are not available in Tcl 8.4
    namespace eval ::math::bigfloat {namespace ensemble create -command ::bigfloat}
    # from now, the bigfloat command takes as subcommands all original math::bigfloat::* commands
    set a [bigfloat sub [bigfloat fromstr 2.000] [bigfloat fromstr 0.530]]
    puts [bigfloat tostr $a]

# <a name='section10'></a>EXAMPLES

Guess what happens when you are doing some astronomy\. Here is an example :

    # convert acurrate angles with a millisecond-rated accuracy
    proc degree-angle {degrees minutes seconds milliseconds} {
        set result 0
        set div 1
        foreach factor {1 1000 60 60} var [list $milliseconds $seconds $minutes $degrees] {
            # we convert each entry var into milliseconds
            set div [expr {$div*$factor}]
            incr result [expr {$var*$div}]

        }
        return [div [int2float $result] $div]

    }
    # load the package
    package require math::bigfloat
    namespace import ::math::bigfloat::*
    # work with angles : a standard formula for navigation (taking bearings)
    set angle1 [deg2rad [degree-angle 20 30 40   0]]
    set angle2 [deg2rad [degree-angle 21  0 50 500]]
    set opposite3 [deg2rad [degree-angle 51  0 50 500]]
    set sinProduct [mul [sin $angle1] [sin $angle2]]
    set cosProduct [mul [cos $angle1] [cos $angle2]]
    set angle3 [asin [add [mul $sinProduct [cos $opposite3]] $cosProduct]]
    puts "angle3 : [tostr [rad2deg $angle3]]"

# <a name='section11'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *math :: bignum :: float*
of the [Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also
report any ideas for enhancements you may have for either package and/or

Changes to embedded/md/tcllib/files/modules/math/bignum.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (math::bignum \- Tcl Math Library)
[//000000002]: # (Generated from file 'bignum\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Salvatore Sanfilippo <antirez at invece dot org>  
Copyright &copy; 2004 Arjen Markus <arjenmarkus at users dot sourceforge dot net>)
[//000000004]: # (math::bignum\(n\) 3\.1 tcllib "Tcl Math Library")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (math::bignum \- Tcl Math Library)
[//000000002]: # (Generated from file 'bignum\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Salvatore Sanfilippo <antirez at invece dot org>)
[//000000004]: # (Copyright &copy; 2004 Arjen Markus <arjenmarkus at users dot sourceforge dot net>)
[//000000005]: # (math::bignum\(n\) 3\.1 tcllib "Tcl Math Library")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
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
This section shows some simple example\. This library being just a way to perform
math operations, examples may be the simplest way to learn how to work with it\.
Consult the API section of this man page for information about individual
procedures\.

    package require math::bignum

    \# Multiplication of two bignums
    set a \[::math::bignum::fromstr 88888881111111\]
    set b \[::math::bignum::fromstr 22222220000000\]
    set c \[::math::bignum::mul $a $b\]
    puts \[::math::bignum::tostr $c\] ; \# => will output 1975308271604953086420000000
    set c \[::math::bignum::sqrt $c\]
    puts \[::math::bignum::tostr $c\] ; \# => will output 44444440277777

    \# From/To string conversion in different radix
    set a \[::math::bignum::fromstr 1100010101010111001001111010111 2\]
    puts \[::math::bignum::tostr $a 16\] ; \# => will output 62ab93d7

    \# Factorial example
    proc fact n \{
        \# fromstr is not needed for 0 and 1
        set z 1
        for \{set i 2\} \{$i <= $n\} \{incr i\} \{
            set z \[::math::bignum::mul $z \[::math::bignum::fromstr $i\]\]
        \}

        return $z
    \}


    puts \[::math::bignum::tostr \[fact 100\]\]

# <a name='section3'></a>API

  - <a name='1'></a>__::math::bignum::fromstr__ *string* ?*radix*?

    Convert *string* into a bignum\. If *radix* is omitted or zero, the
    string is interpreted in hex if prefixed with *0x*, in octal if prefixed







|
|
|
|
|
|
|

|
|
|

|
|
|

|
|
<
>

<
|
>
|







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
This section shows some simple example\. This library being just a way to perform
math operations, examples may be the simplest way to learn how to work with it\.
Consult the API section of this man page for information about individual
procedures\.

    package require math::bignum

    # Multiplication of two bignums
    set a [::math::bignum::fromstr 88888881111111]
    set b [::math::bignum::fromstr 22222220000000]
    set c [::math::bignum::mul $a $b]
    puts [::math::bignum::tostr $c] ; # => will output 1975308271604953086420000000
    set c [::math::bignum::sqrt $c]
    puts [::math::bignum::tostr $c] ; # => will output 44444440277777

    # From/To string conversion in different radix
    set a [::math::bignum::fromstr 1100010101010111001001111010111 2]
    puts [::math::bignum::tostr $a 16] ; # => will output 62ab93d7

    # Factorial example
    proc fact n {
        # fromstr is not needed for 0 and 1
        set z 1
        for {set i 2} {$i <= $n} {incr i} {
            set z [::math::bignum::mul $z [::math::bignum::fromstr $i]]

        }
        return $z

    }

    puts [::math::bignum::tostr [fact 100]]

# <a name='section3'></a>API

  - <a name='1'></a>__::math::bignum::fromstr__ *string* ?*radix*?

    Convert *string* into a bignum\. If *radix* is omitted or zero, the
    string is interpreted in hex if prefixed with *0x*, in octal if prefixed

Changes to embedded/md/tcllib/files/modules/math/calculus.md.

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

  - <a name='12'></a>__::math::calculus::boundaryValueSecondOrder__ *coeff\_func* *force\_func* *leftbnd* *rightbnd* *nostep*

    Solve a second order linear differential equation with boundary values at
    two sides\. The equation has to be of the form \(the "conservative" form\):

        d      dy     d
        \-\- A\(x\)\-\-  \+  \-\- B\(x\)y \+ C\(x\)y  =  D\(x\)
        dx     dx     dx

    Ordinarily, such an equation would be written as:

            d2y        dy
        a\(x\)\-\-\-  \+ b\(x\)\-\- \+ c\(x\) y  =  D\(x\)
            dx2        dx

    The first form is easier to discretise \(by integrating over a finite volume\)
    than the second form\. The relation between the two forms is fairly
    straightforward:

        A\(x\)  =  a\(x\)
        B\(x\)  =  b\(x\) \- a'\(x\)
        C\(x\)  =  c\(x\) \- B'\(x\)  =  c\(x\) \- b'\(x\) \+ a''\(x\)

    Because of the differentiation, however, it is much easier to ask the user
    to provide the functions A, B and C directly\.

      * *coeff\_func*

        Procedure returning the three coefficients \(A, B, C\) of the equation,







|





|






|
|
|







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

  - <a name='12'></a>__::math::calculus::boundaryValueSecondOrder__ *coeff\_func* *force\_func* *leftbnd* *rightbnd* *nostep*

    Solve a second order linear differential equation with boundary values at
    two sides\. The equation has to be of the form \(the "conservative" form\):

        d      dy     d
        -- A(x)--  +  -- B(x)y + C(x)y  =  D(x)
        dx     dx     dx

    Ordinarily, such an equation would be written as:

            d2y        dy
        a(x)---  + b(x)-- + c(x) y  =  D(x)
            dx2        dx

    The first form is easier to discretise \(by integrating over a finite volume\)
    than the second form\. The relation between the two forms is fairly
    straightforward:

        A(x)  =  a(x)
        B(x)  =  b(x) - a'(x)
        C(x)  =  c(x) - B'(x)  =  c(x) - b'(x) + a''(x)

    Because of the differentiation, however, it is much easier to ask the user
    to provide the functions A, B and C directly\.

      * *coeff\_func*

        Procedure returning the three coefficients \(A, B, C\) of the equation,
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332

        List of values on the righthand\-side

  - <a name='14'></a>__::math::calculus::newtonRaphson__ *func* *deriv* *initval*

    Determine the root of an equation given by

        func\(x\) = 0

    using the method of Newton\-Raphson\. The procedure takes the following
    arguments:

      * *func*

        Procedure that returns the value the function at x







|







318
319
320
321
322
323
324
325
326
327
328
329
330
331
332

        List of values on the righthand\-side

  - <a name='14'></a>__::math::calculus::newtonRaphson__ *func* *deriv* *initval*

    Determine the root of an equation given by

        func(x) = 0

    using the method of Newton\-Raphson\. The procedure takes the following
    arguments:

      * *func*

        Procedure that returns the value the function at x
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

Several of the above procedures take the *names* of procedures as arguments\.
To avoid problems with the *visibility* of these procedures, the
fully\-qualified name of these procedures is determined inside the calculus
routines\. For the user this has only one consequence: the named procedure must
be visible in the calling procedure\. For instance:

    namespace eval ::mySpace \{
       namespace export calcfunc
       proc calcfunc \{ x \} \{ return $x \}
    \}
    \#


    \# Use a fully\-qualified name
    \#

    namespace eval ::myCalc \{
       proc detIntegral \{ begin end \} \{
          return \[integral $begin $end 100 ::mySpace::calcfunc\]
       \}
    \}
    \#



    \# Import the name
    \#

    namespace eval ::myCalc \{
       namespace import ::mySpace::calcfunc
       proc detIntegral \{ begin end \} \{
          return \[integral $begin $end 100 calcfunc\]
       \}
    \}



Enhancements for the second\-order boundary value problem:

  - Other types of boundary conditions \(zero gradient, zero flux\)

  - Other schematisation of the first\-order term \(now central differences are
    used, but upstream differences might be useful too\)\.

# <a name='section3'></a>EXAMPLES

Let us take a few simple examples:

Integrate x over the interval \[0,100\] \(20 steps\):

    proc linear\_func \{ x \} \{ return $x \}
    puts "Integral: \[::math::calculus::integral 0 100 20 linear\_func\]"

For simple functions, the alternative could be:

    puts "Integral: \[::math::calculus::integralExpr 0 100 20 \{$x\}\]"

Do not forget the braces\!

The differential equation for a dampened oscillator:

    x'' \+ rx' \+ wx = 0

can be split into a system of first\-order equations:

    x' = y
    y' = \-ry \- wx

Then this system can be solved with code like this:

    proc dampened\_oscillator \{ t xvec \} \{
       set x  \[lindex $xvec 0\]
       set x1 \[lindex $xvec 1\]
       return \[list $x1 \[expr \{\-$x1\-$x\}\]\]
    \}


    set xvec   \{ 1\.0 0\.0 \}
    set t      0\.0
    set tstep  0\.1
    for \{ set i 0 \} \{ $i < 20 \} \{ incr i \} \{
       set result \[::math::calculus::eulerStep $t $tstep $xvec dampened\_oscillator\]
       puts "Result \($t\): $result"
       set t      \[expr \{$t\+$tstep\}\]
       set xvec   $result
    \}


Suppose we have the boundary value problem:

    Dy'' \+ ky = 0
    x = 0: y = 1
    x = L: y = 0

This boundary value problem could originate from the diffusion of a decaying
substance\.

It can be solved with the following fragment:

    proc coeffs \{ x \} \{ return \[list $::Diff 0\.0 $::decay\] \}
    proc force  \{ x \} \{ return 0\.0 \}

    set Diff   1\.0e\-2
    set decay  0\.0001
    set length 100\.0

    set y \[::math::calculus::boundaryValueSecondOrder \\
       coeffs force \{0\.0 1\.0\} \[list $length 0\.0\] 100\]

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *math :: calculus* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report
any ideas for enhancements you may have for either package and/or documentation\.







|

|
<
<
>
>
|
<
>
|
|
|
<
<
<
>
>
>
|
<
>
|

|
|
<
<
>
>














|
|



|





|




|



|
|
|
|
<
|
>
|
|
|
|
|
|
|

<
>



|








|
|

|
|
|

|
|







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

Several of the above procedures take the *names* of procedures as arguments\.
To avoid problems with the *visibility* of these procedures, the
fully\-qualified name of these procedures is determined inside the calculus
routines\. For the user this has only one consequence: the named procedure must
be visible in the calling procedure\. For instance:

    namespace eval ::mySpace {
       namespace export calcfunc
       proc calcfunc { x } { return $x }


    }
    #
    # Use a fully-qualified name

    #
    namespace eval ::myCalc {
       proc detIntegral { begin end } {
          return [integral $begin $end 100 ::mySpace::calcfunc]



       }
    }
    #
    # Import the name

    #
    namespace eval ::myCalc {
       namespace import ::mySpace::calcfunc
       proc detIntegral { begin end } {
          return [integral $begin $end 100 calcfunc]


       }
    }

Enhancements for the second\-order boundary value problem:

  - Other types of boundary conditions \(zero gradient, zero flux\)

  - Other schematisation of the first\-order term \(now central differences are
    used, but upstream differences might be useful too\)\.

# <a name='section3'></a>EXAMPLES

Let us take a few simple examples:

Integrate x over the interval \[0,100\] \(20 steps\):

    proc linear_func { x } { return $x }
    puts "Integral: [::math::calculus::integral 0 100 20 linear_func]"

For simple functions, the alternative could be:

    puts "Integral: [::math::calculus::integralExpr 0 100 20 {$x}]"

Do not forget the braces\!

The differential equation for a dampened oscillator:

    x'' + rx' + wx = 0

can be split into a system of first\-order equations:

    x' = y
    y' = -ry - wx

Then this system can be solved with code like this:

    proc dampened_oscillator { t xvec } {
       set x  [lindex $xvec 0]
       set x1 [lindex $xvec 1]
       return [list $x1 [expr {-$x1-$x}]]

    }

    set xvec   { 1.0 0.0 }
    set t      0.0
    set tstep  0.1
    for { set i 0 } { $i < 20 } { incr i } {
       set result [::math::calculus::eulerStep $t $tstep $xvec dampened_oscillator]
       puts "Result ($t): $result"
       set t      [expr {$t+$tstep}]
       set xvec   $result

    }

Suppose we have the boundary value problem:

    Dy'' + ky = 0
    x = 0: y = 1
    x = L: y = 0

This boundary value problem could originate from the diffusion of a decaying
substance\.

It can be solved with the following fragment:

    proc coeffs { x } { return [list $::Diff 0.0 $::decay] }
    proc force  { x } { return 0.0 }

    set Diff   1.0e-2
    set decay  0.0001
    set length 100.0

    set y [::math::calculus::boundaryValueSecondOrder \
       coeffs force {0.0 1.0} [list $length 0.0] 100]

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *math :: calculus* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report
any ideas for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/math/combinatorics.md.

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  - <a name='1'></a>__::math::ln\_Gamma__ *z*

    Returns the natural logarithm of the Gamma function for the argument *z*\.

    The Gamma function is defined as the improper integral from zero to positive
    infinity of

        t\*\*\(x\-1\)\*exp\(\-t\) dt

    The approximation used in the Tcl Math Library is from Lanczos, *ISIAM J\.
    Numerical Analysis, series B,* volume 1, p\. 86\. For "__x__ > 1", the
    absolute error of the result is claimed to be smaller than 5\.5\*10\*\*\-10 \-\-
    that is, the resulting value of Gamma when

        exp\( ln\_Gamma\( x\) \)

    is computed is expected to be precise to better than nine significant
    figures\.

  - <a name='2'></a>__::math::factorial__ *x*

    Returns the factorial of the argument *x*\.







|






|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  - <a name='1'></a>__::math::ln\_Gamma__ *z*

    Returns the natural logarithm of the Gamma function for the argument *z*\.

    The Gamma function is defined as the improper integral from zero to positive
    infinity of

        t**(x-1)*exp(-t) dt

    The approximation used in the Tcl Math Library is from Lanczos, *ISIAM J\.
    Numerical Analysis, series B,* volume 1, p\. 86\. For "__x__ > 1", the
    absolute error of the result is claimed to be smaller than 5\.5\*10\*\*\-10 \-\-
    that is, the resulting value of Gamma when

        exp( ln_Gamma( x) )

    is computed is expected to be precise to better than nine significant
    figures\.

  - <a name='2'></a>__::math::factorial__ *x*

    Returns the factorial of the argument *x*\.
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
    It is an error to present *x* <= \-1 or *x* > 170, or a value of *x*
    that is not numeric\.

  - <a name='3'></a>__::math::choose__ *n k*

    Returns the binomial coefficient *C\(n, k\)*

        C\(n,k\) = n\! / k\! \(n\-k\)\!

    If both parameters are integers and the result fits in 32 bits, the result
    is rounded to an integer\.

    Integer results are exact up to at least *n* = 34\. Floating point results
    are precise to better than nine significant figures\.

  - <a name='4'></a>__::math::Beta__ *z w*

    Returns the Beta function of the parameters *z* and *w*\.

        Beta\(z,w\) = Beta\(w,z\) = Gamma\(z\) \* Gamma\(w\) / Gamma\(z\+w\)

    Results are returned as a floating point number precise to better than nine
    significant digits provided that *w* and *z* are both at least 1\.

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and







|











|







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
    It is an error to present *x* <= \-1 or *x* > 170, or a value of *x*
    that is not numeric\.

  - <a name='3'></a>__::math::choose__ *n k*

    Returns the binomial coefficient *C\(n, k\)*

        C(n,k) = n! / k! (n-k)!

    If both parameters are integers and the result fits in 32 bits, the result
    is rounded to an integer\.

    Integer results are exact up to at least *n* = 34\. Floating point results
    are precise to better than nine significant figures\.

  - <a name='4'></a>__::math::Beta__ *z w*

    Returns the Beta function of the parameters *z* and *w*\.

        Beta(z,w) = Beta(w,z) = Gamma(z) * Gamma(w) / Gamma(z+w)

    Results are returned as a floating point number precise to better than nine
    significant digits provided that *w* and *z* are both at least 1\.

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and

Changes to embedded/md/tcllib/files/modules/math/constants.md.

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  - One for reporting which constants are defined and what values they actually
    have\.

The motivation for this package is that quite often, with \(mathematical\)
computations, you need a good approximation to, say, the ratio of degrees to
radians\. You can, of course, define this like:

    variable radtodeg \[expr \{180\.0/\(4\.0\*atan\(1\.0\)\)\}\]

and use the variable radtodeg whenever you need the conversion\.

This has two drawbacks:

  - You need to remember the proper formula or value and that is error\-prone\.








|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  - One for reporting which constants are defined and what values they actually
    have\.

The motivation for this package is that quite often, with \(mathematical\)
computations, you need a good approximation to, say, the ratio of degrees to
radians\. You can, of course, define this like:

    variable radtodeg [expr {180.0/(4.0*atan(1.0))}]

and use the variable radtodeg whenever you need the conversion\.

This has two drawbacks:

  - You need to remember the proper formula or value and that is error\-prone\.

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  - basic constants like pi, e, gamma \(Euler's constant\)

  - derived values like ln\(10\) and sqrt\(2\)

  - purely numerical values such as 1/3 that are included for convenience and
    for the fact that certain seemingly trivial computations like:

    set value \[expr \{3\.0\*$onethird\}\]

    give *exactly* the value you expect \(if IEEE arithmetic is available\)\.

The full set of named constants is listed in section
[Constants](#section3)\.

# <a name='section2'></a>PROCEDURES







|







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  - basic constants like pi, e, gamma \(Euler's constant\)

  - derived values like ln\(10\) and sqrt\(2\)

  - purely numerical values such as 1/3 that are included for convenience and
    for the fact that certain seemingly trivial computations like:

    set value [expr {3.0*$onethird}]

    give *exactly* the value you expect \(if IEEE arithmetic is available\)\.

The full set of named constants is listed in section
[Constants](#section3)\.

# <a name='section2'></a>PROCEDURES

Changes to embedded/md/tcllib/files/modules/math/decimal.md.

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
perform decimal math operations, examples may be the simplest way to learn how
to work with it and to see the difference between using this package and
sticking with expr\. Consult the API section of this man page for information
about individual procedures\.

    package require math::decimal

    \# Various operations on two numbers\.
    \# We first convert them to decimal format\.
    set a \[::math::decimal::fromstr 8\.2\]
    set b \[::math::decimal::fromstr \.2\]

    \# Then we perform our operations\. Here we add
    set c \[::math::decimal::\+ $a $b\]

    \# Finally we convert back to string format for presentation to the user\.
    puts \[::math::decimal::tostr $c\] ; \# => will output 8\.4

    \# Other examples
    \#

    \# Subtraction
    set c \[::math::decimal::\- $a $b\]
    puts \[::math::decimal::tostr $c\] ; \# => will output 8\.0

    \# Why bother using this instead of simply expr?
    puts \[expr \{8\.2 \+ \.2\}\] ; \# => will output 8\.399999999999999
    puts \[expr \{8\.2 \- \.2\}\] ; \# => will output 7\.999999999999999
    \# See http://speleotrove\.com/decimal to learn more about why this happens\.

# <a name='section3'></a>API

  - <a name='1'></a>__::math::decimal::fromstr__ *string*

    Convert *string* into a decimal\.








|
|
|
|

|
|

|
|

|
<
>
|
|
|

|
|
|
|







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
perform decimal math operations, examples may be the simplest way to learn how
to work with it and to see the difference between using this package and
sticking with expr\. Consult the API section of this man page for information
about individual procedures\.

    package require math::decimal

    # Various operations on two numbers.
    # We first convert them to decimal format.
    set a [::math::decimal::fromstr 8.2]
    set b [::math::decimal::fromstr .2]

    # Then we perform our operations. Here we add
    set c [::math::decimal::+ $a $b]

    # Finally we convert back to string format for presentation to the user.
    puts [::math::decimal::tostr $c] ; # => will output 8.4

    # Other examples

    #
    # Subtraction
    set c [::math::decimal::- $a $b]
    puts [::math::decimal::tostr $c] ; # => will output 8.0

    # Why bother using this instead of simply expr?
    puts [expr {8.2 + .2}] ; # => will output 8.399999999999999
    puts [expr {8.2 - .2}] ; # => will output 7.999999999999999
    # See http://speleotrove.com/decimal to learn more about why this happens.

# <a name='section3'></a>API

  - <a name='1'></a>__::math::decimal::fromstr__ *string*

    Convert *string* into a decimal\.

Changes to embedded/md/tcllib/files/modules/math/exact.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (math::exact \- Tcl Math Library)
[//000000002]: # (Generated from file 'exact\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2015 Kevin B\. Kenny <kennykb@acm\.org>
Redistribution permitted under the terms of the Open Publication License <http://www\.opencontent\.org/openpub/>)
[//000000004]: # (math::exact\(n\) 1\.0\.1 tcllib "Tcl Math Library")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (math::exact \- Tcl Math Library)
[//000000002]: # (Generated from file 'exact\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2015 Kevin B\. Kenny <kennykb@acm\.org>)
[//000000004]: # (Redistribution permitted under the terms of the Open Publication License <http://www\.opencontent\.org/openpub/>)
[//000000005]: # (math::exact\(n\) 1\.0\.1 tcllib "Tcl Math Library")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
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

The __math::exact::exactexpr__ command provides a system that performs exact
arithmetic over computable real numbers, representing the numbers as algorithms
for successive approximation\. An example, which implements the high\-school
quadratic formula, is shown below\.

    namespace import math::exact::exactexpr
    proc exactquad \{a b c\} \{
        set d \[\[exactexpr \{sqrt\($b\*$b \- 4\*$a\*$c\)\}\] ref\]
        set r0 \[\[exactexpr \{\(\-$b \- $d\) / \(2 \* $a\)\}\] ref\]
        set r1 \[\[exactexpr \{\(\-$b \+ $d\) / \(2 \* $a\)\}\] ref\]
        $d unref
        return \[list $r0 $r1\]
    \}


    set a \[\[exactexpr 1\] ref\]
    set b \[\[exactexpr 200\] ref\]
    set c \[\[exactexpr \{\(\-3/2\) \* 10\*\*\-12\}\] ref\]
    lassign \[exactquad $a $b $c\] r0 r1
    $a unref; $b unref; $c unref
    puts \[list \[$r0 asFloat 70\] \[$r1 asFloat 110\]\]
    $r0 unref; $r1 unref

The program prints the result:

    \-2\.000000000000000075e2 7\.499999999999999719e\-15

Note that if IEEE\-754 floating point had been used, a catastrophic roundoff
error would yield a smaller root that is a factor of two too high:

    \-200\.0 1\.4210854715202004e\-14

The invocations of __exactexpr__ should be fairly self\-explanatory\. The
other commands of note are __ref__ and __unref__\. It is necessary for
the caller to keep track of references to exact expressions \- to call
__ref__ every time an exact expression is stored in a variable and
__unref__ every time the variable goes out of scope or is overwritten\. The
__asFloat__ method emits decimal digits as long as the requested precision







|
|
|
|

|
<
|
>
|
|
|
|

|




|




|







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

The __math::exact::exactexpr__ command provides a system that performs exact
arithmetic over computable real numbers, representing the numbers as algorithms
for successive approximation\. An example, which implements the high\-school
quadratic formula, is shown below\.

    namespace import math::exact::exactexpr
    proc exactquad {a b c} {
        set d [[exactexpr {sqrt($b*$b - 4*$a*$c)}] ref]
        set r0 [[exactexpr {(-$b - $d) / (2 * $a)}] ref]
        set r1 [[exactexpr {(-$b + $d) / (2 * $a)}] ref]
        $d unref
        return [list $r0 $r1]

    }

    set a [[exactexpr 1] ref]
    set b [[exactexpr 200] ref]
    set c [[exactexpr {(-3/2) * 10**-12}] ref]
    lassign [exactquad $a $b $c] r0 r1
    $a unref; $b unref; $c unref
    puts [list [$r0 asFloat 70] [$r1 asFloat 110]]
    $r0 unref; $r1 unref

The program prints the result:

    -2.000000000000000075e2 7.499999999999999719e-15

Note that if IEEE\-754 floating point had been used, a catastrophic roundoff
error would yield a smaller root that is a factor of two too high:

    -200.0 1.4210854715202004e-14

The invocations of __exactexpr__ should be fairly self\-explanatory\. The
other commands of note are __ref__ and __unref__\. It is necessary for
the caller to keep track of references to exact expressions \- to call
__ref__ every time an exact expression is stored in a variable and
__unref__ every time the variable goes out of scope or is overwritten\. The
__asFloat__ method emits decimal digits as long as the requested precision

Changes to embedded/md/tcllib/files/modules/math/fourier.md.

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

If the input length N is a power of two then these procedures will utilize the
O\(N log N\) Fast Fourier Transform algorithm\. If input length is not a power of
two then the DFT will instead be computed using a the naive quadratic algorithm\.

Some examples:

    % dft \{1 2 3 4\}
    \{10 0\.0\} \{\-2\.0 2\.0\} \{\-2 0\.0\} \{\-2\.0 \-2\.0\}
    % inverse\_dft \{\{10 0\.0\} \{\-2\.0 2\.0\} \{\-2 0\.0\} \{\-2\.0 \-2\.0\}\}
    \{1\.0 0\.0\} \{2\.0 0\.0\} \{3\.0 0\.0\} \{4\.0 0\.0\}
    % dft \{1 2 3 4 5\}
    \{15\.0 0\.0\} \{\-2\.5 3\.44095480118\} \{\-2\.5 0\.812299240582\} \{\-2\.5 \-0\.812299240582\} \{\-2\.5 \-3\.44095480118\}
    % inverse\_dft \{\{15\.0 0\.0\} \{\-2\.5 3\.44095480118\} \{\-2\.5 0\.812299240582\} \{\-2\.5 \-0\.812299240582\} \{\-2\.5 \-3\.44095480118\}\}
    \{1\.0 0\.0\} \{2\.0 8\.881784197e\-17\} \{3\.0 4\.4408920985e\-17\} \{4\.0 4\.4408920985e\-17\} \{5\.0 \-8\.881784197e\-17\}

In the last case, the imaginary parts <1e\-16 would have been zero in exact
arithmetic, but aren't here due to rounding errors\.

Internally, the procedures use a flat list format where every even index element
of a list is a real part and every odd index element is an imaginary part\. This
is reflected in the variable names by Re\_ and Im\_ prefixes\.







|
|
|
|
|
|
|
|







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

If the input length N is a power of two then these procedures will utilize the
O\(N log N\) Fast Fourier Transform algorithm\. If input length is not a power of
two then the DFT will instead be computed using a the naive quadratic algorithm\.

Some examples:

    % dft {1 2 3 4}
    {10 0.0} {-2.0 2.0} {-2 0.0} {-2.0 -2.0}
    % inverse_dft {{10 0.0} {-2.0 2.0} {-2 0.0} {-2.0 -2.0}}
    {1.0 0.0} {2.0 0.0} {3.0 0.0} {4.0 0.0}
    % dft {1 2 3 4 5}
    {15.0 0.0} {-2.5 3.44095480118} {-2.5 0.812299240582} {-2.5 -0.812299240582} {-2.5 -3.44095480118}
    % inverse_dft {{15.0 0.0} {-2.5 3.44095480118} {-2.5 0.812299240582} {-2.5 -0.812299240582} {-2.5 -3.44095480118}}
    {1.0 0.0} {2.0 8.881784197e-17} {3.0 4.4408920985e-17} {4.0 4.4408920985e-17} {5.0 -8.881784197e-17}

In the last case, the imaginary parts <1e\-16 would have been zero in exact
arithmetic, but aren't here due to rounding errors\.

Internally, the procedures use a flat list format where every even index element
of a list is a real part and every odd index element is an imaginary part\. This
is reflected in the variable names by Re\_ and Im\_ prefixes\.

Changes to embedded/md/tcllib/files/modules/math/fuzzy.md.

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
  - <a name='10'></a>__::math::fuzzy::troundn__ *value* *ndigits*

    Rounds the floating\-point number off to the specified number of decimals
    \(Pro memorie\)\.

Usage:

    if \{ \[teq $x $y\] \} \{ puts "x == y" \}
    if \{ \[tne $x $y\] \} \{ puts "x \!= y" \}
    if \{ \[tge $x $y\] \} \{ puts "x >= y" \}
    if \{ \[tgt $x $y\] \} \{ puts "x > y" \}
    if \{ \[tlt $x $y\] \} \{ puts "x < y" \}
    if \{ \[tle $x $y\] \} \{ puts "x <= y" \}

    set fx      \[tfloor $x\]
    set fc      \[tceil  $x\]
    set rounded \[tround $x\]
    set roundn  \[troundn $x $nodigits\]

# <a name='section3'></a>TEST CASES

The problems that can occur with floating\-point numbers are illustrated by the
test cases in the file "fuzzy\.test":

  - Several test case use the ordinary comparisons, and they fail invariably to







|
|
|
|
|
|

|
|
|
|







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
  - <a name='10'></a>__::math::fuzzy::troundn__ *value* *ndigits*

    Rounds the floating\-point number off to the specified number of decimals
    \(Pro memorie\)\.

Usage:

    if { [teq $x $y] } { puts "x == y" }
    if { [tne $x $y] } { puts "x != y" }
    if { [tge $x $y] } { puts "x >= y" }
    if { [tgt $x $y] } { puts "x > y" }
    if { [tlt $x $y] } { puts "x < y" }
    if { [tle $x $y] } { puts "x <= y" }

    set fx      [tfloor $x]
    set fc      [tceil  $x]
    set rounded [tround $x]
    set roundn  [troundn $x $nodigits]

# <a name='section3'></a>TEST CASES

The problems that can occur with floating\-point numbers are illustrated by the
test cases in the file "fuzzy\.test":

  - Several test case use the ordinary comparisons, and they fail invariably to

Changes to embedded/md/tcllib/files/modules/math/interpolate.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (math::interpolate \- Tcl Math Library)
[//000000002]: # (Generated from file 'interpolate\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Arjen Markus <arjenmarkus@users\.sourceforge\.net>  
Copyright &copy; 2004 Kevn B\. Kenny <kennykb@users\.sourceforge\.net>)
[//000000004]: # (math::interpolate\(n\) 1\.1 tcllib "Tcl Math Library")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (math::interpolate \- Tcl Math Library)
[//000000002]: # (Generated from file 'interpolate\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Arjen Markus <arjenmarkus@users\.sourceforge\.net>)
[//000000004]: # (Copyright &copy; 2004 Kevn B\. Kenny <kennykb@users\.sourceforge\.net>)
[//000000005]: # (math::interpolate\(n\) 1\.1 tcllib "Tcl Math Library")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
208
209
210
211
212
213
214
215
216
217
218

219
220
221
222
223
224
225
  - <a name='8'></a>__::math::interpolate::interp\-spatial__ *xyvalues* *coord*

    Use a straightforward interpolation method with weights as function of the
    inverse distance to interpolate in 2D and N\-dimensional space

    The list xyvalues is a list of lists:

            \{   \{x1 y1 z1 \{v11 v12 v13 v14\}\}
        	\{x2 y2 z2 \{v21 v22 v23 v24\}\}
        	\.\.\.
            \}


    The last element of each inner list is either a single number or a list in
    itself\. In the latter case the return value is a list with the same number
    of elements\.

    The method is influenced by the search radius and the power of the inverse
    distance







|
|
|
<
>







208
209
210
211
212
213
214
215
216
217

218
219
220
221
222
223
224
225
  - <a name='8'></a>__::math::interpolate::interp\-spatial__ *xyvalues* *coord*

    Use a straightforward interpolation method with weights as function of the
    inverse distance to interpolate in 2D and N\-dimensional space

    The list xyvalues is a list of lists:

            {   {x1 y1 z1 {v11 v12 v13 v14}}
        	{x2 y2 z2 {v21 v22 v23 v24}}
        	...

            }

    The last element of each inner list is either a single number or a list in
    itself\. In the latter case the return value is a list with the same number
    of elements\.

    The method is influenced by the search radius and the power of the inverse
    distance
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
# <a name='section4'></a>EXAMPLES

*Example of using one\-dimensional tables:*

Suppose you have several tabulated functions of one variable:

      x     y1     y2
    0\.0    0\.0    0\.0
    1\.0    1\.0    1\.0
    2\.0    4\.0    8\.0
    3\.0    9\.0   27\.0
    4\.0   16\.0   64\.0

Then to estimate the values at 0\.5, 1\.5, 2\.5 and 3\.5, you can use:

    set table \[::math::interpolate::defineTable table1  \{x y1 y2\} \{   \-      1      2
                    0\.0    0\.0    0\.0
                    1\.0    1\.0    1\.0
                    2\.0    4\.0    8\.0
                    3\.0    9\.0   27\.0
                    4\.0   16\.0   64\.0\}\]
    foreach x \{0\.5 1\.5 2\.5 3\.5\} \{
        puts "$x: \[::math::interpolate::interp\-1d\-table $table $x\]"
    \}


For one\-dimensional tables the first row is not used\. For two\-dimensional
tables, the first row represents the values for the second independent variable\.

*Example of using the cubic splines:*

Suppose the following values are given:

      x       y
    0\.1     1\.0
    0\.3     2\.1
    0\.4     2\.2
    0\.8     4\.11
    1\.0     4\.12

Then to estimate the values at 0\.1, 0\.2, 0\.3, \.\.\. 1\.0, you can use:

    set coeffs \[::math::interpolate::prepare\-cubic\-splines  \{0\.1 0\.3 0\.4 0\.8  1\.0\}  \{1\.0 2\.1 2\.2 4\.11 4\.12\}\]
    foreach x \{0\.1 0\.2 0\.3 0\.4 0\.5 0\.6 0\.7 0\.8 0\.9 1\.0\} \{
       puts "$x: \[::math::interpolate::interp\-cubic\-splines $coeffs $x\]"
    \}


to get the following output:

    0\.1: 1\.0
    0\.2: 1\.68044117647
    0\.3: 2\.1
    0\.4: 2\.2
    0\.5: 3\.11221507353
    0\.6: 4\.25242647059
    0\.7: 5\.41804227941
    0\.8: 4\.11
    0\.9: 3\.95675857843
    1\.0: 4\.12

As you can see, the values at the abscissae are reproduced perfectly\.

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *math :: interpolate* of







|
|
|
|
|



|
|
|
|
|
|
|
|
<
>









|
|
|
|
|



|
|
|
<
|
>


|
|
|
|
|
|
|
|
|
|







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
# <a name='section4'></a>EXAMPLES

*Example of using one\-dimensional tables:*

Suppose you have several tabulated functions of one variable:

      x     y1     y2
    0.0    0.0    0.0
    1.0    1.0    1.0
    2.0    4.0    8.0
    3.0    9.0   27.0
    4.0   16.0   64.0

Then to estimate the values at 0\.5, 1\.5, 2\.5 and 3\.5, you can use:

    set table [::math::interpolate::defineTable table1  {x y1 y2} {   -      1      2
                    0.0    0.0    0.0
                    1.0    1.0    1.0
                    2.0    4.0    8.0
                    3.0    9.0   27.0
                    4.0   16.0   64.0}]
    foreach x {0.5 1.5 2.5 3.5} {
        puts "$x: [::math::interpolate::interp-1d-table $table $x]"

    }

For one\-dimensional tables the first row is not used\. For two\-dimensional
tables, the first row represents the values for the second independent variable\.

*Example of using the cubic splines:*

Suppose the following values are given:

      x       y
    0.1     1.0
    0.3     2.1
    0.4     2.2
    0.8     4.11
    1.0     4.12

Then to estimate the values at 0\.1, 0\.2, 0\.3, \.\.\. 1\.0, you can use:

    set coeffs [::math::interpolate::prepare-cubic-splines  {0.1 0.3 0.4 0.8  1.0}  {1.0 2.1 2.2 4.11 4.12}]
    foreach x {0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0} {
       puts "$x: [::math::interpolate::interp-cubic-splines $coeffs $x]"

    }

to get the following output:

    0.1: 1.0
    0.2: 1.68044117647
    0.3: 2.1
    0.4: 2.2
    0.5: 3.11221507353
    0.6: 4.25242647059
    0.7: 5.41804227941
    0.8: 4.11
    0.9: 3.95675857843
    1.0: 4.12

As you can see, the values at the abscissae are reproduced perfectly\.

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *math :: interpolate* of

Changes to embedded/md/tcllib/files/modules/math/linalg.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

[//000000001]: # (math::linearalgebra \- Tcl Math Library)
[//000000002]: # (Generated from file 'linalg\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004\-2008 Arjen Markus <arjenmarkus@users\.sourceforge\.net>  
Copyright &copy; 2004 Ed Hume <http://www\.hume\.com/contact\.us\.htm>  
Copyright &copy; 2008 Michael Buadin <relaxkmike@users\.sourceforge\.net>)
[//000000004]: # (math::linearalgebra\(n\) 1\.1\.5 tcllib "Tcl Math Library")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14

[//000000001]: # (math::linearalgebra \- Tcl Math Library)
[//000000002]: # (Generated from file 'linalg\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004\-2008 Arjen Markus <arjenmarkus@users\.sourceforge\.net>)
[//000000004]: # (Copyright &copy; 2004 Ed Hume <http://www\.hume\.com/contact\.us\.htm>)
[//000000005]: # (Copyright &copy; 2008 Michael Buadin <relaxkmike@users\.sourceforge\.net>)
[//000000006]: # (math::linearalgebra\(n\) 1\.1\.5 tcllib "Tcl Math Library")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
  - <a name='59'></a>__::math::linearalgebra::dgetrf__ *matrix*

    Computes an LU factorization of a general matrix, using partial, pivoting
    with row interchanges\. Returns the permutation vector\.

    The factorization has the form

        P \* A = L \* U

    where P is a permutation matrix, L is lower triangular with unit diagonal
    elements, and U is upper triangular\. Returns the permutation vector, as a
    list of length n\-1\. The last entry of the permutation is not stored, since
    it is implicitely known, with value n \(the last row is not swapped with any
    other row\)\. At index \#i of the permutation is stored the index of the row \#j
    which is swapped with row \#i at step \#i\. That means that each index of the







|







995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
  - <a name='59'></a>__::math::linearalgebra::dgetrf__ *matrix*

    Computes an LU factorization of a general matrix, using partial, pivoting
    with row interchanges\. Returns the permutation vector\.

    The factorization has the form

        P * A = L * U

    where P is a permutation matrix, L is lower triangular with unit diagonal
    elements, and U is upper triangular\. Returns the permutation vector, as a
    list of length n\-1\. The last entry of the permutation is not stored, since
    it is implicitely known, with value n \(the last row is not swapped with any
    other row\)\. At index \#i of the permutation is stored the index of the row \#j
    which is swapped with row \#i at step \#i\. That means that each index of the
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
    off\-diagonal and the main diagonal\) and n rows\.

  - Element i,j \(i = \-m,\.\.\.,m; j =1,\.\.\.,n\) of "B" corresponds to element k,j of
    "A" where k = M\+i\-1 and M is at least \(\!\) n, the number of rows in "B"\.

  - To set element \(i,j\) of matrix "B" use:

        setelem B $j \[expr \{$N\+$i\-1\}\] $value

\(There is no convenience procedure for this yet\)

# <a name='section4'></a>REMARKS ON THE IMPLEMENTATION

There is a difference between the original LA package by Hume and the current
implementation\. Whereas the LA package uses a linear list, the current package







|







1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
    off\-diagonal and the main diagonal\) and n rows\.

  - Element i,j \(i = \-m,\.\.\.,m; j =1,\.\.\.,n\) of "B" corresponds to element k,j of
    "A" where k = M\+i\-1 and M is at least \(\!\) n, the number of rows in "B"\.

  - To set element \(i,j\) of matrix "B" use:

        setelem B $j [expr {$N+$i-1}] $value

\(There is no convenience procedure for this yet\)

# <a name='section4'></a>REMARKS ON THE IMPLEMENTATION

There is a difference between the original LA package by Hume and the current
implementation\. Whereas the LA package uses a linear list, the current package
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
    namespace import ::math::linearalgebra

results in an error message about "scale"\. This is due to the fact that Tk
defines all its commands in the global namespace\. The solution is to import the
linear algebra commands in a namespace that is not the global one:

    package require math::linearalgebra
    namespace eval compute \{
        namespace import ::math::linearalgebra::\*
        \.\.\. use the linear algebra version of scale \.\.\.
    \}


To use Tk's scale command in that same namespace you can rename it:

    namespace eval compute \{
        rename ::scale scaleTk
        scaleTk \.scale \.\.\.
    \}


# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *math :: linearalgebra* of
the [Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also
report any ideas for enhancements you may have for either package and/or







|
|
|
<
>



|

|
<
>







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
    namespace import ::math::linearalgebra

results in an error message about "scale"\. This is due to the fact that Tk
defines all its commands in the global namespace\. The solution is to import the
linear algebra commands in a namespace that is not the global one:

    package require math::linearalgebra
    namespace eval compute {
        namespace import ::math::linearalgebra::*
        ... use the linear algebra version of scale ...

    }

To use Tk's scale command in that same namespace you can rename it:

    namespace eval compute {
        rename ::scale scaleTk
        scaleTk .scale ...

    }

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *math :: linearalgebra* of
the [Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also
report any ideas for enhancements you may have for either package and/or

Changes to embedded/md/tcllib/files/modules/math/machineparameters.md.

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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

# <a name='description'></a>DESCRIPTION

The *math::machineparameters* package is the Tcl equivalent of the DLAMCH
LAPACK function\. In floating point systems, a floating point number is
represented by

    x = \+/\- d1 d2 \.\.\. dt basis^e

where digits satisfy

    0 <= di <= basis \- 1, i = 1, t

with the convention :

  - t is the size of the mantissa

  - basis is the basis \(the "radix"\)

The __compute__ method computes all machine parameters\. Then, the
__get__ method can be used to get each parameter\. The __print__ method
prints a report on standard output\.

# <a name='section2'></a>EXAMPLE

In the following example, one compute the parameters of a desktop under Linux
with the following Tcl 8\.4\.19 properties :

    % parray tcl\_platform
    tcl\_platform\(byteOrder\) = littleEndian
    tcl\_platform\(machine\)   = i686
    tcl\_platform\(os\)        = Linux
    tcl\_platform\(osVersion\) = 2\.6\.24\-19\-generic
    tcl\_platform\(platform\)  = unix
    tcl\_platform\(tip,268\)   = 1
    tcl\_platform\(tip,280\)   = 1
    tcl\_platform\(user\)      = <username>
    tcl\_platform\(wordSize\)  = 4

The following example creates a machineparameters object, computes the
properties and displays it\.

    set pp \[machineparameters create %AUTO%\]
    $pp compute
    $pp print
    $pp destroy

This prints out :

    Machine parameters
    Epsilon : 1\.11022302463e\-16
    Beta : 2
    Rounding : proper
    Mantissa : 53
    Maximum exponent : 1024
    Minimum exponent : \-1021
    Overflow threshold : 8\.98846567431e\+307
    Underflow threshold : 2\.22507385851e\-308

That compares well with the results produced by Lapack 3\.1\.1 :

    Epsilon                      =   1\.11022302462515654E\-016
    Safe minimum                 =   2\.22507385850720138E\-308
    Base                         =    2\.0000000000000000
    Precision                    =   2\.22044604925031308E\-016
    Number of digits in mantissa =    53\.000000000000000
    Rounding mode                =   1\.00000000000000000
    Minimum exponent             =   \-1021\.0000000000000
    Underflow threshold          =   2\.22507385850720138E\-308
    Largest exponent             =    1024\.0000000000000
    Overflow threshold           =   1\.79769313486231571E\+308
    Reciprocal of safe minimum   =   4\.49423283715578977E\+307

The following example creates a machineparameters object, computes the
properties and gets the epsilon for the machine\.

    set pp \[machineparameters create %AUTO%\]
    $pp compute
    set eps \[$pp get \-epsilon\]
    $pp destroy

# <a name='section3'></a>REFERENCES

  - "Algorithms to Reveal Properties of Floating\-Point Arithmetic", Michael A\.
    Malcolm, Stanford University, Communications of the ACM, Volume 15 , Issue
    11 \(November 1972\), Pages: 949 \- 951







|



|
















|
|
|
|
|
|
|
|
|
|




|







|




|
|
|



|
|
|
|
|
|
|
|
|
|
|




|

|







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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

# <a name='description'></a>DESCRIPTION

The *math::machineparameters* package is the Tcl equivalent of the DLAMCH
LAPACK function\. In floating point systems, a floating point number is
represented by

    x = +/- d1 d2 ... dt basis^e

where digits satisfy

    0 <= di <= basis - 1, i = 1, t

with the convention :

  - t is the size of the mantissa

  - basis is the basis \(the "radix"\)

The __compute__ method computes all machine parameters\. Then, the
__get__ method can be used to get each parameter\. The __print__ method
prints a report on standard output\.

# <a name='section2'></a>EXAMPLE

In the following example, one compute the parameters of a desktop under Linux
with the following Tcl 8\.4\.19 properties :

    % parray tcl_platform
    tcl_platform(byteOrder) = littleEndian
    tcl_platform(machine)   = i686
    tcl_platform(os)        = Linux
    tcl_platform(osVersion) = 2.6.24-19-generic
    tcl_platform(platform)  = unix
    tcl_platform(tip,268)   = 1
    tcl_platform(tip,280)   = 1
    tcl_platform(user)      = <username>
    tcl_platform(wordSize)  = 4

The following example creates a machineparameters object, computes the
properties and displays it\.

    set pp [machineparameters create %AUTO%]
    $pp compute
    $pp print
    $pp destroy

This prints out :

    Machine parameters
    Epsilon : 1.11022302463e-16
    Beta : 2
    Rounding : proper
    Mantissa : 53
    Maximum exponent : 1024
    Minimum exponent : -1021
    Overflow threshold : 8.98846567431e+307
    Underflow threshold : 2.22507385851e-308

That compares well with the results produced by Lapack 3\.1\.1 :

    Epsilon                      =   1.11022302462515654E-016
    Safe minimum                 =   2.22507385850720138E-308
    Base                         =    2.0000000000000000
    Precision                    =   2.22044604925031308E-016
    Number of digits in mantissa =    53.000000000000000
    Rounding mode                =   1.00000000000000000
    Minimum exponent             =   -1021.0000000000000
    Underflow threshold          =   2.22507385850720138E-308
    Largest exponent             =    1024.0000000000000
    Overflow threshold           =   1.79769313486231571E+308
    Reciprocal of safe minimum   =   4.49423283715578977E+307

The following example creates a machineparameters object, computes the
properties and gets the epsilon for the machine\.

    set pp [machineparameters create %AUTO%]
    $pp compute
    set eps [$pp get -epsilon]
    $pp destroy

# <a name='section3'></a>REFERENCES

  - "Algorithms to Reveal Properties of Floating\-Point Arithmetic", Michael A\.
    Malcolm, Stanford University, Communications of the ACM, Volume 15 , Issue
    11 \(November 1972\), Pages: 949 \- 951

Changes to embedded/md/tcllib/files/modules/math/math_geometry.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

[//000000001]: # (math::geometry \- Tcl Math Library)
[//000000002]: # (Generated from file 'math\_geometry\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2001 by Ideogramic ApS and other parties  
Copyright &copy; 2010 by Andreas Kupries  
Copyright &copy; 2010 by Kevin Kenny  
Copyright &copy; 2018 by Arjen Markus)
[//000000004]: # (math::geometry\(n\) 1\.3\.0 tcllib "Tcl Math Library")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

[//000000001]: # (math::geometry \- Tcl Math Library)
[//000000002]: # (Generated from file 'math\_geometry\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2001 by Ideogramic ApS and other parties)
[//000000004]: # (Copyright &copy; 2010 by Andreas Kupries)
[//000000005]: # (Copyright &copy; 2010 by Kevin Kenny)
[//000000006]: # (Copyright &copy; 2018 by Arjen Markus)
[//000000007]: # (math::geometry\(n\) 1\.3\.0 tcllib "Tcl Math Library")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
53
54
55
56
57
58
59



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
[__::math::geometry::h__ *length*](#8)  
[__::math::geometry::v__ *length*](#9)  
[__::math::geometry::between__ *point1* *point2* *s*](#10)  
[__::math::geometry::octant__ *point*](#11)  
[__::math::geometry::rect__ *nw* *se*](#12)  
[__::math::geometry::nwse__ *rect*](#13)  
[__::math::geometry::angle__ *line*](#14)  



[__::math::geometry::calculateDistanceToLine__ *P* *line*](#15)  
[__::math::geometry::calculateDistanceToLineSegment__ *P* *linesegment*](#16)  
[__::math::geometry::calculateDistanceToPolyline__ *P* *polyline*](#17)  
[__::math::geometry::calculateDistanceToPolygon__ *P* *polygon*](#18)  
[__::math::geometry::findClosestPointOnLine__ *P* *line*](#19)  
[__::math::geometry::findClosestPointOnLineSegment__ *P* *linesegment*](#20)  
[__::math::geometry::findClosestPointOnPolyline__ *P* *polyline*](#21)  
[__::math::geometry::lengthOfPolyline__ *polyline*](#22)  
[__::math::geometry::movePointInDirection__ *P* *direction* *dist*](#23)  
[__::math::geometry::lineSegmentsIntersect__ *linesegment1* *linesegment2*](#24)  
[__::math::geometry::findLineSegmentIntersection__ *linesegment1* *linesegment2*](#25)  
[__::math::geometry::findLineIntersection__ *line1* *line2*](#26)  
[__::math::geometry::polylinesIntersect__ *polyline1* *polyline2*](#27)  
[__::math::geometry::polylinesBoundingIntersect__ *polyline1* *polyline2* *granularity*](#28)  
[__::math::geometry::intervalsOverlap__ *y1* *y2* *y3* *y4* *strict*](#29)  
[__::math::geometry::rectanglesOverlap__ *P1* *P2* *Q1* *Q2* *strict*](#30)  
[__::math::geometry::bbox__ *polyline*](#31)  
[__::math::geometry::pointInsidePolygon__ *P* *polyline*](#32)  
[__::math::geometry::pointInsidePolygonAlt__ *P* *polyline*](#33)  
[__::math::geometry::rectangleInsidePolygon__ *P1* *P2* *polyline*](#34)  
[__::math::geometry::areaPolygon__ *polygon*](#35)  
[__::math::geometry::translate__ *vector* *polyline*](#36)  
[__::math::geometry::rotate__ *angle* *polyline*](#37)  
[__::math::geometry::reflect__ *angle* *polyline*](#38)  
[__::math::geometry::degToRad__ *angle*](#39)  
[__::math::geometry::radToDeg__ *angle*](#40)  
[__::math::geometry::circle__ *centre* *radius*](#41)  
[__::math::geometry::circleTwoPoints__ *point1* *point2*](#42)  
[__::math::geometry::pointInsideCircle__ *point* *circle*](#43)  
[__::math::geometry::lineIntersectsCircle__ *line* *circle*](#44)  
[__::math::geometry::lineSegmentIntersectsCircle__ *segment* *circle*](#45)  
[__::math::geometry::intersectionLineWithCircle__ *line* *circle*](#46)  
[__::math::geometry::intersectionCircleWithCircle__ *circle1* *circle2*](#47)  
[__::math::geometry::tangentLinesToCircle__ *point* *circle*](#48)  

# <a name='description'></a>DESCRIPTION

The __math::geometry__ package is a collection of functions for computations
and manipulations on two\-dimensional geometrical objects, such as points, lines
and polygons\.








>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
[__::math::geometry::h__ *length*](#8)  
[__::math::geometry::v__ *length*](#9)  
[__::math::geometry::between__ *point1* *point2* *s*](#10)  
[__::math::geometry::octant__ *point*](#11)  
[__::math::geometry::rect__ *nw* *se*](#12)  
[__::math::geometry::nwse__ *rect*](#13)  
[__::math::geometry::angle__ *line*](#14)  
[__::math::geometry::angleBetween__ *vector1* *vector2*](#15)  
[__::math::geometry::inproduct__ *vector1* *vector2*](#16)  
[__::math::geometry::areaParallellogram__ *vector1* *vector2*](#17)  
[__::math::geometry::calculateDistanceToLine__ *P* *line*](#18)  
[__::math::geometry::calculateDistanceToLineSegment__ *P* *linesegment*](#19)  
[__::math::geometry::calculateDistanceToPolyline__ *P* *polyline*](#20)  
[__::math::geometry::calculateDistanceToPolygon__ *P* *polygon*](#21)  
[__::math::geometry::findClosestPointOnLine__ *P* *line*](#22)  
[__::math::geometry::findClosestPointOnLineSegment__ *P* *linesegment*](#23)  
[__::math::geometry::findClosestPointOnPolyline__ *P* *polyline*](#24)  
[__::math::geometry::lengthOfPolyline__ *polyline*](#25)  
[__::math::geometry::movePointInDirection__ *P* *direction* *dist*](#26)  
[__::math::geometry::lineSegmentsIntersect__ *linesegment1* *linesegment2*](#27)  
[__::math::geometry::findLineSegmentIntersection__ *linesegment1* *linesegment2*](#28)  
[__::math::geometry::findLineIntersection__ *line1* *line2*](#29)  
[__::math::geometry::polylinesIntersect__ *polyline1* *polyline2*](#30)  
[__::math::geometry::polylinesBoundingIntersect__ *polyline1* *polyline2* *granularity*](#31)  
[__::math::geometry::intervalsOverlap__ *y1* *y2* *y3* *y4* *strict*](#32)  
[__::math::geometry::rectanglesOverlap__ *P1* *P2* *Q1* *Q2* *strict*](#33)  
[__::math::geometry::bbox__ *polyline*](#34)  
[__::math::geometry::pointInsidePolygon__ *P* *polyline*](#35)  
[__::math::geometry::pointInsidePolygonAlt__ *P* *polyline*](#36)  
[__::math::geometry::rectangleInsidePolygon__ *P1* *P2* *polyline*](#37)  
[__::math::geometry::areaPolygon__ *polygon*](#38)  
[__::math::geometry::translate__ *vector* *polyline*](#39)  
[__::math::geometry::rotate__ *angle* *polyline*](#40)  
[__::math::geometry::reflect__ *angle* *polyline*](#41)  
[__::math::geometry::degToRad__ *angle*](#42)  
[__::math::geometry::radToDeg__ *angle*](#43)  
[__::math::geometry::circle__ *centre* *radius*](#44)  
[__::math::geometry::circleTwoPoints__ *point1* *point2*](#45)  
[__::math::geometry::pointInsideCircle__ *point* *circle*](#46)  
[__::math::geometry::lineIntersectsCircle__ *line* *circle*](#47)  
[__::math::geometry::lineSegmentIntersectsCircle__ *segment* *circle*](#48)  
[__::math::geometry::intersectionLineWithCircle__ *line* *circle*](#49)  
[__::math::geometry::intersectionCircleWithCircle__ *circle1* *circle2*](#50)  
[__::math::geometry::tangentLinesToCircle__ *point* *circle*](#51)  

# <a name='description'></a>DESCRIPTION

The __math::geometry__ package is a collection of functions for computations
and manipulations on two\-dimensional geometrical objects, such as points, lines
and polygons\.

151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
    command\.

  - <a name='4'></a>__::math::geometry::distance__ *point1* *point2*

    Compute the distance between the two points and return it as the result of
    the command\. This is in essence the same as

        math::geometry::length \[math::geomtry::\- point1 point2\]

  - <a name='5'></a>__::math::geometry::length__ *point*

    Compute the length of the vector and return it as the result of the command\.

  - <a name='6'></a>__::math::geometry::s\*__ *factor* *point*








|







154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
    command\.

  - <a name='4'></a>__::math::geometry::distance__ *point1* *point2*

    Compute the distance between the two points and return it as the result of
    the command\. This is in essence the same as

        math::geometry::length [math::geomtry::- point1 point2]

  - <a name='5'></a>__::math::geometry::length__ *point*

    Compute the length of the vector and return it as the result of the command\.

  - <a name='6'></a>__::math::geometry::s\*__ *factor* *point*

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
    Calculate the angle from the positive x\-axis to a given line \(in two
    dimensions only\)\.

      * list *line*

        Coordinates of the line





































  - <a name='15'></a>__::math::geometry::calculateDistanceToLine__ *P* *line*

    Calculate the distance of point P to the \(infinite\) line and return the
    result

      * list *P*

        List of two numbers, the coordinates of the point

      * list *line*

        List of four numbers, the coordinates of two points on the line

  - <a name='16'></a>__::math::geometry::calculateDistanceToLineSegment__ *P* *linesegment*

    Calculate the distance of point P to the \(finite\) line segment and return
    the result\.

      * list *P*

        List of two numbers, the coordinates of the point

      * list *linesegment*

        List of four numbers, the coordinates of the first and last points of
        the line segment

  - <a name='17'></a>__::math::geometry::calculateDistanceToPolyline__ *P* *polyline*

    Calculate the distance of point P to the polyline and return the result\.
    Note that a polyline needs not to be closed\.

      * list *P*

        List of two numbers, the coordinates of the point

      * list *polyline*

        List of numbers, the coordinates of the vertices of the polyline

  - <a name='18'></a>__::math::geometry::calculateDistanceToPolygon__ *P* *polygon*

    Calculate the distance of point P to the polygon and return the result\. If
    the list of coordinates is not closed \(first and last points differ\), it is
    automatically closed\.

      * list *P*

        List of two numbers, the coordinates of the point

      * list *polygon*

        List of numbers, the coordinates of the vertices of the polygon

  - <a name='19'></a>__::math::geometry::findClosestPointOnLine__ *P* *line*

    Return the point on a line which is closest to a given point\.

      * list *P*

        List of two numbers, the coordinates of the point

      * list *line*

        List of four numbers, the coordinates of two points on the line

  - <a name='20'></a>__::math::geometry::findClosestPointOnLineSegment__ *P* *linesegment*

    Return the point on a *line segment* which is closest to a given point\.

      * list *P*

        List of two numbers, the coordinates of the point

      * list *linesegment*

        List of four numbers, the first and last points on the line segment

  - <a name='21'></a>__::math::geometry::findClosestPointOnPolyline__ *P* *polyline*

    Return the point on a *polyline* which is closest to a given point\.

      * list *P*

        List of two numbers, the coordinates of the point

      * list *polyline*

        List of numbers, the vertices of the polyline

  - <a name='22'></a>__::math::geometry::lengthOfPolyline__ *polyline*

    Return the length of the *polyline* \(note: it not regarded as a polygon\)

      * list *polyline*

        List of numbers, the vertices of the polyline

  - <a name='23'></a>__::math::geometry::movePointInDirection__ *P* *direction* *dist*

    Move a point over a given distance in a given direction and return the new
    coordinates \(in two dimensions only\)\.

      * list *P*

        Coordinates of the point to be moved

      * double *direction*

        Direction \(in degrees; 0 is to the right, 90 upwards\)

      * list *dist*

        Distance over which to move the point

  - <a name='24'></a>__::math::geometry::lineSegmentsIntersect__ *linesegment1* *linesegment2*

    Check if two line segments intersect or coincide\. Returns 1 if that is the
    case, 0 otherwise \(in two dimensions only\)\. If an endpoint of one segment
    lies on the other segment \(or is very close to the segment\), they are
    considered to intersect

      * list *linesegment1*

        First line segment

      * list *linesegment2*

        Second line segment

  - <a name='25'></a>__::math::geometry::findLineSegmentIntersection__ *linesegment1* *linesegment2*

    Find the intersection point of two line segments\. Return the coordinates or
    the keywords "coincident" or "none" if the line segments coincide or have no
    points in common \(in two dimensions only\)\.

      * list *linesegment1*

        First line segment

      * list *linesegment2*

        Second line segment

  - <a name='26'></a>__::math::geometry::findLineIntersection__ *line1* *line2*

    Find the intersection point of two \(infinite\) lines\. Return the coordinates
    or the keywords "coincident" or "none" if the lines coincide or have no
    points in common \(in two dimensions only\)\.

      * list *line1*

        First line

      * list *line2*

        Second line

    See section [References](#section3) for details on the algorithm and
    math behind it\.

  - <a name='27'></a>__::math::geometry::polylinesIntersect__ *polyline1* *polyline2*

    Check if two polylines intersect or not \(in two dimensions only\)\.

      * list *polyline1*

        First polyline

      * list *polyline2*

        Second polyline

  - <a name='28'></a>__::math::geometry::polylinesBoundingIntersect__ *polyline1* *polyline2* *granularity*

    Check whether two polylines intersect, but reduce the correctness of the
    result to the given granularity\. Use this for faster, but weaker,
    intersection checking\.

    How it works:








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|












|













|












|













|











|











|











|







|
















|














|













|
















|











|







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
    Calculate the angle from the positive x\-axis to a given line \(in two
    dimensions only\)\.

      * list *line*

        Coordinates of the line

  - <a name='15'></a>__::math::geometry::angleBetween__ *vector1* *vector2*

    Calculate the angle between two vectors \(in degrees\)

      * list *vector1*

        First vector

      * list *vector2*

        Second vector

  - <a name='16'></a>__::math::geometry::inproduct__ *vector1* *vector2*

    Calculate the inner product of two vectors

      * list *vector1*

        First vector

      * list *vector2*

        Second vector

  - <a name='17'></a>__::math::geometry::areaParallellogram__ *vector1* *vector2*

    Calculate the area of the parallellogram with the two vectors as its sides

      * list *vector1*

        First vector

      * list *vector2*

        Second vector

  - <a name='18'></a>__::math::geometry::calculateDistanceToLine__ *P* *line*

    Calculate the distance of point P to the \(infinite\) line and return the
    result

      * list *P*

        List of two numbers, the coordinates of the point

      * list *line*

        List of four numbers, the coordinates of two points on the line

  - <a name='19'></a>__::math::geometry::calculateDistanceToLineSegment__ *P* *linesegment*

    Calculate the distance of point P to the \(finite\) line segment and return
    the result\.

      * list *P*

        List of two numbers, the coordinates of the point

      * list *linesegment*

        List of four numbers, the coordinates of the first and last points of
        the line segment

  - <a name='20'></a>__::math::geometry::calculateDistanceToPolyline__ *P* *polyline*

    Calculate the distance of point P to the polyline and return the result\.
    Note that a polyline needs not to be closed\.

      * list *P*

        List of two numbers, the coordinates of the point

      * list *polyline*

        List of numbers, the coordinates of the vertices of the polyline

  - <a name='21'></a>__::math::geometry::calculateDistanceToPolygon__ *P* *polygon*

    Calculate the distance of point P to the polygon and return the result\. If
    the list of coordinates is not closed \(first and last points differ\), it is
    automatically closed\.

      * list *P*

        List of two numbers, the coordinates of the point

      * list *polygon*

        List of numbers, the coordinates of the vertices of the polygon

  - <a name='22'></a>__::math::geometry::findClosestPointOnLine__ *P* *line*

    Return the point on a line which is closest to a given point\.

      * list *P*

        List of two numbers, the coordinates of the point

      * list *line*

        List of four numbers, the coordinates of two points on the line

  - <a name='23'></a>__::math::geometry::findClosestPointOnLineSegment__ *P* *linesegment*

    Return the point on a *line segment* which is closest to a given point\.

      * list *P*

        List of two numbers, the coordinates of the point

      * list *linesegment*

        List of four numbers, the first and last points on the line segment

  - <a name='24'></a>__::math::geometry::findClosestPointOnPolyline__ *P* *polyline*

    Return the point on a *polyline* which is closest to a given point\.

      * list *P*

        List of two numbers, the coordinates of the point

      * list *polyline*

        List of numbers, the vertices of the polyline

  - <a name='25'></a>__::math::geometry::lengthOfPolyline__ *polyline*

    Return the length of the *polyline* \(note: it not regarded as a polygon\)

      * list *polyline*

        List of numbers, the vertices of the polyline

  - <a name='26'></a>__::math::geometry::movePointInDirection__ *P* *direction* *dist*

    Move a point over a given distance in a given direction and return the new
    coordinates \(in two dimensions only\)\.

      * list *P*

        Coordinates of the point to be moved

      * double *direction*

        Direction \(in degrees; 0 is to the right, 90 upwards\)

      * list *dist*

        Distance over which to move the point

  - <a name='27'></a>__::math::geometry::lineSegmentsIntersect__ *linesegment1* *linesegment2*

    Check if two line segments intersect or coincide\. Returns 1 if that is the
    case, 0 otherwise \(in two dimensions only\)\. If an endpoint of one segment
    lies on the other segment \(or is very close to the segment\), they are
    considered to intersect

      * list *linesegment1*

        First line segment

      * list *linesegment2*

        Second line segment

  - <a name='28'></a>__::math::geometry::findLineSegmentIntersection__ *linesegment1* *linesegment2*

    Find the intersection point of two line segments\. Return the coordinates or
    the keywords "coincident" or "none" if the line segments coincide or have no
    points in common \(in two dimensions only\)\.

      * list *linesegment1*

        First line segment

      * list *linesegment2*

        Second line segment

  - <a name='29'></a>__::math::geometry::findLineIntersection__ *line1* *line2*

    Find the intersection point of two \(infinite\) lines\. Return the coordinates
    or the keywords "coincident" or "none" if the lines coincide or have no
    points in common \(in two dimensions only\)\.

      * list *line1*

        First line

      * list *line2*

        Second line

    See section [References](#section3) for details on the algorithm and
    math behind it\.

  - <a name='30'></a>__::math::geometry::polylinesIntersect__ *polyline1* *polyline2*

    Check if two polylines intersect or not \(in two dimensions only\)\.

      * list *polyline1*

        First polyline

      * list *polyline2*

        Second polyline

  - <a name='31'></a>__::math::geometry::polylinesBoundingIntersect__ *polyline1* *polyline2* *granularity*

    Check whether two polylines intersect, but reduce the correctness of the
    result to the given granularity\. Use this for faster, but weaker,
    intersection checking\.

    How it works:

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

        Second polyline

      * int *granularity*

        Number of points in each part \(<=1 means check every edge\)

  - <a name='29'></a>__::math::geometry::intervalsOverlap__ *y1* *y2* *y3* *y4* *strict*

    Check if two intervals overlap\.

      * double *y1,y2*

        Begin and end of first interval

      * double *y3,y4*

        Begin and end of second interval

      * logical *strict*

        Check for strict or non\-strict overlap

  - <a name='30'></a>__::math::geometry::rectanglesOverlap__ *P1* *P2* *Q1* *Q2* *strict*

    Check if two rectangles overlap\.

      * list *P1*

        upper\-left corner of the first rectangle








|















|







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

        Second polyline

      * int *granularity*

        Number of points in each part \(<=1 means check every edge\)

  - <a name='32'></a>__::math::geometry::intervalsOverlap__ *y1* *y2* *y3* *y4* *strict*

    Check if two intervals overlap\.

      * double *y1,y2*

        Begin and end of first interval

      * double *y3,y4*

        Begin and end of second interval

      * logical *strict*

        Check for strict or non\-strict overlap

  - <a name='33'></a>__::math::geometry::rectanglesOverlap__ *P1* *P2* *Q1* *Q2* *strict*

    Check if two rectangles overlap\.

      * list *P1*

        upper\-left corner of the first rectangle

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

        lower\-right corner of the second rectangle

      * list *strict*

        choosing strict or non\-strict interpretation

  - <a name='31'></a>__::math::geometry::bbox__ *polyline*

    Calculate the bounding box of a polyline\. Returns a list of four
    coordinates: the upper\-left and the lower\-right corner of the box\.

      * list *polyline*

        The polyline to be examined

  - <a name='32'></a>__::math::geometry::pointInsidePolygon__ *P* *polyline*

    Determine if a point is completely inside a polygon\. If the point touches
    the polygon, then the point is not completely inside the polygon\.

      * list *P*

        Coordinates of the point

      * list *polyline*

        The polyline to be examined

  - <a name='33'></a>__::math::geometry::pointInsidePolygonAlt__ *P* *polyline*

    Determine if a point is completely inside a polygon\. If the point touches
    the polygon, then the point is not completely inside the polygon\. *Note:*
    this alternative procedure uses the so\-called winding number to determine
    this\. It handles self\-intersecting polygons in a "natural" way\.

      * list *P*

        Coordinates of the point

      * list *polyline*

        The polyline to be examined

  - <a name='34'></a>__::math::geometry::rectangleInsidePolygon__ *P1* *P2* *polyline*

    Determine if a rectangle is completely inside a polygon\. If polygon touches
    the rectangle, then the rectangle is not complete inside the polygon\.

      * list *P1*

        Upper\-left corner of the rectangle

      * list *P2*

        Lower\-right corner of the rectangle

      * list *polygon*

        The polygon in question

  - <a name='35'></a>__::math::geometry::areaPolygon__ *polygon*

    Calculate the area of a polygon\.

      * list *polygon*

        The polygon in question

  - <a name='36'></a>__::math::geometry::translate__ *vector* *polyline*

    Translate a polyline over a given vector

      * list *vector*

        Translation vector

      * list *polyline*

        The polyline to be rotated

  - <a name='37'></a>__::math::geometry::rotate__ *angle* *polyline*

    Rotate a polyline over a given angle \(degrees\) around the origin

      * list *angle*

        Angle over which to rotate the polyline \(degrees\)

      * list *polyline*

        The polyline to be translated

  - <a name='38'></a>__::math::geometry::reflect__ *angle* *polyline*

    Reflect a polyline in a line through the origin at a given angle \(degrees\)
    to the x\-axis

      * list *angle*

        Angle of the line of reflection \(degrees\)

      * list *polyline*

        The polyline to be reflected

  - <a name='39'></a>__::math::geometry::degToRad__ *angle*

    Convert from degrees to radians

      * list *angle*

        Angle in degrees

  - <a name='40'></a>__::math::geometry::radToDeg__ *angle*

    Convert from radians to degrees

      * list *angle*

        Angle in radians

  - <a name='41'></a>__::math::geometry::circle__ *centre* *radius*

    Convenience procedure to create a circle from a point and a radius\.

      * list *centre*

        Coordinates of the circle centre

      * list *radius*

        Radius of the circle

  - <a name='42'></a>__::math::geometry::circleTwoPoints__ *point1* *point2*

    Convenience procedure to create a circle from two points on its
    circumference The centre is the point between the two given points, the
    radius is half the distance between them\.

      * list *point1*

        First point

      * list *point2*

        Second point

  - <a name='43'></a>__::math::geometry::pointInsideCircle__ *point* *circle*

    Determine if the given point is inside the circle or on the circumference
    \(1\) or outside \(0\)\.

      * list *point*

        Point to be checked

      * list *circle*

        Circle that may or may not contain the point

  - <a name='44'></a>__::math::geometry::lineIntersectsCircle__ *line* *circle*

    Determine if the given line intersects the circle or touches it \(1\) or does
    not \(0\)\.

      * list *line*

        Line to be checked

      * list *circle*

        Circle that may or may not be intersected

  - <a name='45'></a>__::math::geometry::lineSegmentIntersectsCircle__ *segment* *circle*

    Determine if the given line segment intersects the circle or touches it \(1\)
    or does not \(0\)\.

      * list *segment*

        Line segment to be checked

      * list *circle*

        Circle that may or may not be intersected

  - <a name='46'></a>__::math::geometry::intersectionLineWithCircle__ *line* *circle*

    Determine the points at which the given line intersects the circle\. There
    can be zero, one or two points\. \(If the line touches the circle or is close
    to it, then one point is returned\. An arbitrary margin of 1\.0e\-10 times the
    radius is used to determine this situation\.\)

      * list *line*

        Line to be checked

      * list *circle*

        Circle that may or may not be intersected

  - <a name='47'></a>__::math::geometry::intersectionCircleWithCircle__ *circle1* *circle2*

    Determine the points at which the given two circles intersect\. There can be
    zero, one or two points\. \(If the two circles touch the circle or are very
    close, then one point is returned\. An arbitrary margin of 1\.0e\-10 times the
    mean of the radii of the two circles is used to determine this situation\.\)

      * list *circle1*

        First circle

      * list *circle2*

        Second circle

  - <a name='48'></a>__::math::geometry::tangentLinesToCircle__ *point* *circle*

    Determine the tangent lines from the given point to the circle\. There can be
    zero, one or two lines\. \(If the point is on the cirucmference or very close
    to the circle, then one line is returned\. An arbitrary margin of 1\.0e\-10
    times the radius of the circle is used to determine this situation\.\)

      * list *point*







|








|












|














|
















|







|









|

|









|

|












|







|







|











|













|












|












|












|














|














|







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

        lower\-right corner of the second rectangle

      * list *strict*

        choosing strict or non\-strict interpretation

  - <a name='34'></a>__::math::geometry::bbox__ *polyline*

    Calculate the bounding box of a polyline\. Returns a list of four
    coordinates: the upper\-left and the lower\-right corner of the box\.

      * list *polyline*

        The polyline to be examined

  - <a name='35'></a>__::math::geometry::pointInsidePolygon__ *P* *polyline*

    Determine if a point is completely inside a polygon\. If the point touches
    the polygon, then the point is not completely inside the polygon\.

      * list *P*

        Coordinates of the point

      * list *polyline*

        The polyline to be examined

  - <a name='36'></a>__::math::geometry::pointInsidePolygonAlt__ *P* *polyline*

    Determine if a point is completely inside a polygon\. If the point touches
    the polygon, then the point is not completely inside the polygon\. *Note:*
    this alternative procedure uses the so\-called winding number to determine
    this\. It handles self\-intersecting polygons in a "natural" way\.

      * list *P*

        Coordinates of the point

      * list *polyline*

        The polyline to be examined

  - <a name='37'></a>__::math::geometry::rectangleInsidePolygon__ *P1* *P2* *polyline*

    Determine if a rectangle is completely inside a polygon\. If polygon touches
    the rectangle, then the rectangle is not complete inside the polygon\.

      * list *P1*

        Upper\-left corner of the rectangle

      * list *P2*

        Lower\-right corner of the rectangle

      * list *polygon*

        The polygon in question

  - <a name='38'></a>__::math::geometry::areaPolygon__ *polygon*

    Calculate the area of a polygon\.

      * list *polygon*

        The polygon in question

  - <a name='39'></a>__::math::geometry::translate__ *vector* *polyline*

    Translate a polyline over a given vector

      * list *vector*

        Translation vector

      * list *polyline*

        The polyline to be translated

  - <a name='40'></a>__::math::geometry::rotate__ *angle* *polyline*

    Rotate a polyline over a given angle \(degrees\) around the origin

      * list *angle*

        Angle over which to rotate the polyline \(degrees\)

      * list *polyline*

        The polyline to be rotated

  - <a name='41'></a>__::math::geometry::reflect__ *angle* *polyline*

    Reflect a polyline in a line through the origin at a given angle \(degrees\)
    to the x\-axis

      * list *angle*

        Angle of the line of reflection \(degrees\)

      * list *polyline*

        The polyline to be reflected

  - <a name='42'></a>__::math::geometry::degToRad__ *angle*

    Convert from degrees to radians

      * list *angle*

        Angle in degrees

  - <a name='43'></a>__::math::geometry::radToDeg__ *angle*

    Convert from radians to degrees

      * list *angle*

        Angle in radians

  - <a name='44'></a>__::math::geometry::circle__ *centre* *radius*

    Convenience procedure to create a circle from a point and a radius\.

      * list *centre*

        Coordinates of the circle centre

      * list *radius*

        Radius of the circle

  - <a name='45'></a>__::math::geometry::circleTwoPoints__ *point1* *point2*

    Convenience procedure to create a circle from two points on its
    circumference The centre is the point between the two given points, the
    radius is half the distance between them\.

      * list *point1*

        First point

      * list *point2*

        Second point

  - <a name='46'></a>__::math::geometry::pointInsideCircle__ *point* *circle*

    Determine if the given point is inside the circle or on the circumference
    \(1\) or outside \(0\)\.

      * list *point*

        Point to be checked

      * list *circle*

        Circle that may or may not contain the point

  - <a name='47'></a>__::math::geometry::lineIntersectsCircle__ *line* *circle*

    Determine if the given line intersects the circle or touches it \(1\) or does
    not \(0\)\.

      * list *line*

        Line to be checked

      * list *circle*

        Circle that may or may not be intersected

  - <a name='48'></a>__::math::geometry::lineSegmentIntersectsCircle__ *segment* *circle*

    Determine if the given line segment intersects the circle or touches it \(1\)
    or does not \(0\)\.

      * list *segment*

        Line segment to be checked

      * list *circle*

        Circle that may or may not be intersected

  - <a name='49'></a>__::math::geometry::intersectionLineWithCircle__ *line* *circle*

    Determine the points at which the given line intersects the circle\. There
    can be zero, one or two points\. \(If the line touches the circle or is close
    to it, then one point is returned\. An arbitrary margin of 1\.0e\-10 times the
    radius is used to determine this situation\.\)

      * list *line*

        Line to be checked

      * list *circle*

        Circle that may or may not be intersected

  - <a name='50'></a>__::math::geometry::intersectionCircleWithCircle__ *circle1* *circle2*

    Determine the points at which the given two circles intersect\. There can be
    zero, one or two points\. \(If the two circles touch the circle or are very
    close, then one point is returned\. An arbitrary margin of 1\.0e\-10 times the
    mean of the radii of the two circles is used to determine this situation\.\)

      * list *circle1*

        First circle

      * list *circle2*

        Second circle

  - <a name='51'></a>__::math::geometry::tangentLinesToCircle__ *point* *circle*

    Determine the tangent lines from the given point to the circle\. There can be
    zero, one or two lines\. \(If the point is on the cirucmference or very close
    to the circle, then one line is returned\. An arbitrary margin of 1\.0e\-10
    times the radius of the circle is used to determine this situation\.\)

      * list *point*

Changes to embedded/md/tcllib/files/modules/math/numtheory.md.

49
50
51
52
53
54
55

56
57
58
59
60
61
62
[__math::numtheory::legendre__ *a* *p*](#11)  
[__math::numtheory::jacobi__ *a* *b*](#12)  
[__math::numtheory::gcd__ *m* *n*](#13)  
[__math::numtheory::lcm__ *m* *n*](#14)  
[__math::numtheory::numberPrimesGauss__ *N*](#15)  
[__math::numtheory::numberPrimesLegendre__ *N*](#16)  
[__math::numtheory::numberPrimesLegendreModified__ *N*](#17)  


# <a name='description'></a>DESCRIPTION

This package is for collecting various number\-theoretic operations, with a
slight bias to prime numbers\.

  - <a name='1'></a>__math::numtheory::isprime__ *N* ?*option* *value* \.\.\.?







>







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
[__math::numtheory::legendre__ *a* *p*](#11)  
[__math::numtheory::jacobi__ *a* *b*](#12)  
[__math::numtheory::gcd__ *m* *n*](#13)  
[__math::numtheory::lcm__ *m* *n*](#14)  
[__math::numtheory::numberPrimesGauss__ *N*](#15)  
[__math::numtheory::numberPrimesLegendre__ *N*](#16)  
[__math::numtheory::numberPrimesLegendreModified__ *N*](#17)  
[__math::numtheory::differenceNumberPrimesLegendreModified__ *lower* *upper*](#18)  

# <a name='description'></a>DESCRIPTION

This package is for collecting various number\-theoretic operations, with a
slight bias to prime numbers\.

  - <a name='1'></a>__math::numtheory::isprime__ *N* ?*option* *value* \.\.\.?
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

  - <a name='15'></a>__math::numtheory::numberPrimesGauss__ *N*

    Estimate the number of primes according the formula by Gauss\.

      * integer *N* \(in\)

        Number in question

  - <a name='16'></a>__math::numtheory::numberPrimesLegendre__ *N*

    Estimate the number of primes according the formula by Legendre\.

      * integer *N* \(in\)

        Number in question

  - <a name='17'></a>__math::numtheory::numberPrimesLegendreModified__ *N*

    Estimate the number of primes according the modified formula by Legendre\.

      * integer *N* \(in\)

        Number in question














# <a name='section2'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *math :: numtheory* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report
any ideas for enhancements you may have for either package and/or documentation\.







|







|







|
>
>
>
>
>
>
>
>
>
>
>
>
>







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

  - <a name='15'></a>__math::numtheory::numberPrimesGauss__ *N*

    Estimate the number of primes according the formula by Gauss\.

      * integer *N* \(in\)

        Number in question, should be larger than 0

  - <a name='16'></a>__math::numtheory::numberPrimesLegendre__ *N*

    Estimate the number of primes according the formula by Legendre\.

      * integer *N* \(in\)

        Number in question, should be larger than 0

  - <a name='17'></a>__math::numtheory::numberPrimesLegendreModified__ *N*

    Estimate the number of primes according the modified formula by Legendre\.

      * integer *N* \(in\)

        Number in question, should be larger than 0

  - <a name='18'></a>__math::numtheory::differenceNumberPrimesLegendreModified__ *lower* *upper*

    Estimate the number of primes between tow limits according the modified
    formula by Legendre\.

      * integer *lower* \(in\)

        Lower limit for the primes, should be larger than 0

      * integer *upper* \(in\)

        Upper limit for the primes, should be larger than 0

# <a name='section2'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *math :: numtheory* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report
any ideas for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/math/optimize.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (math::optimize \- Tcl Math Library)
[//000000002]: # (Generated from file 'optimize\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Arjen Markus <arjenmarkus@users\.sourceforge\.net>  
Copyright &copy; 2004,2005 Kevn B\. Kenny <kennykb@users\.sourceforge\.net>)
[//000000004]: # (math::optimize\(n\) 1\.0 tcllib "Tcl Math Library")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (math::optimize \- Tcl Math Library)
[//000000002]: # (Generated from file 'optimize\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Arjen Markus <arjenmarkus@users\.sourceforge\.net>)
[//000000004]: # (Copyright &copy; 2004,2005 Kevn B\. Kenny <kennykb@users\.sourceforge\.net>)
[//000000005]: # (math::optimize\(n\) 1\.0 tcllib "Tcl Math Library")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
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

Several of the above procedures take the *names* of procedures as arguments\.
To avoid problems with the *visibility* of these procedures, the
fully\-qualified name of these procedures is determined inside the optimize
routines\. For the user this has only one consequence: the named procedure must
be visible in the calling procedure\. For instance:

    namespace eval ::mySpace \{
       namespace export calcfunc
       proc calcfunc \{ x \} \{ return $x \}
    \}
    \#


    \# Use a fully\-qualified name
    \#

    namespace eval ::myCalc \{
       puts \[min\_bound\_1d ::myCalc::calcfunc $begin $end\]
    \}
    \#


    \# Import the name
    \#

    namespace eval ::myCalc \{
       namespace import ::mySpace::calcfunc
       puts \[min\_bound\_1d calcfunc $begin $end\]
    \}


The simple procedures *minimum* and *maximum* have been deprecated: the
alternatives are much more flexible, robust and require less function
evaluations\.

# <a name='section4'></a>EXAMPLES

Let us take a few simple examples:

Determine the maximum of f\(x\) = x^3 exp\(\-3x\), on the interval \(0,10\):

    proc efunc \{ x \} \{ expr \{$x\*$x\*$x \* exp\(\-3\.0\*$x\)\} \}
    puts "Maximum at: \[::math::optimize::max\_bound\_1d efunc 0\.0 10\.0\]"

The maximum allowed error determines the number of steps taken \(with each step
in the iteration the interval is reduced with a factor 1/2\)\. Hence, a maximum
error of 0\.0001 is achieved in approximately 14 steps\.

An example of a *linear program* is:

Optimise the expression 3x\+2y, where:

    x >= 0 and y >= 0 \(implicit constraints, part of the
                      definition of linear programs\)

    x \+ y   <= 1      \(constraints specific to the problem\)
    2x \+ 5y <= 10

This problem can be solved as follows:

    set solution \[::math::optimize::solveLinearProgram  \{ 3\.0   2\.0 \}  \{ \{ 1\.0   1\.0   1\.0 \}
         \{ 2\.0   5\.0  10\.0 \} \} \]

Note, that a constraint like:

    x \+ y >= 1

can be turned into standard form using:

    \-x  \-y <= \-1

The theory of linear programming is the subject of many a text book and the
Simplex algorithm that is implemented here is the best\-known method to solve
this type of problems, but it is not the only one\.

# <a name='section5'></a>Bugs, Ideas, Feedback








|

|
<
<
>
>
|
<
>
|
|
<
<
>
>
|
<
>
|

|
<
>











|
|









|
|

|
|



|
|



|



|







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

Several of the above procedures take the *names* of procedures as arguments\.
To avoid problems with the *visibility* of these procedures, the
fully\-qualified name of these procedures is determined inside the optimize
routines\. For the user this has only one consequence: the named procedure must
be visible in the calling procedure\. For instance:

    namespace eval ::mySpace {
       namespace export calcfunc
       proc calcfunc { x } { return $x }


    }
    #
    # Use a fully-qualified name

    #
    namespace eval ::myCalc {
       puts [min_bound_1d ::myCalc::calcfunc $begin $end]


    }
    #
    # Import the name

    #
    namespace eval ::myCalc {
       namespace import ::mySpace::calcfunc
       puts [min_bound_1d calcfunc $begin $end]

    }

The simple procedures *minimum* and *maximum* have been deprecated: the
alternatives are much more flexible, robust and require less function
evaluations\.

# <a name='section4'></a>EXAMPLES

Let us take a few simple examples:

Determine the maximum of f\(x\) = x^3 exp\(\-3x\), on the interval \(0,10\):

    proc efunc { x } { expr {$x*$x*$x * exp(-3.0*$x)} }
    puts "Maximum at: [::math::optimize::max_bound_1d efunc 0.0 10.0]"

The maximum allowed error determines the number of steps taken \(with each step
in the iteration the interval is reduced with a factor 1/2\)\. Hence, a maximum
error of 0\.0001 is achieved in approximately 14 steps\.

An example of a *linear program* is:

Optimise the expression 3x\+2y, where:

    x >= 0 and y >= 0 (implicit constraints, part of the
                      definition of linear programs)

    x + y   <= 1      (constraints specific to the problem)
    2x + 5y <= 10

This problem can be solved as follows:

    set solution [::math::optimize::solveLinearProgram  { 3.0   2.0 }  { { 1.0   1.0   1.0 }
         { 2.0   5.0  10.0 } } ]

Note, that a constraint like:

    x + y >= 1

can be turned into standard form using:

    -x  -y <= -1

The theory of linear programming is the subject of many a text book and the
Simplex algorithm that is implemented here is the best\-known method to solve
this type of problems, but it is not the only one\.

# <a name='section5'></a>Bugs, Ideas, Feedback

Changes to embedded/md/tcllib/files/modules/math/polynomials.md.

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

The package defines the following public procedures:

  - <a name='1'></a>__::math::polynomials::polynomial__ *coeffs*

    Return an \(encoded\) list that defines the polynomial\. A polynomial

        f\(x\) = a \+ b\.x \+ c\.x\*\*2 \+ d\.x\*\*3

    can be defined via:

        set f \[::math::polynomials::polynomial \[list $a $b $c $d\]

      * list *coeffs*

        Coefficients of the polynomial \(in ascending order\)

  - <a name='2'></a>__::math::polynomials::polynCmd__ *coeffs*








|



|







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

The package defines the following public procedures:

  - <a name='1'></a>__::math::polynomials::polynomial__ *coeffs*

    Return an \(encoded\) list that defines the polynomial\. A polynomial

        f(x) = a + b.x + c.x**2 + d.x**3

    can be defined via:

        set f [::math::polynomials::polynomial [list $a $b $c $d]

      * list *coeffs*

        Coefficients of the polynomial \(in ascending order\)

  - <a name='2'></a>__::math::polynomials::polynCmd__ *coeffs*

Changes to embedded/md/tcllib/files/modules/math/qcomplex.md.

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
valid \(representations of\) "complex numbers", that is, lists of two numbers
defining the real and imaginary part of a complex number \(though this is a mere
detail: rely on the *complex* command to construct a valid number\.\)

Most procedures implement the basic arithmetic operations or elementary
functions whereas several others convert to and from different representations:

    set z \[complex 0 1\]
    puts "z = \[tostring $z\]"
    puts "z\*\*2 = \[\* $z $z\]

would result in:

    z = i
    z\*\*2 = \-1

# <a name='section2'></a>AVAILABLE PROCEDURES

The package implements all or most basic operations and elementary functions\.

*The arithmetic operations are:*








|
|
|




|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
valid \(representations of\) "complex numbers", that is, lists of two numbers
defining the real and imaginary part of a complex number \(though this is a mere
detail: rely on the *complex* command to construct a valid number\.\)

Most procedures implement the basic arithmetic operations or elementary
functions whereas several others convert to and from different representations:

    set z [complex 0 1]
    puts "z = [tostring $z]"
    puts "z**2 = [* $z $z]

would result in:

    z = i
    z**2 = -1

# <a name='section2'></a>AVAILABLE PROCEDURES

The package implements all or most basic operations and elementary functions\.

*The arithmetic operations are:*

Added embedded/md/tcllib/files/modules/math/quasirandom.md.















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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

[//000000001]: # (math::quasirandom \- Tcl Math Library)
[//000000002]: # (Generated from file 'quasirandom\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (math::quasirandom\(n\) 1 tcllib "Tcl Math Library")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

# NAME

math::quasirandom \- Quasi\-random points for integration and Monte Carlo type
methods

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Synopsis](#synopsis)

  - [Description](#section1)

  - [COMMANDS](#section2)

  - [TODO](#section3)

  - [References](#section4)

  - [Keywords](#keywords)

  - [Category](#category)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require TclOO  
package require math::quasirandom 1  

[__::math::quasirandom::qrpoint create__ *NAME* *DIM* ?ARGS?](#1)  
[__gen next__](#2)  
[__gen set\-start__ *index*](#3)  
[__gen set\-evaluations__ *number*](#4)  
[__gen integral__ *func* *minmax* *args*](#5)  

# <a name='description'></a>DESCRIPTION

In many applications pseudo\-random numbers and pseudo\-random points in a
\(limited\) sample space play an important role\. For instance in any type of Monte
Carlo simulation\. Pseudo\-random numbers, however, may be too random and as a
consequence a large number of data points is required to reduce the error or
fluctuation in the results to the desired value\.

Quasi\-random numbers can be used as an alternative: instead of "completely"
arbitrary points, points are generated that are diverse enough to cover the
entire sample space in a more or less uniform way\. As a consequence convergence
to the limit can be much faster, when such quasi\-random numbers are well\-chosen\.

The package defines a *[class](\.\./\.\./\.\./\.\./index\.md\#class)* "qrpoint" that
creates a command to generate quasi\-random points in 1, 2 or more dimensions\.
The command can either generate separate points, so that they can be used in a
user\-defined algorithm or use these points to calculate integrals of functions
defined over 1, 2 or more dimensions\. It also holds several other common
algorithms\. \(NOTE: these are not implemented yet\)

One particular characteristic of the generators is that there are no tuning
parameters involved, which makes the use particularly simple\.

# <a name='section2'></a>COMMANDS

A quasi\-random point generator is created using the *qrpoint* class:

  - <a name='1'></a>__::math::quasirandom::qrpoint create__ *NAME* *DIM* ?ARGS?

    This command takes the following arguments:

      * string *NAME*

        The name of the command to be created \(alternatively: the *new*
        subcommand will generate a unique name\)

      * integer/string *DIM*

        The number of dimensions or one of: "circle", "disk", "sphere" or "ball"

      * strings *ARGS*

        Zero or more key\-value pairs\. The supported options are:

          + *\-start index*: The index for the next point to be generated
            \(default: 1\)

          + *\-evaluations number*: The number of evaluations to be used by
            default \(default: 100\)

The points that are returned lie in the hyperblock \[0,1\[^n \(n the number of
dimensions\) or on the unit circle, within the unit disk, on the unit sphere or
within the unit ball\.

Each generator supports the following subcommands:

  - <a name='2'></a>__gen next__

    Return the coordinates of the next quasi\-random point

  - <a name='3'></a>__gen set\-start__ *index*

    Reset the index for the next quasi\-random point\. This is useful to control
    which list of points is returned\. Returns the new or the current value, if
    no value is given\.

  - <a name='4'></a>__gen set\-evaluations__ *number*

    Reset the default number of evaluations in compound algorithms\. Note that
    the actual number is the smallest 4\-fold larger or equal to the given
    number\. \(The 4\-fold plays a role in the detailed integration routine\.\)

  - <a name='5'></a>__gen integral__ *func* *minmax* *args*

    Calculate the integral of the given function over the block \(or the circle,
    sphere etc\.\)

      * string *func*

        The name of the function to be integrated

      * list *minmax*

        List of pairs of minimum and maximum coordinates\. This can be used to
        map the quasi\-random coordinates to the desired hyper\-block\.

        If the space is a circle, disk etc\. then this argument should be a
        single value, the radius\. The circle, disk, etc\. is centred at the
        origin\. If this is not what is required, then a coordinate
        transformation should be made within the function\.

      * strings *args*

        Zero or more key\-value pairs\. The following options are supported:

          + *\-evaluations number*: The number of evaluations to be used\. If
            not specified use the default of the generator object\.

# <a name='section3'></a>TODO

Implement other algorithms and variants

Implement more unit tests\.

Comparison to pseudo\-random numbers for integration\.

# <a name='section4'></a>References

Various algorithms exist for generating quasi\-random numbers\. The generators
created in this package are based on:
[http://extremelearning\.com\.au/unreasonable\-effectiveness\-of\-quasirandom\-sequences/](http://extremelearning\.com\.au/unreasonable\-effectiveness\-of\-quasirandom\-sequences/)

# <a name='keywords'></a>KEYWORDS

[mathematics](\.\./\.\./\.\./\.\./index\.md\#mathematics),
[quasi\-random](\.\./\.\./\.\./\.\./index\.md\#quasi\_random)

# <a name='category'></a>CATEGORY

Mathematics

Changes to embedded/md/tcllib/files/modules/math/rational_funcs.md.

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
The package defines the following public procedures:

  - <a name='1'></a>__::math::rationalfunctions::rationalFunction__ *num* *den*

    Return an \(encoded\) list that defines the rational function\. A rational
    function

                  1 \+ x^3
        f\(x\) = \-\-\-\-\-\-\-\-\-\-\-\-
               1 \+ 2x \+ x^2

    can be defined via:

        set f \[::math::rationalfunctions::rationalFunction \[list 1 0 0 1\]  \[list 1 2 1\]\]

      * list *num*

        Coefficients of the numerator of the rational function \(in ascending
        order\)

      * list *den*







|
|
|



|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
The package defines the following public procedures:

  - <a name='1'></a>__::math::rationalfunctions::rationalFunction__ *num* *den*

    Return an \(encoded\) list that defines the rational function\. A rational
    function

                  1 + x^3
        f(x) = ------------
               1 + 2x + x^2

    can be defined via:

        set f [::math::rationalfunctions::rationalFunction [list 1 0 0 1]  [list 1 2 1]]

      * list *num*

        Coefficients of the numerator of the rational function \(in ascending
        order\)

      * list *den*

Changes to embedded/md/tcllib/files/modules/math/romberg.md.

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
dx/sqrt\(1\-x\*\*2\) maps to du\. Choosing x=sin\(u\), we can find that dx=cos\(u\)\*du,
and sqrt\(1\-x\*\*2\)=cos\(u\)\. The integral from a to b of f\(x\) is the integral from
asin\(a\) to asin\(b\) of f\(sin\(u\)\)\*cos\(u\)\.

We can make a function __g__ that accepts an arbitrary function __f__
and the parameter u, and computes this new integrand\.

    proc g \{ f u \} \{
        set x \[expr \{ sin\($u\) \}\]
        set cmd $f; lappend cmd $x; set y \[eval $cmd\]
        return \[expr \{ $y / cos\($u\) \}\]
    \}


Now integrating __f__ from *a* to *b* is the same as integrating
__g__ from *asin\(a\)* to *asin\(b\)*\. It's a little tricky to get __f__
consistently evaluated in the caller's scope; the following procedure does it\.

    proc romberg\_sine \{ f a b args \} \{
        set f \[lreplace $f 0 0 \[uplevel 1 \[list namespace which \[lindex $f 0\]\]\]\]
        set f \[list g $f\]
        return \[eval \[linsert $args 0 romberg $f \[expr \{ asin\($a\) \}\] \[expr \{ asin\($b\) \}\]\]\]
    \}


This __romberg\_sine__ procedure will do any function with sqrt\(1\-x\*x\) in the
denominator\. Our sample function is f\(x\)=exp\(x\)/sqrt\(1\-x\*x\):

    proc f \{ x \} \{
        expr \{ exp\($x\) / sqrt\( 1\. \- $x\*$x \) \}
    \}


Integrating it is a matter of applying __romberg\_sine__ as we would any of
the other __romberg__ procedures:

    foreach \{ value error \} \[romberg\_sine f \-1\.0 1\.0\] break
    puts \[format "integral is %\.6g \+/\- %\.6g" $value $error\]

    integral is 3\.97746 \+/\- 2\.3557e\-010

# <a name='section8'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *math :: calculus* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report
any ideas for enhancements you may have for either package and/or documentation\.







|
|
|
|
<
>





|
|
|
|
<
>




|
|
<
>




|
|

|







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
dx/sqrt\(1\-x\*\*2\) maps to du\. Choosing x=sin\(u\), we can find that dx=cos\(u\)\*du,
and sqrt\(1\-x\*\*2\)=cos\(u\)\. The integral from a to b of f\(x\) is the integral from
asin\(a\) to asin\(b\) of f\(sin\(u\)\)\*cos\(u\)\.

We can make a function __g__ that accepts an arbitrary function __f__
and the parameter u, and computes this new integrand\.

    proc g { f u } {
        set x [expr { sin($u) }]
        set cmd $f; lappend cmd $x; set y [eval $cmd]
        return [expr { $y / cos($u) }]

    }

Now integrating __f__ from *a* to *b* is the same as integrating
__g__ from *asin\(a\)* to *asin\(b\)*\. It's a little tricky to get __f__
consistently evaluated in the caller's scope; the following procedure does it\.

    proc romberg_sine { f a b args } {
        set f [lreplace $f 0 0 [uplevel 1 [list namespace which [lindex $f 0]]]]
        set f [list g $f]
        return [eval [linsert $args 0 romberg $f [expr { asin($a) }] [expr { asin($b) }]]]

    }

This __romberg\_sine__ procedure will do any function with sqrt\(1\-x\*x\) in the
denominator\. Our sample function is f\(x\)=exp\(x\)/sqrt\(1\-x\*x\):

    proc f { x } {
        expr { exp($x) / sqrt( 1. - $x*$x ) }

    }

Integrating it is a matter of applying __romberg\_sine__ as we would any of
the other __romberg__ procedures:

    foreach { value error } [romberg_sine f -1.0 1.0] break
    puts [format "integral is %.6g +/- %.6g" $value $error]

    integral is 3.97746 +/- 2.3557e-010

# <a name='section8'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *math :: calculus* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report
any ideas for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/math/special.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (math::special \- Tcl Math Library)
[//000000002]: # (Generated from file 'special\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Arjen Markus <arjenmarkus@users\.sourceforge\.net>)
[//000000004]: # (math::special\(n\) 0\.3 tcllib "Tcl Math Library")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>




|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (math::special \- Tcl Math Library)
[//000000002]: # (Generated from file 'special\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Arjen Markus <arjenmarkus@users\.sourceforge\.net>)
[//000000004]: # (math::special\(n\) 0\.4 tcllib "Tcl Math Library")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
37
38
39
40
41
42
43
44
45
46
47


48

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl ?8\.3?  
package require math::special ?0\.3?  

[__::math::special::Beta__ *x* *y*](#1)  


[__::math::special::Gamma__ *x*](#2)  

[__::math::special::erf__ *x*](#3)  
[__::math::special::erfc__ *x*](#4)  
[__::math::special::invnorm__ *p*](#5)  
[__::math::special::J0__ *x*](#6)  
[__::math::special::J1__ *x*](#7)  
[__::math::special::Jn__ *n* *x*](#8)  
[__::math::special::J1/2__ *x*](#9)  
[__::math::special::J\-1/2__ *x*](#10)  
[__::math::special::I\_n__ *x*](#11)  
[__::math::special::cn__ *u* *k*](#12)  
[__::math::special::dn__ *u* *k*](#13)  
[__::math::special::sn__ *u* *k*](#14)  
[__::math::special::elliptic\_K__ *k*](#15)  
[__::math::special::elliptic\_E__ *k*](#16)  
[__::math::special::exponential\_Ei__ *x*](#17)  
[__::math::special::exponential\_En__ *n* *x*](#18)  
[__::math::special::exponential\_li__ *x*](#19)  
[__::math::special::exponential\_Ci__ *x*](#20)  
[__::math::special::exponential\_Si__ *x*](#21)  
[__::math::special::exponential\_Chi__ *x*](#22)  
[__::math::special::exponential\_Shi__ *x*](#23)  
[__::math::special::fresnel\_C__ *x*](#24)  
[__::math::special::fresnel\_S__ *x*](#25)  
[__::math::special::sinc__ *x*](#26)  
[__::math::special::legendre__ *n*](#27)  
[__::math::special::chebyshev__ *n*](#28)  
[__::math::special::laguerre__ *alpha* *n*](#29)  
[__::math::special::hermite__ *n*](#30)  

# <a name='description'></a>DESCRIPTION

This package implements several so\-called special functions, like the Gamma
function, the Bessel functions and such\.

Each function is implemented by a procedure that bears its name \(well, in close







|
|


>
>
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl ?8\.5?  
package require math::special ?0\.4?  

[__::math::special::Beta__ *x* *y*](#1)  
[__::math::special::incBeta__ *a* *b* *x*](#2)  
[__::math::special::regIncBeta__ *a* *b* *x*](#3)  
[__::math::special::Gamma__ *x*](#4)  
[__::math::special::digamma__ *x*](#5)  
[__::math::special::erf__ *x*](#6)  
[__::math::special::erfc__ *x*](#7)  
[__::math::special::invnorm__ *p*](#8)  
[__::math::special::J0__ *x*](#9)  
[__::math::special::J1__ *x*](#10)  
[__::math::special::Jn__ *n* *x*](#11)  
[__::math::special::J1/2__ *x*](#12)  
[__::math::special::J\-1/2__ *x*](#13)  
[__::math::special::I\_n__ *x*](#14)  
[__::math::special::cn__ *u* *k*](#15)  
[__::math::special::dn__ *u* *k*](#16)  
[__::math::special::sn__ *u* *k*](#17)  
[__::math::special::elliptic\_K__ *k*](#18)  
[__::math::special::elliptic\_E__ *k*](#19)  
[__::math::special::exponential\_Ei__ *x*](#20)  
[__::math::special::exponential\_En__ *n* *x*](#21)  
[__::math::special::exponential\_li__ *x*](#22)  
[__::math::special::exponential\_Ci__ *x*](#23)  
[__::math::special::exponential\_Si__ *x*](#24)  
[__::math::special::exponential\_Chi__ *x*](#25)  
[__::math::special::exponential\_Shi__ *x*](#26)  
[__::math::special::fresnel\_C__ *x*](#27)  
[__::math::special::fresnel\_S__ *x*](#28)  
[__::math::special::sinc__ *x*](#29)  
[__::math::special::legendre__ *n*](#30)  
[__::math::special::chebyshev__ *n*](#31)  
[__::math::special::laguerre__ *alpha* *n*](#32)  
[__::math::special::hermite__ *n*](#33)  

# <a name='description'></a>DESCRIPTION

This package implements several so\-called special functions, like the Gamma
function, the Bessel functions and such\.

Each function is implemented by a procedure that bears its name \(well, in close
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

# <a name='section2'></a>OVERVIEW

In the following table several characteristics of the functions in this package
are summarized: the domain for the argument, the values for the parameters and
error bounds\.

    Family       &#124; Function    &#124; Domain x    &#124; Parameter   &#124; Error bound
    \-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-
    Bessel       &#124; J0, J1,     &#124; all of R    &#124; n = integer &#124;   < 1\.0e\-8
                 &#124; Jn          &#124;             &#124;             &#124;  \(&#124;x&#124;<20, n<20\)
    Bessel       &#124; J1/2, J\-1/2,&#124;  x > 0      &#124; n = integer &#124;   exact
    Bessel       &#124; I\_n         &#124; all of R    &#124; n = integer &#124;   < 1\.0e\-6
                 &#124;             &#124;             &#124;             &#124;
    Elliptic     &#124; cn          &#124; 0 <= x <= 1 &#124;     \-\-      &#124;   < 1\.0e\-10
    functions    &#124; dn          &#124; 0 <= x <= 1 &#124;     \-\-      &#124;   < 1\.0e\-10
                 &#124; sn          &#124; 0 <= x <= 1 &#124;     \-\-      &#124;   < 1\.0e\-10
    Elliptic     &#124; K           &#124; 0 <= x < 1  &#124;     \-\-      &#124;   < 1\.0e\-6
    integrals    &#124; E           &#124; 0 <= x < 1  &#124;     \-\-      &#124;   < 1\.0e\-6
                 &#124;             &#124;             &#124;             &#124;
    Error        &#124; erf         &#124;             &#124;     \-\-      &#124;
    functions    &#124; erfc        &#124;             &#124;             &#124;
                 &#124;             &#124;             &#124;             &#124;
    Inverse      &#124; invnorm     &#124; 0 < x < 1   &#124;     \-\-      &#124;   < 1\.2e\-9
    normal       &#124;             &#124;             &#124;             &#124;

    distribution &#124;             &#124;             &#124;             &#124;



                 &#124;             &#124;             &#124;             &#124;
    Exponential  &#124; Ei          &#124;  x \!= 0     &#124;     \-\-      &#124;   < 1\.0e\-10 \(relative\)
    integrals    &#124; En          &#124;  x >  0     &#124;     \-\-      &#124;   as Ei
                 &#124; li          &#124;  x > 0      &#124;     \-\-      &#124;   as Ei
                 &#124; Chi         &#124;  x > 0      &#124;     \-\-      &#124;   < 1\.0e\-8
                 &#124; Shi         &#124;  x > 0      &#124;     \-\-      &#124;   < 1\.0e\-8
                 &#124; Ci          &#124;  x > 0      &#124;     \-\-      &#124;   < 2\.0e\-4
                 &#124; Si          &#124;  x > 0      &#124;     \-\-      &#124;   < 2\.0e\-4
                 &#124;             &#124;             &#124;             &#124;
    Fresnel      &#124; C           &#124;  all of R   &#124;     \-\-      &#124;   < 2\.0e\-3
    integrals    &#124; S           &#124;  all of R   &#124;     \-\-      &#124;   < 2\.0e\-3
                 &#124;             &#124;             &#124;             &#124;
    general      &#124; Beta        &#124; \(see Gamma\) &#124;     \-\-      &#124;   < 1\.0e\-9
                 &#124; Gamma       &#124;  x \!= 0,\-1, &#124;     \-\-      &#124;   < 1\.0e\-9
                 &#124;             &#124;  \-2, \.\.\.    &#124;             &#124;





                 &#124; sinc        &#124;  all of R   &#124;     \-\-      &#124;   exact
                 &#124;             &#124;             &#124;             &#124;
    orthogonal   &#124; Legendre    &#124;  all of R   &#124; n = 0,1,\.\.\. &#124;   exact
    polynomials  &#124; Chebyshev   &#124;  all of R   &#124; n = 0,1,\.\.\. &#124;   exact
                 &#124; Laguerre    &#124;  all of R   &#124; n = 0,1,\.\.\. &#124;   exact
                 &#124;             &#124;             &#124; alpha el\. R &#124;
                 &#124; Hermite     &#124;  all of R   &#124; n = 0,1,\.\.\. &#124;   exact

*Note:* Some of the error bounds are estimated, as no "formal" bounds were
available with the implemented approximation method, others hold for the
auxiliary functions used for estimating the primary functions\.

The following well\-known functions are currently missing from the package:

  - Bessel functions of the second kind \(Y\_n, K\_n\)

  - Bessel functions of arbitrary order \(and hence the Airy functions\)

  - Chebyshev polynomials of the second kind \(U\_n\)

  - The digamma function \(psi\)

  - The incomplete gamma and beta functions

# <a name='section3'></a>PROCEDURES

The package defines the following public procedures:

  - <a name='1'></a>__::math::special::Beta__ *x* *y*

    Compute the Beta function for arguments "x" and "y"

      * float *x*

        First argument for the Beta function

      * float *y*

        Second argument for the Beta function

  - <a name='2'></a>__::math::special::Gamma__ *x*



































    Compute the Gamma function for argument "x"

      * float *x*

        Argument for the Gamma function









  - <a name='3'></a>__::math::special::erf__ *x*

    Compute the error function for argument "x"

      * float *x*

        Argument for the error function

  - <a name='4'></a>__::math::special::erfc__ *x*

    Compute the complementary error function for argument "x"

      * float *x*

        Argument for the complementary error function

  - <a name='5'></a>__::math::special::invnorm__ *p*

    Compute the inverse of the normal distribution function for argument "p"

      * float *p*

        Argument for the inverse normal distribution function \(p must be greater
        than 0 and lower than 1\)

  - <a name='6'></a>__::math::special::J0__ *x*

    Compute the zeroth\-order Bessel function of the first kind for the argument
    "x"

      * float *x*

        Argument for the Bessel function

  - <a name='7'></a>__::math::special::J1__ *x*

    Compute the first\-order Bessel function of the first kind for the argument
    "x"

      * float *x*

        Argument for the Bessel function

  - <a name='8'></a>__::math::special::Jn__ *n* *x*

    Compute the nth\-order Bessel function of the first kind for the argument "x"

      * integer *n*

        Order of the Bessel function

      * float *x*

        Argument for the Bessel function

  - <a name='9'></a>__::math::special::J1/2__ *x*

    Compute the half\-order Bessel function of the first kind for the argument
    "x"

      * float *x*

        Argument for the Bessel function

  - <a name='10'></a>__::math::special::J\-1/2__ *x*

    Compute the minus\-half\-order Bessel function of the first kind for the
    argument "x"

      * float *x*

        Argument for the Bessel function

  - <a name='11'></a>__::math::special::I\_n__ *x*

    Compute the modified Bessel function of the first kind of order n for the
    argument "x"

      * int *x*

        Positive integer order of the function

      * float *x*

        Argument for the function

  - <a name='12'></a>__::math::special::cn__ *u* *k*

    Compute the elliptic function *cn* for the argument "u" and parameter "k"\.

      * float *u*

        Argument for the function

      * float *k*

        Parameter

  - <a name='13'></a>__::math::special::dn__ *u* *k*

    Compute the elliptic function *dn* for the argument "u" and parameter "k"\.

      * float *u*

        Argument for the function

      * float *k*

        Parameter

  - <a name='14'></a>__::math::special::sn__ *u* *k*

    Compute the elliptic function *sn* for the argument "u" and parameter "k"\.

      * float *u*

        Argument for the function

      * float *k*

        Parameter

  - <a name='15'></a>__::math::special::elliptic\_K__ *k*

    Compute the complete elliptic integral of the first kind for the argument
    "k"

      * float *k*

        Argument for the function

  - <a name='16'></a>__::math::special::elliptic\_E__ *k*

    Compute the complete elliptic integral of the second kind for the argument
    "k"

      * float *k*

        Argument for the function

  - <a name='17'></a>__::math::special::exponential\_Ei__ *x*

    Compute the exponential integral of the second kind for the argument "x"

      * float *x*

        Argument for the function \(x \!= 0\)

  - <a name='18'></a>__::math::special::exponential\_En__ *n* *x*

    Compute the exponential integral of the first kind for the argument "x" and
    order n

      * int *n*

        Order of the integral \(n >= 0\)

      * float *x*

        Argument for the function \(x >= 0\)

  - <a name='19'></a>__::math::special::exponential\_li__ *x*

    Compute the logarithmic integral for the argument "x"

      * float *x*

        Argument for the function \(x > 0\)

  - <a name='20'></a>__::math::special::exponential\_Ci__ *x*

    Compute the cosine integral for the argument "x"

      * float *x*

        Argument for the function \(x > 0\)

  - <a name='21'></a>__::math::special::exponential\_Si__ *x*

    Compute the sine integral for the argument "x"

      * float *x*

        Argument for the function \(x > 0\)

  - <a name='22'></a>__::math::special::exponential\_Chi__ *x*

    Compute the hyperbolic cosine integral for the argument "x"

      * float *x*

        Argument for the function \(x > 0\)

  - <a name='23'></a>__::math::special::exponential\_Shi__ *x*

    Compute the hyperbolic sine integral for the argument "x"

      * float *x*

        Argument for the function \(x > 0\)

  - <a name='24'></a>__::math::special::fresnel\_C__ *x*

    Compute the Fresnel cosine integral for real argument x

      * float *x*

        Argument for the function

  - <a name='25'></a>__::math::special::fresnel\_S__ *x*

    Compute the Fresnel sine integral for real argument x

      * float *x*

        Argument for the function

  - <a name='26'></a>__::math::special::sinc__ *x*

    Compute the sinc function for real argument x

      * float *x*

        Argument for the function

  - <a name='27'></a>__::math::special::legendre__ *n*

    Return the Legendre polynomial of degree n \(see [THE ORTHOGONAL
    POLYNOMIALS](#section4)\)

      * int *n*

        Degree of the polynomial

  - <a name='28'></a>__::math::special::chebyshev__ *n*

    Return the Chebyshev polynomial of degree n \(of the first kind\)

      * int *n*

        Degree of the polynomial

  - <a name='29'></a>__::math::special::laguerre__ *alpha* *n*

    Return the Laguerre polynomial of degree n with parameter alpha

      * float *alpha*

        Parameter of the Laguerre polynomial

      * int *n*

        Degree of the polynomial

  - <a name='30'></a>__::math::special::hermite__ *n*

    Return the Hermite polynomial of degree n

      * int *n*

        Degree of the polynomial

# <a name='section4'></a>THE ORTHOGONAL POLYNOMIALS

For dealing with the classical families of orthogonal polynomials, the package
relies on the *math::polynomials* package\. To evaluate the polynomial at some
coordinate, use the *evalPolyn* command:

    set leg2 \[::math::special::legendre 2\]
    puts "Value at x=$x: \[::math::polynomials::evalPolyn $leg2 $x\]"

The return value from the *legendre* and other commands is actually the
definition of the corresponding polynomial as used in that package\.

# <a name='section5'></a>REMARKS ON THE IMPLEMENTATION

It should be noted, that the actual implementation of J0 and J1 depends on







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
>
>
>
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
|
|
|
|
|
|
|













<
<
|

















|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







>
>
>
>
>
>
>
>
|







|







|








|








|








|











|








|








|












|











|











|











|








|








|







|












|







|







|







|







|







|







|







|







|








|







|











|













|
|







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

# <a name='section2'></a>OVERVIEW

In the following table several characteristics of the functions in this package
are summarized: the domain for the argument, the values for the parameters and
error bounds\.

    Family       | Function    | Domain x    | Parameter   | Error bound
    -------------+-------------+-------------+-------------+--------------
    Bessel       | J0, J1,     | all of R    | n = integer |   < 1.0e-8
                 | Jn          |             |             |  (|x|<20, n<20)
    Bessel       | J1/2, J-1/2,|  x > 0      | n = integer |   exact
    Bessel       | I_n         | all of R    | n = integer |   < 1.0e-6
                 |             |             |             |
    Elliptic     | cn          | 0 <= x <= 1 |     --      |   < 1.0e-10
    functions    | dn          | 0 <= x <= 1 |     --      |   < 1.0e-10
                 | sn          | 0 <= x <= 1 |     --      |   < 1.0e-10
    Elliptic     | K           | 0 <= x < 1  |     --      |   < 1.0e-6
    integrals    | E           | 0 <= x < 1  |     --      |   < 1.0e-6
                 |             |             |             |
    Error        | erf         |             |     --      |
    functions    | erfc        |             |             |
                 |             |             |             |
    Inverse      | invnorm     | 0 < x < 1   |     --      |   < 1.2e-9
    normal       |             |             |             |
    distribution |             |             |             |
                 |             |             |             |
    Exponential  | Ei          |  x != 0     |     --      |   < 1.0e-10 (relative)
    integrals    | En          |  x >  0     |     --      |   as Ei
                 | li          |  x > 0      |     --      |   as Ei




                 | Chi         |  x > 0      |     --      |   < 1.0e-8
                 | Shi         |  x > 0      |     --      |   < 1.0e-8
                 | Ci          |  x > 0      |     --      |   < 2.0e-4
                 | Si          |  x > 0      |     --      |   < 2.0e-4
                 |             |             |             |
    Fresnel      | C           |  all of R   |     --      |   < 2.0e-3
    integrals    | S           |  all of R   |     --      |   < 2.0e-3
                 |             |             |             |
    general      | Beta        | (see Gamma) |     --      |   < 1.0e-9
                 | Gamma       |  x != 0,-1, |     --      |   < 1.0e-9
                 |             |  -2, ...    |             |
                 | incBeta     |             |  a, b > 0   |   < 1.0e-9
                 | regIncBeta  |             |  a, b > 0   |   < 1.0e-9
                 | digamma     |  x != 0,-1  |             |   < 1.0e-9
                 |             |  -2, ...    |             |
                 |             |             |             |
                 | sinc        |  all of R   |     --      |   exact
                 |             |             |             |
    orthogonal   | Legendre    |  all of R   | n = 0,1,... |   exact
    polynomials  | Chebyshev   |  all of R   | n = 0,1,... |   exact
                 | Laguerre    |  all of R   | n = 0,1,... |   exact
                 |             |             | alpha el. R |
                 | Hermite     |  all of R   | n = 0,1,... |   exact

*Note:* Some of the error bounds are estimated, as no "formal" bounds were
available with the implemented approximation method, others hold for the
auxiliary functions used for estimating the primary functions\.

The following well\-known functions are currently missing from the package:

  - Bessel functions of the second kind \(Y\_n, K\_n\)

  - Bessel functions of arbitrary order \(and hence the Airy functions\)

  - Chebyshev polynomials of the second kind \(U\_n\)



  - The incomplete gamma function

# <a name='section3'></a>PROCEDURES

The package defines the following public procedures:

  - <a name='1'></a>__::math::special::Beta__ *x* *y*

    Compute the Beta function for arguments "x" and "y"

      * float *x*

        First argument for the Beta function

      * float *y*

        Second argument for the Beta function

  - <a name='2'></a>__::math::special::incBeta__ *a* *b* *x*

    Compute the incomplete Beta function for argument "x" with parameters "a"
    and "b"

      * float *a*

        First parameter for the incomplete Beta function, a > 0

      * float *b*

        Second parameter for the incomplete Beta function, b > 0

      * float *x*

        Argument for the incomplete Beta function

  - <a name='3'></a>__::math::special::regIncBeta__ *a* *b* *x*

    Compute the regularized incomplete Beta function for argument "x" with
    parameters "a" and "b"

      * float *a*

        First parameter for the incomplete Beta function, a > 0

      * float *b*

        Second parameter for the incomplete Beta function, b > 0

      * float *x*

        Argument for the regularized incomplete Beta function

  - <a name='4'></a>__::math::special::Gamma__ *x*

    Compute the Gamma function for argument "x"

      * float *x*

        Argument for the Gamma function

  - <a name='5'></a>__::math::special::digamma__ *x*

    Compute the digamma function \(psi\) for argument "x"

      * float *x*

        Argument for the digamma function

  - <a name='6'></a>__::math::special::erf__ *x*

    Compute the error function for argument "x"

      * float *x*

        Argument for the error function

  - <a name='7'></a>__::math::special::erfc__ *x*

    Compute the complementary error function for argument "x"

      * float *x*

        Argument for the complementary error function

  - <a name='8'></a>__::math::special::invnorm__ *p*

    Compute the inverse of the normal distribution function for argument "p"

      * float *p*

        Argument for the inverse normal distribution function \(p must be greater
        than 0 and lower than 1\)

  - <a name='9'></a>__::math::special::J0__ *x*

    Compute the zeroth\-order Bessel function of the first kind for the argument
    "x"

      * float *x*

        Argument for the Bessel function

  - <a name='10'></a>__::math::special::J1__ *x*

    Compute the first\-order Bessel function of the first kind for the argument
    "x"

      * float *x*

        Argument for the Bessel function

  - <a name='11'></a>__::math::special::Jn__ *n* *x*

    Compute the nth\-order Bessel function of the first kind for the argument "x"

      * integer *n*

        Order of the Bessel function

      * float *x*

        Argument for the Bessel function

  - <a name='12'></a>__::math::special::J1/2__ *x*

    Compute the half\-order Bessel function of the first kind for the argument
    "x"

      * float *x*

        Argument for the Bessel function

  - <a name='13'></a>__::math::special::J\-1/2__ *x*

    Compute the minus\-half\-order Bessel function of the first kind for the
    argument "x"

      * float *x*

        Argument for the Bessel function

  - <a name='14'></a>__::math::special::I\_n__ *x*

    Compute the modified Bessel function of the first kind of order n for the
    argument "x"

      * int *x*

        Positive integer order of the function

      * float *x*

        Argument for the function

  - <a name='15'></a>__::math::special::cn__ *u* *k*

    Compute the elliptic function *cn* for the argument "u" and parameter "k"\.

      * float *u*

        Argument for the function

      * float *k*

        Parameter

  - <a name='16'></a>__::math::special::dn__ *u* *k*

    Compute the elliptic function *dn* for the argument "u" and parameter "k"\.

      * float *u*

        Argument for the function

      * float *k*

        Parameter

  - <a name='17'></a>__::math::special::sn__ *u* *k*

    Compute the elliptic function *sn* for the argument "u" and parameter "k"\.

      * float *u*

        Argument for the function

      * float *k*

        Parameter

  - <a name='18'></a>__::math::special::elliptic\_K__ *k*

    Compute the complete elliptic integral of the first kind for the argument
    "k"

      * float *k*

        Argument for the function

  - <a name='19'></a>__::math::special::elliptic\_E__ *k*

    Compute the complete elliptic integral of the second kind for the argument
    "k"

      * float *k*

        Argument for the function

  - <a name='20'></a>__::math::special::exponential\_Ei__ *x*

    Compute the exponential integral of the second kind for the argument "x"

      * float *x*

        Argument for the function \(x \!= 0\)

  - <a name='21'></a>__::math::special::exponential\_En__ *n* *x*

    Compute the exponential integral of the first kind for the argument "x" and
    order n

      * int *n*

        Order of the integral \(n >= 0\)

      * float *x*

        Argument for the function \(x >= 0\)

  - <a name='22'></a>__::math::special::exponential\_li__ *x*

    Compute the logarithmic integral for the argument "x"

      * float *x*

        Argument for the function \(x > 0\)

  - <a name='23'></a>__::math::special::exponential\_Ci__ *x*

    Compute the cosine integral for the argument "x"

      * float *x*

        Argument for the function \(x > 0\)

  - <a name='24'></a>__::math::special::exponential\_Si__ *x*

    Compute the sine integral for the argument "x"

      * float *x*

        Argument for the function \(x > 0\)

  - <a name='25'></a>__::math::special::exponential\_Chi__ *x*

    Compute the hyperbolic cosine integral for the argument "x"

      * float *x*

        Argument for the function \(x > 0\)

  - <a name='26'></a>__::math::special::exponential\_Shi__ *x*

    Compute the hyperbolic sine integral for the argument "x"

      * float *x*

        Argument for the function \(x > 0\)

  - <a name='27'></a>__::math::special::fresnel\_C__ *x*

    Compute the Fresnel cosine integral for real argument x

      * float *x*

        Argument for the function

  - <a name='28'></a>__::math::special::fresnel\_S__ *x*

    Compute the Fresnel sine integral for real argument x

      * float *x*

        Argument for the function

  - <a name='29'></a>__::math::special::sinc__ *x*

    Compute the sinc function for real argument x

      * float *x*

        Argument for the function

  - <a name='30'></a>__::math::special::legendre__ *n*

    Return the Legendre polynomial of degree n \(see [THE ORTHOGONAL
    POLYNOMIALS](#section4)\)

      * int *n*

        Degree of the polynomial

  - <a name='31'></a>__::math::special::chebyshev__ *n*

    Return the Chebyshev polynomial of degree n \(of the first kind\)

      * int *n*

        Degree of the polynomial

  - <a name='32'></a>__::math::special::laguerre__ *alpha* *n*

    Return the Laguerre polynomial of degree n with parameter alpha

      * float *alpha*

        Parameter of the Laguerre polynomial

      * int *n*

        Degree of the polynomial

  - <a name='33'></a>__::math::special::hermite__ *n*

    Return the Hermite polynomial of degree n

      * int *n*

        Degree of the polynomial

# <a name='section4'></a>THE ORTHOGONAL POLYNOMIALS

For dealing with the classical families of orthogonal polynomials, the package
relies on the *math::polynomials* package\. To evaluate the polynomial at some
coordinate, use the *evalPolyn* command:

    set leg2 [::math::special::legendre 2]
    puts "Value at x=$x: [::math::polynomials::evalPolyn $leg2 $x]"

The return value from the *legendre* and other commands is actually the
definition of the corresponding polynomial as used in that package\.

# <a name='section5'></a>REMARKS ON THE IMPLEMENTATION

It should be noted, that the actual implementation of J0 and J1 depends on

Changes to embedded/md/tcllib/files/modules/math/statistics.md.

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
[__::math::statistics::print\-2x2__ *n11* *n21* *n12* *n22*](#31)  
[__::math::statistics::control\-xbar__ *data* ?nsamples?](#32)  
[__::math::statistics::control\-Rchart__ *data* ?nsamples?](#33)  
[__::math::statistics::test\-xbar__ *control* *data*](#34)  
[__::math::statistics::test\-Rchart__ *control* *data*](#35)  
[__::math::statistics::test\-Kruskal\-Wallis__ *confidence* *args*](#36)  
[__::math::statistics::analyse\-Kruskal\-Wallis__ *args*](#37)  


[__::math::statistics::group\-rank__ *args*](#38)  
[__::math::statistics::test\-Wilcoxon__ *sample\_a* *sample\_b*](#39)  
[__::math::statistics::spearman\-rank__ *sample\_a* *sample\_b*](#40)  
[__::math::statistics::spearman\-rank\-extended__ *sample\_a* *sample\_b*](#41)  
[__::math::statistics::kernel\-density__ *data* opt *\-option value* \.\.\.](#42)  
[__::math::statistics::bootstrap__ *data* *sampleSize* ?numberSamples?](#43)  
[__::math::statistics::wasserstein\-distance__ *prob1* *prob2*](#44)  
[__::math::statistics::kl\-divergence__ *prob1* *prob2*](#45)  
[__::math::statistics::logistic\-model__ *xdata* *ydata*](#46)  
[__::math::statistics::logistic\-probability__ *coeffs* *x*](#47)  
[__::math::statistics::tstat__ *dof* ?alpha?](#48)  
[__::math::statistics::mv\-wls__ *wt1* *weights\_and\_values*](#49)  
[__::math::statistics::mv\-ols__ *values*](#50)  
[__::math::statistics::pdf\-normal__ *mean* *stdev* *value*](#51)  
[__::math::statistics::pdf\-lognormal__ *mean* *stdev* *value*](#52)  
[__::math::statistics::pdf\-exponential__ *mean* *value*](#53)  
[__::math::statistics::pdf\-uniform__ *xmin* *xmax* *value*](#54)  


[__::math::statistics::pdf\-gamma__ *alpha* *beta* *value*](#55)  
[__::math::statistics::pdf\-poisson__ *mu* *k*](#56)  
[__::math::statistics::pdf\-chisquare__ *df* *value*](#57)  
[__::math::statistics::pdf\-student\-t__ *df* *value*](#58)  
[__::math::statistics::pdf\-gamma__ *a* *b* *value*](#59)  
[__::math::statistics::pdf\-beta__ *a* *b* *value*](#60)  
[__::math::statistics::pdf\-weibull__ *scale* *shape* *value*](#61)  
[__::math::statistics::pdf\-gumbel__ *location* *scale* *value*](#62)  
[__::math::statistics::pdf\-pareto__ *scale* *shape* *value*](#63)  
[__::math::statistics::pdf\-cauchy__ *location* *scale* *value*](#64)  



[__::math::statistics::cdf\-normal__ *mean* *stdev* *value*](#65)  
[__::math::statistics::cdf\-lognormal__ *mean* *stdev* *value*](#66)  
[__::math::statistics::cdf\-exponential__ *mean* *value*](#67)  
[__::math::statistics::cdf\-uniform__ *xmin* *xmax* *value*](#68)  


[__::math::statistics::cdf\-students\-t__ *degrees* *value*](#69)  
[__::math::statistics::cdf\-gamma__ *alpha* *beta* *value*](#70)  
[__::math::statistics::cdf\-poisson__ *mu* *k*](#71)  
[__::math::statistics::cdf\-beta__ *a* *b* *value*](#72)  
[__::math::statistics::cdf\-weibull__ *scale* *shape* *value*](#73)  
[__::math::statistics::cdf\-gumbel__ *location* *scale* *value*](#74)  
[__::math::statistics::cdf\-pareto__ *scale* *shape* *value*](#75)  
[__::math::statistics::cdf\-cauchy__ *location* *scale* *value*](#76)  
[__::math::statistics::cdf\-F__ *nf1* *nf2* *value*](#77)  



[__::math::statistics::empirical\-distribution__ *values*](#78)  
[__::math::statistics::random\-normal__ *mean* *stdev* *number*](#79)  
[__::math::statistics::random\-lognormal__ *mean* *stdev* *number*](#80)  
[__::math::statistics::random\-exponential__ *mean* *number*](#81)  
[__::math::statistics::random\-uniform__ *xmin* *xmax* *number*](#82)  


[__::math::statistics::random\-gamma__ *alpha* *beta* *number*](#83)  
[__::math::statistics::random\-poisson__ *mu* *number*](#84)  
[__::math::statistics::random\-chisquare__ *df* *number*](#85)  
[__::math::statistics::random\-student\-t__ *df* *number*](#86)  
[__::math::statistics::random\-beta__ *a* *b* *number*](#87)  
[__::math::statistics::random\-weibull__ *scale* *shape* *number*](#88)  
[__::math::statistics::random\-gumbel__ *location* *scale* *number*](#89)  
[__::math::statistics::random\-pareto__ *scale* *shape* *number*](#90)  
[__::math::statistics::random\-cauchy__ *location* *scale* *number*](#91)  



[__::math::statistics::histogram\-uniform__ *xmin* *xmax* *limits* *number*](#92)  
[__::math::statistics::incompleteGamma__ *x* *p* ?tol?](#93)  
[__::math::statistics::incompleteBeta__ *a* *b* *x* ?tol?](#94)  
[__::math::statistics::estimate\-pareto__ *values*](#95)  



[__::math::statistics::filter__ *varname* *data* *expression*](#96)  
[__::math::statistics::map__ *varname* *data* *expression*](#97)  
[__::math::statistics::samplescount__ *varname* *list* *expression*](#98)  
[__::math::statistics::subdivide__](#99)  
[__::math::statistics::plot\-scale__ *canvas* *xmin* *xmax* *ymin* *ymax*](#100)  
[__::math::statistics::plot\-xydata__ *canvas* *xdata* *ydata* *tag*](#101)  
[__::math::statistics::plot\-xyline__ *canvas* *xdata* *ydata* *tag*](#102)  
[__::math::statistics::plot\-tdata__ *canvas* *tdata* *tag*](#103)  
[__::math::statistics::plot\-tline__ *canvas* *tdata* *tag*](#104)  
[__::math::statistics::plot\-histogram__ *canvas* *counts* *limits* *tag*](#105)  

# <a name='description'></a>DESCRIPTION

The __math::statistics__ package contains functions and procedures for basic
statistical data analysis, such as:

  - Descriptive statistical parameters \(mean, minimum, maximum, standard







>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
>
>
>
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
>
>
>
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
>
>
>
|
|
|
|
>
>
>
|
|
|
|
|
|
|
|
|
|







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
[__::math::statistics::print\-2x2__ *n11* *n21* *n12* *n22*](#31)  
[__::math::statistics::control\-xbar__ *data* ?nsamples?](#32)  
[__::math::statistics::control\-Rchart__ *data* ?nsamples?](#33)  
[__::math::statistics::test\-xbar__ *control* *data*](#34)  
[__::math::statistics::test\-Rchart__ *control* *data*](#35)  
[__::math::statistics::test\-Kruskal\-Wallis__ *confidence* *args*](#36)  
[__::math::statistics::analyse\-Kruskal\-Wallis__ *args*](#37)  
[__::math::statistics::test\-Levene__ *groups*](#38)  
[__::math::statistics::test\-Brown\-Forsythe__ *groups*](#39)  
[__::math::statistics::group\-rank__ *args*](#40)  
[__::math::statistics::test\-Wilcoxon__ *sample\_a* *sample\_b*](#41)  
[__::math::statistics::spearman\-rank__ *sample\_a* *sample\_b*](#42)  
[__::math::statistics::spearman\-rank\-extended__ *sample\_a* *sample\_b*](#43)  
[__::math::statistics::kernel\-density__ *data* opt *\-option value* \.\.\.](#44)  
[__::math::statistics::bootstrap__ *data* *sampleSize* ?numberSamples?](#45)  
[__::math::statistics::wasserstein\-distance__ *prob1* *prob2*](#46)  
[__::math::statistics::kl\-divergence__ *prob1* *prob2*](#47)  
[__::math::statistics::logistic\-model__ *xdata* *ydata*](#48)  
[__::math::statistics::logistic\-probability__ *coeffs* *x*](#49)  
[__::math::statistics::tstat__ *dof* ?alpha?](#50)  
[__::math::statistics::mv\-wls__ *wt1* *weights\_and\_values*](#51)  
[__::math::statistics::mv\-ols__ *values*](#52)  
[__::math::statistics::pdf\-normal__ *mean* *stdev* *value*](#53)  
[__::math::statistics::pdf\-lognormal__ *mean* *stdev* *value*](#54)  
[__::math::statistics::pdf\-exponential__ *mean* *value*](#55)  
[__::math::statistics::pdf\-uniform__ *xmin* *xmax* *value*](#56)  
[__::math::statistics::pdf\-triangular__ *xmin* *xmax* *value*](#57)  
[__::math::statistics::pdf\-symmetric\-triangular__ *xmin* *xmax* *value*](#58)  
[__::math::statistics::pdf\-gamma__ *alpha* *beta* *value*](#59)  
[__::math::statistics::pdf\-poisson__ *mu* *k*](#60)  
[__::math::statistics::pdf\-chisquare__ *df* *value*](#61)  
[__::math::statistics::pdf\-student\-t__ *df* *value*](#62)  
[__::math::statistics::pdf\-gamma__ *a* *b* *value*](#63)  
[__::math::statistics::pdf\-beta__ *a* *b* *value*](#64)  
[__::math::statistics::pdf\-weibull__ *scale* *shape* *value*](#65)  
[__::math::statistics::pdf\-gumbel__ *location* *scale* *value*](#66)  
[__::math::statistics::pdf\-pareto__ *scale* *shape* *value*](#67)  
[__::math::statistics::pdf\-cauchy__ *location* *scale* *value*](#68)  
[__::math::statistics::pdf\-laplace__ *location* *scale* *value*](#69)  
[__::math::statistics::pdf\-kumaraswamy__ *a* *b* *value*](#70)  
[__::math::statistics::pdf\-negative\-binomial__ *r* *p* *value*](#71)  
[__::math::statistics::cdf\-normal__ *mean* *stdev* *value*](#72)  
[__::math::statistics::cdf\-lognormal__ *mean* *stdev* *value*](#73)  
[__::math::statistics::cdf\-exponential__ *mean* *value*](#74)  
[__::math::statistics::cdf\-uniform__ *xmin* *xmax* *value*](#75)  
[__::math::statistics::cdf\-triangular__ *xmin* *xmax* *value*](#76)  
[__::math::statistics::cdf\-symmetric\-triangular__ *xmin* *xmax* *value*](#77)  
[__::math::statistics::cdf\-students\-t__ *degrees* *value*](#78)  
[__::math::statistics::cdf\-gamma__ *alpha* *beta* *value*](#79)  
[__::math::statistics::cdf\-poisson__ *mu* *k*](#80)  
[__::math::statistics::cdf\-beta__ *a* *b* *value*](#81)  
[__::math::statistics::cdf\-weibull__ *scale* *shape* *value*](#82)  
[__::math::statistics::cdf\-gumbel__ *location* *scale* *value*](#83)  
[__::math::statistics::cdf\-pareto__ *scale* *shape* *value*](#84)  
[__::math::statistics::cdf\-cauchy__ *location* *scale* *value*](#85)  
[__::math::statistics::cdf\-F__ *nf1* *nf2* *value*](#86)  
[__::math::statistics::cdf\-laplace__ *location* *scale* *value*](#87)  
[__::math::statistics::cdf\-kumaraswamy__ *a* *b* *value*](#88)  
[__::math::statistics::cdf\-negative\-binomial__ *r* *p* *value*](#89)  
[__::math::statistics::empirical\-distribution__ *values*](#90)  
[__::math::statistics::random\-normal__ *mean* *stdev* *number*](#91)  
[__::math::statistics::random\-lognormal__ *mean* *stdev* *number*](#92)  
[__::math::statistics::random\-exponential__ *mean* *number*](#93)  
[__::math::statistics::random\-uniform__ *xmin* *xmax* *number*](#94)  
[__::math::statistics::random\-triangular__ *xmin* *xmax* *number*](#95)  
[__::math::statistics::random\-symmetric\-triangular__ *xmin* *xmax* *number*](#96)  
[__::math::statistics::random\-gamma__ *alpha* *beta* *number*](#97)  
[__::math::statistics::random\-poisson__ *mu* *number*](#98)  
[__::math::statistics::random\-chisquare__ *df* *number*](#99)  
[__::math::statistics::random\-student\-t__ *df* *number*](#100)  
[__::math::statistics::random\-beta__ *a* *b* *number*](#101)  
[__::math::statistics::random\-weibull__ *scale* *shape* *number*](#102)  
[__::math::statistics::random\-gumbel__ *location* *scale* *number*](#103)  
[__::math::statistics::random\-pareto__ *scale* *shape* *number*](#104)  
[__::math::statistics::random\-cauchy__ *location* *scale* *number*](#105)  
[__::math::statistics::random\-laplace__ *location* *scale* *number*](#106)  
[__::math::statistics::random\-kumaraswamy__ *a* *b* *number*](#107)  
[__::math::statistics::random\-negative\-binomial__ *r* *p* *number*](#108)  
[__::math::statistics::histogram\-uniform__ *xmin* *xmax* *limits* *number*](#109)  
[__::math::statistics::incompleteGamma__ *x* *p* ?tol?](#110)  
[__::math::statistics::incompleteBeta__ *a* *b* *x* ?tol?](#111)  
[__::math::statistics::estimate\-pareto__ *values*](#112)  
[__::math::statistics::estimate\-exponential__ *values*](#113)  
[__::math::statistics::estimate\-laplace__ *values*](#114)  
[__::math::statistics::estimante\-negative\-binomial__ *r* *values*](#115)  
[__::math::statistics::filter__ *varname* *data* *expression*](#116)  
[__::math::statistics::map__ *varname* *data* *expression*](#117)  
[__::math::statistics::samplescount__ *varname* *list* *expression*](#118)  
[__::math::statistics::subdivide__](#119)  
[__::math::statistics::plot\-scale__ *canvas* *xmin* *xmax* *ymin* *ymax*](#120)  
[__::math::statistics::plot\-xydata__ *canvas* *xdata* *ydata* *tag*](#121)  
[__::math::statistics::plot\-xyline__ *canvas* *xdata* *ydata* *tag*](#122)  
[__::math::statistics::plot\-tdata__ *canvas* *tdata* *tag*](#123)  
[__::math::statistics::plot\-tline__ *canvas* *tdata* *tag*](#124)  
[__::math::statistics::plot\-histogram__ *canvas* *counts* *limits* *tag*](#125)  

# <a name='description'></a>DESCRIPTION

The __math::statistics__ package contains functions and procedures for basic
statistical data analysis, such as:

  - Descriptive statistical parameters \(mean, minimum, maximum, standard
430
431
432
433
434
435
436
437
438

439
440

441
442
443
444
445
446
447
448
    are\. This is a one\-way ANOVA test\. The groups may also be stored in a nested
    list: The procedure returns a list of the comparison results for each pair
    of groups\. Each element of this list contains: the index of the first group
    and that of the second group, whether the means are likely to be different
    \(1\) or not \(0\) and the confidence interval the conclusion is based on\. The
    groups may also be stored in a nested list:

        test\-anova\-F 0\.05 $A $B $C
        \#

        \# Or equivalently:
        \#

        test\-anova\-F 0\.05 \[list $A $B $C\]

      * float *alpha*

        \- Significance level

      * list *args*








|
<
>
|
<
>
|







450
451
452
453
454
455
456
457

458
459

460
461
462
463
464
465
466
467
468
    are\. This is a one\-way ANOVA test\. The groups may also be stored in a nested
    list: The procedure returns a list of the comparison results for each pair
    of groups\. Each element of this list contains: the index of the first group
    and that of the second group, whether the means are likely to be different
    \(1\) or not \(0\) and the confidence interval the conclusion is based on\. The
    groups may also be stored in a nested list:

        test-anova-F 0.05 $A $B $C

        #
        # Or equivalently:

        #
        test-anova-F 0.05 [list $A $B $C]

      * float *alpha*

        \- Significance level

      * list *args*

475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
    this list contains: whether the means are likely to be different \(1\) or not
    \(0\) and the confidence interval the conclusion is based on\. The groups may
    also be stored in a nested list, just as with the ANOVA test\.

    Note: some care is required if there is only one group to compare the
    control with:

        test\-Dunnett\-F 0\.05 $control \[list $A\]

    Otherwise the group A is split up into groups of one element \- this is due
    to an ambiguity\.

      * float *alpha*

        \- Significance level \- either 0\.05 or 0\.01







|







495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
    this list contains: whether the means are likely to be different \(1\) or not
    \(0\) and the confidence interval the conclusion is based on\. The groups may
    also be stored in a nested list, just as with the ANOVA test\.

    Note: some care is required if there is only one group to compare the
    control with:

        test-Dunnett-F 0.05 $control [list $A]

    Otherwise the group A is split up into groups of one element \- this is due
    to an ambiguity\.

      * float *alpha*

        \- Significance level \- either 0\.05 or 0\.01
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
    Kruskal\-Wallis statistic and the probability that that value would occur
    assuming the medians of the populations are equal\.

      * list *args*

        \- Two or more lists of data

  - <a name='38'></a>__::math::statistics::group\-rank__ *args*
























    Rank the groups of data with respect to the complete set\. Returns a list
    consisting of the group ID, the value and the rank \(possibly a rational
    number, in case of ties\) for each data item\.

      * list *args*

        \- Two or more lists of data

  - <a name='39'></a>__::math::statistics::test\-Wilcoxon__ *sample\_a* *sample\_b*

    Compute the Wilcoxon test statistic to determine if two samples have the
    same median or not\. \(The statistic can be regarded as standard normal, if
    the sample sizes are both larger than 10\. Returns the value of this
    statistic\.

      * list *sample\_a*

        \- List of data comprising the first sample

      * list *sample\_b*

        \- List of data comprising the second sample

  - <a name='40'></a>__::math::statistics::spearman\-rank__ *sample\_a* *sample\_b*

    Return the Spearman rank correlation as an alternative to the ordinary
    \(Pearson's\) correlation coefficient\. The two samples should have the same
    number of data\.

      * list *sample\_a*

        \- First list of data

      * list *sample\_b*

        \- Second list of data

  - <a name='41'></a>__::math::statistics::spearman\-rank\-extended__ *sample\_a* *sample\_b*

    Return the Spearman rank correlation as an alternative to the ordinary
    \(Pearson's\) correlation coefficient as well as additional data\. The two
    samples should have the same number of data\. The procedure returns the
    correlation coefficient, the number of data pairs used and the z\-score, an
    approximately standard normal statistic, indicating the significance of the
    correlation\.

      * list *sample\_a*

        \- First list of data

      * list *sample\_b*

        \- Second list of data

  - <a name='42'></a>__::math::statistics::kernel\-density__ *data* opt *\-option value* \.\.\.

    Return the density function based on kernel density estimation\. The
    procedure is controlled by a small set of options, each of which is given a
    reasonable default\.

    The return value consists of three lists: the centres of the bins, the
    associated probability density and a list of computational parameters \(begin







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









|



|










|













|
















|







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
    Kruskal\-Wallis statistic and the probability that that value would occur
    assuming the medians of the populations are equal\.

      * list *args*

        \- Two or more lists of data

  - <a name='38'></a>__::math::statistics::test\-Levene__ *groups*

    Compute the Levene statistic to determine if groups of data have the same
    variance \(are homoscadastic\) or not\. The data are organised in groups\. This
    version uses the mean of the data as the measure to determine the
    deviations\. The statistic is equivalent to an F statistic with degrees of
    freedom k\-1 and N\-k, k being the number of groups and N the total number of
    data\.

      * list *groups*

        \- List of groups of data

  - <a name='39'></a>__::math::statistics::test\-Brown\-Forsythe__ *groups*

    Compute the Brown\-Forsythe statistic to determine if groups of data have the
    same variance \(are homoscadastic\) or not\. Like the Levene test, but this
    version uses the median of the data\.

      * list *groups*

        \- List of groups of data

  - <a name='40'></a>__::math::statistics::group\-rank__ *args*

    Rank the groups of data with respect to the complete set\. Returns a list
    consisting of the group ID, the value and the rank \(possibly a rational
    number, in case of ties\) for each data item\.

      * list *args*

        \- Two or more lists of data

  - <a name='41'></a>__::math::statistics::test\-Wilcoxon__ *sample\_a* *sample\_b*

    Compute the Wilcoxon test statistic to determine if two samples have the
    same median or not\. \(The statistic can be regarded as standard normal, if
    the sample sizes are both larger than 10\.\) Returns the value of this
    statistic\.

      * list *sample\_a*

        \- List of data comprising the first sample

      * list *sample\_b*

        \- List of data comprising the second sample

  - <a name='42'></a>__::math::statistics::spearman\-rank__ *sample\_a* *sample\_b*

    Return the Spearman rank correlation as an alternative to the ordinary
    \(Pearson's\) correlation coefficient\. The two samples should have the same
    number of data\.

      * list *sample\_a*

        \- First list of data

      * list *sample\_b*

        \- Second list of data

  - <a name='43'></a>__::math::statistics::spearman\-rank\-extended__ *sample\_a* *sample\_b*

    Return the Spearman rank correlation as an alternative to the ordinary
    \(Pearson's\) correlation coefficient as well as additional data\. The two
    samples should have the same number of data\. The procedure returns the
    correlation coefficient, the number of data pairs used and the z\-score, an
    approximately standard normal statistic, indicating the significance of the
    correlation\.

      * list *sample\_a*

        \- First list of data

      * list *sample\_b*

        \- Second list of data

  - <a name='44'></a>__::math::statistics::kernel\-density__ *data* opt *\-option value* \.\.\.

    Return the density function based on kernel density estimation\. The
    procedure is controlled by a small set of options, each of which is given a
    reasonable default\.

    The return value consists of three lists: the centres of the bins, the
    associated probability density and a list of computational parameters \(begin
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
            \(default: mean \+/\- 3\*standard deviation\)

          + __\-kernel__ *function*

            Kernel to be used \(One of: gaussian, cosine, epanechnikov, uniform,
            triangular, biweight, logistic; default: gaussian\)

  - <a name='43'></a>__::math::statistics::bootstrap__ *data* *sampleSize* ?numberSamples?

    Create a subsample or subsamples from a given list of data\. The data in the
    samples are chosen from this list \- multiples may occur\. If there is only
    one subsample, the sample itself is returned \(as a list of "sampleSize"
    values\), otherwise a list of samples is returned\.

      * list *data*

        List of values to chose from

      * int *sampleSize*

        Number of values per sample

      * int *numberSamples*

        Number of samples \(default: 1\)

  - <a name='44'></a>__::math::statistics::wasserstein\-distance__ *prob1* *prob2*

    Compute the Wasserstein distance or earth mover's distance for two
    equidstantly spaced histograms or probability densities\. The histograms need
    not to be normalised to sum to one, but they must have the same number of
    entries\.

    Note: the histograms are assumed to be based on the same equidistant
    intervals\. As the bounds are not passed, the value is expressed in the
    length of the intervals\.

      * list *prob1*

        List of values for the first histogram/probability density

      * list *prob2*

        List of values for the second histogram/probability density

  - <a name='45'></a>__::math::statistics::kl\-divergence__ *prob1* *prob2*

    Compute the Kullback\-Leibler \(KL\) divergence for two equidstantly spaced
    histograms or probability densities\. The histograms need not to be
    normalised to sum to one, but they must have the same number of entries\.

    Note: the histograms are assumed to be based on the same equidistant
    intervals\. As the bounds are not passed, the value is expressed in the







|


















|


















|







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
            \(default: mean \+/\- 3\*standard deviation\)

          + __\-kernel__ *function*

            Kernel to be used \(One of: gaussian, cosine, epanechnikov, uniform,
            triangular, biweight, logistic; default: gaussian\)

  - <a name='45'></a>__::math::statistics::bootstrap__ *data* *sampleSize* ?numberSamples?

    Create a subsample or subsamples from a given list of data\. The data in the
    samples are chosen from this list \- multiples may occur\. If there is only
    one subsample, the sample itself is returned \(as a list of "sampleSize"
    values\), otherwise a list of samples is returned\.

      * list *data*

        List of values to chose from

      * int *sampleSize*

        Number of values per sample

      * int *numberSamples*

        Number of samples \(default: 1\)

  - <a name='46'></a>__::math::statistics::wasserstein\-distance__ *prob1* *prob2*

    Compute the Wasserstein distance or earth mover's distance for two
    equidstantly spaced histograms or probability densities\. The histograms need
    not to be normalised to sum to one, but they must have the same number of
    entries\.

    Note: the histograms are assumed to be based on the same equidistant
    intervals\. As the bounds are not passed, the value is expressed in the
    length of the intervals\.

      * list *prob1*

        List of values for the first histogram/probability density

      * list *prob2*

        List of values for the second histogram/probability density

  - <a name='47'></a>__::math::statistics::kl\-divergence__ *prob1* *prob2*

    Compute the Kullback\-Leibler \(KL\) divergence for two equidstantly spaced
    histograms or probability densities\. The histograms need not to be
    normalised to sum to one, but they must have the same number of entries\.

    Note: the histograms are assumed to be based on the same equidistant
    intervals\. As the bounds are not passed, the value is expressed in the
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

        List of values for the first histogram/probability density

      * list *prob2*

        List of values for the second histogram/probability density

  - <a name='46'></a>__::math::statistics::logistic\-model__ *xdata* *ydata*

    Estimate the coefficients of the logistic model that fits the data best\. The
    data consist of independent x\-values and the outcome 0 or 1 for each of the
    x\-values\. The result can be used to estimate the probability that a certain
    x\-value gives 1\.

      * list *xdata*

        List of values for which the success \(1\) or failure \(0\) is known

      * list *ydata*

        List of successes or failures corresponding to each value in *xdata*\.

  - <a name='47'></a>__::math::statistics::logistic\-probability__ *coeffs* *x*

    Calculate the probability of success for the value *x* given the
    coefficients of the logistic model\.

      * list *coeffs*

        List of coefficients as determine by the __logistic\-model__ command







|














|







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

        List of values for the first histogram/probability density

      * list *prob2*

        List of values for the second histogram/probability density

  - <a name='48'></a>__::math::statistics::logistic\-model__ *xdata* *ydata*

    Estimate the coefficients of the logistic model that fits the data best\. The
    data consist of independent x\-values and the outcome 0 or 1 for each of the
    x\-values\. The result can be used to estimate the probability that a certain
    x\-value gives 1\.

      * list *xdata*

        List of values for which the success \(1\) or failure \(0\) is known

      * list *ydata*

        List of successes or failures corresponding to each value in *xdata*\.

  - <a name='49'></a>__::math::statistics::logistic\-probability__ *coeffs* *x*

    Calculate the probability of success for the value *x* given the
    coefficients of the logistic model\.

      * list *coeffs*

        List of coefficients as determine by the __logistic\-model__ command
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
value of the t\-statistic for the specified number of degrees of freedom that is
required to demonstrate a given level of significance\.

Note: These procedures depend on the math::linearalgebra package\.

*Description of the procedures*

  - <a name='48'></a>__::math::statistics::tstat__ *dof* ?alpha?

    Returns the value of the t\-distribution t\* satisfying

        P\(t\*\)  =  1 \- alpha/2
        P\(\-t\*\) =  alpha/2

    for the number of degrees of freedom dof\.

    Given a sample of normally\-distributed data x, with an estimate xbar for the
    mean and sbar for the standard deviation, the alpha confidence interval for
    the estimate of the mean can be calculated as

        \( xbar \- t\* sbar , xbar \+ t\* sbar\)

    The return values from this procedure can be compared to an estimated
    t\-statistic to determine whether the estimated value of a parameter is
    significantly different from zero at the given confidence level\.

      * int *dof*

        Number of degrees of freedom

      * float *alpha*

        Confidence level of the t\-distribution\. Defaults to 0\.05\.

  - <a name='49'></a>__::math::statistics::mv\-wls__ *wt1* *weights\_and\_values*

    Carries out a weighted least squares linear regression for the data points
    provided, with weights assigned to each point\.

    The linear model is of the form

        y = b0 \+ b1 \* x1 \+ b2 \* x2 \.\.\. \+ bN \* xN \+ error

    and each point satisfies

        yi = b0 \+ b1 \* xi1 \+ b2 \* xi2 \+ \.\.\. \+ bN \* xiN \+ Residual\_i

    The procedure returns a list with the following elements:

      * The r\-squared statistic

      * The adjusted r\-squared statistic








|



|
|







|













|






|



|







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
value of the t\-statistic for the specified number of degrees of freedom that is
required to demonstrate a given level of significance\.

Note: These procedures depend on the math::linearalgebra package\.

*Description of the procedures*

  - <a name='50'></a>__::math::statistics::tstat__ *dof* ?alpha?

    Returns the value of the t\-distribution t\* satisfying

        P(t*)  =  1 - alpha/2
        P(-t*) =  alpha/2

    for the number of degrees of freedom dof\.

    Given a sample of normally\-distributed data x, with an estimate xbar for the
    mean and sbar for the standard deviation, the alpha confidence interval for
    the estimate of the mean can be calculated as

        ( xbar - t* sbar , xbar + t* sbar)

    The return values from this procedure can be compared to an estimated
    t\-statistic to determine whether the estimated value of a parameter is
    significantly different from zero at the given confidence level\.

      * int *dof*

        Number of degrees of freedom

      * float *alpha*

        Confidence level of the t\-distribution\. Defaults to 0\.05\.

  - <a name='51'></a>__::math::statistics::mv\-wls__ *wt1* *weights\_and\_values*

    Carries out a weighted least squares linear regression for the data points
    provided, with weights assigned to each point\.

    The linear model is of the form

        y = b0 + b1 * x1 + b2 * x2 ... + bN * xN + error

    and each point satisfies

        yi = b0 + b1 * xi1 + b2 * xi2 + ... + bN * xiN + Residual_i

    The procedure returns a list with the following elements:

      * The r\-squared statistic

      * The adjusted r\-squared statistic

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

        A list consisting of: the weight for the first observation, the data for
        the first observation \(as a sublist\), the weight for the second
        observation \(as a sublist\) and so on\. The sublists of data are organised
        as lists of the value of the dependent variable y and the independent
        variables x1, x2 to xN\.

  - <a name='50'></a>__::math::statistics::mv\-ols__ *values*

    Carries out an ordinary least squares linear regression for the data points
    provided\.

    This procedure simply calls ::mvlinreg::wls with the weights set to 1\.0, and
    returns the same information\.

*Example of the use:*

    \# Store the value of the unicode value for the "\+/\-" character
    set pm "\\u00B1"

    \# Provide some data
    set data \{\{  \-\.67  14\.18  60\.03 \-7\.5  \}
              \{ 36\.97  15\.52  34\.24 14\.61 \}
              \{\-29\.57  21\.85  83\.36 \-7\.   \}
              \{\-16\.9   11\.79  51\.67 \-6\.56 \}
              \{ 14\.09  16\.24  36\.97 \-12\.84\}
              \{ 31\.52  20\.93  45\.99 \-25\.4 \}
              \{ 24\.05  20\.69  50\.27  17\.27\}
              \{ 22\.23  16\.91  45\.07  \-4\.3 \}
              \{ 40\.79  20\.49  38\.92  \-\.73 \}
              \{\-10\.35  17\.24  58\.77  18\.78\}\}

    \# Call the ols routine
    set results \[::math::statistics::mv\-ols $data\]

    \# Pretty\-print the results
    puts "R\-squared: \[lindex $results 0\]"
    puts "Adj R\-squared: \[lindex $results 1\]"
    puts "Coefficients $pm s\.e\. \-\- \\\[95% confidence interval\\\]:"
    foreach val \[lindex $results 2\] se \[lindex $results 3\] bounds \[lindex $results 4\] \{
        set lb \[lindex $bounds 0\]
        set ub \[lindex $bounds 1\]
        puts "   $val $pm $se \-\- \\\[$lb to $ub\\\]"
    \}


# <a name='section4'></a>STATISTICAL DISTRIBUTIONS

In the literature a large number of probability distributions can be found\. The
statistics package supports:

  - The normal or Gaussian distribution as well as the log\-normal distribution







|









|
|

|
|
|
|
|
|
|
|
|
|
|

|
|

|
|
|
|
|
|
|
|
<
>







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

        A list consisting of: the weight for the first observation, the data for
        the first observation \(as a sublist\), the weight for the second
        observation \(as a sublist\) and so on\. The sublists of data are organised
        as lists of the value of the dependent variable y and the independent
        variables x1, x2 to xN\.

  - <a name='52'></a>__::math::statistics::mv\-ols__ *values*

    Carries out an ordinary least squares linear regression for the data points
    provided\.

    This procedure simply calls ::mvlinreg::wls with the weights set to 1\.0, and
    returns the same information\.

*Example of the use:*

    # Store the value of the unicode value for the "+/-" character
    set pm "\u00B1"

    # Provide some data
    set data {{  -.67  14.18  60.03 -7.5  }
              { 36.97  15.52  34.24 14.61 }
              {-29.57  21.85  83.36 -7.   }
              {-16.9   11.79  51.67 -6.56 }
              { 14.09  16.24  36.97 -12.84}
              { 31.52  20.93  45.99 -25.4 }
              { 24.05  20.69  50.27  17.27}
              { 22.23  16.91  45.07  -4.3 }
              { 40.79  20.49  38.92  -.73 }
              {-10.35  17.24  58.77  18.78}}

    # Call the ols routine
    set results [::math::statistics::mv-ols $data]

    # Pretty-print the results
    puts "R-squared: [lindex $results 0]"
    puts "Adj R-squared: [lindex $results 1]"
    puts "Coefficients $pm s.e. -- \[95% confidence interval\]:"
    foreach val [lindex $results 2] se [lindex $results 3] bounds [lindex $results 4] {
        set lb [lindex $bounds 0]
        set ub [lindex $bounds 1]
        puts "   $val $pm $se -- \[$lb to $ub\]"

    }

# <a name='section4'></a>STATISTICAL DISTRIBUTIONS

In the literature a large number of probability distributions can be found\. The
statistics package supports:

  - The normal or Gaussian distribution as well as the log\-normal distribution
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
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783






















































1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853





































1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928

  - Histograms for the given distribution \(histogram\-\*\)

  - List of random values with the given distribution \(random\-\*\)

The following procedures have been implemented:

  - <a name='51'></a>__::math::statistics::pdf\-normal__ *mean* *stdev* *value*

    Return the probability of a given value for a normal distribution with given
    mean and standard deviation\.

      * float *mean*

        \- Mean value of the distribution

      * float *stdev*

        \- Standard deviation of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='52'></a>__::math::statistics::pdf\-lognormal__ *mean* *stdev* *value*

    Return the probability of a given value for a log\-normal distribution with
    given mean and standard deviation\.

      * float *mean*

        \- Mean value of the distribution

      * float *stdev*

        \- Standard deviation of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='53'></a>__::math::statistics::pdf\-exponential__ *mean* *value*

    Return the probability of a given value for an exponential distribution with
    given mean\.

      * float *mean*

        \- Mean value of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='54'></a>__::math::statistics::pdf\-uniform__ *xmin* *xmax* *value*

    Return the probability of a given value for a uniform distribution with
    given extremes\.

      * float *xmin*

        \- Minimum value of the distribution

      * float *xmin*

        \- Maximum value of the distribution

      * float *value*

        \- Value for which the probability is required






































  - <a name='55'></a>__::math::statistics::pdf\-gamma__ *alpha* *beta* *value*

    Return the probability of a given value for a Gamma distribution with given
    shape and rate parameters

      * float *alpha*

        \- Shape parameter

      * float *beta*

        \- Rate parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='56'></a>__::math::statistics::pdf\-poisson__ *mu* *k*

    Return the probability of a given number of occurrences in the same interval
    \(k\) for a Poisson distribution with given mean \(mu\)

      * float *mu*

        \- Mean number of occurrences

      * int *k*

        \- Number of occurences

  - <a name='57'></a>__::math::statistics::pdf\-chisquare__ *df* *value*

    Return the probability of a given value for a chi square distribution with
    given degrees of freedom

      * float *df*

        \- Degrees of freedom

      * float *value*

        \- Value for which the probability is required

  - <a name='58'></a>__::math::statistics::pdf\-student\-t__ *df* *value*

    Return the probability of a given value for a Student's t distribution with
    given degrees of freedom

      * float *df*

        \- Degrees of freedom

      * float *value*

        \- Value for which the probability is required

  - <a name='59'></a>__::math::statistics::pdf\-gamma__ *a* *b* *value*

    Return the probability of a given value for a Gamma distribution with given
    shape and rate parameters

      * float *a*

        \- Shape parameter

      * float *b*

        \- Rate parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='60'></a>__::math::statistics::pdf\-beta__ *a* *b* *value*

    Return the probability of a given value for a Beta distribution with given
    shape parameters

      * float *a*

        \- First shape parameter

      * float *b*

        \- Second shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='61'></a>__::math::statistics::pdf\-weibull__ *scale* *shape* *value*

    Return the probability of a given value for a Weibull distribution with
    given scale and shape parameters

      * float *location*

        \- Scale parameter

      * float *scale*

        \- Shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='62'></a>__::math::statistics::pdf\-gumbel__ *location* *scale* *value*

    Return the probability of a given value for a Gumbel distribution with given
    location and shape parameters

      * float *location*

        \- Location parameter

      * float *scale*

        \- Shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='63'></a>__::math::statistics::pdf\-pareto__ *scale* *shape* *value*

    Return the probability of a given value for a Pareto distribution with given
    scale and shape parameters

      * float *scale*

        \- Scale parameter

      * float *shape*

        \- Shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='64'></a>__::math::statistics::pdf\-cauchy__ *location* *scale* *value*

    Return the probability of a given value for a Cauchy distribution with given
    location and shape parameters\. Note that the Cauchy distribution has no
    finite higher\-order moments\.

      * float *location*

        \- Location parameter

      * float *scale*

        \- Shape parameter

      * float *value*

        \- Value for which the probability is required























































  - <a name='65'></a>__::math::statistics::cdf\-normal__ *mean* *stdev* *value*

    Return the cumulative probability of a given value for a normal distribution
    with given mean and standard deviation, that is the probability for values
    up to the given one\.

      * float *mean*

        \- Mean value of the distribution

      * float *stdev*

        \- Standard deviation of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='66'></a>__::math::statistics::cdf\-lognormal__ *mean* *stdev* *value*

    Return the cumulative probability of a given value for a log\-normal
    distribution with given mean and standard deviation, that is the probability
    for values up to the given one\.

      * float *mean*

        \- Mean value of the distribution

      * float *stdev*

        \- Standard deviation of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='67'></a>__::math::statistics::cdf\-exponential__ *mean* *value*

    Return the cumulative probability of a given value for an exponential
    distribution with given mean\.

      * float *mean*

        \- Mean value of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='68'></a>__::math::statistics::cdf\-uniform__ *xmin* *xmax* *value*

    Return the cumulative probability of a given value for a uniform
    distribution with given extremes\.

      * float *xmin*

        \- Minimum value of the distribution

      * float *xmin*

        \- Maximum value of the distribution

      * float *value*

        \- Value for which the probability is required




































  - <a name='69'></a>__::math::statistics::cdf\-students\-t__ *degrees* *value*

    Return the cumulative probability of a given value for a Student's t
    distribution with given number of degrees\.

      * int *degrees*

        \- Number of degrees of freedom

      * float *value*

        \- Value for which the probability is required

  - <a name='70'></a>__::math::statistics::cdf\-gamma__ *alpha* *beta* *value*

    Return the cumulative probability of a given value for a Gamma distribution
    with given shape and rate parameters\.

      * float *alpha*

        \- Shape parameter

      * float *beta*

        \- Rate parameter

      * float *value*

        \- Value for which the cumulative probability is required

  - <a name='71'></a>__::math::statistics::cdf\-poisson__ *mu* *k*

    Return the cumulative probability of a given number of occurrences in the
    same interval \(k\) for a Poisson distribution with given mean \(mu\)\.

      * float *mu*

        \- Mean number of occurrences

      * int *k*

        \- Number of occurences

  - <a name='72'></a>__::math::statistics::cdf\-beta__ *a* *b* *value*

    Return the cumulative probability of a given value for a Beta distribution
    with given shape parameters

      * float *a*

        \- First shape parameter

      * float *b*

        \- Second shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='73'></a>__::math::statistics::cdf\-weibull__ *scale* *shape* *value*

    Return the cumulative probability of a given value for a Weibull
    distribution with given scale and shape parameters\.

      * float *scale*

        \- Scale parameter

      * float *shape*

        \- Shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='74'></a>__::math::statistics::cdf\-gumbel__ *location* *scale* *value*

    Return the cumulative probability of a given value for a Gumbel distribution
    with given location and scale parameters\.

      * float *location*

        \- Location parameter

      * float *scale*

        \- Scale parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='75'></a>__::math::statistics::cdf\-pareto__ *scale* *shape* *value*

    Return the cumulative probability of a given value for a Pareto distribution
    with given scale and shape parameters

      * float *scale*

        \- Scale parameter

      * float *shape*

        \- Shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='76'></a>__::math::statistics::cdf\-cauchy__ *location* *scale* *value*

    Return the cumulative probability of a given value for a Cauchy distribution
    with given location and scale parameters\.

      * float *location*

        \- Location parameter

      * float *scale*

        \- Scale parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='77'></a>__::math::statistics::cdf\-F__ *nf1* *nf2* *value*

    Return the cumulative probability of a given value for an F distribution
    with nf1 and nf2 degrees of freedom\.

      * float *nf1*

        \- Degrees of freedom for the numerator

      * float *nf2*

        \- Degrees of freedom for the denominator

      * float *value*

        \- Value for which the probability is required

























































  - <a name='78'></a>__::math::statistics::empirical\-distribution__ *values*

    Return a list of values and their empirical probability\. The values are
    sorted in increasing order\. \(The implementation follows the description at
    the corresponding Wikipedia page\)

      * list *values*

        \- List of data to be examined

  - <a name='79'></a>__::math::statistics::random\-normal__ *mean* *stdev* *number*

    Return a list of "number" random values satisfying a normal distribution
    with given mean and standard deviation\.

      * float *mean*

        \- Mean value of the distribution

      * float *stdev*

        \- Standard deviation of the distribution

      * int *number*

        \- Number of values to be returned

  - <a name='80'></a>__::math::statistics::random\-lognormal__ *mean* *stdev* *number*

    Return a list of "number" random values satisfying a log\-normal distribution
    with given mean and standard deviation\.

      * float *mean*

        \- Mean value of the distribution

      * float *stdev*

        \- Standard deviation of the distribution

      * int *number*

        \- Number of values to be returned

  - <a name='81'></a>__::math::statistics::random\-exponential__ *mean* *number*

    Return a list of "number" random values satisfying an exponential
    distribution with given mean\.

      * float *mean*

        \- Mean value of the distribution

      * int *number*

        \- Number of values to be returned

  - <a name='82'></a>__::math::statistics::random\-uniform__ *xmin* *xmax* *number*

    Return a list of "number" random values satisfying a uniform distribution
    with given extremes\.

      * float *xmin*

        \- Minimum value of the distribution

      * float *xmax*

        \- Maximum value of the distribution

      * int *number*

        \- Number of values to be returned




































  - <a name='83'></a>__::math::statistics::random\-gamma__ *alpha* *beta* *number*

    Return a list of "number" random values satisfying a Gamma distribution with
    given shape and rate parameters\.

      * float *alpha*

        \- Shape parameter

      * float *beta*

        \- Rate parameter

      * int *number*

        \- Number of values to be returned

  - <a name='84'></a>__::math::statistics::random\-poisson__ *mu* *number*

    Return a list of "number" random values satisfying a Poisson distribution
    with given mean\.

      * float *mu*

        \- Mean of the distribution

      * int *number*

        \- Number of values to be returned

  - <a name='85'></a>__::math::statistics::random\-chisquare__ *df* *number*

    Return a list of "number" random values satisfying a chi square distribution
    with given degrees of freedom\.

      * float *df*

        \- Degrees of freedom

      * int *number*

        \- Number of values to be returned

  - <a name='86'></a>__::math::statistics::random\-student\-t__ *df* *number*

    Return a list of "number" random values satisfying a Student's t
    distribution with given degrees of freedom\.

      * float *df*

        \- Degrees of freedom

      * int *number*

        \- Number of values to be returned

  - <a name='87'></a>__::math::statistics::random\-beta__ *a* *b* *number*

    Return a list of "number" random values satisfying a Beta distribution with
    given shape parameters\.

      * float *a*

        \- First shape parameter

      * float *b*

        \- Second shape parameter

      * int *number*

        \- Number of values to be returned

  - <a name='88'></a>__::math::statistics::random\-weibull__ *scale* *shape* *number*

    Return a list of "number" random values satisfying a Weibull distribution
    with given scale and shape parameters\.

      * float *scale*

        \- Scale parameter

      * float *shape*

        \- Shape parameter

      * int *number*

        \- Number of values to be returned

  - <a name='89'></a>__::math::statistics::random\-gumbel__ *location* *scale* *number*

    Return a list of "number" random values satisfying a Gumbel distribution
    with given location and scale parameters\.

      * float *location*

        \- Location parameter

      * float *scale*

        \- Scale parameter

      * int *number*

        \- Number of values to be returned

  - <a name='90'></a>__::math::statistics::random\-pareto__ *scale* *shape* *number*

    Return a list of "number" random values satisfying a Pareto distribution
    with given scale and shape parameters\.

      * float *scale*

        \- Scale parameter

      * float *shape*

        \- Shape parameter

      * int *number*

        \- Number of values to be returned

  - <a name='91'></a>__::math::statistics::random\-cauchy__ *location* *scale* *number*

    Return a list of "number" random values satisfying a Cauchy distribution
    with given location and scale parameters\.

      * float *location*

        \- Location parameter

      * float *scale*

        \- Scale parameter

      * int *number*

        \- Number of values to be returned























































  - <a name='92'></a>__::math::statistics::histogram\-uniform__ *xmin* *xmax* *limits* *number*

    Return the expected histogram for a uniform distribution\.

      * float *xmin*

        \- Minimum value of the distribution

      * float *xmax*

        \- Maximum value of the distribution

      * list *limits*

        \- Upper limits for the buckets in the histogram

      * int *number*

        \- Total number of "observations" in the histogram

  - <a name='93'></a>__::math::statistics::incompleteGamma__ *x* *p* ?tol?

    Evaluate the incomplete Gamma integral

                  1       / x               p\-1
    P\(p,x\) =  \-\-\-\-\-\-\-\-   &#124;   dt exp\(\-t\) \* t
              Gamma\(p\)  / 0

      * float *x*

        \- Value of x \(limit of the integral\)

      * float *p*

        \- Value of p in the integrand

      * float *tol*

        \- Required tolerance \(default: 1\.0e\-9\)

  - <a name='94'></a>__::math::statistics::incompleteBeta__ *a* *b* *x* ?tol?

    Evaluate the incomplete Beta integral

      * float *a*

        \- First shape parameter

      * float *b*

        \- Second shape parameter

      * float *x*

        \- Value of x \(limit of the integral\)

      * float *tol*

        \- Required tolerance \(default: 1\.0e\-9\)

  - <a name='95'></a>__::math::statistics::estimate\-pareto__ *values*

    Estimate the parameters for the Pareto distribution that comes closest to
    the given values\. Returns the estimated scale and shape parameters, as well
    as the standard error for the shape parameter\.

      * list *values*

        \- List of values, assumed to be distributed according to a Pareto
        distribution






































TO DO: more function descriptions to be added

# <a name='section5'></a>DATA MANIPULATION

The data manipulation procedures act on lists or lists of lists:

  - <a name='96'></a>__::math::statistics::filter__ *varname* *data* *expression*

    Return a list consisting of the data for which the logical expression is
    true \(this command works analogously to the command
    __[foreach](\.\./\.\./\.\./\.\./index\.md\#foreach)__\)\.

      * string *varname*

        \- Name of the variable used in the expression

      * list *data*

        \- List of data

      * string *expression*

        \- Logical expression using the variable name

  - <a name='97'></a>__::math::statistics::map__ *varname* *data* *expression*

    Return a list consisting of the data that are transformed via the
    expression\.

      * string *varname*

        \- Name of the variable used in the expression

      * list *data*

        \- List of data

      * string *expression*

        \- Expression to be used to transform \(map\) the data

  - <a name='98'></a>__::math::statistics::samplescount__ *varname* *list* *expression*

    Return a list consisting of the *counts* of all data in the sublists of
    the "list" argument for which the expression is true\.

      * string *varname*

        \- Name of the variable used in the expression

      * list *data*

        \- List of sublists, each containing the data

      * string *expression*

        \- Logical expression to test the data \(defaults to "true"\)\.

  - <a name='99'></a>__::math::statistics::subdivide__

    Routine *PM* \- not implemented yet

# <a name='section6'></a>PLOT PROCEDURES

The following simple plotting procedures are available:

  - <a name='100'></a>__::math::statistics::plot\-scale__ *canvas* *xmin* *xmax* *ymin* *ymax*

    Set the scale for a plot in the given canvas\. All plot routines expect this
    function to be called first\. There is no automatic scaling provided\.

      * widget *canvas*

        \- Canvas widget to use







|
















|
















|












|
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
















|












|












|












|
















|
















|
















|
















|
















|

















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

















|

















|












|
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|












|
















|












|
















|
















|
















|
















|
















|
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|









|
















|
















|












|
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
















|












|












|












|
















|
















|
















|
















|
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|



















|



|
|
|













|



















|









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|

















|
















|
















|







|







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
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279

  - Histograms for the given distribution \(histogram\-\*\)

  - List of random values with the given distribution \(random\-\*\)

The following procedures have been implemented:

  - <a name='53'></a>__::math::statistics::pdf\-normal__ *mean* *stdev* *value*

    Return the probability of a given value for a normal distribution with given
    mean and standard deviation\.

      * float *mean*

        \- Mean value of the distribution

      * float *stdev*

        \- Standard deviation of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='54'></a>__::math::statistics::pdf\-lognormal__ *mean* *stdev* *value*

    Return the probability of a given value for a log\-normal distribution with
    given mean and standard deviation\.

      * float *mean*

        \- Mean value of the distribution

      * float *stdev*

        \- Standard deviation of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='55'></a>__::math::statistics::pdf\-exponential__ *mean* *value*

    Return the probability of a given value for an exponential distribution with
    given mean\.

      * float *mean*

        \- Mean value of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='56'></a>__::math::statistics::pdf\-uniform__ *xmin* *xmax* *value*

    Return the probability of a given value for a uniform distribution with
    given extremes\.

      * float *xmin*

        \- Minimum value of the distribution

      * float *xmin*

        \- Maximum value of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='57'></a>__::math::statistics::pdf\-triangular__ *xmin* *xmax* *value*

    Return the probability of a given value for a triangular distribution with
    given extremes\. If the argument min is lower than the argument max, then
    smaller values have higher probability and vice versa\. In the first case the
    probability density function is of the form *f\(x\) = 2\(1\-x\)* and the other
    case it is of the form *f\(x\) = 2x*\.

      * float *xmin*

        \- Minimum value of the distribution

      * float *xmin*

        \- Maximum value of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='58'></a>__::math::statistics::pdf\-symmetric\-triangular__ *xmin* *xmax* *value*

    Return the probability of a given value for a symmetric triangular
    distribution with given extremes\.

      * float *xmin*

        \- Minimum value of the distribution

      * float *xmin*

        \- Maximum value of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='59'></a>__::math::statistics::pdf\-gamma__ *alpha* *beta* *value*

    Return the probability of a given value for a Gamma distribution with given
    shape and rate parameters

      * float *alpha*

        \- Shape parameter

      * float *beta*

        \- Rate parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='60'></a>__::math::statistics::pdf\-poisson__ *mu* *k*

    Return the probability of a given number of occurrences in the same interval
    \(k\) for a Poisson distribution with given mean \(mu\)

      * float *mu*

        \- Mean number of occurrences

      * int *k*

        \- Number of occurences

  - <a name='61'></a>__::math::statistics::pdf\-chisquare__ *df* *value*

    Return the probability of a given value for a chi square distribution with
    given degrees of freedom

      * float *df*

        \- Degrees of freedom

      * float *value*

        \- Value for which the probability is required

  - <a name='62'></a>__::math::statistics::pdf\-student\-t__ *df* *value*

    Return the probability of a given value for a Student's t distribution with
    given degrees of freedom

      * float *df*

        \- Degrees of freedom

      * float *value*

        \- Value for which the probability is required

  - <a name='63'></a>__::math::statistics::pdf\-gamma__ *a* *b* *value*

    Return the probability of a given value for a Gamma distribution with given
    shape and rate parameters

      * float *a*

        \- Shape parameter

      * float *b*

        \- Rate parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='64'></a>__::math::statistics::pdf\-beta__ *a* *b* *value*

    Return the probability of a given value for a Beta distribution with given
    shape parameters

      * float *a*

        \- First shape parameter

      * float *b*

        \- Second shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='65'></a>__::math::statistics::pdf\-weibull__ *scale* *shape* *value*

    Return the probability of a given value for a Weibull distribution with
    given scale and shape parameters

      * float *location*

        \- Scale parameter

      * float *scale*

        \- Shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='66'></a>__::math::statistics::pdf\-gumbel__ *location* *scale* *value*

    Return the probability of a given value for a Gumbel distribution with given
    location and shape parameters

      * float *location*

        \- Location parameter

      * float *scale*

        \- Shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='67'></a>__::math::statistics::pdf\-pareto__ *scale* *shape* *value*

    Return the probability of a given value for a Pareto distribution with given
    scale and shape parameters

      * float *scale*

        \- Scale parameter

      * float *shape*

        \- Shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='68'></a>__::math::statistics::pdf\-cauchy__ *location* *scale* *value*

    Return the probability of a given value for a Cauchy distribution with given
    location and shape parameters\. Note that the Cauchy distribution has no
    finite higher\-order moments\.

      * float *location*

        \- Location parameter

      * float *scale*

        \- Shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='69'></a>__::math::statistics::pdf\-laplace__ *location* *scale* *value*

    Return the probability of a given value for a Laplace distribution with
    given location and shape parameters\. The Laplace distribution consists of
    two exponential functions, is peaked and has heavier tails than the normal
    distribution\.

      * float *location*

        \- Location parameter \(mean\)

      * float *scale*

        \- Shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='70'></a>__::math::statistics::pdf\-kumaraswamy__ *a* *b* *value*

    Return the probability of a given value for a Kumaraswamy distribution with
    given parameters a and b\. The Kumaraswamy distribution is related to the
    Beta distribution, but has a tractable cumulative distribution function\.

      * float *a*

        \- Parameter a

      * float *b*

        \- Parameter b

      * float *value*

        \- Value for which the probability is required

  - <a name='71'></a>__::math::statistics::pdf\-negative\-binomial__ *r* *p* *value*

    Return the probability of a given value for a negative binomial distribution
    with an allowed number of failures and the probability of success\.

      * int *r*

        \- Allowed number of failures \(at least 1\)

      * float *p*

        \- Probability of success

      * int *value*

        \- Number of successes for which the probability is to be returned

  - <a name='72'></a>__::math::statistics::cdf\-normal__ *mean* *stdev* *value*

    Return the cumulative probability of a given value for a normal distribution
    with given mean and standard deviation, that is the probability for values
    up to the given one\.

      * float *mean*

        \- Mean value of the distribution

      * float *stdev*

        \- Standard deviation of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='73'></a>__::math::statistics::cdf\-lognormal__ *mean* *stdev* *value*

    Return the cumulative probability of a given value for a log\-normal
    distribution with given mean and standard deviation, that is the probability
    for values up to the given one\.

      * float *mean*

        \- Mean value of the distribution

      * float *stdev*

        \- Standard deviation of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='74'></a>__::math::statistics::cdf\-exponential__ *mean* *value*

    Return the cumulative probability of a given value for an exponential
    distribution with given mean\.

      * float *mean*

        \- Mean value of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='75'></a>__::math::statistics::cdf\-uniform__ *xmin* *xmax* *value*

    Return the cumulative probability of a given value for a uniform
    distribution with given extremes\.

      * float *xmin*

        \- Minimum value of the distribution

      * float *xmin*

        \- Maximum value of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='76'></a>__::math::statistics::cdf\-triangular__ *xmin* *xmax* *value*

    Return the cumulative probability of a given value for a triangular
    distribution with given extremes\. If xmin < xmax, then lower values have a
    higher probability and vice versa, see also *pdf\-triangular*

      * float *xmin*

        \- Minimum value of the distribution

      * float *xmin*

        \- Maximum value of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='77'></a>__::math::statistics::cdf\-symmetric\-triangular__ *xmin* *xmax* *value*

    Return the cumulative probability of a given value for a symmetric
    triangular distribution with given extremes\.

      * float *xmin*

        \- Minimum value of the distribution

      * float *xmin*

        \- Maximum value of the distribution

      * float *value*

        \- Value for which the probability is required

  - <a name='78'></a>__::math::statistics::cdf\-students\-t__ *degrees* *value*

    Return the cumulative probability of a given value for a Student's t
    distribution with given number of degrees\.

      * int *degrees*

        \- Number of degrees of freedom

      * float *value*

        \- Value for which the probability is required

  - <a name='79'></a>__::math::statistics::cdf\-gamma__ *alpha* *beta* *value*

    Return the cumulative probability of a given value for a Gamma distribution
    with given shape and rate parameters\.

      * float *alpha*

        \- Shape parameter

      * float *beta*

        \- Rate parameter

      * float *value*

        \- Value for which the cumulative probability is required

  - <a name='80'></a>__::math::statistics::cdf\-poisson__ *mu* *k*

    Return the cumulative probability of a given number of occurrences in the
    same interval \(k\) for a Poisson distribution with given mean \(mu\)\.

      * float *mu*

        \- Mean number of occurrences

      * int *k*

        \- Number of occurences

  - <a name='81'></a>__::math::statistics::cdf\-beta__ *a* *b* *value*

    Return the cumulative probability of a given value for a Beta distribution
    with given shape parameters

      * float *a*

        \- First shape parameter

      * float *b*

        \- Second shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='82'></a>__::math::statistics::cdf\-weibull__ *scale* *shape* *value*

    Return the cumulative probability of a given value for a Weibull
    distribution with given scale and shape parameters\.

      * float *scale*

        \- Scale parameter

      * float *shape*

        \- Shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='83'></a>__::math::statistics::cdf\-gumbel__ *location* *scale* *value*

    Return the cumulative probability of a given value for a Gumbel distribution
    with given location and scale parameters\.

      * float *location*

        \- Location parameter

      * float *scale*

        \- Scale parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='84'></a>__::math::statistics::cdf\-pareto__ *scale* *shape* *value*

    Return the cumulative probability of a given value for a Pareto distribution
    with given scale and shape parameters

      * float *scale*

        \- Scale parameter

      * float *shape*

        \- Shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='85'></a>__::math::statistics::cdf\-cauchy__ *location* *scale* *value*

    Return the cumulative probability of a given value for a Cauchy distribution
    with given location and scale parameters\.

      * float *location*

        \- Location parameter

      * float *scale*

        \- Scale parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='86'></a>__::math::statistics::cdf\-F__ *nf1* *nf2* *value*

    Return the cumulative probability of a given value for an F distribution
    with nf1 and nf2 degrees of freedom\.

      * float *nf1*

        \- Degrees of freedom for the numerator

      * float *nf2*

        \- Degrees of freedom for the denominator

      * float *value*

        \- Value for which the probability is required

  - <a name='87'></a>__::math::statistics::cdf\-laplace__ *location* *scale* *value*

    Return the cumulative probability of a given value for a Laplace
    distribution with given location and shape parameters\. The Laplace
    distribution consists of two exponential functions, is peaked and has
    heavier tails than the normal distribution\.

      * float *location*

        \- Location parameter \(mean\)

      * float *scale*

        \- Shape parameter

      * float *value*

        \- Value for which the probability is required

  - <a name='88'></a>__::math::statistics::cdf\-kumaraswamy__ *a* *b* *value*

    Return the cumulative probability of a given value for a Kumaraswamy
    distribution with given parameters a and b\. The Kumaraswamy distribution is
    related to the Beta distribution, but has a tractable cumulative
    distribution function\.

      * float *a*

        \- Parameter a

      * float *b*

        \- Parameter b

      * float *value*

        \- Value for which the probability is required

  - <a name='89'></a>__::math::statistics::cdf\-negative\-binomial__ *r* *p* *value*

    Return the cumulative probability of a given value for a negative binomial
    distribution with an allowed number of failures and the probability of
    success\.

      * int *r*

        \- Allowed number of failures \(at least 1\)

      * float *p*

        \- Probability of success

      * int *value*

        \- Greatest number of successes

  - <a name='90'></a>__::math::statistics::empirical\-distribution__ *values*

    Return a list of values and their empirical probability\. The values are
    sorted in increasing order\. \(The implementation follows the description at
    the corresponding Wikipedia page\)

      * list *values*

        \- List of data to be examined

  - <a name='91'></a>__::math::statistics::random\-normal__ *mean* *stdev* *number*

    Return a list of "number" random values satisfying a normal distribution
    with given mean and standard deviation\.

      * float *mean*

        \- Mean value of the distribution

      * float *stdev*

        \- Standard deviation of the distribution

      * int *number*

        \- Number of values to be returned

  - <a name='92'></a>__::math::statistics::random\-lognormal__ *mean* *stdev* *number*

    Return a list of "number" random values satisfying a log\-normal distribution
    with given mean and standard deviation\.

      * float *mean*

        \- Mean value of the distribution

      * float *stdev*

        \- Standard deviation of the distribution

      * int *number*

        \- Number of values to be returned

  - <a name='93'></a>__::math::statistics::random\-exponential__ *mean* *number*

    Return a list of "number" random values satisfying an exponential
    distribution with given mean\.

      * float *mean*

        \- Mean value of the distribution

      * int *number*

        \- Number of values to be returned

  - <a name='94'></a>__::math::statistics::random\-uniform__ *xmin* *xmax* *number*

    Return a list of "number" random values satisfying a uniform distribution
    with given extremes\.

      * float *xmin*

        \- Minimum value of the distribution

      * float *xmax*

        \- Maximum value of the distribution

      * int *number*

        \- Number of values to be returned

  - <a name='95'></a>__::math::statistics::random\-triangular__ *xmin* *xmax* *number*

    Return a list of "number" random values satisfying a triangular distribution
    with given extremes\. If xmin < xmax, then lower values have a higher
    probability and vice versa \(see also *pdf\-triangular*\.

      * float *xmin*

        \- Minimum value of the distribution

      * float *xmax*

        \- Maximum value of the distribution

      * int *number*

        \- Number of values to be returned

  - <a name='96'></a>__::math::statistics::random\-symmetric\-triangular__ *xmin* *xmax* *number*

    Return a list of "number" random values satisfying a symmetric triangular
    distribution with given extremes\.

      * float *xmin*

        \- Minimum value of the distribution

      * float *xmax*

        \- Maximum value of the distribution

      * int *number*

        \- Number of values to be returned

  - <a name='97'></a>__::math::statistics::random\-gamma__ *alpha* *beta* *number*

    Return a list of "number" random values satisfying a Gamma distribution with
    given shape and rate parameters\.

      * float *alpha*

        \- Shape parameter

      * float *beta*

        \- Rate parameter

      * int *number*

        \- Number of values to be returned

  - <a name='98'></a>__::math::statistics::random\-poisson__ *mu* *number*

    Return a list of "number" random values satisfying a Poisson distribution
    with given mean\.

      * float *mu*

        \- Mean of the distribution

      * int *number*

        \- Number of values to be returned

  - <a name='99'></a>__::math::statistics::random\-chisquare__ *df* *number*

    Return a list of "number" random values satisfying a chi square distribution
    with given degrees of freedom\.

      * float *df*

        \- Degrees of freedom

      * int *number*

        \- Number of values to be returned

  - <a name='100'></a>__::math::statistics::random\-student\-t__ *df* *number*

    Return a list of "number" random values satisfying a Student's t
    distribution with given degrees of freedom\.

      * float *df*

        \- Degrees of freedom

      * int *number*

        \- Number of values to be returned

  - <a name='101'></a>__::math::statistics::random\-beta__ *a* *b* *number*

    Return a list of "number" random values satisfying a Beta distribution with
    given shape parameters\.

      * float *a*

        \- First shape parameter

      * float *b*

        \- Second shape parameter

      * int *number*

        \- Number of values to be returned

  - <a name='102'></a>__::math::statistics::random\-weibull__ *scale* *shape* *number*

    Return a list of "number" random values satisfying a Weibull distribution
    with given scale and shape parameters\.

      * float *scale*

        \- Scale parameter

      * float *shape*

        \- Shape parameter

      * int *number*

        \- Number of values to be returned

  - <a name='103'></a>__::math::statistics::random\-gumbel__ *location* *scale* *number*

    Return a list of "number" random values satisfying a Gumbel distribution
    with given location and scale parameters\.

      * float *location*

        \- Location parameter

      * float *scale*

        \- Scale parameter

      * int *number*

        \- Number of values to be returned

  - <a name='104'></a>__::math::statistics::random\-pareto__ *scale* *shape* *number*

    Return a list of "number" random values satisfying a Pareto distribution
    with given scale and shape parameters\.

      * float *scale*

        \- Scale parameter

      * float *shape*

        \- Shape parameter

      * int *number*

        \- Number of values to be returned

  - <a name='105'></a>__::math::statistics::random\-cauchy__ *location* *scale* *number*

    Return a list of "number" random values satisfying a Cauchy distribution
    with given location and scale parameters\.

      * float *location*

        \- Location parameter

      * float *scale*

        \- Scale parameter

      * int *number*

        \- Number of values to be returned

  - <a name='106'></a>__::math::statistics::random\-laplace__ *location* *scale* *number*

    Return a list of "number" random values satisfying a Laplace distribution
    with given location and shape parameters\. The Laplace distribution consists
    of two exponential functions, is peaked and has heavier tails than the
    normal distribution\.

      * float *location*

        \- Location parameter \(mean\)

      * float *scale*

        \- Shape parameter

      * int *number*

        \- Number of values to be returned

  - <a name='107'></a>__::math::statistics::random\-kumaraswamy__ *a* *b* *number*

    Return a list of "number" random values satisying a Kumaraswamy distribution
    with given parameters a and b\. The Kumaraswamy distribution is related to
    the Beta distribution, but has a tractable cumulative distribution function\.

      * float *a*

        \- Parameter a

      * float *b*

        \- Parameter b

      * int *number*

        \- Number of values to be returned

  - <a name='108'></a>__::math::statistics::random\-negative\-binomial__ *r* *p* *number*

    Return a list of "number" random values satisying a negative binomial
    distribution\.

      * int *r*

        \- Allowed number of failures \(at least 1\)

      * float *p*

        \- Probability of success

      * int *number*

        \- Number of values to be returned

  - <a name='109'></a>__::math::statistics::histogram\-uniform__ *xmin* *xmax* *limits* *number*

    Return the expected histogram for a uniform distribution\.

      * float *xmin*

        \- Minimum value of the distribution

      * float *xmax*

        \- Maximum value of the distribution

      * list *limits*

        \- Upper limits for the buckets in the histogram

      * int *number*

        \- Total number of "observations" in the histogram

  - <a name='110'></a>__::math::statistics::incompleteGamma__ *x* *p* ?tol?

    Evaluate the incomplete Gamma integral

                  1       / x               p-1
    P(p,x) =  --------   |   dt exp(-t) * t
              Gamma(p)  / 0

      * float *x*

        \- Value of x \(limit of the integral\)

      * float *p*

        \- Value of p in the integrand

      * float *tol*

        \- Required tolerance \(default: 1\.0e\-9\)

  - <a name='111'></a>__::math::statistics::incompleteBeta__ *a* *b* *x* ?tol?

    Evaluate the incomplete Beta integral

      * float *a*

        \- First shape parameter

      * float *b*

        \- Second shape parameter

      * float *x*

        \- Value of x \(limit of the integral\)

      * float *tol*

        \- Required tolerance \(default: 1\.0e\-9\)

  - <a name='112'></a>__::math::statistics::estimate\-pareto__ *values*

    Estimate the parameters for the Pareto distribution that comes closest to
    the given values\. Returns the estimated scale and shape parameters, as well
    as the standard error for the shape parameter\.

      * list *values*

        \- List of values, assumed to be distributed according to a Pareto
        distribution

  - <a name='113'></a>__::math::statistics::estimate\-exponential__ *values*

    Estimate the parameter for the exponential distribution that comes closest
    to the given values\. Returns an estimate of the one parameter and of the
    standard error\.

      * list *values*

        \- List of values, assumed to be distributed according to an exponential
        distribution

  - <a name='114'></a>__::math::statistics::estimate\-laplace__ *values*

    Estimate the parameters for the Laplace distribution that comes closest to
    the given values\. Returns an estimate of respectively the location and scale
    parameters, based on maximum likelihood\.

      * list *values*

        \- List of values, assumed to be distributed according to an exponential
        distribution

  - <a name='115'></a>__::math::statistics::estimante\-negative\-binomial__ *r* *values*

    Estimate the probability of success for the negative binomial distribution
    that comes closest to the given values\. The allowed number of failures must
    be given\.

      * int *r*

        \- Allowed number of failures \(at least 1\)

      * int *number*

        \- List of values, assumed to be distributed according to a negative
        binomial distribution\.

TO DO: more function descriptions to be added

# <a name='section5'></a>DATA MANIPULATION

The data manipulation procedures act on lists or lists of lists:

  - <a name='116'></a>__::math::statistics::filter__ *varname* *data* *expression*

    Return a list consisting of the data for which the logical expression is
    true \(this command works analogously to the command
    __[foreach](\.\./\.\./\.\./\.\./index\.md\#foreach)__\)\.

      * string *varname*

        \- Name of the variable used in the expression

      * list *data*

        \- List of data

      * string *expression*

        \- Logical expression using the variable name

  - <a name='117'></a>__::math::statistics::map__ *varname* *data* *expression*

    Return a list consisting of the data that are transformed via the
    expression\.

      * string *varname*

        \- Name of the variable used in the expression

      * list *data*

        \- List of data

      * string *expression*

        \- Expression to be used to transform \(map\) the data

  - <a name='118'></a>__::math::statistics::samplescount__ *varname* *list* *expression*

    Return a list consisting of the *counts* of all data in the sublists of
    the "list" argument for which the expression is true\.

      * string *varname*

        \- Name of the variable used in the expression

      * list *data*

        \- List of sublists, each containing the data

      * string *expression*

        \- Logical expression to test the data \(defaults to "true"\)\.

  - <a name='119'></a>__::math::statistics::subdivide__

    Routine *PM* \- not implemented yet

# <a name='section6'></a>PLOT PROCEDURES

The following simple plotting procedures are available:

  - <a name='120'></a>__::math::statistics::plot\-scale__ *canvas* *xmin* *xmax* *ymin* *ymax*

    Set the scale for a plot in the given canvas\. All plot routines expect this
    function to be called first\. There is no automatic scaling provided\.

      * widget *canvas*

        \- Canvas widget to use
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032

        \- Minimum y value

      * float *ymax*

        \- Maximum y value

  - <a name='101'></a>__::math::statistics::plot\-xydata__ *canvas* *xdata* *ydata* *tag*

    Create a simple XY plot in the given canvas \- the data are shown as a
    collection of dots\. The tag can be used to manipulate the appearance\.

      * widget *canvas*

        \- Canvas widget to use

      * float *xdata*

        \- Series of independent data

      * float *ydata*

        \- Series of dependent data

      * string *tag*

        \- Tag to give to the plotted data \(defaults to xyplot\)

  - <a name='102'></a>__::math::statistics::plot\-xyline__ *canvas* *xdata* *ydata* *tag*

    Create a simple XY plot in the given canvas \- the data are shown as a line
    through the data points\. The tag can be used to manipulate the appearance\.

      * widget *canvas*

        \- Canvas widget to use

      * list *xdata*

        \- Series of independent data

      * list *ydata*

        \- Series of dependent data

      * string *tag*

        \- Tag to give to the plotted data \(defaults to xyplot\)

  - <a name='103'></a>__::math::statistics::plot\-tdata__ *canvas* *tdata* *tag*

    Create a simple XY plot in the given canvas \- the data are shown as a
    collection of dots\. The horizontal coordinate is equal to the index\. The tag
    can be used to manipulate the appearance\. This type of presentation is
    suitable for autocorrelation functions for instance or for inspecting the
    time\-dependent behaviour\.

      * widget *canvas*

        \- Canvas widget to use

      * list *tdata*

        \- Series of dependent data

      * string *tag*

        \- Tag to give to the plotted data \(defaults to xyplot\)

  - <a name='104'></a>__::math::statistics::plot\-tline__ *canvas* *tdata* *tag*

    Create a simple XY plot in the given canvas \- the data are shown as a line\.
    See plot\-tdata for an explanation\.

      * widget *canvas*

        \- Canvas widget to use

      * list *tdata*

        \- Series of dependent data

      * string *tag*

        \- Tag to give to the plotted data \(defaults to xyplot\)

  - <a name='105'></a>__::math::statistics::plot\-histogram__ *canvas* *counts* *limits* *tag*

    Create a simple histogram in the given canvas

      * widget *canvas*

        \- Canvas widget to use








|




















|




















|



















|
















|







2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383

        \- Minimum y value

      * float *ymax*

        \- Maximum y value

  - <a name='121'></a>__::math::statistics::plot\-xydata__ *canvas* *xdata* *ydata* *tag*

    Create a simple XY plot in the given canvas \- the data are shown as a
    collection of dots\. The tag can be used to manipulate the appearance\.

      * widget *canvas*

        \- Canvas widget to use

      * float *xdata*

        \- Series of independent data

      * float *ydata*

        \- Series of dependent data

      * string *tag*

        \- Tag to give to the plotted data \(defaults to xyplot\)

  - <a name='122'></a>__::math::statistics::plot\-xyline__ *canvas* *xdata* *ydata* *tag*

    Create a simple XY plot in the given canvas \- the data are shown as a line
    through the data points\. The tag can be used to manipulate the appearance\.

      * widget *canvas*

        \- Canvas widget to use

      * list *xdata*

        \- Series of independent data

      * list *ydata*

        \- Series of dependent data

      * string *tag*

        \- Tag to give to the plotted data \(defaults to xyplot\)

  - <a name='123'></a>__::math::statistics::plot\-tdata__ *canvas* *tdata* *tag*

    Create a simple XY plot in the given canvas \- the data are shown as a
    collection of dots\. The horizontal coordinate is equal to the index\. The tag
    can be used to manipulate the appearance\. This type of presentation is
    suitable for autocorrelation functions for instance or for inspecting the
    time\-dependent behaviour\.

      * widget *canvas*

        \- Canvas widget to use

      * list *tdata*

        \- Series of dependent data

      * string *tag*

        \- Tag to give to the plotted data \(defaults to xyplot\)

  - <a name='124'></a>__::math::statistics::plot\-tline__ *canvas* *tdata* *tag*

    Create a simple XY plot in the given canvas \- the data are shown as a line\.
    See plot\-tdata for an explanation\.

      * widget *canvas*

        \- Canvas widget to use

      * list *tdata*

        \- Series of dependent data

      * string *tag*

        \- Tag to give to the plotted data \(defaults to xyplot\)

  - <a name='125'></a>__::math::statistics::plot\-histogram__ *canvas* *counts* *limits* *tag*

    Create a simple histogram in the given canvas

      * widget *canvas*

        \- Canvas widget to use

2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082

2083
2084
2085

2086
2087

2088
2089
2090
2091
2092
2093

2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104


2105

2106
2107

2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119

2120
2121
2122
2123

2124
2125

2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139

2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192

  - subdivide

# <a name='section8'></a>EXAMPLES

The code below is a small example of how you can examine a set of data:

    \# Simple example:
    \# \- Generate data \(as a cheap way of getting some\)
    \# \- Perform statistical analysis to describe the data
    \#

    package require math::statistics

    \#

    \# Two auxiliary procs
    \#

    proc pause \{time\} \{
       set wait 0
       after \[expr \{$time\*1000\}\] \{set ::wait 1\}
       vwait wait
    \}


    proc print\-histogram \{counts limits\} \{
       foreach count $counts limit $limits \{
          if \{ $limit \!= \{\} \} \{
             puts \[format "<%12\.4g\\t%d" $limit $count\]
             set prev\_limit $limit
          \} else \{
             puts \[format ">%12\.4g\\t%d" $prev\_limit $count\]
          \}
       \}
    \}



    \#

    \# Our source of arbitrary data
    \#

    proc generateData \{ data1 data2 \} \{
       upvar 1 $data1 \_data1
       upvar 1 $data2 \_data2

       set d1 0\.0
       set d2 0\.0
       for \{ set i 0 \} \{ $i < 100 \} \{ incr i \} \{
          set d1 \[expr \{10\.0\-2\.0\*cos\(2\.0\*3\.1415926\*$i/24\.0\)\+3\.5\*rand\(\)\}\]
          set d2 \[expr \{0\.7\*$d2\+0\.3\*$d1\+0\.7\*rand\(\)\}\]
          lappend \_data1 $d1
          lappend \_data2 $d2
       \}

       return \{\}
    \}

    \#

    \# The analysis session
    \#

    package require Tk
    console show
    canvas \.plot1
    canvas \.plot2
    pack   \.plot1 \.plot2 \-fill both \-side top

    generateData data1 data2

    puts "Basic statistics:"
    set b1 \[::math::statistics::basic\-stats $data1\]
    set b2 \[::math::statistics::basic\-stats $data2\]
    foreach label \{mean min max number stdev var\} v1 $b1 v2 $b2 \{
       puts "$label\\t$v1\\t$v2"
    \}

    puts "Plot the data as function of \\"time\\" and against each other"
    ::math::statistics::plot\-scale \.plot1  0 100  0 20
    ::math::statistics::plot\-scale \.plot2  0 20   0 20
    ::math::statistics::plot\-tline \.plot1 $data1
    ::math::statistics::plot\-tline \.plot1 $data2
    ::math::statistics::plot\-xydata \.plot2 $data1 $data2

    puts "Correlation coefficient:"
    puts \[::math::statistics::corr $data1 $data2\]

    pause 2
    puts "Plot histograms"
    \.plot2 delete all
    ::math::statistics::plot\-scale \.plot2  0 20 0 100
    set limits         \[::math::statistics::minmax\-histogram\-limits 7 16\]
    set histogram\_data \[::math::statistics::histogram $limits $data1\]
    ::math::statistics::plot\-histogram \.plot2 $histogram\_data $limits

    puts "First series:"
    print\-histogram $histogram\_data $limits

    pause 2
    set limits         \[::math::statistics::minmax\-histogram\-limits 0 15 10\]
    set histogram\_data \[::math::statistics::histogram $limits $data2\]
    ::math::statistics::plot\-histogram \.plot2 $histogram\_data $limits d2
    \.plot2 itemconfigure d2 \-fill red

    puts "Second series:"
    print\-histogram $histogram\_data $limits

    puts "Autocorrelation function:"
    set  autoc \[::math::statistics::autocorr $data1\]
    puts \[::math::statistics::map $autoc \{\[format "%\.2f" $x\]\}\]
    puts "Cross\-correlation function:"
    set  crossc \[::math::statistics::crosscorr $data1 $data2\]
    puts \[::math::statistics::map $crossc \{\[format "%\.2f" $x\]\}\]

    ::math::statistics::plot\-scale \.plot1  0 100 \-1  4
    ::math::statistics::plot\-tline \.plot1  $autoc "autoc"
    ::math::statistics::plot\-tline \.plot1  $crossc "crossc"
    \.plot1 itemconfigure autoc  \-fill green
    \.plot1 itemconfigure crossc \-fill yellow

    puts "Quantiles: 0\.1, 0\.2, 0\.5, 0\.8, 0\.9"
    puts "First:  \[::math::statistics::quantiles $data1 \{0\.1 0\.2 0\.5 0\.8 0\.9\}\]"
    puts "Second: \[::math::statistics::quantiles $data2 \{0\.1 0\.2 0\.5 0\.8 0\.9\}\]"

If you run this example, then the following should be clear:

  - There is a strong correlation between two time series, as displayed by the
    raw data and especially by the correlation functions\.

  - Both time series show a significant periodic component







|
|
|
<
>


<
>
|
<
>
|

|

<
|
>
|
|
|
|
|
|
|
<
<
<
|
>
>
|
>
|
<
>
|
|
|

|
|
|
|
|
|
|
<
>
|
<
|
|
>
|
<
>


|
|
|




|
|
|
|
<
>
|
|
|
|
|
|


|



|
|
|
|
|


|


|
|
|
|


|


|
|
|
|
|

|
|
|
|
|

|
|
|







2423
2424
2425
2426
2427
2428
2429
2430
2431
2432

2433
2434
2435

2436
2437

2438
2439
2440
2441
2442

2443
2444
2445
2446
2447
2448
2449
2450
2451



2452
2453
2454
2455
2456
2457

2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469

2470
2471

2472
2473
2474
2475

2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489

2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543

  - subdivide

# <a name='section8'></a>EXAMPLES

The code below is a small example of how you can examine a set of data:

    # Simple example:
    # - Generate data (as a cheap way of getting some)
    # - Perform statistical analysis to describe the data

    #
    package require math::statistics


    #
    # Two auxiliary procs

    #
    proc pause {time} {
       set wait 0
       after [expr {$time*1000}] {set ::wait 1}
       vwait wait

    }

    proc print-histogram {counts limits} {
       foreach count $counts limit $limits {
          if { $limit != {} } {
             puts [format "<%12.4g\t%d" $limit $count]
             set prev_limit $limit
          } else {
             puts [format ">%12.4g\t%d" $prev_limit $count]



          }
       }
    }

    #
    # Our source of arbitrary data

    #
    proc generateData { data1 data2 } {
       upvar 1 $data1 _data1
       upvar 1 $data2 _data2

       set d1 0.0
       set d2 0.0
       for { set i 0 } { $i < 100 } { incr i } {
          set d1 [expr {10.0-2.0*cos(2.0*3.1415926*$i/24.0)+3.5*rand()}]
          set d2 [expr {0.7*$d2+0.3*$d1+0.7*rand()}]
          lappend _data1 $d1
          lappend _data2 $d2

       }
       return {}

    }

    #
    # The analysis session

    #
    package require Tk
    console show
    canvas .plot1
    canvas .plot2
    pack   .plot1 .plot2 -fill both -side top

    generateData data1 data2

    puts "Basic statistics:"
    set b1 [::math::statistics::basic-stats $data1]
    set b2 [::math::statistics::basic-stats $data2]
    foreach label {mean min max number stdev var} v1 $b1 v2 $b2 {
       puts "$label\t$v1\t$v2"

    }
    puts "Plot the data as function of \"time\" and against each other"
    ::math::statistics::plot-scale .plot1  0 100  0 20
    ::math::statistics::plot-scale .plot2  0 20   0 20
    ::math::statistics::plot-tline .plot1 $data1
    ::math::statistics::plot-tline .plot1 $data2
    ::math::statistics::plot-xydata .plot2 $data1 $data2

    puts "Correlation coefficient:"
    puts [::math::statistics::corr $data1 $data2]

    pause 2
    puts "Plot histograms"
    .plot2 delete all
    ::math::statistics::plot-scale .plot2  0 20 0 100
    set limits         [::math::statistics::minmax-histogram-limits 7 16]
    set histogram_data [::math::statistics::histogram $limits $data1]
    ::math::statistics::plot-histogram .plot2 $histogram_data $limits

    puts "First series:"
    print-histogram $histogram_data $limits

    pause 2
    set limits         [::math::statistics::minmax-histogram-limits 0 15 10]
    set histogram_data [::math::statistics::histogram $limits $data2]
    ::math::statistics::plot-histogram .plot2 $histogram_data $limits d2
    .plot2 itemconfigure d2 -fill red

    puts "Second series:"
    print-histogram $histogram_data $limits

    puts "Autocorrelation function:"
    set  autoc [::math::statistics::autocorr $data1]
    puts [::math::statistics::map $autoc {[format "%.2f" $x]}]
    puts "Cross-correlation function:"
    set  crossc [::math::statistics::crosscorr $data1 $data2]
    puts [::math::statistics::map $crossc {[format "%.2f" $x]}]

    ::math::statistics::plot-scale .plot1  0 100 -1  4
    ::math::statistics::plot-tline .plot1  $autoc "autoc"
    ::math::statistics::plot-tline .plot1  $crossc "crossc"
    .plot1 itemconfigure autoc  -fill green
    .plot1 itemconfigure crossc -fill yellow

    puts "Quantiles: 0.1, 0.2, 0.5, 0.8, 0.9"
    puts "First:  [::math::statistics::quantiles $data1 {0.1 0.2 0.5 0.8 0.9}]"
    puts "Second: [::math::statistics::quantiles $data2 {0.1 0.2 0.5 0.8 0.9}]"

If you run this example, then the following should be clear:

  - There is a strong correlation between two time series, as displayed by the
    raw data and especially by the correlation functions\.

  - Both time series show a significant periodic component

Changes to embedded/md/tcllib/files/modules/math/symdiff.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (math::calculus::symdiff \- Symbolic differentiation for Tcl)
[//000000002]: # (Generated from file 'symdiff\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2010 by Kevin B\. Kenny <kennykb@acm\.org>
Redistribution permitted under the terms of the Open Publication License <http://www\.opencontent\.org/openpub/>)
[//000000004]: # (math::calculus::symdiff\(n\) 1\.0\.1 tcllib "Symbolic differentiation for Tcl")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (math::calculus::symdiff \- Symbolic differentiation for Tcl)
[//000000002]: # (Generated from file 'symdiff\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2010 by Kevin B\. Kenny <kennykb@acm\.org>)
[//000000004]: # (Redistribution permitted under the terms of the Open Publication License <http://www\.opencontent\.org/openpub/>)
[//000000005]: # (math::calculus::symdiff\(n\) 1\.0\.1 tcllib "Symbolic differentiation for Tcl")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
    __sinh__\. __sqrt__, __tan__, and __tanh__\.

Command substitution, backslash substitution, and argument expansion are not
accepted\.

# <a name='section4'></a>Examples

    math::calculus::symdiff::symdiff \{\($a\*$x\+$b\)\*\($c\*$x\+$d\)\} x
    ==> \(\($c \* \(\($a \* $x\) \+ $b\)\) \+ \($a \* \(\($c \* $x\) \+ $d\)\)\)
    math::calculus::symdiff::jacobian \{x \{$a \* $x \+ $b \* $y\}
                             y \{$c \* $x \+ $d \* $y\}\}
    ==> \{\{$a\} \{$b\}\} \{\{$c\} \{$d\}\}

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *math :: calculus* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report
any ideas for enhancements you may have for either package and/or documentation\.







|
|
|
|
|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
    __sinh__\. __sqrt__, __tan__, and __tanh__\.

Command substitution, backslash substitution, and argument expansion are not
accepted\.

# <a name='section4'></a>Examples

    math::calculus::symdiff::symdiff {($a*$x+$b)*($c*$x+$d)} x
    ==> (($c * (($a * $x) + $b)) + ($a * (($c * $x) + $d)))
    math::calculus::symdiff::jacobian {x {$a * $x + $b * $y}
                             y {$c * $x + $d * $y}}
    ==> {{$a} {$b}} {{$c} {$d}}

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *math :: calculus* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report
any ideas for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/md4/md4.md.

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

  - <a name='8'></a>__::md4::HMACFinal__ *token*

    These commands are identical to the MD4 equivalent commands\.

# <a name='section4'></a>EXAMPLES

    % md4::md4 \-hex "Tcl does MD4"
    858da9b31f57648a032230447bd15f25

    % md4::hmac \-hex \-key Sekret "Tcl does MD4"
    c324088e5752872689caedf2a0464758

    % set tok \[md4::MD4Init\]
    ::md4::1
    % md4::MD4Update $tok "Tcl "
    % md4::MD4Update $tok "does "
    % md4::MD4Update $tok "MD4"
    % md4::Hex \[md4::MD4Final $tok\]
    858da9b31f57648a032230447bd15f25

# <a name='section5'></a>REFERENCES

  1. Rivest, R\., "The MD4 Message Digest Algorithm", RFC 1320, MIT, April 1992\.
     \([http://www\.rfc\-editor\.org/rfc/rfc1320\.txt](http://www\.rfc\-editor\.org/rfc/rfc1320\.txt)\)








|


|


|




|







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

  - <a name='8'></a>__::md4::HMACFinal__ *token*

    These commands are identical to the MD4 equivalent commands\.

# <a name='section4'></a>EXAMPLES

    % md4::md4 -hex "Tcl does MD4"
    858da9b31f57648a032230447bd15f25

    % md4::hmac -hex -key Sekret "Tcl does MD4"
    c324088e5752872689caedf2a0464758

    % set tok [md4::MD4Init]
    ::md4::1
    % md4::MD4Update $tok "Tcl "
    % md4::MD4Update $tok "does "
    % md4::MD4Update $tok "MD4"
    % md4::Hex [md4::MD4Final $tok]
    858da9b31f57648a032230447bd15f25

# <a name='section5'></a>REFERENCES

  1. Rivest, R\., "The MD4 Message Digest Algorithm", RFC 1320, MIT, April 1992\.
     \([http://www\.rfc\-editor\.org/rfc/rfc1320\.txt](http://www\.rfc\-editor\.org/rfc/rfc1320\.txt)\)

Changes to embedded/md/tcllib/files/modules/md5/md5.md.

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

  - <a name='8'></a>__::md5::HMACFinal__ *token*

    These commands are identical to the MD5 equivalent commands\.

# <a name='section4'></a>EXAMPLES

    % md5::md5 \-hex "Tcl does MD5"
    8AAC1EE01E20BB347104FABB90310433

    % md5::hmac \-hex \-key Sekret "Tcl does MD5"
    35BBA244FD56D3EDF5F3C47474DACB5D

    % set tok \[md5::MD5Init\]
    ::md5::1
    % md5::MD5Update $tok "Tcl "
    % md5::MD5Update $tok "does "
    % md5::MD5Update $tok "MD5"
    % md5::Hex \[md5::MD5Final $tok\]
    8AAC1EE01E20BB347104FABB90310433

# <a name='section5'></a>REFERENCES

  1. Rivest, R\., "The MD5 Message\-Digest Algorithm", RFC 1321, MIT and RSA Data
     Security, Inc, April 1992\.
     \([http://www\.rfc\-editor\.org/rfc/rfc1321\.txt](http://www\.rfc\-editor\.org/rfc/rfc1321\.txt)\)







|


|


|




|







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

  - <a name='8'></a>__::md5::HMACFinal__ *token*

    These commands are identical to the MD5 equivalent commands\.

# <a name='section4'></a>EXAMPLES

    % md5::md5 -hex "Tcl does MD5"
    8AAC1EE01E20BB347104FABB90310433

    % md5::hmac -hex -key Sekret "Tcl does MD5"
    35BBA244FD56D3EDF5F3C47474DACB5D

    % set tok [md5::MD5Init]
    ::md5::1
    % md5::MD5Update $tok "Tcl "
    % md5::MD5Update $tok "does "
    % md5::MD5Update $tok "MD5"
    % md5::Hex [md5::MD5Final $tok]
    8AAC1EE01E20BB347104FABB90310433

# <a name='section5'></a>REFERENCES

  1. Rivest, R\., "The MD5 Message\-Digest Algorithm", RFC 1321, MIT and RSA Data
     Security, Inc, April 1992\.
     \([http://www\.rfc\-editor\.org/rfc/rfc1321\.txt](http://www\.rfc\-editor\.org/rfc/rfc1321\.txt)\)

Changes to embedded/md/tcllib/files/modules/md5crypt/md5crypt.md.

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

    % md5crypt::md5crypt password 01234567
    $1$01234567$b5lh2mHyD2PdJjFfALlEz1

    % md5crypt::aprcrypt password 01234567
    $apr1$01234567$IXBaQywhAhc0d75ZbaSDp/

    % md5crypt::md5crypt password \[md5crypt::salt\]
    $1$dFmvyRmO$T\.V3OmzqeEf3hqJp2WFcb\.

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *md5crypt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|
|







92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

    % md5crypt::md5crypt password 01234567
    $1$01234567$b5lh2mHyD2PdJjFfALlEz1

    % md5crypt::aprcrypt password 01234567
    $apr1$01234567$IXBaQywhAhc0d75ZbaSDp/

    % md5crypt::md5crypt password [md5crypt::salt]
    $1$dFmvyRmO$T.V3OmzqeEf3hqJp2WFcb.

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *md5crypt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/mime/mime.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (mime \- Mime)
[//000000002]: # (Generated from file 'mime\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 1999\-2000 Marshall T\. Rose)
[//000000004]: # (mime\(n\) 1\.6 tcllib "Mime")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>




|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (mime \- Mime)
[//000000002]: # (Generated from file 'mime\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 1999\-2000 Marshall T\. Rose)
[//000000004]: # (mime\(n\) 1\.6\.2 tcllib "Mime")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require mime ?1\.6?  

[__::mime::initialize__ ?__\-canonical__ *type/subtype* ?__\-param__ \{*key value*\}\.\.\.? ?__\-encoding__ *value*? ?__\-header__ \{*key value*\}\.\.\.?? \(__\-file__ *name* &#124; __\-string__ *value* &#124; __\-parts__ \{*token1* \.\.\. *tokenN*\}\)](#1)  
[__::mime::finalize__ *token* ?__\-subordinates__ __all__ &#124; __dynamic__ &#124; __none__?](#2)  
[__::mime::getproperty__ *token* ?*property* &#124; __\-names__?](#3)  
[__::mime::getheader__ *token* ?*key* &#124; __\-names__?](#4)  
[__::mime::setheader__ *token* *key value* ?__\-mode__ __write__ &#124; __append__ &#124; __delete__?](#5)  
[__::mime::getbody__ *token* ?__\-decode__? ?__\-command__ *callback* ?__\-blocksize__ *octets*??](#6)  







|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require mime ?1\.6\.2?  

[__::mime::initialize__ ?__\-canonical__ *type/subtype* ?__\-param__ \{*key value*\}\.\.\.? ?__\-encoding__ *value*? ?__\-header__ \{*key value*\}\.\.\.?? \(__\-file__ *name* &#124; __\-string__ *value* &#124; __\-parts__ \{*token1* \.\.\. *tokenN*\}\)](#1)  
[__::mime::finalize__ *token* ?__\-subordinates__ __all__ &#124; __dynamic__ &#124; __none__?](#2)  
[__::mime::getproperty__ *token* ?*property* &#124; __\-names__?](#3)  
[__::mime::getheader__ *token* ?*key* &#124; __\-names__?](#4)  
[__::mime::setheader__ *token* *key value* ?__\-mode__ __write__ &#124; __append__ &#124; __delete__?](#5)  
[__::mime::getbody__ *token* ?__\-decode__? ?__\-command__ *callback* ?__\-blocksize__ *octets*??](#6)  
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

    This command returns a string containing the body of the leaf MIME part
    represented by *token* in canonical form\.

    If the __\-command__ option is present, then it is repeatedly invoked
    with a fragment of the body as this:

        uplevel \#0 $callback \[list "data" $fragment\]

    \(The __\-blocksize__ option, if present, specifies the maximum size of
    each fragment passed to the callback\.\)

    When the end of the body is reached, the callback is invoked as:

        uplevel \#0 $callback "end"

    Alternatively, if an error occurs, the callback is invoked as:

        uplevel \#0 $callback \[list "error" reason\]

    Regardless, the return value of the final invocation of the callback is
    propagated upwards by __::mime::getbody__\.

    If the __\-command__ option is absent, then the return value of
    __::mime::getbody__ is a string containing the MIME part's entire body\.








|






|



|







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

    This command returns a string containing the body of the leaf MIME part
    represented by *token* in canonical form\.

    If the __\-command__ option is present, then it is repeatedly invoked
    with a fragment of the body as this:

        uplevel #0 $callback [list "data" $fragment]

    \(The __\-blocksize__ option, if present, specifies the maximum size of
    each fragment passed to the callback\.\)

    When the end of the body is reached, the callback is invoked as:

        uplevel #0 $callback "end"

    Alternatively, if an error occurs, the callback is invoked as:

        uplevel #0 $callback [list "error" reason]

    Regardless, the return value of the final invocation of the callback is
    propagated upwards by __::mime::getbody__\.

    If the __\-command__ option is absent, then the return value of
    __::mime::getbody__ is a string containing the MIME part's entire body\.

Changes to embedded/md/tcllib/files/modules/mime/smtp.md.

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
__sasl__ depends on a lot of the cryptographic \(secure\) hashes, i\.e\. all of
__[md5](\.\./md5/md5\.md)__, __[otp](\.\./otp/otp\.md)__,
__[md4](\.\./md4/md4\.md)__, __[sha1](\.\./sha1/sha1\.md)__, and
__[ripemd160](\.\./ripemd/ripemd160\.md)__\.

# <a name='section3'></a>EXAMPLE

    proc send\_simple\_message \{recipient email\_server subject body\} \{
        package require smtp
        package require mime

        set token \[mime::initialize \-canonical text/plain \\\\
    	\-string $body\]
        mime::setheader $token Subject $subject
        smtp::sendmessage $token \\\\
    	\-recipients $recipient \-servers $email\_server
        mime::finalize $token
    \}


    send\_simple\_message someone@somewhere\.com localhost \\\\
        "This is the subject\." "This is the message\."

# <a name='section4'></a>TLS Security Considerations

This package uses the __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ package to
handle the security for __https__ urls and other socket connections\.

Policy decisions like the set of protocols to support and what ciphers to use







|



|
|

|
|

<
|
>
|
|







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
__sasl__ depends on a lot of the cryptographic \(secure\) hashes, i\.e\. all of
__[md5](\.\./md5/md5\.md)__, __[otp](\.\./otp/otp\.md)__,
__[md4](\.\./md4/md4\.md)__, __[sha1](\.\./sha1/sha1\.md)__, and
__[ripemd160](\.\./ripemd/ripemd160\.md)__\.

# <a name='section3'></a>EXAMPLE

    proc send_simple_message {recipient email_server subject body} {
        package require smtp
        package require mime

        set token [mime::initialize -canonical text/plain \
    	-string $body]
        mime::setheader $token Subject $subject
        smtp::sendmessage $token \
    	-recipients $recipient -servers $email_server
        mime::finalize $token

    }

    send_simple_message [email protected] localhost \
        "This is the subject." "This is the message."

# <a name='section4'></a>TLS Security Considerations

This package uses the __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ package to
handle the security for __https__ urls and other socket connections\.

Policy decisions like the set of protocols to support and what ciphers to use
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init \-tls1 1 ;\# forcibly activate support for the TLS1 protocol

    \.\.\. your own application code \.\.\.

# <a name='section5'></a>REFERENCES

  1. Jonathan B\. Postel, "SIMPLE MAIL TRANSFER PROTOCOL", RFC 821, August 1982\.
     \([http://www\.rfc\-editor\.org/rfc/rfc821\.txt](http://www\.rfc\-editor\.org/rfc/rfc821\.txt)\)

  1. J\. Klensin, "Simple Mail Transfer Protocol", RFC 2821, April 2001\.







|

|







211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol

    ... your own application code ...

# <a name='section5'></a>REFERENCES

  1. Jonathan B\. Postel, "SIMPLE MAIL TRANSFER PROTOCOL", RFC 821, August 1982\.
     \([http://www\.rfc\-editor\.org/rfc/rfc821\.txt](http://www\.rfc\-editor\.org/rfc/rfc821\.txt)\)

  1. J\. Klensin, "Simple Mail Transfer Protocol", RFC 2821, April 2001\.

Changes to embedded/md/tcllib/files/modules/multiplexer/multiplexer.md.

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
It is possible to have different multiplexers running concurrently\.

  - <a name='1'></a>__::multiplexer::create__

    The __create__ command creates a new multiplexer 'instance'\. For
    example:

        set mp \[::multiplexer::create\]

    This instance can then be manipulated like so:

        $\{mp\}::Init 35100

  - <a name='2'></a>__$\{multiplexer\_instance\}::Init__ *port*

    This starts the multiplexer listening on the specified port\.

  - <a name='3'></a>__$\{multiplexer\_instance\}::Config__ *key* *value*








|



|







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
It is possible to have different multiplexers running concurrently\.

  - <a name='1'></a>__::multiplexer::create__

    The __create__ command creates a new multiplexer 'instance'\. For
    example:

        set mp [::multiplexer::create]

    This instance can then be manipulated like so:

        ${mp}::Init 35100

  - <a name='2'></a>__$\{multiplexer\_instance\}::Init__ *port*

    This starts the multiplexer listening on the specified port\.

  - <a name='3'></a>__$\{multiplexer\_instance\}::Config__ *key* *value*

Changes to embedded/md/tcllib/files/modules/namespacex/namespacex.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

[//000000001]: # (namespacex \- Namespace utility commands)
[//000000002]: # (Generated from file 'namespacex\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 200? Neil Madden \(http://wiki\.tcl\.tk/12790\)  
Copyright &copy; 200? Various \(http://wiki\.tcl\.tk/1489\)  
Copyright &copy; 2010 Documentation, Andreas Kupries)
[//000000004]: # (namespacex\(n\) 0\.2 tcllib "Namespace utility commands")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14

[//000000001]: # (namespacex \- Namespace utility commands)
[//000000002]: # (Generated from file 'namespacex\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 200? Neil Madden \(http://wiki\.tcl\.tk/12790\))
[//000000004]: # (Copyright &copy; 200? Various \(http://wiki\.tcl\.tk/1489\))
[//000000005]: # (Copyright &copy; 2010 Documentation, Andreas Kupries)
[//000000006]: # (namespacex\(n\) 0\.2 tcllib "Namespace utility commands")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

Changes to embedded/md/tcllib/files/modules/ncgi/ncgi.md.

1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (ncgi \- CGI Support)
[//000000002]: # (Generated from file 'ncgi\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (ncgi\(n\) 1\.4\.3 tcllib "CGI Support")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|







1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (ncgi \- CGI Support)
[//000000002]: # (Generated from file 'ncgi\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (ncgi\(n\) 1\.4\.4 tcllib "CGI Support")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  - [Keywords](#keywords)

  - [Category](#category)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.4  
package require ncgi ?1\.4\.3?  

[__::ncgi::cookie__ *cookie*](#1)  
[__::ncgi::decode__ *str*](#2)  
[__::ncgi::empty__ *name*](#3)  
[__::ncgi::exists__ *name*](#4)  
[__::ncgi::encode__ *string*](#5)  
[__::ncgi::header__ ?*type*? *args*](#6)  







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  - [Keywords](#keywords)

  - [Category](#category)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.4  
package require ncgi ?1\.4\.4?  

[__::ncgi::cookie__ *cookie*](#1)  
[__::ncgi::decode__ *str*](#2)  
[__::ncgi::empty__ *name*](#3)  
[__::ncgi::exists__ *name*](#4)  
[__::ncgi::encode__ *string*](#5)  
[__::ncgi::header__ ?*type*? *args*](#6)  
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

# <a name='section2'></a>EXAMPLES

Uploading a file

    HTML:
    <html>
    <form action="/cgi\-bin/upload\.cgi" method="POST" enctype="multipart/form\-data">
    Path: <input type="file" name="filedata"><br>
    Name: <input type="text" name="filedesc"><br>
    <input type="submit">
    </form>
    </html>

    TCL: upload\.cgi
    \#\!/usr/local/bin/tclsh

    ::ncgi::parse
    set filedata \[::ncgi::value filedata\]
    set filedesc \[::ncgi::value filedesc\]

    puts "<html> File uploaded at <a href=\\"/images/$filedesc\\">$filedesc</a> </html>"

    set filename /www/images/$filedesc

    set fh \[open $filename w\]
    puts \-nonewline $fh $filedata
    close $fh

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *ncgi* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas







|






|
|


|
|

|



|
|







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

# <a name='section2'></a>EXAMPLES

Uploading a file

    HTML:
    <html>
    <form action="/cgi-bin/upload.cgi" method="POST" enctype="multipart/form-data">
    Path: <input type="file" name="filedata"><br>
    Name: <input type="text" name="filedesc"><br>
    <input type="submit">
    </form>
    </html>

    TCL: upload.cgi
    #!/usr/local/bin/tclsh

    ::ncgi::parse
    set filedata [::ncgi::value filedata]
    set filedesc [::ncgi::value filedesc]

    puts "<html> File uploaded at <a href=\"/images/$filedesc\">$filedesc</a> </html>"

    set filename /www/images/$filedesc

    set fh [open $filename w]
    puts -nonewline $fh $filedata
    close $fh

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *ncgi* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas

Changes to embedded/md/tcllib/files/modules/nmea/nmea.md.

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

  - <a name='1'></a>__::nmea::input__ *sentence*

    Processes and dispatches the supplied sentence\. If *sentence* contains no
    commas it is treated as a Tcl list, otherwise it must be standard comma
    delimited NMEA data, with an optional checksum and leading __$__\.

        nmea::input \{$GPGSA,A,3,04,05,,09,12,,,24,,,,,2\.5,1\.3,2\.1\*39\}
        nmea::input \[list GPGSA A 3 04 05  09 12 "" "" 24 "" "" ""  2\.5 1\.3 2\.1\]

  - <a name='2'></a>__::nmea::open\_port__ *port* ?speed?

    Open the specified COM port and read NMEA sentences when available\. Port
    speed is set to 4800bps by default or to *speed*\.

  - <a name='3'></a>__::nmea::close\_port__







|
|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

  - <a name='1'></a>__::nmea::input__ *sentence*

    Processes and dispatches the supplied sentence\. If *sentence* contains no
    commas it is treated as a Tcl list, otherwise it must be standard comma
    delimited NMEA data, with an optional checksum and leading __$__\.

        nmea::input {$GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39}
        nmea::input [list GPGSA A 3 04 05  09 12 "" "" 24 "" "" ""  2.5 1.3 2.1]

  - <a name='2'></a>__::nmea::open\_port__ *port* ?speed?

    Open the specified COM port and read NMEA sentences when available\. Port
    speed is set to 4800bps by default or to *speed*\.

  - <a name='3'></a>__::nmea::close\_port__
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

154
155

156
157
158
159
160
161
162
    EOF handler is invoked when End Of File is reached on the open file or port\.

    The handler procedures, with the exception of the builtin types,must take
    exactly one argument, which is a list of the data values\. The DEFAULT
    handler should have two arguments, the sentence type and the data values\.
    The EOF handler has no arguments\.

        nmea::event gpgsa parse\_sat\_detail
        nmea::event default handle\_unknown

        proc parse\_sat\_detail \{data\} \{
            puts \[lindex $data 1\]
        \}

        proc handle\_unknown \{name data\} \{

            puts "unknown data type $name"
        \}


# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *nmea* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|
|

|
|
<
|
|
>

<
>







139
140
141
142
143
144
145
146
147
148
149
150

151
152
153
154

155
156
157
158
159
160
161
162
    EOF handler is invoked when End Of File is reached on the open file or port\.

    The handler procedures, with the exception of the builtin types,must take
    exactly one argument, which is a list of the data values\. The DEFAULT
    handler should have two arguments, the sentence type and the data values\.
    The EOF handler has no arguments\.

        nmea::event gpgsa parse_sat_detail
        nmea::event default handle_unknown

        proc parse_sat_detail {data} {
            puts [lindex $data 1]

        }

        proc handle_unknown {name data} {
            puts "unknown data type $name"

        }

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *nmea* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/nntp/nntp.md.

348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
        *msgid2*\) are queried\.

# <a name='section3'></a>EXAMPLE

A bigger example for posting a single article\.

    package require nntp
    set n \[nntp::nntp NNTP\_SERVER\]
    $n post "From: USER@DOMAIN\.EXT \(USER\_FULL\)
    Path: COMPUTERNAME\!USERNAME
    Newsgroups: alt\.test
    Subject: Tcl test post \-ignore
    Message\-ID: <\[pid\]\[clock seconds\]
    @COMPUTERNAME>
    Date: \[clock format \[clock seconds\] \-format "%a, %d %
    b %y %H:%M:%S GMT" \-gmt true\]

    Test message body"

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *nntp* of the [Tcllib







|
|
|
|
|
|

|
|







348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
        *msgid2*\) are queried\.

# <a name='section3'></a>EXAMPLE

A bigger example for posting a single article\.

    package require nntp
    set n [nntp::nntp NNTP_SERVER]
    $n post "From: [email protected] (USER_FULL)
    Path: COMPUTERNAME!USERNAME
    Newsgroups: alt.test
    Subject: Tcl test post -ignore
    Message-ID: <[pid][clock seconds]
    @COMPUTERNAME>
    Date: [clock format [clock seconds] -format "%a, %d %
    b %y %H:%M:%S GMT" -gmt true]

    Test message body"

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *nntp* of the [Tcllib

Changes to embedded/md/tcllib/files/modules/ntp/ntp_time.md.

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

    Wait for a query to complete and return the status upon completion\.

  - <a name='10'></a>__::time::cleanup__ *token*

    Remove all state variables associated with the request\.

    % set tok \[::time::gettime ntp2a\.mcc\.ac\.uk\]
    % set t \[::time::unixtime $tok\]
    % ::time::cleanup $tok

    % set tok \[::time::getsntp pool\.ntp\.org\]
    % set t \[::time::unixtime $tok\]
    % ::time::cleanup $tok

    proc on\_time \{token\} \{
       if \{\[time::status $token\] eq "ok"\} \{
          puts \[clock format \[time::unixtime $token\]\]
       \} else \{
          puts \[time::error $token\]
       \}

       time::cleanup $token
    \}

    time::getsntp \-command on\_time pool\.ntp\.org

# <a name='section3'></a>AUTHORS

Pat Thoyts

# <a name='section4'></a>Bugs, Ideas, Feedback








|
|


|
|


|
|
|
|
|
<
>

<
>
|







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

    Wait for a query to complete and return the status upon completion\.

  - <a name='10'></a>__::time::cleanup__ *token*

    Remove all state variables associated with the request\.

    % set tok [::time::gettime ntp2a.mcc.ac.uk]
    % set t [::time::unixtime $tok]
    % ::time::cleanup $tok

    % set tok [::time::getsntp pool.ntp.org]
    % set t [::time::unixtime $tok]
    % ::time::cleanup $tok

    proc on_time {token} {
       if {[time::status $token] eq "ok"} {
          puts [clock format [time::unixtime $token]]
       } else {
          puts [time::error $token]

       }
       time::cleanup $token

    }
    time::getsntp -command on_time pool.ntp.org

# <a name='section3'></a>AUTHORS

Pat Thoyts

# <a name='section4'></a>Bugs, Ideas, Feedback

Changes to embedded/md/tcllib/files/modules/oauth/oauth.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (oauth \- oauth)
[//000000002]: # (Generated from file 'oauth\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2014 Javi P\. <hxm@eggdrop\.es>)
[//000000004]: # (oauth\(n\) 1\.0\.2 tcllib "oauth")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>




|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (oauth \- oauth)
[//000000002]: # (Generated from file 'oauth\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2014 Javi P\. <hxm@eggdrop\.es>)
[//000000004]: # (oauth\(n\) 1\.0\.3 tcllib "oauth")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require oauth ?1\.0\.2?  

[__::oauth::config__](#1)  
[__::oauth::config__ ?*options*\.\.\.?](#2)  
[__::oauth::header__ *baseURL* ?*postQuery*?](#3)  
[__::oauth::query__ *baseURL* ?*postQuery*?](#4)  

# <a name='description'></a>DESCRIPTION







|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require oauth ?1\.0\.3?  

[__::oauth::config__](#1)  
[__::oauth::config__ ?*options*\.\.\.?](#2)  
[__::oauth::header__ *baseURL* ?*postQuery*?](#3)  
[__::oauth::query__ *baseURL* ?*postQuery*?](#4)  

# <a name='description'></a>DESCRIPTION
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init \-tls1 1 ;\# forcibly activate support for the TLS1 protocol

    \.\.\. your own application code \.\.\.

# <a name='section3'></a>Commands

  - <a name='1'></a>__::oauth::config__

    When this command is invoked without arguments it returns a dictionary
    containing the current values of all options\.







|

|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol

    ... your own application code ...

# <a name='section3'></a>Commands

  - <a name='1'></a>__::oauth::config__

    When this command is invoked without arguments it returns a dictionary
    containing the current values of all options\.
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

      * url *baseURL*

        This argument is the URI path to the OAuth API server\. If you plan send
        a GET query, you should provide a full path\.

    HTTP GET
    ::oauth::header \{https://api\.twitter\.com/1\.1/users/lookup\.json?screen\_name=AbiertaMente\}

      * url\-encoded\-string *postQuery*

        When you have to send a header in POST format, you have to put the query
        string into this argument\.

    ::oauth::header \{https://api\.twitter\.com/1\.1/friendships/create\.json\} \{user\_id=158812437&follow=true\}

  - <a name='4'></a>__::oauth::query__ *baseURL* ?*postQuery*?

    This procedure will use the settings made with __::oauth::config__ to
    create the basic authentication and then send the command to the server API\.
    It takes the same arguments as __::oauth::header__\.

    The returned result will be a list containing 2 elements\. The first element
    will be a dictionary containing the HTTP header data response\. This allows
    you, for example, to check the X\-Rate\-Limit from OAuth\. The second element
    will be the raw data returned from API server\. This string is usually a json
    object which can be further decoded with the functions of package
    __[json](\.\./json/json\.md)__, or any other json\-parser for Tcl\.

    Here is an example of how it would work in Twitter\. Do not forget to replace
    the placeholder tokens and keys of the example with your own tokens and keys
    when trying it out\.

    % package require oauth
    % package require json
    % oauth::config \-consumerkey \{your\_consumer\_key\} \-consumersecret \{your\_consumer\_key\_secret\} \-accesstoken \{your\_access\_token\} \-accesstokensecret \{your\_access\_token\_secret\}

    % set response \[oauth::query https://api\.twitter\.com/1\.1/users/lookup\.json?screen\_name=AbiertaMente\]
    % set jsondata \[lindex $response 1\]
    % set data \[json::json2dict $jsondata\]
    $ set data \[lindex $data 0\]
    % dict for \{key val\} $data \{puts "$key => $val"\}
    id => 158812437
    id\_str => 158812437
    name => Un Librepensador
    screen\_name => AbiertaMente
    location => Explico mis tuits ahí →
    description => 160Caracteres para un SMS y contaba mi vida entera sin recortar vocales\. Ahora en Twitter, podemos usar hasta 140 y a mí me sobrarían 20 para contaros todo lo q
    url => http://t\.co/SGs3k9odBn
    entities => url \{urls \{\{url http://t\.co/SGs3k9odBn expanded\_url http://librepensamiento\.es display\_url librepensamiento\.es indices \{0 22\}\}\}\} description \{urls \{\}\}
    protected => false
    followers\_count => 72705
    friends\_count => 53099
    listed\_count => 258
    created\_at => Wed Jun 23 18:29:58 \+0000 2010
    favourites\_count => 297
    utc\_offset => 7200
    time\_zone => Madrid
    geo\_enabled => false
    verified => false
    statuses\_count => 8996
    lang => es
    status => created\_at \{Sun Oct 12 08:02:38 \+0000 2014\} id 521209314087018496 id\_str 521209314087018496 text \{@thesamethanhim http://t\.co/WFoXOAofCt\} source \{<a href="http://twitter\.com" rel="nofollow">Twitter Web Client</a>\} truncated false in\_reply\_to\_status\_id 521076457490350081 in\_reply\_to\_status\_id\_str 521076457490350081 in\_reply\_to\_user\_id 2282730867 in\_reply\_to\_user\_id\_str 2282730867 in\_reply\_to\_screen\_name thesamethanhim geo null coordinates null place null contributors null retweet\_count 0 favorite\_count 0 entities \{hashtags \{\} symbols \{\} urls \{\{url http://t\.co/WFoXOAofCt expanded\_url http://www\.elmundo\.es/internacional/2014/03/05/53173dc1268e3e3f238b458a\.html display\_url elmundo\.es/internacional/… indices \{16 38\}\}\} user\_mentions \{\{screen\_name thesamethanhim name Ἑλένη id 2282730867 id\_str 2282730867 indices \{0 15\}\}\}\} favorited false retweeted false possibly\_sensitive false lang und
    contributors\_enabled => false
    is\_translator => true
    is\_translation\_enabled => false
    profile\_background\_color => 709397
    profile\_background\_image\_url => http://pbs\.twimg\.com/profile\_background\_images/704065051/9309c02aa2728bdf543505ddbd408e2e\.jpeg
    profile\_background\_image\_url\_https => https://pbs\.twimg\.com/profile\_background\_images/704065051/9309c02aa2728bdf543505ddbd408e2e\.jpeg
    profile\_background\_tile => true
    profile\_image\_url => http://pbs\.twimg\.com/profile\_images/2629816665/8035fb81919b840c5cc149755d3d7b0b\_normal\.jpeg
    profile\_image\_url\_https => https://pbs\.twimg\.com/profile\_images/2629816665/8035fb81919b840c5cc149755d3d7b0b\_normal\.jpeg
    profile\_banner\_url => https://pbs\.twimg\.com/profile\_banners/158812437/1400828874
    profile\_link\_color => FF3300
    profile\_sidebar\_border\_color => FFFFFF
    profile\_sidebar\_fill\_color => A0C5C7
    profile\_text\_color => 333333
    profile\_use\_background\_image => true
    default\_profile => false
    default\_profile\_image => false
    following => true
    follow\_request\_sent => false
    notifications => false

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *oauth* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas







|






|




















|

|
|
|
|
|

|

|

|
|
|

|
|
|
|
|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|







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

      * url *baseURL*

        This argument is the URI path to the OAuth API server\. If you plan send
        a GET query, you should provide a full path\.

    HTTP GET
    ::oauth::header {https://api.twitter.com/1.1/users/lookup.json?screen_name=AbiertaMente}

      * url\-encoded\-string *postQuery*

        When you have to send a header in POST format, you have to put the query
        string into this argument\.

    ::oauth::header {https://api.twitter.com/1.1/friendships/create.json} {user_id=158812437&follow=true}

  - <a name='4'></a>__::oauth::query__ *baseURL* ?*postQuery*?

    This procedure will use the settings made with __::oauth::config__ to
    create the basic authentication and then send the command to the server API\.
    It takes the same arguments as __::oauth::header__\.

    The returned result will be a list containing 2 elements\. The first element
    will be a dictionary containing the HTTP header data response\. This allows
    you, for example, to check the X\-Rate\-Limit from OAuth\. The second element
    will be the raw data returned from API server\. This string is usually a json
    object which can be further decoded with the functions of package
    __[json](\.\./json/json\.md)__, or any other json\-parser for Tcl\.

    Here is an example of how it would work in Twitter\. Do not forget to replace
    the placeholder tokens and keys of the example with your own tokens and keys
    when trying it out\.

    % package require oauth
    % package require json
    % oauth::config -consumerkey {your_consumer_key} -consumersecret {your_consumer_key_secret} -accesstoken {your_access_token} -accesstokensecret {your_access_token_secret}

    % set response [oauth::query https://api.twitter.com/1.1/users/lookup.json?screen_name=AbiertaMente]
    % set jsondata [lindex $response 1]
    % set data [json::json2dict $jsondata]
    $ set data [lindex $data 0]
    % dict for {key val} $data {puts "$key => $val"}
    id => 158812437
    id_str => 158812437
    name => Un Librepensador
    screen_name => AbiertaMente
    location => Explico mis tuits ahí →
    description => 160Caracteres para un SMS y contaba mi vida entera sin recortar vocales. Ahora en Twitter, podemos usar hasta 140 y a mí me sobrarían 20 para contaros todo lo q
    url => http://t.co/SGs3k9odBn
    entities => url {urls {{url http://t.co/SGs3k9odBn expanded_url http://librepensamiento.es display_url librepensamiento.es indices {0 22}}}} description {urls {}}
    protected => false
    followers_count => 72705
    friends_count => 53099
    listed_count => 258
    created_at => Wed Jun 23 18:29:58 +0000 2010
    favourites_count => 297
    utc_offset => 7200
    time_zone => Madrid
    geo_enabled => false
    verified => false
    statuses_count => 8996
    lang => es
    status => created_at {Sun Oct 12 08:02:38 +0000 2014} id 521209314087018496 id_str 521209314087018496 text {@thesamethanhim http://t.co/WFoXOAofCt} source {<a href="http://twitter.com" rel="nofollow">Twitter Web Client</a>} truncated false in_reply_to_status_id 521076457490350081 in_reply_to_status_id_str 521076457490350081 in_reply_to_user_id 2282730867 in_reply_to_user_id_str 2282730867 in_reply_to_screen_name thesamethanhim geo null coordinates null place null contributors null retweet_count 0 favorite_count 0 entities {hashtags {} symbols {} urls {{url http://t.co/WFoXOAofCt expanded_url http://www.elmundo.es/internacional/2014/03/05/53173dc1268e3e3f238b458a.html display_url elmundo.es/internacional/… indices {16 38}}} user_mentions {{screen_name thesamethanhim name Ἑλένη id 2282730867 id_str 2282730867 indices {0 15}}}} favorited false retweeted false possibly_sensitive false lang und
    contributors_enabled => false
    is_translator => true
    is_translation_enabled => false
    profile_background_color => 709397
    profile_background_image_url => http://pbs.twimg.com/profile_background_images/704065051/9309c02aa2728bdf543505ddbd408e2e.jpeg
    profile_background_image_url_https => https://pbs.twimg.com/profile_background_images/704065051/9309c02aa2728bdf543505ddbd408e2e.jpeg
    profile_background_tile => true
    profile_image_url => http://pbs.twimg.com/profile_images/2629816665/8035fb81919b840c5cc149755d3d7b0b_normal.jpeg
    profile_image_url_https => https://pbs.twimg.com/profile_images/2629816665/8035fb81919b840c5cc149755d3d7b0b_normal.jpeg
    profile_banner_url => https://pbs.twimg.com/profile_banners/158812437/1400828874
    profile_link_color => FF3300
    profile_sidebar_border_color => FFFFFF
    profile_sidebar_fill_color => A0C5C7
    profile_text_color => 333333
    profile_use_background_image => true
    default_profile => false
    default_profile_image => false
    following => true
    follow_request_sent => false
    notifications => false

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *oauth* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas

Changes to embedded/md/tcllib/files/modules/oometa/oometa.md.

54
55
56
57
58
59
60
61
62
63

64
65
66
67

68
69
70
71
72

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

# <a name='description'></a>DESCRIPTION

The __oo::meta__ package provides a data registry service for TclOO classes\.

# <a name='section2'></a>Usage

    oo::class create animal \{
      meta set biodata animal: 1
    \}

    oo::class create mammal \{
      superclass animal
      meta set biodata mammal: 1
    \}

    oo::class create cat \{
      superclass mammal
      meta set biodata diet: carnivore
    \}


    cat create felix
    puts \[felix meta dump biodata\]
    > animal: 1 mammal: 1 diet: carnivore

    felix meta set biodata likes: \{birds mice\}
    puts \[felix meta get biodata\]
    > animal: 1 mammal: 1 diet: carnivore likes: \{bird mice\}

    \# Modify a class
    mammal meta set biodata metabolism: warm\-blooded
    puts \[felix meta get biodata\]
    > animal: 1 mammal: 1 metabolism: warm\-blooded diet: carnivore likes: \{birds mice\}

    \# Overwrite class info
    felix meta set biodata mammal: yes
    puts \[felix meta get biodata\]
    > animal: 1 mammal: yes metabolism: warm\-blooded diet: carnivore likes: \{birds mice\}

# <a name='section3'></a>Concept

The concept behind __oo::meta__ is that each class contributes a snippet of
*local* data\. When __oo::meta::metadata__ is called, the system walks
through the linear ancestry produced by __oo::meta::ancestors__, and
recursively combines all of that local data for all of a class' ancestors into a







|

<
>
|


<
>
|


<
|
>

|


|
|
|

|
|
|
|

|

|
|







54
55
56
57
58
59
60
61
62

63
64
65
66

67
68
69
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

# <a name='description'></a>DESCRIPTION

The __oo::meta__ package provides a data registry service for TclOO classes\.

# <a name='section2'></a>Usage

    oo::class create animal {
      meta set biodata animal: 1

    }
    oo::class create mammal {
      superclass animal
      meta set biodata mammal: 1

    }
    oo::class create cat {
      superclass mammal
      meta set biodata diet: carnivore

    }

    cat create felix
    puts [felix meta dump biodata]
    > animal: 1 mammal: 1 diet: carnivore

    felix meta set biodata likes: {birds mice}
    puts [felix meta get biodata]
    > animal: 1 mammal: 1 diet: carnivore likes: {bird mice}

    # Modify a class
    mammal meta set biodata metabolism: warm-blooded
    puts [felix meta get biodata]
    > animal: 1 mammal: 1 metabolism: warm-blooded diet: carnivore likes: {birds mice}

    # Overwrite class info
    felix meta set biodata mammal: yes
    puts [felix meta get biodata]
    > animal: 1 mammal: yes metabolism: warm-blooded diet: carnivore likes: {birds mice}

# <a name='section3'></a>Concept

The concept behind __oo::meta__ is that each class contributes a snippet of
*local* data\. When __oo::meta::metadata__ is called, the system walks
through the linear ancestry produced by __oo::meta::ancestors__, and
recursively combines all of that local data for all of a class' ancestors into a
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
    following:

  - <a name='2'></a>__oo::meta::info branchget__ ?*key*? ?\.\.\.?

    Returns a dict representation of the element at *args*, but with any
    trailing : removed from field names\.

    ::oo::meta::info $myclass set option color \{default: green widget: colorselect\}
    puts \[::oo::meta::info $myclass get option color\]
    > \{default: green widget: color\}
    puts \[::oo::meta::info $myclass branchget option color\]
    > \{default green widget color\}

  - <a name='3'></a>__oo::meta::info branchset__ ?*key\.\.\.*? *key* *value*

    Merges *dict* with any other information contaned at node ?*key\.\.\.*?,
    and adding a trailing : to all field names\.

    ::oo::meta::info $myclass branchset option color \{default green widget colorselect\}
    puts \[::oo::meta::info $myclass get option color\]
    > \{default: green widget: color\}

  - <a name='4'></a>__oo::meta::info dump__ *class*

    Returns the complete snapshot of a class metadata, as producted by
    __oo::meta::metadata__

  - <a name='5'></a>__oo::meta::info__ *class* __is__ *type* ?*args*?

    Returns a boolean true or false if the element ?*args*? would match
    __string is__ *type* *value*

    ::oo::meta::info $myclass set constant mammal 1
    puts \[::oo::meta::info $myclass is true constant mammal\]
    > 1

  - <a name='6'></a>__oo::meta::info__ *class* __[merge](\.\./\.\./\.\./\.\./index\.md\#merge)__ ?*dict*? ?*dict*? ?*\.\.\.*?

    Combines all of the arguments into a single dict, which is then stored as
    the new local representation for this class\.








|
|
|
|
|






|
|
|












|







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
    following:

  - <a name='2'></a>__oo::meta::info branchget__ ?*key*? ?\.\.\.?

    Returns a dict representation of the element at *args*, but with any
    trailing : removed from field names\.

    ::oo::meta::info $myclass set option color {default: green widget: colorselect}
    puts [::oo::meta::info $myclass get option color]
    > {default: green widget: color}
    puts [::oo::meta::info $myclass branchget option color]
    > {default green widget color}

  - <a name='3'></a>__oo::meta::info branchset__ ?*key\.\.\.*? *key* *value*

    Merges *dict* with any other information contaned at node ?*key\.\.\.*?,
    and adding a trailing : to all field names\.

    ::oo::meta::info $myclass branchset option color {default green widget colorselect}
    puts [::oo::meta::info $myclass get option color]
    > {default: green widget: color}

  - <a name='4'></a>__oo::meta::info dump__ *class*

    Returns the complete snapshot of a class metadata, as producted by
    __oo::meta::metadata__

  - <a name='5'></a>__oo::meta::info__ *class* __is__ *type* ?*args*?

    Returns a boolean true or false if the element ?*args*? would match
    __string is__ *type* *value*

    ::oo::meta::info $myclass set constant mammal 1
    puts [::oo::meta::info $myclass is true constant mammal]
    > 1

  - <a name='6'></a>__oo::meta::info__ *class* __[merge](\.\./\.\./\.\./\.\./index\.md\#merge)__ ?*dict*? ?*dict*? ?*\.\.\.*?

    Combines all of the arguments into a single dict, which is then stored as
    the new local representation for this class\.

157
158
159
160
161
162
163
164
165
166

167
168
169
170
171
172
173

  - <a name='9'></a>__oo::define meta__

    The package injects a command __oo::define::meta__ which works to
    provide a class in the process of definition access to
    __oo::meta::info__, but without having to look the name up\.

    oo::define myclass \{
      meta set foo bar: baz
    \}


  - <a name='10'></a>__oo::class method meta__

    The package injects a new method __meta__ into __oo::class__ which
    works to provide a class instance access to __oo::meta::info__\.

  - <a name='11'></a>__oo::object method meta__







|

<
>







157
158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
173

  - <a name='9'></a>__oo::define meta__

    The package injects a command __oo::define::meta__ which works to
    provide a class in the process of definition access to
    __oo::meta::info__, but without having to look the name up\.

    oo::define myclass {
      meta set foo bar: baz

    }

  - <a name='10'></a>__oo::class method meta__

    The package injects a new method __meta__ into __oo::class__ which
    works to provide a class instance access to __oo::meta::info__\.

  - <a name='11'></a>__oo::object method meta__

Changes to embedded/md/tcllib/files/modules/ooutil/ooutil.md.

76
77
78
79
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
    available to a user of the class and of derived classes\.

    Note: The command is equivalent to the command __typemethod__ provided
    by the OO package __[snit](\.\./snit/snit\.md)__ for the same purpose\.

    Example

        oo::class create ActiveRecord \{
            classmethod find args \{ puts "\[self\] called with arguments: $args" \}
        \}

        oo::class create Table \{
            superclass ActiveRecord
        \}

        puts \[Table find foo bar\]
        \# ======
        \# which will write
        \# ======
        \# ::Table called with arguments: foo bar

  - <a name='3'></a>__classvariable__ ?*arg*\.\.\.?

    This command is available within instance methods\. It takes a series of
    variable names and makes them available in the method's scope\. The
    originating scope for the variables is the class \(instance\) the object
    instance belongs to\. In other words, the referenced variables are shared
    between all instances of their class\.

    Note: The command is roughly equivalent to the command __typevariable__
    provided by the OO package __[snit](\.\./snit/snit\.md)__ for the same
    purpose\. The difference is that it cannot be used in the class definition
    itself\.

    Example:

        % oo::class create Foo \{
            method bar \{z\} \{
                classvariable x y
                return \[incr x $z\],\[incr y\]
            \}
        \}


        ::Foo
        % Foo create a
        ::a
        % Foo create b
        ::b
        % a bar 2
        2,1
        % a bar 3
        5,2
        % b bar 7
        12,3
        % b bar \-1
        11,4
        % a bar 0
        11,5

  - <a name='4'></a>__link__ *method*\.\.\.

  - <a name='5'></a>__link__ \{*alias* *method*\}\.\.\.

    This command is available within instance methods\. It takes a list of method
    names and/or pairs of alias\- and method\-name and makes the named methods
    available to all instance methods without requiring the __my__ command\.

    The alias name under which the method becomes available defaults to the
    method name, except where explicitly specified through an alias/method pair\.

    Examples:

        link foo
        \# The method foo is now directly accessible as foo instead of my foo\.

        link \{bar foo\}
        \# The method foo is now directly accessible as bar\.

        link a b c
        \# The methods a, b, and c all become directly acessible under their
        \# own names\.

    The main use of this command is expected to be in instance constructors, for
    convenience, or to set up some methods for use in a mini DSL\.

  - <a name='6'></a>__ooutil::singleton__ ?*arg*\.\.\.?

    This command is a meta\-class, i\.e\. a variant of the builtin
    __oo::class__ which ensures that it creates only a single instance of
    the classes defined with it\.

    Syntax and results are like for __oo::class__\.

    Example:

        % oo::class create example \{
           self mixin singleton
           method foo \{\} \{self\}
        \}

        ::example
        % \[example new\] foo
        ::oo::Obj22
        % \[example new\] foo
        ::oo::Obj22

# <a name='section3'></a>AUTHORS

Donal Fellows, Andreas Kupries

# <a name='section4'></a>Bugs, Ideas, Feedback







|
|
<
>
|

<
>
|
|
|
|
|
















|
|

|
<
<
>
>











|


















|

|
|


|
|














|

|
<
>

|

|







76
77
78
79
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
    available to a user of the class and of derived classes\.

    Note: The command is equivalent to the command __typemethod__ provided
    by the OO package __[snit](\.\./snit/snit\.md)__ for the same purpose\.

    Example

        oo::class create ActiveRecord {
            classmethod find args { puts "[self] called with arguments: $args" }

        }
        oo::class create Table {
            superclass ActiveRecord

        }
        puts [Table find foo bar]
        # ======
        # which will write
        # ======
        # ::Table called with arguments: foo bar

  - <a name='3'></a>__classvariable__ ?*arg*\.\.\.?

    This command is available within instance methods\. It takes a series of
    variable names and makes them available in the method's scope\. The
    originating scope for the variables is the class \(instance\) the object
    instance belongs to\. In other words, the referenced variables are shared
    between all instances of their class\.

    Note: The command is roughly equivalent to the command __typevariable__
    provided by the OO package __[snit](\.\./snit/snit\.md)__ for the same
    purpose\. The difference is that it cannot be used in the class definition
    itself\.

    Example:

        % oo::class create Foo {
            method bar {z} {
                classvariable x y
                return [incr x $z],[incr y]


            }
        }
        ::Foo
        % Foo create a
        ::a
        % Foo create b
        ::b
        % a bar 2
        2,1
        % a bar 3
        5,2
        % b bar 7
        12,3
        % b bar -1
        11,4
        % a bar 0
        11,5

  - <a name='4'></a>__link__ *method*\.\.\.

  - <a name='5'></a>__link__ \{*alias* *method*\}\.\.\.

    This command is available within instance methods\. It takes a list of method
    names and/or pairs of alias\- and method\-name and makes the named methods
    available to all instance methods without requiring the __my__ command\.

    The alias name under which the method becomes available defaults to the
    method name, except where explicitly specified through an alias/method pair\.

    Examples:

        link foo
        # The method foo is now directly accessible as foo instead of my foo.

        link {bar foo}
        # The method foo is now directly accessible as bar.

        link a b c
        # The methods a, b, and c all become directly acessible under their
        # own names.

    The main use of this command is expected to be in instance constructors, for
    convenience, or to set up some methods for use in a mini DSL\.

  - <a name='6'></a>__ooutil::singleton__ ?*arg*\.\.\.?

    This command is a meta\-class, i\.e\. a variant of the builtin
    __oo::class__ which ensures that it creates only a single instance of
    the classes defined with it\.

    Syntax and results are like for __oo::class__\.

    Example:

        % oo::class create example {
           self mixin singleton
           method foo {} {self}

        }
        ::example
        % [example new] foo
        ::oo::Obj22
        % [example new] foo
        ::oo::Obj22

# <a name='section3'></a>AUTHORS

Donal Fellows, Andreas Kupries

# <a name='section4'></a>Bugs, Ideas, Feedback

Changes to embedded/md/tcllib/files/modules/otp/otp.md.

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

  - <a name='3'></a>__::otp::otp\-sha1__ ?*\-hex*? ?*\-words*? *\-seed seed* *\-count count* *data*

  - <a name='4'></a>__::otp::otp\-rmd160__ ?*\-hex*? ?*\-words*? *\-seed seed* *\-count count* *data*

# <a name='section3'></a>EXAMPLES

    % otp::otp\-md5 \-count 99 \-seed host67821 "My Secret Pass Phrase"
    \(binary gibberish\)
    % otp::otp\-md5 \-words \-count 99 \-seed host67821 "My Secret Pass Phrase"
    SOON ARAB BURG LIMB FILE WAD
    % otp::otp\-md5 \-hex \-count 99 \-seed host67821 "My Secret Pass Phrase"
    e249b58257c80087

# <a name='section4'></a>REFERENCES

  1. Haller, N\. et al\., "A One\-Time Password System", RFC 2289, February 1998\.
     [http://www\.rfc\-editor\.org/rfc/rfc2289\.txt](http://www\.rfc\-editor\.org/rfc/rfc2289\.txt)








|
|
|

|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

  - <a name='3'></a>__::otp::otp\-sha1__ ?*\-hex*? ?*\-words*? *\-seed seed* *\-count count* *data*

  - <a name='4'></a>__::otp::otp\-rmd160__ ?*\-hex*? ?*\-words*? *\-seed seed* *\-count count* *data*

# <a name='section3'></a>EXAMPLES

    % otp::otp-md5 -count 99 -seed host67821 "My Secret Pass Phrase"
    (binary gibberish)
    % otp::otp-md5 -words -count 99 -seed host67821 "My Secret Pass Phrase"
    SOON ARAB BURG LIMB FILE WAD
    % otp::otp-md5 -hex -count 99 -seed host67821 "My Secret Pass Phrase"
    e249b58257c80087

# <a name='section4'></a>REFERENCES

  1. Haller, N\. et al\., "A One\-Time Password System", RFC 2289, February 1998\.
     [http://www\.rfc\-editor\.org/rfc/rfc2289\.txt](http://www\.rfc\-editor\.org/rfc/rfc2289\.txt)

Changes to embedded/md/tcllib/files/modules/page/page_util_peg.md.

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    more users\.

        A used by B and C,
        B is reachable,
        C is not,

        so A now loses the node in the expression for C calling it,
        or rather, not calling it anymore\.

    This command updates the cross\-references and which nonterminals are now
    undefined\.

  - <a name='4'></a>__::page::util::peg::flatten__ *treequery* *tree*

    This commands flattens nested sequence and choice operators in the AST







|







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    more users\.

        A used by B and C,
        B is reachable,
        C is not,

        so A now loses the node in the expression for C calling it,
        or rather, not calling it anymore.

    This command updates the cross\-references and which nonterminals are now
    undefined\.

  - <a name='4'></a>__::page::util::peg::flatten__ *treequery* *tree*

    This commands flattens nested sequence and choice operators in the AST

Changes to embedded/md/tcllib/files/modules/pki/pki.md.

95
96
97
98
99
100
101
102

103


104
105





106

107
108
109
110
111







112
113
114
115
116
117
118

      1. "openssl rsautl \-decrypt" == "::pki::decrypt \-binary \-priv"

      1. "openssl rsautl \-verify" == "::pki::decrypt \-binary \-pub"

  - <a name='3'></a>__::pki::sign__ *input* *key* ?*algo*?

    Digitally sign message *input* using the private *key*\. If *algo* is

    ommited "sha1" is assumed\. Possible values for *algo* include "md5",


    "sha1", "sha256", and "raw"\. Specifyin "raw" for *algo* will inhibit the
    building of an ASN\.1 structure to encode which hashing algorithm was chosen\.





    The *input* should be the plain text, hashing will be performed on it\. The

    *key* should include the private key\.

  - <a name='4'></a>__::pki::verify__ *signedmessage* *plaintext* *key* ?*algo*?

    Verify a digital signature using a public *key*\. Returns true or false\.








  - <a name='5'></a>__::pki::key__ *key* ?*password*? ?*encodePem*?

    Convert a key structure into a serialized PEM \(default\) or DER encoded
    private key suitable for other applications\. For RSA keys this means PKCS\#1\.

  - <a name='6'></a>__::pki::pkcs::parse\_key__ *key* ?*password*?







|
>
|
>
>
|
|
>
>
>
>
>
|
>
|




>
>
>
>
>
>
>







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

      1. "openssl rsautl \-decrypt" == "::pki::decrypt \-binary \-priv"

      1. "openssl rsautl \-verify" == "::pki::decrypt \-binary \-pub"

  - <a name='3'></a>__::pki::sign__ *input* *key* ?*algo*?

    Digitally sign message *input* using the private *key*\.

    If *algo* is ommited "sha1" is assumed\. Possible values for *algo*
    include "__md5__", "__sha1__", "__sha256__", and "__raw__"\.

    Specifying "__raw__" for *algo* will inhibit the building of an ASN\.1
    structure to encode which hashing algorithm was chosen\. *Attention*: In
    this case the corresponding __pkgi::verify__ must be called __with__
    algorithm information\. Conversely, specifying a non\-"__raw__" algorithm
    here means that the corresponding __pkgi::verify__ invokation has to be
    made *without* algorithm information\.

    The *input* should be the plain text, hashing will be performed on it\.

    The *key* should include the private key\.

  - <a name='4'></a>__::pki::verify__ *signedmessage* *plaintext* *key* ?*algo*?

    Verify a digital signature using a public *key*\. Returns true or false\.

    *Attention*: The algorithm information *algo* has to be specified if and
    only if the __pki::sign__ which generated the *signedmessage* was
    called with algorithm "__raw__"\. This inhibited the building of the
    ASN\.1 structure encoding the chosen hashing algorithm\. Conversely, if a
    proper algorithm was specified during signing then you *must not* specify
    an algorithm here\.

  - <a name='5'></a>__::pki::key__ *key* ?*password*? ?*encodePem*?

    Convert a key structure into a serialized PEM \(default\) or DER encoded
    private key suitable for other applications\. For RSA keys this means PKCS\#1\.

  - <a name='6'></a>__::pki::pkcs::parse\_key__ *key* ?*password*?
201
202
203
204
205
206
207




208
209
210
211
212
213
214
    to specify as a boolean value whether or not we can be used a certificate
    authority \(CA\)\. The *caDepth* argument indicates how many children CAs can
    be children of this CA in a depth\-wise fashion\. A value of "0" for the
    *caDepth* argument means that this CA cannot sign a CA certificate and
    have the result be valid\. A value of "\-1" indicates infinite depth\.

# <a name='section3'></a>EXAMPLES





# <a name='section4'></a>REFERENCES

# <a name='section5'></a>AUTHORS

Roy Keene








>
>
>
>







217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
    to specify as a boolean value whether or not we can be used a certificate
    authority \(CA\)\. The *caDepth* argument indicates how many children CAs can
    be children of this CA in a depth\-wise fashion\. A value of "0" for the
    *caDepth* argument means that this CA cannot sign a CA certificate and
    have the result be valid\. A value of "\-1" indicates infinite depth\.

# <a name='section3'></a>EXAMPLES





# <a name='section4'></a>REFERENCES

# <a name='section5'></a>AUTHORS

Roy Keene

Changes to embedded/md/tcllib/files/modules/pluginmgr/pluginmgr.md.

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
    \(underscore for environment variables, backslash for registry entries, and /
    for directories\)\.

    Examples:

        ::pluginmgr::paths ::obj docidx

        => env  DOCIDX\_PLUGINS
           reg  HKEY\_LOCAL\_MACHINE\\SOFTWARE\\docidx\\PLUGINS
           reg  HKEY\_CURRENT\_USER\\SOFTWARE\\docidx\\PLUGINS
           path ~/\.docidx/plugins

        ::pluginmgr::paths ::obj doctools::idx

        => env  DOCTOOLS\_PLUGINS
           env  DOCTOOLS\_IDX\_PLUGINS
           reg  HKEY\_LOCAL\_MACHINE\\SOFTWARE\\doctools\\PLUGINS
           reg  HKEY\_LOCAL\_MACHINE\\SOFTWARE\\doctools\\idx\\PLUGINS
           reg  HKEY\_CURRENT\_USER\\SOFTWARE\\doctools\\PLUGINS
           reg  HKEY\_CURRENT\_USER\\SOFTWARE\\doctools\\idx\\PLUGINS
           path ~/\.doctools/plugin
           path ~/\.doctools/idx/plugin

## <a name='subsection2'></a>OBJECT COMMAND

All commands created by the command __::pluginmgr__ \(See section [PACKAGE
COMMANDS](#subsection1)\) have the following general form and may be used to
invoke various operations on their plugin manager object\.








|
|
|
|



|
|
|
|
|
|
|
|







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
    \(underscore for environment variables, backslash for registry entries, and /
    for directories\)\.

    Examples:

        ::pluginmgr::paths ::obj docidx

        => env  DOCIDX_PLUGINS
           reg  HKEY_LOCAL_MACHINE\SOFTWARE\docidx\PLUGINS
           reg  HKEY_CURRENT_USER\SOFTWARE\docidx\PLUGINS
           path ~/.docidx/plugins

        ::pluginmgr::paths ::obj doctools::idx

        => env  DOCTOOLS_PLUGINS
           env  DOCTOOLS_IDX_PLUGINS
           reg  HKEY_LOCAL_MACHINE\SOFTWARE\doctools\PLUGINS
           reg  HKEY_LOCAL_MACHINE\SOFTWARE\doctools\idx\PLUGINS
           reg  HKEY_CURRENT_USER\SOFTWARE\doctools\PLUGINS
           reg  HKEY_CURRENT_USER\SOFTWARE\doctools\idx\PLUGINS
           path ~/.doctools/plugin
           path ~/.doctools/idx/plugin

## <a name='subsection2'></a>OBJECT COMMAND

All commands created by the command __::pluginmgr__ \(See section [PACKAGE
COMMANDS](#subsection1)\) have the following general form and may be used to
invoke various operations on their plugin manager object\.

Changes to embedded/md/tcllib/files/modules/png/png.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (png \- Image manipulation)
[//000000002]: # (Generated from file 'png\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004, Code: Aaron Faupell <afaupell@users\.sourceforge\.net>  
Copyright &copy; 2004, Doc:  Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (png\(n\) 0\.3 tcllib "Image manipulation")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (png \- Image manipulation)
[//000000002]: # (Generated from file 'png\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004, Code: Aaron Faupell <afaupell@users\.sourceforge\.net>)
[//000000004]: # (Copyright &copy; 2004, Doc:  Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000005]: # (png\(n\) 0\.3 tcllib "Image manipulation")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

Changes to embedded/md/tcllib/files/modules/pop3/pop3.md.

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init \-tls1 1 ;\# forcibly activate support for the TLS1 protocol

    \.\.\. your own application code \.\.\.

# <a name='section3'></a>API

  - <a name='1'></a>__::pop3::open__ ?__\-msex__ 0&#124;1? ?__\-retr\-mode__ retr&#124;list&#124;slow? ?__\-socketcmd__ cmdprefix? ?__\-stls__ 0&#124;1? ?__\-tls\-callback__ stls\-callback\-command? *host username password* ?*port*?

    Open a socket connection to the server specified by *host*, transmit the
    *username* and *password* as login information to the server\. The







|

|







78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol

    ... your own application code ...

# <a name='section3'></a>API

  - <a name='1'></a>__::pop3::open__ ?__\-msex__ 0&#124;1? ?__\-retr\-mode__ retr&#124;list&#124;slow? ?__\-socketcmd__ cmdprefix? ?__\-stls__ 0&#124;1? ?__\-tls\-callback__ stls\-callback\-command? *host username password* ?*port*?

    Open a socket connection to the server specified by *host*, transmit the
    *username* and *password* as login information to the server\. The
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
__\-socketcmd__ or the option __\-stls__ of the command
__pop3::open__\. The first method, option __\-socketcmd__, will force the
use of the __tls::socket__ command when opening the connection\. This is
suitable for POP3 servers which expect SSL connections only\. These will
generally be listening on port 995\.

    package require tls
    tls::init \-cafile /path/to/ca/cert \-keyfile \.\.\.

    \# Create secured pop3 channel
    pop3::open \-socketcmd tls::socket \\\\
    	$thehost $theuser $thepassword

    \.\.\.

The second method, option __\-stls__, will connect to the standard POP3 port
and then perform an STARTTLS handshake\. This will only work for POP3 servers
which have this capability\. The package will confirm that the server supports
STARTTLS and the handshake was performed correctly before proceeding with
authentication\.

    package require tls
    tls::init \-cafile /path/to/ca/cert \-keyfile \.\.\.

    \# Create secured pop3 channel
    pop3::open \-stls 1 \\\\
    	$thehost $theuser $thepassword

    \.\.\.

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pop3* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|

|
|


|








|

|
|


|







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
__\-socketcmd__ or the option __\-stls__ of the command
__pop3::open__\. The first method, option __\-socketcmd__, will force the
use of the __tls::socket__ command when opening the connection\. This is
suitable for POP3 servers which expect SSL connections only\. These will
generally be listening on port 995\.

    package require tls
    tls::init -cafile /path/to/ca/cert -keyfile ...

    # Create secured pop3 channel
    pop3::open -socketcmd tls::socket \
    	$thehost $theuser $thepassword

    ...

The second method, option __\-stls__, will connect to the standard POP3 port
and then perform an STARTTLS handshake\. This will only work for POP3 servers
which have this capability\. The package will confirm that the server supports
STARTTLS and the handshake was performed correctly before proceeding with
authentication\.

    package require tls
    tls::init -cafile /path/to/ca/cert -keyfile ...

    # Create secured pop3 channel
    pop3::open -stls 1 \
    	$thehost $theuser $thepassword

    ...

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pop3* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pop3d/pop3d.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (pop3d \- Tcl POP3 Server Package)
[//000000002]: # (Generated from file 'pop3d\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2002\-2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>  
Copyright &copy; 2005 Reinhard Max  <max@suse\.de>)
[//000000004]: # (pop3d\(n\) 1\.1\.0 tcllib "Tcl POP3 Server Package")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (pop3d \- Tcl POP3 Server Package)
[//000000002]: # (Generated from file 'pop3d\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2002\-2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (Copyright &copy; 2005 Reinhard Max  <max@suse\.de>)
[//000000005]: # (pop3d\(n\) 1\.1\.0 tcllib "Tcl POP3 Server Package")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276

The option __\-socket__ \(see [Options](#section2)\) enables users of the
package to override how the server opens its listening socket\. The envisioned
main use is the specification of the __tls::socket__ command, see package
__[tls](\.\./\.\./\.\./\.\./index\.md\#tls)__, to secure the communication\.

    package require tls
    tls::init \\\\
    	\.\.\.

    pop3d::new S \-socket tls::socket
    \.\.\.

# <a name='section6'></a>References

  1. [RFC 1939](http://www\.rfc\-editor\.org/rfc/rfc1939\.txt)

  1. [RFC 2449](http://www\.rfc\-editor\.org/rfc/rfc2449\.txt)








|
|

|
|







258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276

The option __\-socket__ \(see [Options](#section2)\) enables users of the
package to override how the server opens its listening socket\. The envisioned
main use is the specification of the __tls::socket__ command, see package
__[tls](\.\./\.\./\.\./\.\./index\.md\#tls)__, to secure the communication\.

    package require tls
    tls::init \
    	...

    pop3d::new S -socket tls::socket
    ...

# <a name='section6'></a>References

  1. [RFC 1939](http://www\.rfc\-editor\.org/rfc/rfc1939\.txt)

  1. [RFC 2449](http://www\.rfc\-editor\.org/rfc/rfc2449\.txt)

Changes to embedded/md/tcllib/files/modules/practcl/practcl.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27






































































28
29
30
31
32
33
34
35
36
37
38
39



































































































































































































































40
41




42

43
44

















45


46
47







48
















49



50


















51
52
53
54
55
56











57
58
59
60

61

62















































































































































63

64


65

66































































































































































67
68
69














































































































70
71

72











































73











































































































74
75

76

77

78














































79



















































































































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

[//000000001]: # (practcl \- The The Proper Rational API for C to Tool Command Language Module)
[//000000002]: # (Generated from file 'practcl\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2016\-2018 Sean Woods <yoda@etoyoc\.com>)
[//000000004]: # (practcl\(n\) 0\.11 tcllib "The The Proper Rational API for C to Tool Command Language Module")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

# NAME

practcl \- The Practcl Module

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Synopsis](#synopsis)

  - [Description](#section1)

  - [COMMANDS](#section2)







































































  - [Bugs, Ideas, Feedback](#section3)

  - [Keywords](#keywords)

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require TclOO 1\.0  
package require practcl 0\.11  




































































































































































































































[__CPUTS__ *varname* *body* ?*body*\.\.\.?](#1)  




[__practcl::\_isdirectory__ *path*](#2)  

[__practcl::object__ *parent* ?*keyvaluelist*?](#3)  
[__practcl::library__ ?*keyvaluelist*?](#4)  

















[__practcl::exe__ ?*keyvaluelist*?](#5)  


[__practcl::product__ *parent* ?*keyvaluelist*?](#6)  
[__practcl::cheader__ *parent* ?*keyvaluelist*?](#7)  







[__practcl::csource__ *parent* ?*keyvaluelist*?](#8)  
















[__practcl::module__ *parent* ?*keyvaluelist*?](#9)  



[__practcl::submodule__ *parent* ?*keyvaluelist*?](#10)  



















# <a name='description'></a>DESCRIPTION

The Practcl module is a tool for integrating large modules for C API Tcl code
that requires custom Tcl types and TclOO objects\.












# <a name='section2'></a>COMMANDS

  - <a name='1'></a>__CPUTS__ *varname* *body* ?*body*\.\.\.?


    Appends blocks of text to a buffer\. This command tries to reduce the number

    of line breaks between bodies\.

















































































































































  - <a name='2'></a>__practcl::\_isdirectory__ *path*




    Returns true if *path* is a directory, using the test
































































































































































  - <a name='3'></a>__practcl::object__ *parent* ?*keyvaluelist*?















































































































    A generic Practcl object


  - <a name='4'></a>__practcl::library__ ?*keyvaluelist*?























































































































































    A Practcl object representing a library container


  - <a name='5'></a>__practcl::exe__ ?*keyvaluelist*?



    A Practcl object representing a wrapped executable


































































































































































  - <a name='6'></a>__practcl::product__ *parent* ?*keyvaluelist*?


    A Practcl object representing a compiled product











































  - <a name='7'></a>__practcl::cheader__ *parent* ?*keyvaluelist*?




    A Practcl object representing an externally generated c header





  - <a name='8'></a>__practcl::csource__ *parent* ?*keyvaluelist*?
























































































































































    A Practcl object representing an externally generated c source file



















































































































  - <a name='9'></a>__practcl::module__ *parent* ?*keyvaluelist*?


    A Practcl object representing a dynamically generated C/H/Tcl suite










































  - <a name='10'></a>__practcl::submodule__ *parent* ?*keyvaluelist*?



    A Practcl object representing a dynamically generated C/H/Tcl suite,






















































































    subordinate to a module



































































# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *practcl* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

When proposing code changes, please provide *unified diffs*, i\.e the output of




|




















|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|










|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
|
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
<
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






>
>
>
>
>
>
>
>
>
>
>
|

|

>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
|
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>

>
|
>

>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726

[//000000001]: # (practcl \- The The Proper Rational API for C to Tool Command Language Module)
[//000000002]: # (Generated from file 'practcl\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2016\-2018 Sean Woods <yoda@etoyoc\.com>)
[//000000004]: # (practcl\(n\) 0\.16\.4 tcllib "The The Proper Rational API for C to Tool Command Language Module")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

# NAME

practcl \- The Practcl Module

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Synopsis](#synopsis)

  - [Description](#section1)

  - [Commands](#section2)

  - [Classes](#section3)

      - [Class practcl::doctool](#subsection1)

      - [Class practcl::metaclass](#subsection2)

      - [Class practcl::toolset](#subsection3)

      - [Class practcl::toolset\.gcc](#subsection4)

      - [Class practcl::toolset\.msvc](#subsection5)

      - [Class practcl::make\_obj](#subsection6)

      - [Class practcl::object](#subsection7)

      - [Class practcl::dynamic](#subsection8)

      - [Class practcl::product](#subsection9)

      - [Class practcl::product\.cheader](#subsection10)

      - [Class practcl::product\.csource](#subsection11)

      - [Class practcl::product\.clibrary](#subsection12)

      - [Class practcl::product\.dynamic](#subsection13)

      - [Class practcl::product\.critcl](#subsection14)

      - [Class practcl::module](#subsection15)

      - [Class practcl::project](#subsection16)

      - [Class practcl::library](#subsection17)

      - [Class practcl::tclkit](#subsection18)

      - [Class practcl::distribution](#subsection19)

      - [Class practcl::distribution\.snapshot](#subsection20)

      - [Class practcl::distribution\.fossil](#subsection21)

      - [Class practcl::distribution\.git](#subsection22)

      - [Class practcl::subproject](#subsection23)

      - [Class practcl::subproject\.source](#subsection24)

      - [Class practcl::subproject\.teapot](#subsection25)

      - [Class practcl::subproject\.kettle](#subsection26)

      - [Class practcl::subproject\.critcl](#subsection27)

      - [Class practcl::subproject\.sak](#subsection28)

      - [Class practcl::subproject\.practcl](#subsection29)

      - [Class practcl::subproject\.binary](#subsection30)

      - [Class practcl::subproject\.tea](#subsection31)

      - [Class practcl::subproject\.library](#subsection32)

      - [Class practcl::subproject\.external](#subsection33)

      - [Class practcl::subproject\.core](#subsection34)

  - [Bugs, Ideas, Feedback](#section4)

  - [Keywords](#keywords)

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require TclOO 1\.0  

[proc __practcl::cat__ *fname*](#1)  
[proc __practcl::docstrip__ *text*](#2)  
[proc __putb__ ?*map*? *text*](#3)  
[proc __[Proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ *name* *arglist* *body*](#4)  
[proc __noop__ ?*args*?](#5)  
[proc __practcl::debug__ ?*args*?](#6)  
[proc __practcl::doexec__ ?*args*?](#7)  
[proc __practcl::doexec\_in__ *path* ?*args*?](#8)  
[proc __practcl::dotclexec__ ?*args*?](#9)  
[proc __practcl::domake__ *path* ?*args*?](#10)  
[proc __practcl::domake\.tcl__ *path* ?*args*?](#11)  
[proc __practcl::fossil__ *path* ?*args*?](#12)  
[proc __practcl::fossil\_status__ *dir*](#13)  
[proc __practcl::os__](#14)  
[proc __practcl::mkzip__ *exename* *barekit* *vfspath*](#15)  
[proc __practcl::sort\_dict__ *list*](#16)  
[proc __practcl::local\_os__](#17)  
[proc __practcl::config\.tcl__ *path*](#18)  
[proc __practcl::read\_configuration__ *path*](#19)  
[proc __practcl::tcllib\_require__ *pkg* ?*args*?](#20)  
[proc __practcl::platform::tcl\_core\_options__ *os*](#21)  
[proc __practcl::platform::tk\_core\_options__ *os*](#22)  
[proc __practcl::read\_rc\_file__ *filename* ?*localdat* ____?](#23)  
[proc __practcl::read\_sh\_subst__ *line* *info*](#24)  
[proc __practcl::read\_sh\_file__ *filename* ?*localdat* ____?](#25)  
[proc __practcl::read\_Config\.sh__ *filename*](#26)  
[proc __practcl::read\_Makefile__ *filename*](#27)  
[proc __practcl::cputs__ *varname* ?*args*?](#28)  
[proc __practcl::tcl\_to\_c__ *body*](#29)  
[proc __practcl::\_tagblock__ *text* ?*style* __tcl__? ?*note* ____?](#30)  
[proc __practcl::de\_shell__ *data*](#31)  
[proc __practcl::grep__ *pattern* ?*files* ____?](#32)  
[proc __practcl::file\_lexnormalize__ *sp*](#33)  
[proc __practcl::file\_relative__ *base* *dst*](#34)  
[proc __practcl::findByPattern__ *basedir* *patterns*](#35)  
[proc __practcl::log__ *fname* *comment*](#36)  
[proc __practcl::\_pkgindex\_simpleIndex__ *path*](#37)  
[proc __practcl::\_pkgindex\_directory__ *path*](#38)  
[proc __practcl::\_pkgindex\_path\_subdir__ *path*](#39)  
[proc __practcl::pkgindex\_path__ ?*args*?](#40)  
[proc __practcl::installDir__ *d1* *d2*](#41)  
[proc __practcl::copyDir__ *d1* *d2* ?*toplevel* __1__?](#42)  
[proc __practcl::buildModule__ *modpath*](#43)  
[proc __practcl::installModule__ *modpath* *DEST*](#44)  
[proc __practcl::trigger__ ?*args*?](#45)  
[proc __practcl::depends__ ?*args*?](#46)  
[proc __practcl::target__ *name* *info* ?*action* ____?](#47)  
[method __constructor__](#48)  
[method __argspec__ *argspec*](#49)  
[method __[comment](\.\./\.\./\.\./\.\./index\.md\#comment)__ *block*](#50)  
[method __keyword\.Annotation__ *resultvar* *commentblock* *type* *name* *body*](#51)  
[method __keyword\.Class__ *resultvar* *commentblock* *name* *body*](#52)  
[method __keyword\.class__ *resultvar* *commentblock* *name* *body*](#53)  
[method __keyword\.Class\_Method__ *resultvar* *commentblock* *name* ?*args*?](#54)  
[method __keyword\.method__ *resultvar* *commentblock* *name* ?*args*?](#55)  
[method __keyword\.proc__ *commentblock* *name* *argspec*](#56)  
[method __reset__](#57)  
[method __Main__](#58)  
[method __section\.method__ *keyword* *method* *minfo*](#59)  
[method __section\.annotation__ *type* *name* *iinfo*](#60)  
[method __section\.class__ *class\_name* *class\_info*](#61)  
[method __section\.command__ *procinfo*](#62)  
[method __[manpage](\.\./\.\./\.\./\.\./index\.md\#manpage)__ ?__header *value*__? ?__footer *value*__? ?__authors *list*__?](#63)  
[method __scan\_text__ *text*](#64)  
[method __scan\_file__ *filename*](#65)  
[method __\_MorphPatterns__](#66)  
[method __[define](\.\./\.\./\.\./\.\./index\.md\#define)__ *submethod* ?*args*?](#67)  
[method __graft__ ?*args*?](#68)  
[method __initialize__](#69)  
[method __link__ *command* ?*args*?](#70)  
[method __morph__ *classname*](#71)  
[method __script__ *script*](#72)  
[method __select__](#73)  
[method __[source](\.\./\.\./\.\./\.\./index\.md\#source)__ *filename*](#74)  
[classmethod __select__ *object*](#75)  
[method __config\.sh__](#76)  
[method __BuildDir__ *PWD*](#77)  
[method __MakeDir__ *srcdir*](#78)  
[method __read\_configuration__](#79)  
[method __build\-cflags__ *PROJECT* *DEFS* *namevar* *versionvar* *defsvar*](#80)  
[method __critcl__ ?*args*?](#81)  
[method __Autoconf__](#82)  
[method __BuildDir__ *PWD*](#83)  
[method __ConfigureOpts__](#84)  
[method __MakeDir__ *srcdir*](#85)  
[method __make \{\} autodetect__](#86)  
[method __make \{\} clean__](#87)  
[method __make \{\} compile__](#88)  
[method __make \{\} install__ *DEST*](#89)  
[method __build\-compile\-sources__ *PROJECT* *COMPILE* *CPPCOMPILE* *INCLUDES*](#90)  
[method __build\-Makefile__ *path* *PROJECT*](#91)  
[method __build\-library__ *outfile* *PROJECT*](#92)  
[method __build\-tclsh__ *outfile* *PROJECT* ?*path* __auto__?](#93)  
[method __BuildDir__ *PWD*](#94)  
[method __make \{\} autodetect__](#95)  
[method __make \{\} clean__](#96)  
[method __make \{\} compile__](#97)  
[method __make \{\} install__ *DEST*](#98)  
[method __MakeDir__ *srcdir*](#99)  
[method __NmakeOpts__](#100)  
[method __constructor__ *module\_object* *name* *info* ?*action\_body* ____?](#101)  
[method __[do](\.\./\.\./\.\./\.\./index\.md\#do)__](#102)  
[method __check__](#103)  
[method __output__](#104)  
[method __reset__](#105)  
[method __triggers__](#106)  
[method __constructor__ *parent* ?*args*?](#107)  
[method __child__ *method*](#108)  
[method __go__](#109)  
[method __cstructure__ *name* *definition* ?*argdat* ____?](#110)  
[method __include__ *header*](#111)  
[method __include\_dir__ ?*args*?](#112)  
[method __include\_directory__ ?*args*?](#113)  
[method __c\_header__ *body*](#114)  
[method __c\_code__ *body*](#115)  
[method __c\_function__ *header* *body* ?*info* ____?](#116)  
[method __c\_tcloomethod__ *name* *body* ?*arginfo* ____?](#117)  
[method __cmethod__ *name* *body* ?*arginfo* ____?](#118)  
[method __c\_tclproc\_nspace__ *nspace*](#119)  
[method __c\_tclcmd__ *name* *body* ?*arginfo* ____?](#120)  
[method __c\_tclproc\_raw__ *name* *body* ?*arginfo* ____?](#121)  
[method __tcltype__ *name* *argdat*](#122)  
[method __project\-compile\-products__](#123)  
[method __implement__ *path*](#124)  
[method __initialize__](#125)  
[method __linktype__](#126)  
[method __generate\-cfile\-constant__](#127)  
[method __generate\-cfile\-header__](#128)  
[method __generate\-cfile\-tclapi__](#129)  
[method __generate\-loader\-module__](#130)  
[method __Collate\_Source__ *CWD*](#131)  
[method __select__](#132)  
[classmethod __select__ *object*](#133)  
[method __code__ *section* *body*](#134)  
[method __Collate\_Source__ *CWD*](#135)  
[method __project\-compile\-products__](#136)  
[method __generate\-debug__ ?*spaces* ____?](#137)  
[method __generate\-cfile\-constant__](#138)  
[method __generate\-cfile\-public\-structure__](#139)  
[method __generate\-cfile\-header__](#140)  
[method __generate\-cfile\-global__](#141)  
[method __generate\-cfile\-private\-typedef__](#142)  
[method __generate\-cfile\-private\-structure__](#143)  
[method __generate\-cfile\-functions__](#144)  
[method __generate\-cfile\-tclapi__](#145)  
[method __generate\-hfile\-public\-define__](#146)  
[method __generate\-hfile\-public\-macro__](#147)  
[method __generate\-hfile\-public\-typedef__](#148)  
[method __generate\-hfile\-public\-structure__](#149)  
[method __generate\-hfile\-public\-headers__](#150)  
[method __generate\-hfile\-public\-function__](#151)  
[method __generate\-hfile\-public\-includes__](#152)  
[method __generate\-hfile\-public\-verbatim__](#153)  
[method __generate\-loader\-external__](#154)  
[method __generate\-loader\-module__](#155)  
[method __generate\-stub\-function__](#156)  
[method __IncludeAdd__ *headervar* ?*args*?](#157)  
[method __generate\-tcl\-loader__](#158)  
[method __generate\-tcl\-pre__](#159)  
[method __generate\-tcl\-post__](#160)  
[method __linktype__](#161)  
[method __Ofile__ *filename*](#162)  
[method __project\-static\-packages__](#163)  
[method __toolset\-include\-directory__](#164)  
[method __target__ *method* ?*args*?](#165)  
[method __project\-compile\-products__](#166)  
[method __generate\-loader\-module__](#167)  
[method __project\-compile\-products__](#168)  
[method __linker\-products__ *configdict*](#169)  
[method __initialize__](#170)  
[variable __make\_object__](#171)  
[method __\_MorphPatterns__](#172)  
[method __add__ ?*args*?](#173)  
[method __install\-headers__ ?*args*?](#174)  
[method __make \{\} \_preamble__](#175)  
[method __make \{\} pkginfo__](#176)  
[method __make \{\} objects__](#177)  
[method __make \{\} object__ *name*](#178)  
[method __make \{\} reset__](#179)  
[method __make \{\} trigger__ ?*args*?](#180)  
[method __make \{\} depends__ ?*args*?](#181)  
[method __make \{\} filename__ *name*](#182)  
[method __make \{\} target__ *name* *Info* *body*](#183)  
[method __make \{\} todo__](#184)  
[method __make \{\} do__](#185)  
[method __child__ *which*](#186)  
[method __generate\-c__](#187)  
[method __generate\-h__](#188)  
[method __generate\-loader__](#189)  
[method __initialize__](#190)  
[method __implement__ *path*](#191)  
[method __linktype__](#192)  
[method __\_MorphPatterns__](#193)  
[method __constructor__ ?*args*?](#194)  
[method __add\_object__ *object*](#195)  
[method __add\_project__ *pkg* *info* ?*oodefine* ____?](#196)  
[method __add\_tool__ *pkg* *info* ?*oodefine* ____?](#197)  
[method __build\-tclcore__](#198)  
[method __child__ *which*](#199)  
[method __linktype__](#200)  
[method __project__ *pkg* ?*args*?](#201)  
[method __tclcore__](#202)  
[method __tkcore__](#203)  
[method __[tool](\.\./tool/tool\.md)__ *pkg* ?*args*?](#204)  
[method __clean__ *PATH*](#205)  
[method __project\-compile\-products__](#206)  
[method __go__](#207)  
[method __generate\-decls__ *pkgname* *path*](#208)  
[method __implement__ *path*](#209)  
[method __generate\-make__ *path*](#210)  
[method __linktype__](#211)  
[method __package\-ifneeded__ ?*args*?](#212)  
[method __shared\_library__ ?*filename* ____?](#213)  
[method __static\_library__ ?*filename* ____?](#214)  
[method __build\-tclkit\_main__ *PROJECT* *PKG\_OBJS*](#215)  
[method __Collate\_Source__ *CWD*](#216)  
[method __wrap__ *PWD* *exename* *vfspath* ?*args*?](#217)  
[classmethod __Sandbox__ *object*](#218)  
[classmethod __select__ *object*](#219)  
[classmethod __claim\_option__](#220)  
[classmethod __claim\_object__ *object*](#221)  
[classmethod __claim\_path__ *path*](#222)  
[method __scm\_info__](#223)  
[method __DistroMixIn__](#224)  
[method __Sandbox__](#225)  
[method __SrcDir__](#226)  
[method __ScmTag__](#227)  
[method __ScmClone__](#228)  
[method __ScmUnpack__](#229)  
[method __ScmUpdate__](#230)  
[method __Unpack__](#231)  
[classmethod __claim\_object__ *object*](#232)  
[classmethod __claim\_option__](#233)  
[classmethod __claim\_path__ *path*](#234)  
[method __ScmUnpack__](#235)  
[classmethod __claim\_object__ *obj*](#236)  

[classmethod __claim\_option__](#237)  
[classmethod __claim\_path__ *path*](#238)  
[method __scm\_info__](#239)  
[method __ScmClone__](#240)  
[method __ScmTag__](#241)  
[method __ScmUnpack__](#242)  
[method __ScmUpdate__](#243)  
[classmethod __claim\_object__ *obj*](#244)  
[classmethod __claim\_option__](#245)  
[classmethod __claim\_path__ *path*](#246)  
[method __ScmTag__](#247)  
[method __ScmUnpack__](#248)  
[method __ScmUpdate__](#249)  
[method __\_MorphPatterns__](#250)  
[method __BuildDir__ *PWD*](#251)  
[method __child__ *which*](#252)  
[method __compile__](#253)  
[method __go__](#254)  
[method __install__ ?*args*?](#255)  
[method __linktype__](#256)  
[method __linker\-products__ *configdict*](#257)  

[method __linker\-external__ *configdict*](#258)  
[method __linker\-extra__ *configdict*](#259)  
[method __env\-bootstrap__](#260)  
[method __env\-exec__](#261)  
[method __env\-install__](#262)  
[method __env\-load__](#263)  
[method __env\-present__](#264)  
[method __sources__](#265)  
[method __[update](\.\./\.\./\.\./\.\./index\.md\#update)__](#266)  
[method __unpack__](#267)  
[method __env\-bootstrap__](#268)  
[method __env\-present__](#269)  
[method __linktype__](#270)  
[method __env\-bootstrap__](#271)  
[method __env\-install__](#272)  
[method __env\-present__](#273)  
[method __install__ *DEST*](#274)  
[method __kettle__ *path* ?*args*?](#275)  
[method __install__ *DEST*](#276)  
[method __install__ *DEST*](#277)  
[method __env\-bootstrap__](#278)  
[method __env\-install__](#279)  
[method __env\-present__](#280)  
[method __install__ *DEST*](#281)  
[method __install\-module__ *DEST* ?*args*?](#282)  
[method __env\-bootstrap__](#283)  
[method __env\-install__](#284)  
[method __install__ *DEST*](#285)  
[method __install\-module__ *DEST* ?*args*?](#286)  
[method __clean__](#287)  
[method __env\-install__](#288)  
[method __project\-compile\-products__](#289)  
[method __ComputeInstall__](#290)  
[method __go__](#291)  
[method __linker\-products__ *configdict*](#292)  
[method __project\-static\-packages__](#293)  
[method __BuildDir__ *PWD*](#294)  
[method __compile__](#295)  
[method __Configure__](#296)  
[method __install__ *DEST*](#297)  
[method __install__ *DEST*](#298)  
[method __install__ *DEST*](#299)  
[method __env\-bootstrap__](#300)  
[method __env\-present__](#301)  
[method __env\-install__](#302)  
[method __go__](#303)  
[method __linktype__](#304)  

# <a name='description'></a>DESCRIPTION

The Practcl module is a tool for integrating large modules for C API Tcl code
that requires custom Tcl types and TclOO objects\.

The concept with Practcl is that is a single file package that can assist any
tcl based project with distribution, compilation, linking, VFS preparation,
executable assembly, and installation\. Practcl also allows one project to invoke
the build system from another project, allowing complex projects such as a
statically linked basekit to be assembled with relative ease\.

Practcl ships as a single file, and aside from a Tcl 8\.6 interpreter, has no
external dependencies\.

Making a practcl project

# <a name='section2'></a>Commands

  - <a name='1'></a>proc __practcl::cat__ *fname*

    Concatenate a file

  - <a name='2'></a>proc __practcl::docstrip__ *text*

    Strip the global comments from tcl code\. Used to prevent the documentation
    markup comments from clogging up files intended for distribution in machine
    readable format\.

  - <a name='3'></a>proc __putb__ ?*map*? *text*

    Append a line of text to a variable\. Optionally apply a string mapping\.

  - <a name='4'></a>proc __[Proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ *name* *arglist* *body*

    Generate a proc if no command already exists by that name

  - <a name='5'></a>proc __noop__ ?*args*?

    A command to do nothing\. A handy way of negating an instruction without
    having to comment it completely out\. It's also a handy attachment point for
    an object to be named later

  - <a name='6'></a>proc __practcl::debug__ ?*args*?

  - <a name='7'></a>proc __practcl::doexec__ ?*args*?

    Drop in a static copy of Tcl

  - <a name='8'></a>proc __practcl::doexec\_in__ *path* ?*args*?

  - <a name='9'></a>proc __practcl::dotclexec__ ?*args*?

  - <a name='10'></a>proc __practcl::domake__ *path* ?*args*?

  - <a name='11'></a>proc __practcl::domake\.tcl__ *path* ?*args*?

  - <a name='12'></a>proc __practcl::fossil__ *path* ?*args*?

  - <a name='13'></a>proc __practcl::fossil\_status__ *dir*

  - <a name='14'></a>proc __practcl::os__

  - <a name='15'></a>proc __practcl::mkzip__ *exename* *barekit* *vfspath*

    Build a zipfile\. On tcl8\.6 this invokes the native Zip implementation on
    older interpreters this invokes zip via exec

  - <a name='16'></a>proc __practcl::sort\_dict__ *list*

    Dictionary sort a key/value list\. Needed because pre tcl8\.6 does not have
    *lsort \-stride 2*

  - <a name='17'></a>proc __practcl::local\_os__

    Returns a dictionary describing the local operating system\. Fields return
    include:

      * download \- Filesystem path where fossil repositories and source tarballs
        are downloaded for the current user

      * EXEEXT \- The extension to give to executables\. \(i\.e\. \.exe on windows\)

      * fossil\_mirror \- A URI for a local network web server who acts as a
        fossil repository mirror

      * local\_install \- Filesystem path where packages for local consumption by
        the current user are installed

      * prefix \- The prefix as given to the Tcl core/TEA for installation to
        local\_install in \./configure

      * sandbox \- The file location where this project unpacks external projects

      * TEACUP\_PROFILE \- The ActiveState/Teacup canonical name for this platform
        \(i\.e\. win32\-ix86 macosx10\.5\-i386\-x86\_84\)

      * TEACUP\_OS \- The local operating system \(windows, macosx, openbsd, etc\)\.
        Gives the same answer as tcl\.m4, except that macosx is given as macosx
        instead of Darwin\.

      * TEA\_PLATFORM \- The platform returned by uname \-s\-uname \-r \(on Unix\), or
        "windows" on Windows

      * TEACUP\_ARCH \- The processor architecture for the local os \(i\.e\. ix86,
        x86\_64\)

      * TEACUP\_ARCH \- The processor architecture for the local os \(i\.e\. ix86,
        x86\_64\)

      * teapot \- Filesystem path where teapot package files are downloaded for
        the current user

      * userhome \- File path to store localized preferences, cache download
        files, etc for the current user

    This command uses a combination of local checks with Exec, any tclConfig\.sh
    file that is resident, autoconf data where already computed, and data
    gleaned from a file named practcl\.rc in userhome\. The location for userhome
    varies by platform and operating system:

      * Windows: ::env\(LOCALAPPDATA\)/Tcl

      * Macos: ~/Library/Application Support/Tcl

      * Other: ~/tcl

  - <a name='18'></a>proc __practcl::config\.tcl__ *path*

    A transparent call to ::practcl::read\_configuration to preserve backward
    compadibility with older copies of Practcl

  - <a name='19'></a>proc __practcl::read\_configuration__ *path*

    Detect local platform\. This command looks for data gleaned by autoconf or
    autosetup in the path specified, or perform its own logic tests if neither
    has been run\. A file named config\.site present in the location indicates
    that this project is cross compiling, and the data stored in that file is
    used for the compiler and linker\.

    This command looks for information from the following files, in the
    following order:

      * config\.tcl \- A file generated by autoconf/configure in newer editions of
        TEA, encoded as a Tcl script\.

      * config\.site \- A file containing cross compiler information, encoded as a
        SH script

      * ::env\(VisualStudioVersion\) \- On Windows, and environmental value that
        indicates MS Visual Studio is installed

    This command returns a dictionary containing all of the data cleaned from
    the sources above\. In the absence of any guidance this command returns the
    same output as ::practcl::local\_os\. In this mode, if the environmental
    variable VisualStudioVersion exists, this command will provide a template of
    fields that are appropriate for compiling on Windows under Microsoft Visual
    Studio\. The USEMSVC flag in the dictionary is a boolean flag to indicate if
    this is indeed the case\.

  - <a name='20'></a>proc __practcl::tcllib\_require__ *pkg* ?*args*?

    Try to load a package, and failing that retrieve tcllib

  - <a name='21'></a>proc __practcl::platform::tcl\_core\_options__ *os*

    Return the string to pass to \./configure to compile the Tcl core for the
    given OS\.

      * windows: \-\-with\-tzdata \-\-with\-encoding utf\-8

      * macosx: \-\-enable\-corefoundation=yes \-\-enable\-framework=no \-\-with\-tzdata
        \-\-with\-encoding utf\-8

      * other: \-\-with\-tzdata \-\-with\-encoding utf\-8

  - <a name='22'></a>proc __practcl::platform::tk\_core\_options__ *os*

  - <a name='23'></a>proc __practcl::read\_rc\_file__ *filename* ?*localdat* ____?

    Read a stylized key/value list stored in a file

  - <a name='24'></a>proc __practcl::read\_sh\_subst__ *line* *info*

    Converts a XXX\.sh file into a series of Tcl variables

  - <a name='25'></a>proc __practcl::read\_sh\_file__ *filename* ?*localdat* ____?

  - <a name='26'></a>proc __practcl::read\_Config\.sh__ *filename*

    A simpler form of read\_sh\_file tailored to pulling data from
    \(tcl&#124;tk\)Config\.sh

  - <a name='27'></a>proc __practcl::read\_Makefile__ *filename*

    A simpler form of read\_sh\_file tailored to pulling data from a Makefile

  - <a name='28'></a>proc __practcl::cputs__ *varname* ?*args*?

    Append arguments to a buffer The command works like puts in that each call
    will also insert a line feed\. Unlike puts, blank links in the interstitial
    are suppressed

  - <a name='29'></a>proc __practcl::tcl\_to\_c__ *body*

  - <a name='30'></a>proc __practcl::\_tagblock__ *text* ?*style* __tcl__? ?*note* ____?

  - <a name='31'></a>proc __practcl::de\_shell__ *data*

  - <a name='32'></a>proc __practcl::grep__ *pattern* ?*files* ____?

    Search for the pattern *pattern* amongst $files

  - <a name='33'></a>proc __practcl::file\_lexnormalize__ *sp*

  - <a name='34'></a>proc __practcl::file\_relative__ *base* *dst*

    Calculate a relative path between base and dst

    Example:

        ::practcl::file_relative ~/build/tcl/unix ~/build/tcl/library
        > ../library

  - <a name='35'></a>proc __practcl::findByPattern__ *basedir* *patterns*

  - <a name='36'></a>proc __practcl::log__ *fname* *comment*

    Record an event in the practcl log

  - <a name='37'></a>proc __practcl::\_pkgindex\_simpleIndex__ *path*

  - <a name='38'></a>proc __practcl::\_pkgindex\_directory__ *path*

    Return true if the pkgindex file contains any statement other than "package
    ifneeded" and/or if any package ifneeded loads a DLL

  - <a name='39'></a>proc __practcl::\_pkgindex\_path\_subdir__ *path*

    Helper function for ::practcl::pkgindex\_path

  - <a name='40'></a>proc __practcl::pkgindex\_path__ ?*args*?

    Index all paths given as though they will end up in the same virtual file
    system

  - <a name='41'></a>proc __practcl::installDir__ *d1* *d2*

    Delete the contents of *d2*, and then recusively Ccopy the contents of
    *d1* to *d2*\.

  - <a name='42'></a>proc __practcl::copyDir__ *d1* *d2* ?*toplevel* __1__?

    Recursively copy the contents of *d1* to *d2*

  - <a name='43'></a>proc __practcl::buildModule__ *modpath*

  - <a name='44'></a>proc __practcl::installModule__ *modpath* *DEST*

    Install a module from MODPATH to the directory specified\. *dpath* is
    assumed to be the fully qualified path where module is to be placed\. Any
    existing files will be deleted at that path\. If the path is symlink the
    process will return with no error and no action\. If the module has contents
    in the build/ directory that are newer than the \.tcl files in the module
    source directory, and a build/build\.tcl file exists, the build/build\.tcl
    file is run\. If the source directory includes a file named index\.tcl, the
    directory is assumed to be in the tao style of modules, and the entire
    directory \(and all subdirectories\) are copied verbatim\. If no index\.tcl file
    is present, all \.tcl files are copied from the module source directory, and
    a pkgIndex\.tcl file is generated if non yet exists\. I a folder named htdocs
    exists in the source directory, that directory is copied verbatim to the
    destination\.

  - <a name='45'></a>proc __practcl::trigger__ ?*args*?

    Trigger build targets, and recompute dependencies

    Internals:

        ::practcl::LOCAL make trigger {*}$args
        foreach {name obj} [::practcl::LOCAL make objects] {
          set ::make($name) [$obj do]
        }

  - <a name='46'></a>proc __practcl::depends__ ?*args*?

    Calculate if a dependency for any of the arguments needs to be fulfilled or
    rebuilt\.

    Internals:

        ::practcl::LOCAL make depends {*}$args

  - <a name='47'></a>proc __practcl::target__ *name* *info* ?*action* ____?

    Declare a build product\. This proc is just a shorthand for
    *::practcl::LOCAL make task $name $info $action*

    Registering a build product with this command will create an entry in the
    global array, and populate a value in the global array\.

    Internals:

        set obj [::practcl::LOCAL make task $name $info $action]
        set ::make($name) 0
        set filename [$obj define get filename]
        if {$filename ne {}} {
          set ::target($name) $filename
        }

# <a name='section3'></a>Classes

## <a name='subsection1'></a>Class  practcl::doctool

    { set authors {
       {John Doe} {[email protected]}
       {Tom RichardHarry} {[email protected]}
     }
     # Create the object
     ::practcl::doctool create AutoDoc
     set fout [open [file join $moddir module.tcl] w]
     foreach file [glob [file join $srcdir *.tcl]] {
       set content [::practcl::cat [file join $srcdir $file]]
        # Scan the file
        AutoDoc scan_text $content
        # Strip the comments from the distribution
        puts $fout [::practcl::docstrip $content]
     }
     # Write out the manual page
     set manout [open [file join $moddir module.man] w]
     dict set args header [string map $modmap [::practcl::cat [file join $srcdir manual.txt]]]
     dict set args footer [string map $modmap [::practcl::cat [file join $srcdir footer.txt]]]
     dict set args authors $authors
     puts $manout [AutoDoc manpage {*}$args]
     close $manout


    }

Tool for build scripts to dynamically generate manual files from comments in
source code files

__Methods__

  - <a name='48'></a>method __constructor__

  - <a name='49'></a>method __argspec__ *argspec*

    Process an argument list into an informational dict\. This method also
    understands non\-positional arguments expressed in the notation of Tip 471
    [https://core\.tcl\-lang\.org/tips/doc/trunk/tip/479\.md](https://core\.tcl\-lang\.org/tips/doc/trunk/tip/479\.md)\.

    The output will be a dictionary of all of the fields and whether the fields
    are __positional__, __mandatory__, and whether they have a
    __default__ value\.

    Example:

    my argspec {a b {c 10}}

    > a {positional 1 mandatory 1} b {positional 1 mandatory 1} c {positional 1 mandatory 0 default 10}

  - <a name='50'></a>method __[comment](\.\./\.\./\.\./\.\./index\.md\#comment)__ *block*

    Convert a block of comments into an informational dictionary\. If lines in
    the comment start with a single word ending in a colon, all subsequent lines
    are appended to a dictionary field of that name\. If no fields are given, all
    of the text is appended to the __description__ field\.

    Example:

    my comment {Does something cool}
    > description {Does something cool}

    my comment {
    title : Something really cool
    author : Sean Woods
    author : John Doe
    description :
    This does something really cool!
    }
    > description {This does something really cool!}
      title {Something really cool}
      author {Sean Woods
      John Doe}

  - <a name='51'></a>method __keyword\.Annotation__ *resultvar* *commentblock* *type* *name* *body*

  - <a name='52'></a>method __keyword\.Class__ *resultvar* *commentblock* *name* *body*

    Process an oo::objdefine call that modifies the class object itself

  - <a name='53'></a>method __keyword\.class__ *resultvar* *commentblock* *name* *body*

    Process an oo::define, clay::define, etc statement\.

  - <a name='54'></a>method __keyword\.Class\_Method__ *resultvar* *commentblock* *name* ?*args*?

    Process a statement for a clay style class method

  - <a name='55'></a>method __keyword\.method__ *resultvar* *commentblock* *name* ?*args*?

    Process a statement for a tcloo style object method

  - <a name='56'></a>method __keyword\.proc__ *commentblock* *name* *argspec*

    Process a proc statement

  - <a name='57'></a>method __reset__

    Reset the state of the object and its embedded coroutine

  - <a name='58'></a>method __Main__

    Main body of the embedded coroutine for the object

  - <a name='59'></a>method __section\.method__ *keyword* *method* *minfo*

    Generate the manual page text for a method or proc

  - <a name='60'></a>method __section\.annotation__ *type* *name* *iinfo*

  - <a name='61'></a>method __section\.class__ *class\_name* *class\_info*

    Generate the manual page text for a class

  - <a name='62'></a>method __section\.command__ *procinfo*

    Generate the manual page text for the commands section

  - <a name='63'></a>method __[manpage](\.\./\.\./\.\./\.\./index\.md\#manpage)__ ?__header *value*__? ?__footer *value*__? ?__authors *list*__?

    Generate the manual page\. Returns the completed text suitable for saving in
    \.man file\. The header argument is a block of doctools text to go in before
    the machine generated section\. footer is a block of doctools text to go in
    after the machine generated section\. authors is a list of individual authors
    and emails in the form of AUTHOR EMAIL ?AUTHOR EMAIL?\.\.\.

  - <a name='64'></a>method __scan\_text__ *text*

    Scan a block of text

  - <a name='65'></a>method __scan\_file__ *filename*

    Scan a file of text

## <a name='subsection2'></a>Class  practcl::metaclass

The metaclass for all practcl objects

__Methods__

  - <a name='66'></a>method __\_MorphPatterns__

  - <a name='67'></a>method __[define](\.\./\.\./\.\./\.\./index\.md\#define)__ *submethod* ?*args*?

  - <a name='68'></a>method __graft__ ?*args*?

  - <a name='69'></a>method __initialize__

  - <a name='70'></a>method __link__ *command* ?*args*?

  - <a name='71'></a>method __morph__ *classname*

  - <a name='72'></a>method __script__ *script*

  - <a name='73'></a>method __select__

  - <a name='74'></a>method __[source](\.\./\.\./\.\./\.\./index\.md\#source)__ *filename*

## <a name='subsection3'></a>Class  practcl::toolset

Ancestor\-less class intended to be a mixin which defines a family of build
related behaviors that are modified when targetting either gcc or msvc

__Class Methods__

  - <a name='75'></a>classmethod __select__ *object*

    Perform the selection for the toolset mixin

__Methods__

  - <a name='76'></a>method __config\.sh__

    find or fake a key/value list describing this project

  - <a name='77'></a>method __BuildDir__ *PWD*

    Compute the location where the product will be built

  - <a name='78'></a>method __MakeDir__ *srcdir*

    Return where the Makefile is located relative to *srcdir*\. For this
    implementation the MakeDir is always srcdir\.

  - <a name='79'></a>method __read\_configuration__

    Read information about the build process for this package\. For this
    implementation, data is sought in the following locations in the following
    order: config\.tcl \(generated by practcl\.\) PKGConfig\.sh\. The Makefile

    If the Makefile needs to be consulted, but does not exist, the Configure
    method is invoked

  - <a name='80'></a>method __build\-cflags__ *PROJECT* *DEFS* *namevar* *versionvar* *defsvar*

    method DEFS This method populates 4 variables: name \- The name of the
    package version \- The version of the package defs \- C flags passed to the
    compiler includedir \- A list of paths to feed to the compiler for finding
    headers

  - <a name='81'></a>method __critcl__ ?*args*?

    Invoke critcl in an external process

## <a name='subsection4'></a>Class  practcl::toolset\.gcc

*ancestors*: __practcl::toolset__

__Methods__

  - <a name='82'></a>method __Autoconf__

  - <a name='83'></a>method __BuildDir__ *PWD*

  - <a name='84'></a>method __ConfigureOpts__

  - <a name='85'></a>method __MakeDir__ *srcdir*

    Detect what directory contains the Makefile template

  - <a name='86'></a>method __make \{\} autodetect__

  - <a name='87'></a>method __make \{\} clean__

  - <a name='88'></a>method __make \{\} compile__

  - <a name='89'></a>method __make \{\} install__ *DEST*

  - <a name='90'></a>method __build\-compile\-sources__ *PROJECT* *COMPILE* *CPPCOMPILE* *INCLUDES*

  - <a name='91'></a>method __build\-Makefile__ *path* *PROJECT*

  - <a name='92'></a>method __build\-library__ *outfile* *PROJECT*

    Produce a static or dynamic library

  - <a name='93'></a>method __build\-tclsh__ *outfile* *PROJECT* ?*path* __auto__?

    Produce a static executable

## <a name='subsection5'></a>Class  practcl::toolset\.msvc

*ancestors*: __practcl::toolset__

__Methods__

  - <a name='94'></a>method __BuildDir__ *PWD*

    MSVC always builds in the source directory

  - <a name='95'></a>method __make \{\} autodetect__

    Do nothing

  - <a name='96'></a>method __make \{\} clean__

  - <a name='97'></a>method __make \{\} compile__

  - <a name='98'></a>method __make \{\} install__ *DEST*

  - <a name='99'></a>method __MakeDir__ *srcdir*

    Detect what directory contains the Makefile template

  - <a name='100'></a>method __NmakeOpts__

## <a name='subsection6'></a>Class  practcl::make\_obj

*ancestors*: __practcl::metaclass__

A build deliverable object\. Normally an object file, header, or tcl script which
must be compiled or generated in some way

__Methods__

  - <a name='101'></a>method __constructor__ *module\_object* *name* *info* ?*action\_body* ____?

  - <a name='102'></a>method __[do](\.\./\.\./\.\./\.\./index\.md\#do)__

  - <a name='103'></a>method __check__

  - <a name='104'></a>method __output__

  - <a name='105'></a>method __reset__

  - <a name='106'></a>method __triggers__

## <a name='subsection7'></a>Class  practcl::object

*ancestors*: __practcl::metaclass__

A generic Practcl object

__Methods__

  - <a name='107'></a>method __constructor__ *parent* ?*args*?

  - <a name='108'></a>method __child__ *method*

  - <a name='109'></a>method __go__

## <a name='subsection8'></a>Class  practcl::dynamic

Dynamic blocks do not generate their own \.c files, instead the contribute to the
amalgamation of the main library file

__Methods__

  - <a name='110'></a>method __cstructure__ *name* *definition* ?*argdat* ____?

    Parser functions

  - <a name='111'></a>method __include__ *header*

  - <a name='112'></a>method __include\_dir__ ?*args*?

  - <a name='113'></a>method __include\_directory__ ?*args*?

  - <a name='114'></a>method __c\_header__ *body*

  - <a name='115'></a>method __c\_code__ *body*

  - <a name='116'></a>method __c\_function__ *header* *body* ?*info* ____?

  - <a name='117'></a>method __c\_tcloomethod__ *name* *body* ?*arginfo* ____?

  - <a name='118'></a>method __cmethod__ *name* *body* ?*arginfo* ____?

    Alias to classic name

  - <a name='119'></a>method __c\_tclproc\_nspace__ *nspace*

  - <a name='120'></a>method __c\_tclcmd__ *name* *body* ?*arginfo* ____?

  - <a name='121'></a>method __c\_tclproc\_raw__ *name* *body* ?*arginfo* ____?

    Alias to classic name

  - <a name='122'></a>method __tcltype__ *name* *argdat*

  - <a name='123'></a>method __project\-compile\-products__

    Module interactions

  - <a name='124'></a>method __implement__ *path*

  - <a name='125'></a>method __initialize__

    Practcl internals

  - <a name='126'></a>method __linktype__

  - <a name='127'></a>method __generate\-cfile\-constant__

  - <a name='128'></a>method __generate\-cfile\-header__

  - <a name='129'></a>method __generate\-cfile\-tclapi__

    Generate code that provides implements Tcl API calls

  - <a name='130'></a>method __generate\-loader\-module__

    Generate code that runs when the package/module is initialized into the
    interpreter

  - <a name='131'></a>method __Collate\_Source__ *CWD*

  - <a name='132'></a>method __select__

    Once an object marks itself as some flavor of dynamic, stop trying to morph
    it into something else

## <a name='subsection9'></a>Class  practcl::product

A deliverable for the build system

__Class Methods__

  - <a name='133'></a>classmethod __select__ *object*

__Methods__

  - <a name='134'></a>method __code__ *section* *body*

  - <a name='135'></a>method __Collate\_Source__ *CWD*

  - <a name='136'></a>method __project\-compile\-products__

  - <a name='137'></a>method __generate\-debug__ ?*spaces* ____?

  - <a name='138'></a>method __generate\-cfile\-constant__

  - <a name='139'></a>method __generate\-cfile\-public\-structure__

    Populate const static data structures

  - <a name='140'></a>method __generate\-cfile\-header__

  - <a name='141'></a>method __generate\-cfile\-global__

  - <a name='142'></a>method __generate\-cfile\-private\-typedef__

  - <a name='143'></a>method __generate\-cfile\-private\-structure__

  - <a name='144'></a>method __generate\-cfile\-functions__

    Generate code that provides subroutines called by Tcl API methods

  - <a name='145'></a>method __generate\-cfile\-tclapi__

    Generate code that provides implements Tcl API calls

  - <a name='146'></a>method __generate\-hfile\-public\-define__

  - <a name='147'></a>method __generate\-hfile\-public\-macro__

  - <a name='148'></a>method __generate\-hfile\-public\-typedef__

  - <a name='149'></a>method __generate\-hfile\-public\-structure__

  - <a name='150'></a>method __generate\-hfile\-public\-headers__

  - <a name='151'></a>method __generate\-hfile\-public\-function__

  - <a name='152'></a>method __generate\-hfile\-public\-includes__

  - <a name='153'></a>method __generate\-hfile\-public\-verbatim__

  - <a name='154'></a>method __generate\-loader\-external__

  - <a name='155'></a>method __generate\-loader\-module__

  - <a name='156'></a>method __generate\-stub\-function__

  - <a name='157'></a>method __IncludeAdd__ *headervar* ?*args*?

  - <a name='158'></a>method __generate\-tcl\-loader__

  - <a name='159'></a>method __generate\-tcl\-pre__

    This methods generates any Tcl script file which is required to
    pre\-initialize the C library

  - <a name='160'></a>method __generate\-tcl\-post__

  - <a name='161'></a>method __linktype__

  - <a name='162'></a>method __Ofile__ *filename*

  - <a name='163'></a>method __project\-static\-packages__

    Methods called by the master project

  - <a name='164'></a>method __toolset\-include\-directory__

    Methods called by the toolset

  - <a name='165'></a>method __target__ *method* ?*args*?

## <a name='subsection10'></a>Class  practcl::product\.cheader

*ancestors*: __practcl::product__

A product which generated from a C header file\. Which is to say, nothing\.

__Methods__

  - <a name='166'></a>method __project\-compile\-products__

  - <a name='167'></a>method __generate\-loader\-module__

## <a name='subsection11'></a>Class  practcl::product\.csource

*ancestors*: __practcl::product__

A product which generated from a C source file\. Normally an object \(\.o\) file\.

__Methods__

  - <a name='168'></a>method __project\-compile\-products__

## <a name='subsection12'></a>Class  practcl::product\.clibrary

*ancestors*: __practcl::product__

A product which is generated from a compiled C library\. Usually a \.a or a \.dylib
file, but in complex cases may actually just be a conduit for one project to
integrate the source code of another

__Methods__

  - <a name='169'></a>method __linker\-products__ *configdict*

## <a name='subsection13'></a>Class  practcl::product\.dynamic

*ancestors*: __practcl::dynamic__ __practcl::product__

A product which is generated from C code that itself is generated by practcl or
some other means\. This C file may or may not produce its own \.o file, depending
on whether it is eligible to become part of an amalgamation

__Methods__

  - <a name='170'></a>method __initialize__

## <a name='subsection14'></a>Class  practcl::product\.critcl

*ancestors*: __practcl::dynamic__ __practcl::product__

A binary product produced by critcl\. Note: The implementation is not written
yet, this class does nothing\.

## <a name='subsection15'></a>Class  practcl::module

*ancestors*: __practcl::object__ __practcl::product\.dynamic__

In the end, all C code must be loaded into a module This will either be a
dynamically loaded library implementing a tcl extension, or a compiled in
segment of a custom shell/app

__Variable__

  - <a name='171'></a>variable __make\_object__

__Methods__

  - <a name='172'></a>method __\_MorphPatterns__

  - <a name='173'></a>method __add__ ?*args*?

  - <a name='174'></a>method __install\-headers__ ?*args*?

  - <a name='175'></a>method __make \{\} \_preamble__

  - <a name='176'></a>method __make \{\} pkginfo__

  - <a name='177'></a>method __make \{\} objects__

    Return a dictionary of all handles and associated objects

  - <a name='178'></a>method __make \{\} object__ *name*

    Return the object associated with handle *name*

  - <a name='179'></a>method __make \{\} reset__

    Reset all deputy objects

  - <a name='180'></a>method __make \{\} trigger__ ?*args*?

    Exercise the triggers method for all handles listed

  - <a name='181'></a>method __make \{\} depends__ ?*args*?

    Exercise the check method for all handles listed

  - <a name='182'></a>method __make \{\} filename__ *name*

    Return the file name of the build product for the listed handle

  - <a name='183'></a>method __make \{\} target__ *name* *Info* *body*

  - <a name='184'></a>method __make \{\} todo__

    Return a list of handles for object which return true for the do method

  - <a name='185'></a>method __make \{\} do__

    For each target exercise the action specified in the *action* definition
    if the *do* method returns true

  - <a name='186'></a>method __child__ *which*

  - <a name='187'></a>method __generate\-c__

    This methods generates the contents of an amalgamated \.c file which
    implements the loader for a batch of tools

  - <a name='188'></a>method __generate\-h__

    This methods generates the contents of an amalgamated \.h file which
    describes the public API of this module

  - <a name='189'></a>method __generate\-loader__

  - <a name='190'></a>method __initialize__

  - <a name='191'></a>method __implement__ *path*

  - <a name='192'></a>method __linktype__

## <a name='subsection16'></a>Class  practcl::project

*ancestors*: __practcl::module__

A toplevel project that is a collection of other projects

__Methods__

  - <a name='193'></a>method __\_MorphPatterns__

  - <a name='194'></a>method __constructor__ ?*args*?

  - <a name='195'></a>method __add\_object__ *object*

  - <a name='196'></a>method __add\_project__ *pkg* *info* ?*oodefine* ____?

  - <a name='197'></a>method __add\_tool__ *pkg* *info* ?*oodefine* ____?

  - <a name='198'></a>method __build\-tclcore__

    Compile the Tcl core\. If the define *tk* is true, compile the Tk core as
    well

  - <a name='199'></a>method __child__ *which*

  - <a name='200'></a>method __linktype__

  - <a name='201'></a>method __project__ *pkg* ?*args*?

    Exercise the methods of a sub\-object

  - <a name='202'></a>method __tclcore__

  - <a name='203'></a>method __tkcore__

  - <a name='204'></a>method __[tool](\.\./tool/tool\.md)__ *pkg* ?*args*?

## <a name='subsection17'></a>Class  practcl::library

*ancestors*: __practcl::project__

A toplevel project that produces a library

__Methods__

  - <a name='205'></a>method __clean__ *PATH*

  - <a name='206'></a>method __project\-compile\-products__

  - <a name='207'></a>method __go__

  - <a name='208'></a>method __generate\-decls__ *pkgname* *path*

  - <a name='209'></a>method __implement__ *path*

  - <a name='210'></a>method __generate\-make__ *path*

    Backward compadible call

  - <a name='211'></a>method __linktype__

  - <a name='212'></a>method __package\-ifneeded__ ?*args*?

    Create a "package ifneeded" Args are a list of aliases for which this
    package will answer to

  - <a name='213'></a>method __shared\_library__ ?*filename* ____?

  - <a name='214'></a>method __static\_library__ ?*filename* ____?

## <a name='subsection18'></a>Class  practcl::tclkit

*ancestors*: __practcl::library__

A toplevel project that produces a self\-contained executable

__Methods__

  - <a name='215'></a>method __build\-tclkit\_main__ *PROJECT* *PKG\_OBJS*

  - <a name='216'></a>method __Collate\_Source__ *CWD*

  - <a name='217'></a>method __wrap__ *PWD* *exename* *vfspath* ?*args*?

    Wrap an executable

## <a name='subsection19'></a>Class  practcl::distribution

Standalone class to manage code distribution This class is intended to be mixed
into another class \(Thus the lack of ancestors\)

__Class Methods__

  - <a name='218'></a>classmethod __Sandbox__ *object*

  - <a name='219'></a>classmethod __select__ *object*

  - <a name='220'></a>classmethod __claim\_option__

  - <a name='221'></a>classmethod __claim\_object__ *object*

  - <a name='222'></a>classmethod __claim\_path__ *path*

__Methods__

  - <a name='223'></a>method __scm\_info__

  - <a name='224'></a>method __DistroMixIn__

  - <a name='225'></a>method __Sandbox__

  - <a name='226'></a>method __SrcDir__

  - <a name='227'></a>method __ScmTag__

  - <a name='228'></a>method __ScmClone__

  - <a name='229'></a>method __ScmUnpack__

  - <a name='230'></a>method __ScmUpdate__

  - <a name='231'></a>method __Unpack__

## <a name='subsection20'></a>Class  practcl::distribution\.snapshot

*ancestors*: __practcl::distribution__

A file distribution from zip, tarball, or other non\-scm archive format

__Class Methods__

  - <a name='232'></a>classmethod __claim\_object__ *object*

  - <a name='233'></a>classmethod __claim\_option__

  - <a name='234'></a>classmethod __claim\_path__ *path*

__Methods__

  - <a name='235'></a>method __ScmUnpack__

## <a name='subsection21'></a>Class  practcl::distribution\.fossil

*ancestors*: __practcl::distribution__

A file distribution based on fossil

__Class Methods__

  - <a name='236'></a>classmethod __claim\_object__ *obj*

    Check for markers in the metadata

  - <a name='237'></a>classmethod __claim\_option__

  - <a name='238'></a>classmethod __claim\_path__ *path*

    Check for markers in the source root

__Methods__

  - <a name='239'></a>method __scm\_info__

  - <a name='240'></a>method __ScmClone__

    Clone the source

  - <a name='241'></a>method __ScmTag__

  - <a name='242'></a>method __ScmUnpack__

  - <a name='243'></a>method __ScmUpdate__

## <a name='subsection22'></a>Class  practcl::distribution\.git

*ancestors*: __practcl::distribution__

A file distribution based on git

__Class Methods__

  - <a name='244'></a>classmethod __claim\_object__ *obj*

  - <a name='245'></a>classmethod __claim\_option__

  - <a name='246'></a>classmethod __claim\_path__ *path*

__Methods__

  - <a name='247'></a>method __ScmTag__

  - <a name='248'></a>method __ScmUnpack__

  - <a name='249'></a>method __ScmUpdate__

## <a name='subsection23'></a>Class  practcl::subproject

*ancestors*: __practcl::module__

A subordinate project

__Methods__

  - <a name='250'></a>method __\_MorphPatterns__

  - <a name='251'></a>method __BuildDir__ *PWD*

  - <a name='252'></a>method __child__ *which*

  - <a name='253'></a>method __compile__

  - <a name='254'></a>method __go__

  - <a name='255'></a>method __install__ ?*args*?

    Install project into the local build system

  - <a name='256'></a>method __linktype__

  - <a name='257'></a>method __linker\-products__ *configdict*

  - <a name='258'></a>method __linker\-external__ *configdict*

  - <a name='259'></a>method __linker\-extra__ *configdict*

  - <a name='260'></a>method __env\-bootstrap__

    Methods for packages/tools that can be downloaded possibly built and used
    internally by this Practcl process Load the facility into the interpreter

  - <a name='261'></a>method __env\-exec__

    Return a file path that exec can call

  - <a name='262'></a>method __env\-install__

    Install the tool into the local environment

  - <a name='263'></a>method __env\-load__

    Do whatever is necessary to get the tool into the local environment

  - <a name='264'></a>method __env\-present__

    Check if tool is available for load/already loaded

  - <a name='265'></a>method __sources__

  - <a name='266'></a>method __[update](\.\./\.\./\.\./\.\./index\.md\#update)__

  - <a name='267'></a>method __unpack__

## <a name='subsection24'></a>Class  practcl::subproject\.source

*ancestors*: __practcl::subproject__ __practcl::library__

A project which the kit compiles and integrates the source for itself

__Methods__

  - <a name='268'></a>method __env\-bootstrap__

  - <a name='269'></a>method __env\-present__

  - <a name='270'></a>method __linktype__

## <a name='subsection25'></a>Class  practcl::subproject\.teapot

*ancestors*: __practcl::subproject__

a copy from the teapot

__Methods__

  - <a name='271'></a>method __env\-bootstrap__

  - <a name='272'></a>method __env\-install__

  - <a name='273'></a>method __env\-present__

  - <a name='274'></a>method __install__ *DEST*

## <a name='subsection26'></a>Class  practcl::subproject\.kettle

*ancestors*: __practcl::subproject__

__Methods__

  - <a name='275'></a>method __kettle__ *path* ?*args*?

  - <a name='276'></a>method __install__ *DEST*

## <a name='subsection27'></a>Class  practcl::subproject\.critcl

*ancestors*: __practcl::subproject__

__Methods__

  - <a name='277'></a>method __install__ *DEST*

## <a name='subsection28'></a>Class  practcl::subproject\.sak

*ancestors*: __practcl::subproject__

__Methods__

  - <a name='278'></a>method __env\-bootstrap__

  - <a name='279'></a>method __env\-install__

  - <a name='280'></a>method __env\-present__

  - <a name='281'></a>method __install__ *DEST*

  - <a name='282'></a>method __install\-module__ *DEST* ?*args*?

## <a name='subsection29'></a>Class  practcl::subproject\.practcl

*ancestors*: __practcl::subproject__

__Methods__

  - <a name='283'></a>method __env\-bootstrap__

  - <a name='284'></a>method __env\-install__

  - <a name='285'></a>method __install__ *DEST*

  - <a name='286'></a>method __install\-module__ *DEST* ?*args*?

## <a name='subsection30'></a>Class  practcl::subproject\.binary

*ancestors*: __practcl::subproject__

A subordinate binary package

__Methods__

  - <a name='287'></a>method __clean__

  - <a name='288'></a>method __env\-install__

  - <a name='289'></a>method __project\-compile\-products__

  - <a name='290'></a>method __ComputeInstall__

  - <a name='291'></a>method __go__

  - <a name='292'></a>method __linker\-products__ *configdict*

  - <a name='293'></a>method __project\-static\-packages__

  - <a name='294'></a>method __BuildDir__ *PWD*

  - <a name='295'></a>method __compile__

  - <a name='296'></a>method __Configure__

  - <a name='297'></a>method __install__ *DEST*

## <a name='subsection31'></a>Class  practcl::subproject\.tea

*ancestors*: __practcl::subproject\.binary__

A subordinate TEA based binary package

## <a name='subsection32'></a>Class  practcl::subproject\.library

*ancestors*: __practcl::subproject\.binary__ __practcl::library__

A subordinate C library built by this project

__Methods__

  - <a name='298'></a>method __install__ *DEST*

## <a name='subsection33'></a>Class  practcl::subproject\.external

*ancestors*: __practcl::subproject\.binary__

A subordinate external C library

__Methods__

  - <a name='299'></a>method __install__ *DEST*

## <a name='subsection34'></a>Class  practcl::subproject\.core

*ancestors*: __practcl::subproject\.binary__

__Methods__

  - <a name='300'></a>method __env\-bootstrap__

  - <a name='301'></a>method __env\-present__

  - <a name='302'></a>method __env\-install__

  - <a name='303'></a>method __go__

  - <a name='304'></a>method __linktype__

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *practcl* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

When proposing code changes, please provide *unified diffs*, i\.e the output of

Changes to embedded/md/tcllib/files/modules/profiler/profiler.md.

1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (profiler \- Tcl Profiler)
[//000000002]: # (Generated from file 'profiler\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (profiler\(n\) 0\.3 tcllib "Tcl Profiler")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|







1
2
3
4
5
6
7
8
9
10
11

[//000000001]: # (profiler \- Tcl Profiler)
[//000000002]: # (Generated from file 'profiler\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (profiler\(n\) 0\.5 tcllib "Tcl Profiler")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43


44
45
46
47
48
49
50
51
  - [Keywords](#keywords)

  - [Category](#category)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.3  
package require profiler ?0\.3?  

[__::profiler::init__](#1)  
[__::profiler::dump__ *pattern*](#2)  
[__::profiler::print__ ?*pattern*?](#3)  
[__::profiler::reset__ ?*pattern*?](#4)  
[__::profiler::suspend__ ?*pattern*?](#5)  
[__::profiler::resume__ ?*pattern*?](#6)  


[__::profiler::sortFunctions__ *key*](#7)  

# <a name='description'></a>DESCRIPTION

The __profiler__ package provides a simple Tcl source code profiler\. It is a
function\-level profiler; that is, it collects only function\-level information,
not the more detailed line\-level information\. It operates by redefining the Tcl
__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ command\. Profiling is initiated







|







>
>
|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  - [Keywords](#keywords)

  - [Category](#category)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.3  
package require profiler ?0\.5?  

[__::profiler::init__](#1)  
[__::profiler::dump__ *pattern*](#2)  
[__::profiler::print__ ?*pattern*?](#3)  
[__::profiler::reset__ ?*pattern*?](#4)  
[__::profiler::suspend__ ?*pattern*?](#5)  
[__::profiler::resume__ ?*pattern*?](#6)  
[__::profiler::new\-disabled__](#7)  
[__::profiler::new\-enabled__](#8)  
[__::profiler::sortFunctions__ *key*](#9)  

# <a name='description'></a>DESCRIPTION

The __profiler__ package provides a simple Tcl source code profiler\. It is a
function\-level profiler; that is, it collects only function\-level information,
not the more detailed line\-level information\. It operates by redefining the Tcl
__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ command\. Profiling is initiated
118
119
120
121
122
123
124
125














126
127
128
129
130
131
132

  - <a name='6'></a>__::profiler::resume__ ?*pattern*?

    Resume profiling for all functions matching *pattern*\. If no pattern is
    specified, profiling will be resumed for all functions\. This command should
    be invoked after suspending the profiler in the code\.

  - <a name='7'></a>__::profiler::sortFunctions__ *key*















    Return a list of functions sorted by a particular profiling statistic\.
    Supported values for *key* are: __calls__, __exclusiveTime__,
    __compileTime__, __nonCompileTime__, __totalRuntime__,
    __avgExclusiveTime__, and __avgRuntime__\. The return result is a
    list of lists, where each sublist consists of a function name and the value
    of *key* for that function\.







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

  - <a name='6'></a>__::profiler::resume__ ?*pattern*?

    Resume profiling for all functions matching *pattern*\. If no pattern is
    specified, profiling will be resumed for all functions\. This command should
    be invoked after suspending the profiler in the code\.

  - <a name='7'></a>__::profiler::new\-disabled__

    Change the initial profiling state for new procedures\. Invoking this command
    disables profiling for all procedures created after this command until
    __new\-enabled__ is invoked\. Activate profiling of specific procedures
    via __resume__\.

  - <a name='8'></a>__::profiler::new\-enabled__

    Change the initial profiling state for new procedures\. Invoking this command
    enables profiling for all procedures created after this command until
    __new\-disabled__ is invoked\. Prevent profiling of specific procedures
    via __suspend__\.

  - <a name='9'></a>__::profiler::sortFunctions__ *key*

    Return a list of functions sorted by a particular profiling statistic\.
    Supported values for *key* are: __calls__, __exclusiveTime__,
    __compileTime__, __nonCompileTime__, __totalRuntime__,
    __avgExclusiveTime__, and __avgRuntime__\. The return result is a
    list of lists, where each sublist consists of a function name and the value
    of *key* for that function\.

Changes to embedded/md/tcllib/files/modules/pt/pt_astree.md.

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
      1. The string representation of the value is the canonical representation
         of a pure Tcl list\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection1'></a>Example

Assuming the parsing expression grammar below

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

and the input string

    120\+5

then a parser should deliver the abstract syntax tree below \(except for
whitespace\)

    set ast \{Expression 0 4
        \{Factor 0 4
            \{Term 0 2
                \{Number 0 2
                    \{Digit 0 0\}
                    \{Digit 1 1\}
                    \{Digit 2 2\}
                \}
            \}


            \{AddOp 3 3\}
            \{Term 4 4
                \{Number 4 4
                    \{Digit 4 4\}
                \}
            \}
        \}
    \}





Or, more graphical

![](\.\./\.\./\.\./\.\./image/expr\_ast\.png)

# <a name='section4'></a>Bugs, Ideas, Feedback








|
|
|
|
|
|
|
|
|




|




|
|
|
|
|
|
|
<
<
>
>
|
|
|
|
<
<
<
<
>
>
>
>







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
      1. The string representation of the value is the canonical representation
         of a pure Tcl list\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection1'></a>Example

Assuming the parsing expression grammar below

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

and the input string

    120+5

then a parser should deliver the abstract syntax tree below \(except for
whitespace\)

    set ast {Expression 0 4
        {Factor 0 4
            {Term 0 2
                {Number 0 2
                    {Digit 0 0}
                    {Digit 1 1}
                    {Digit 2 2}


                }
            }
            {AddOp 3 3}
            {Term 4 4
                {Number 4 4
                    {Digit 4 4}




                }
            }
        }
    }

Or, more graphical

![](\.\./\.\./\.\./\.\./image/expr\_ast\.png)

# <a name='section4'></a>Bugs, Ideas, Feedback

Changes to embedded/md/tcllib/files/modules/pt/pt_from_api.md.

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
     the plugin in a state where another usage cycle can be run without
     problems\.

# <a name='section4'></a>Usage

To use a converter do

    \# Get the converter \(single command here, not class\)
    package require the\-converter\-package

    \# Perform the conversion
    set serial \[theconverter convert $thegrammartext\]

    \.\.\. process the result \.\.\.

To use a plugin __FOO__ do

    \# Get an import plugin manager
    package require pt::peg::import
    pt::peg::import I

    \# Run the plugin, and the converter inside\.
    set serial \[I import serial $thegrammartext FOO\]

    \.\.\. process the result \.\.\.

# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a PEG







|
|

|
|

|



|



|
|

|







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
     the plugin in a state where another usage cycle can be run without
     problems\.

# <a name='section4'></a>Usage

To use a converter do

    # Get the converter (single command here, not class)
    package require the-converter-package

    # Perform the conversion
    set serial [theconverter convert $thegrammartext]

    ... process the result ...

To use a plugin __FOO__ do

    # Get an import plugin manager
    package require pt::peg::import
    pt::peg::import I

    # Run the plugin, and the converter inside.
    set serial [I import serial $thegrammartext FOO]

    ... process the result ...

# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a PEG
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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection2'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection2'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_json_language.md.

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
themselves are not translated further, but kept as JSON strings containing a
nested Tcl list, and there is no concept of canonicity for the JSON either\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

a JSON serialization for it is

    \{

        "pt::grammar::peg" : \{
            "rules" : \{
                "AddOp"     : \{
                    "is"   : "\\/ \{t \-\} \{t \+\}",
                    "mode" : "value"
                \},
                "Digit"     : \{
                    "is"   : "\\/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}",
                    "mode" : "value"
                \},
                "Expression" : \{
                    "is"   : "\\/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}",
                    "mode" : "value"
                \},
                "Factor"    : \{
                    "is"   : "x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}",
                    "mode" : "value"
                \},
                "MulOp"     : \{
                    "is"   : "\\/ \{t \*\} \{t \\/\}",
                    "mode" : "value"
                \},
                "Number"    : \{
                    "is"   : "x \{? \{n Sign\}\} \{\+ \{n Digit\}\}",
                    "mode" : "value"
                \},
                "Sign"      : \{
                    "is"   : "\\/ \{t \-\} \{t \+\}",
                    "mode" : "value"
                \},
                "Term"      : \{
                    "is"   : "n Number",
                    "mode" : "value"
                \}

            \},
            "start" : "n Expression"
        \}
    \}



and a Tcl serialization of the same is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


The similarity of the latter to the JSON should be quite obvious\.

# <a name='section2'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.







|
|
|
|
|
|
|
|
|




<
>
|
|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|


<
>
|

<
<
|
>
>


|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
themselves are not translated further, but kept as JSON strings containing a
nested Tcl list, and there is no concept of canonicity for the JSON either\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

a JSON serialization for it is


    {
        "pt::grammar::peg" : {
            "rules" : {
                "AddOp"     : {
                    "is"   : "\/ {t -} {t +}",
                    "mode" : "value"
                },
                "Digit"     : {
                    "is"   : "\/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}",
                    "mode" : "value"
                },
                "Expression" : {
                    "is"   : "\/ {x {t (} {n Expression} {t )}} {x {n Factor} {* {x {n MulOp} {n Factor}}}}",
                    "mode" : "value"
                },
                "Factor"    : {
                    "is"   : "x {n Term} {* {x {n AddOp} {n Term}}}",
                    "mode" : "value"
                },
                "MulOp"     : {
                    "is"   : "\/ {t *} {t \/}",
                    "mode" : "value"
                },
                "Number"    : {
                    "is"   : "x {? {n Sign}} {+ {n Digit}}",
                    "mode" : "value"
                },
                "Sign"      : {
                    "is"   : "\/ {t -} {t +}",
                    "mode" : "value"
                },
                "Term"      : {
                    "is"   : "n Number",
                    "mode" : "value"

                }
            },
            "start" : "n Expression"


        }
    }

and a Tcl serialization of the same is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

The similarity of the latter to the JSON should be quite obvious\.

# <a name='section2'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.
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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section3'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section3'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_param.md.

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
__[pt::rde](pt\_rdengine\.md)__, is not only coded in Tcl, but also relies
on Tcl commands to provide it with control flow \(instructions\)\.

# <a name='section4'></a>Interaction of the Instructions with the Architectural State

    Instruction		Inputs				Outputs
    ======================= =======================		====================
    ast\_pop\_discard		AS			\->	AS
    ast\_pop\_rewind		AS			\->	AS, ARS
    ast\_push		ARS, AS			\->	AS
    ast\_value\_push		SV, ARS			\->	ARS
    ======================= =======================		====================
    error\_clear		\-			\->	ER
    error\_nonterminal sym	ER, LS			\->	ER
    error\_pop\_merge   	ES, ER			\->	ER
    error\_push		ES, ER			\->	ES
    ======================= =======================		====================
    input\_next msg		IN			\->	TC, CL, CC, ST, ER
    ======================= =======================		====================
    loc\_pop\_discard		LS			\->	LS
    loc\_pop\_rewind		LS			\->	LS, CL
    loc\_push		CL, LS			\->	LS
    ======================= =======================		====================
    status\_fail		\-			\->	ST
    status\_negate		ST			\->	ST
    status\_ok		\-			\->	ST
    ======================= =======================		====================
    symbol\_restore sym	NC			\->	CL, ST, ER, SV
    symbol\_save    sym	CL, ST, ER, SV LS	\->	NC
    ======================= =======================		====================
    test\_alnum  		CC			\->	ST, ER
    test\_alpha		CC			\->	ST, ER
    test\_ascii		CC			\->	ST, ER
    test\_char char		CC			\->	ST, ER
    test\_ddigit		CC			\->	ST, ER
    test\_digit		CC			\->	ST, ER
    test\_graph		CC			\->	ST, ER
    test\_lower		CC			\->	ST, ER
    test\_print		CC			\->	ST, ER
    test\_punct		CC			\->	ST, ER
    test\_range chars chare	CC			\->	ST, ER
    test\_space		CC			\->	ST, ER
    test\_upper		CC			\->	ST, ER
    test\_wordchar		CC			\->	ST, ER
    test\_xdigit		CC			\->	ST, ER
    ======================= =======================		====================
    value\_clear		\-			\->	SV
    value\_leaf symbol	LS, CL			\->	SV
    value\_reduce symbol	ARS, LS, CL		\->	SV
    ======================= =======================		====================

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas







|
|
|
|

|
|
|
|

|

|
|
|

|
|
|

|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|







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
__[pt::rde](pt\_rdengine\.md)__, is not only coded in Tcl, but also relies
on Tcl commands to provide it with control flow \(instructions\)\.

# <a name='section4'></a>Interaction of the Instructions with the Architectural State

    Instruction		Inputs				Outputs
    ======================= =======================		====================
    ast_pop_discard		AS			->	AS
    ast_pop_rewind		AS			->	AS, ARS
    ast_push		ARS, AS			->	AS
    ast_value_push		SV, ARS			->	ARS
    ======================= =======================		====================
    error_clear		-			->	ER
    error_nonterminal sym	ER, LS			->	ER
    error_pop_merge   	ES, ER			->	ER
    error_push		ES, ER			->	ES
    ======================= =======================		====================
    input_next msg		IN			->	TC, CL, CC, ST, ER
    ======================= =======================		====================
    loc_pop_discard		LS			->	LS
    loc_pop_rewind		LS			->	LS, CL
    loc_push		CL, LS			->	LS
    ======================= =======================		====================
    status_fail		-			->	ST
    status_negate		ST			->	ST
    status_ok		-			->	ST
    ======================= =======================		====================
    symbol_restore sym	NC			->	CL, ST, ER, SV
    symbol_save    sym	CL, ST, ER, SV LS	->	NC
    ======================= =======================		====================
    test_alnum  		CC			->	ST, ER
    test_alpha		CC			->	ST, ER
    test_ascii		CC			->	ST, ER
    test_char char		CC			->	ST, ER
    test_ddigit		CC			->	ST, ER
    test_digit		CC			->	ST, ER
    test_graph		CC			->	ST, ER
    test_lower		CC			->	ST, ER
    test_print		CC			->	ST, ER
    test_punct		CC			->	ST, ER
    test_range chars chare	CC			->	ST, ER
    test_space		CC			->	ST, ER
    test_upper		CC			->	ST, ER
    test_wordchar		CC			->	ST, ER
    test_xdigit		CC			->	ST, ER
    ======================= =======================		====================
    value_clear		-			->	SV
    value_leaf symbol	LS, CL			->	SV
    value_reduce symbol	ARS, LS, CL		->	SV
    ======================= =======================		====================

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas

Changes to embedded/md/tcllib/files/modules/pt/pt_parser_api.md.

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
    This method runs the parser using the string in *text* as input\. In all
    other ways it behaves like the method __parse__, shown above\.

# <a name='section4'></a>Usage

A generated parser is used like this

    package require the\-parser\-package ;\# Generated by result\-formats 'critcl', 'snit' or 'oo' of 'pt'\.
    set parser \[the\-parser\-class\]

    set ast \[$parser parse $channel\]
    \.\.\. process the abstract syntax tree \.\.\.

When using a grammar interpreter for parsing some differences creep in

    package require the\-grammar\-package ;\# Generated by result\-format 'container' of 'pt'\.
    set grammar \[the\-grammar\-class\]

    package require pt::peg::interp
    set parser \[pt::peg::interp\]

    $parser use $grammar

    set ast \[$parser parse $channel\]
    $parser destroy

    \.\.\. process the abstract syntax tree \.\.\.

# <a name='section5'></a>AST serialization format

Here we specify the format used by the Parser Tools to serialize Abstract Syntax
Trees \(ASTs\) as immutable values for transport, comparison, etc\.

Each node in an AST represents a nonterminal symbol of a grammar, and the range







|
|

|
|



|
|


|



|


|







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
    This method runs the parser using the string in *text* as input\. In all
    other ways it behaves like the method __parse__, shown above\.

# <a name='section4'></a>Usage

A generated parser is used like this

    package require the-parser-package ;# Generated by result-formats 'critcl', 'snit' or 'oo' of 'pt'.
    set parser [the-parser-class]

    set ast [$parser parse $channel]
    ... process the abstract syntax tree ...

When using a grammar interpreter for parsing some differences creep in

    package require the-grammar-package ;# Generated by result-format 'container' of 'pt'.
    set grammar [the-grammar-class]

    package require pt::peg::interp
    set parser [pt::peg::interp]

    $parser use $grammar

    set ast [$parser parse $channel]
    $parser destroy

    ... process the abstract syntax tree ...

# <a name='section5'></a>AST serialization format

Here we specify the format used by the Parser Tools to serialize Abstract Syntax
Trees \(ASTs\) as immutable values for transport, comparison, etc\.

Each node in an AST represents a nonterminal symbol of a grammar, and the range
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
      1. The string representation of the value is the canonical representation
         of a pure Tcl list\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection1'></a>Example

Assuming the parsing expression grammar below

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

and the input string

    120\+5

then a parser should deliver the abstract syntax tree below \(except for
whitespace\)

    set ast \{Expression 0 4
        \{Factor 0 4
            \{Term 0 2
                \{Number 0 2
                    \{Digit 0 0\}
                    \{Digit 1 1\}
                    \{Digit 2 2\}
                \}
            \}


            \{AddOp 3 3\}
            \{Term 4 4
                \{Number 4 4
                    \{Digit 4 4\}
                \}
            \}
        \}
    \}





Or, more graphical

![](\.\./\.\./\.\./\.\./image/expr\_ast\.png)

# <a name='section6'></a>PE serialization format








|
|
|
|
|
|
|
|
|




|




|
|
|
|
|
|
|
<
<
>
>
|
|
|
|
<
<
<
<
>
>
>
>







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
      1. The string representation of the value is the canonical representation
         of a pure Tcl list\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection1'></a>Example

Assuming the parsing expression grammar below

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

and the input string

    120+5

then a parser should deliver the abstract syntax tree below \(except for
whitespace\)

    set ast {Expression 0 4
        {Factor 0 4
            {Term 0 2
                {Number 0 2
                    {Digit 0 0}
                    {Digit 1 1}
                    {Digit 2 2}


                }
            }
            {AddOp 3 3}
            {Term 4 4
                {Number 4 4
                    {Digit 4 4}




                }
            }
        }
    }

Or, more graphical

![](\.\./\.\./\.\./\.\./image/expr\_ast\.png)

# <a name='section6'></a>PE serialization format

393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection2'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection2'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_container.md.

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

    This method assigns the contents of the PEG object *source* to ourselves,
    overwriting the existing definition\. This is the assignment operator for
    grammars\.

    This operation is in effect equivalent to

        *objectName* __deserialize =__ \[*source* __serialize__\]

  - <a name='9'></a>*objectName* __\-\->__ *destination*

    This method assigns our contents to the PEG object *destination*,
    overwriting the existing definition\. This is the reverse assignment operator
    for grammars\.

    This operation is in effect equivalent to

        *destination* __deserialize =__ \[*objectName* __serialize__\]

  - <a name='10'></a>*objectName* __serialize__ ?*format*?

    This method returns our grammar in some textual form usable for transfer,
    persistent storage, etc\. If no *format* is not specified the returned
    result is the canonical serialization of the grammar, as specified in the
    section [PEG serialization format](#section2)\.







|









|







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

    This method assigns the contents of the PEG object *source* to ourselves,
    overwriting the existing definition\. This is the assignment operator for
    grammars\.

    This operation is in effect equivalent to

    > *objectName* __deserialize =__ \[*source* __serialize__\]

  - <a name='9'></a>*objectName* __\-\->__ *destination*

    This method assigns our contents to the PEG object *destination*,
    overwriting the existing definition\. This is the reverse assignment operator
    for grammars\.

    This operation is in effect equivalent to

    > *destination* __deserialize =__ \[*objectName* __serialize__\]

  - <a name='10'></a>*objectName* __serialize__ ?*format*?

    This method returns our grammar in some textual form usable for transfer,
    persistent storage, etc\. If no *format* is not specified the returned
    result is the canonical serialization of the grammar, as specified in the
    section [PEG serialization format](#section2)\.
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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection3'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section3'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection3'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section3'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection4'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection4'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_export.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (pt::peg::export \- Parser Tools)
[//000000002]: # (Generated from file 'pt\_peg\_export\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (pt::peg::export\(n\) 1 tcllib "Parser Tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>




|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (pt::peg::export \- Parser Tools)
[//000000002]: # (Generated from file 'pt\_peg\_export\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (pt::peg::export\(n\) 1\.0\.1 tcllib "Parser Tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require snit  
package require configuration  
package require pt::peg  
package require pluginmgr  
package require pt::peg::export ?1?  

[__::pt::peg::export__ *objectName*](#1)  
[__objectName__ __method__ ?*arg arg \.\.\.*?](#2)  
[*objectName* __destroy__](#3)  
[*objectName* __export serial__ *serial* ?*format*?](#4)  
[*objectName* __export object__ *object* ?*format*?](#5)  
[*objectName* __configuration names__](#6)  







|


|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require snit  
package require struct::map  
package require pt::peg  
package require pluginmgr  
package require pt::peg::export ?1\.0\.1?  

[__::pt::peg::export__ *objectName*](#1)  
[__objectName__ __method__ ?*arg arg \.\.\.*?](#2)  
[*objectName* __destroy__](#3)  
[*objectName* __export serial__ *serial* ?*format*?](#4)  
[*objectName* __export object__ *object* ?*format*?](#5)  
[*objectName* __configuration names__](#6)  
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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection4'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section4'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection4'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section4'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection5'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection5'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_export_container.md.

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

It has no direct formal specification beyond what was said above\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

one possible CONTAINER serialization for it is

    snit::type a\_pe\_grammar \{
        constructor \{\} \{
            install myg using pt::peg::container $\{selfns\}::G
            $myg start \{n Expression\}
            $myg add   AddOp Digit Expression Factor MulOp Number Sign Term
            $myg modes \{
                AddOp      value
                Digit      value
                Expression value
                Factor     value
                MulOp      value
                Number     value
                Sign       value
                Term       value
            \}

            $myg rules \{
                AddOp      \{/ \{t \-\} \{t \+\}\}
                Digit      \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}
                Expression \{/ \{x \{t \\50\} \{n Expression\} \{t \\51\}\} \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}\}
                Factor     \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}
                MulOp      \{/ \{t \*\} \{t /\}\}
                Number     \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}
                Sign       \{/ \{t \-\} \{t \+\}\}
                Term       \{n Number\}
            \}

            return
        \}


        component myg
        delegate method \* to myg
    \}


# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a PEG







|
|
|
|
|
|
|
|
|




|
|
|
|

|








<
>
|
|
|
|
|
|
|
|
|
<
>

<
|
>

|
<
>







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

It has no direct formal specification beyond what was said above\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

one possible CONTAINER serialization for it is

    snit::type a_pe_grammar {
        constructor {} {
            install myg using pt::peg::container ${selfns}::G
            $myg start {n Expression}
            $myg add   AddOp Digit Expression Factor MulOp Number Sign Term
            $myg modes {
                AddOp      value
                Digit      value
                Expression value
                Factor     value
                MulOp      value
                Number     value
                Sign       value
                Term       value

            }
            $myg rules {
                AddOp      {/ {t -} {t +}}
                Digit      {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}
                Expression {/ {x {t \50} {n Expression} {t \51}} {x {n Factor} {* {x {n MulOp} {n Factor}}}}}
                Factor     {x {n Term} {* {x {n AddOp} {n Term}}}}
                MulOp      {/ {t *} {t /}}
                Number     {x {? {n Sign}} {+ {n Digit}}}
                Sign       {/ {t -} {t +}}
                Term       {n Number}

            }
            return

        }

        component myg
        delegate method * to myg

    }

# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a PEG
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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_export_json.md.

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
themselves are not translated further, but kept as JSON strings containing a
nested Tcl list, and there is no concept of canonicity for the JSON either\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

a JSON serialization for it is

    \{

        "pt::grammar::peg" : \{
            "rules" : \{
                "AddOp"     : \{
                    "is"   : "\\/ \{t \-\} \{t \+\}",
                    "mode" : "value"
                \},
                "Digit"     : \{
                    "is"   : "\\/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}",
                    "mode" : "value"
                \},
                "Expression" : \{
                    "is"   : "\\/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}",
                    "mode" : "value"
                \},
                "Factor"    : \{
                    "is"   : "x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}",
                    "mode" : "value"
                \},
                "MulOp"     : \{
                    "is"   : "\\/ \{t \*\} \{t \\/\}",
                    "mode" : "value"
                \},
                "Number"    : \{
                    "is"   : "x \{? \{n Sign\}\} \{\+ \{n Digit\}\}",
                    "mode" : "value"
                \},
                "Sign"      : \{
                    "is"   : "\\/ \{t \-\} \{t \+\}",
                    "mode" : "value"
                \},
                "Term"      : \{
                    "is"   : "n Number",
                    "mode" : "value"
                \}

            \},
            "start" : "n Expression"
        \}
    \}



and a Tcl serialization of the same is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


The similarity of the latter to the JSON should be quite obvious\.

# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.







|
|
|
|
|
|
|
|
|




<
>
|
|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|


<
>
|

<
<
|
>
>


|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
themselves are not translated further, but kept as JSON strings containing a
nested Tcl list, and there is no concept of canonicity for the JSON either\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

a JSON serialization for it is


    {
        "pt::grammar::peg" : {
            "rules" : {
                "AddOp"     : {
                    "is"   : "\/ {t -} {t +}",
                    "mode" : "value"
                },
                "Digit"     : {
                    "is"   : "\/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}",
                    "mode" : "value"
                },
                "Expression" : {
                    "is"   : "\/ {x {t (} {n Expression} {t )}} {x {n Factor} {* {x {n MulOp} {n Factor}}}}",
                    "mode" : "value"
                },
                "Factor"    : {
                    "is"   : "x {n Term} {* {x {n AddOp} {n Term}}}",
                    "mode" : "value"
                },
                "MulOp"     : {
                    "is"   : "\/ {t *} {t \/}",
                    "mode" : "value"
                },
                "Number"    : {
                    "is"   : "x {? {n Sign}} {+ {n Digit}}",
                    "mode" : "value"
                },
                "Sign"      : {
                    "is"   : "\/ {t -} {t +}",
                    "mode" : "value"
                },
                "Term"      : {
                    "is"   : "n Number",
                    "mode" : "value"

                }
            },
            "start" : "n Expression"


        }
    }

and a Tcl serialization of the same is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

The similarity of the latter to the JSON should be quite obvious\.

# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.
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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_export_peg.md.

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
writing the specification of a grammar easy, something the other formats found
in the Parser Tools do not lend themselves too\.

It is formally specified by the grammar shown below, written in itself\. For a
tutorial / introduction to the language please go and read the *[PEG Language
Tutorial](pt\_peg\_language\.md)*\.

    PEG pe\-grammar\-for\-peg \(Grammar\)

    	\# \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
            \# Syntactical constructs

            Grammar         <\- WHITESPACE Header Definition\* Final EOF ;

            Header          <\- PEG Identifier StartExpr ;
            Definition      <\- Attribute? Identifier IS Expression SEMICOLON ;
            Attribute       <\- \(VOID / LEAF\) COLON ;
            Expression      <\- Sequence \(SLASH Sequence\)\* ;
            Sequence        <\- Prefix\+ ;
            Prefix          <\- \(AND / NOT\)? Suffix ;
            Suffix          <\- Primary \(QUESTION / STAR / PLUS\)? ;
            Primary         <\- ALNUM / ALPHA / ASCII / CONTROL / DDIGIT / DIGIT
                            /  GRAPH / LOWER / PRINTABLE / PUNCT / SPACE / UPPER
                            /  WORDCHAR / XDIGIT
                            / Identifier
                            /  OPEN Expression CLOSE
                            /  Literal
                            /  Class
                            /  DOT
                            ;
            Literal         <\- APOSTROPH  \(\!APOSTROPH  Char\)\* APOSTROPH  WHITESPACE
                            /  DAPOSTROPH \(\!DAPOSTROPH Char\)\* DAPOSTROPH WHITESPACE ;
            Class           <\- OPENB \(\!CLOSEB Range\)\* CLOSEB WHITESPACE ;
            Range           <\- Char TO Char / Char ;

            StartExpr       <\- OPEN Expression CLOSE ;
    void:   Final           <\- "END" WHITESPACE SEMICOLON WHITESPACE ;

            \# \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
            \# Lexing constructs

            Identifier      <\- Ident WHITESPACE ;
    leaf:   Ident           <\- \(\[\_:\] / <alpha>\) \(\[\_:\] / <alnum>\)\* ;
            Char            <\- CharSpecial / CharOctalFull / CharOctalPart
                            /  CharUnicode / CharUnescaped
                            ;

    leaf:   CharSpecial     <\- "\\\\" \[nrt'"\\\[\\\]\\\\\] ;
    leaf:   CharOctalFull   <\- "\\\\" \[0\-2\]\[0\-7\]\[0\-7\] ;
    leaf:   CharOctalPart   <\- "\\\\" \[0\-7\]\[0\-7\]? ;
    leaf:   CharUnicode     <\- "\\\\" 'u' HexDigit \(HexDigit \(HexDigit HexDigit?\)?\)? ;
    leaf:   CharUnescaped   <\- \!"\\\\" \. ;

    void:   HexDigit        <\- \[0\-9a\-fA\-F\] ;

    void:   TO              <\- '\-'           ;
    void:   OPENB           <\- "\["           ;
    void:   CLOSEB          <\- "\]"           ;
    void:   APOSTROPH       <\- "'"           ;
    void:   DAPOSTROPH      <\- '"'           ;
    void:   PEG             <\- "PEG" \!\(\[\_:\] / <alnum>\) WHITESPACE ;
    void:   IS              <\- "<\-"    WHITESPACE ;
    leaf:   VOID            <\- "void"  WHITESPACE ; \# Implies that definition has no semantic value\.
    leaf:   LEAF            <\- "leaf"  WHITESPACE ; \# Implies that definition has no terminals\.
    void:   SEMICOLON       <\- ";"     WHITESPACE ;
    void:   COLON           <\- ":"     WHITESPACE ;
    void:   SLASH           <\- "/"     WHITESPACE ;
    leaf:   AND             <\- "&"     WHITESPACE ;
    leaf:   NOT             <\- "\!"     WHITESPACE ;
    leaf:   QUESTION        <\- "?"     WHITESPACE ;
    leaf:   STAR            <\- "\*"     WHITESPACE ;
    leaf:   PLUS            <\- "\+"     WHITESPACE ;
    void:   OPEN            <\- "\("     WHITESPACE ;
    void:   CLOSE           <\- "\)"     WHITESPACE ;
    leaf:   DOT             <\- "\."     WHITESPACE ;

    leaf:   ALNUM           <\- "<alnum>"    WHITESPACE ;
    leaf:   ALPHA           <\- "<alpha>"    WHITESPACE ;
    leaf:   ASCII           <\- "<ascii>"    WHITESPACE ;
    leaf:   CONTROL         <\- "<control>"  WHITESPACE ;
    leaf:   DDIGIT          <\- "<ddigit>"   WHITESPACE ;
    leaf:   DIGIT           <\- "<digit>"    WHITESPACE ;
    leaf:   GRAPH           <\- "<graph>"    WHITESPACE ;
    leaf:   LOWER           <\- "<lower>"    WHITESPACE ;
    leaf:   PRINTABLE       <\- "<print>"    WHITESPACE ;
    leaf:   PUNCT           <\- "<punct>"    WHITESPACE ;
    leaf:   SPACE           <\- "<space>"    WHITESPACE ;
    leaf:   UPPER           <\- "<upper>"    WHITESPACE ;
    leaf:   WORDCHAR        <\- "<wordchar>" WHITESPACE ;
    leaf:   XDIGIT          <\- "<xdigit>"   WHITESPACE ;

    void:   WHITESPACE      <\- \(" " / "\\t" / EOL / COMMENT\)\* ;
    void:   COMMENT         <\- '\#' \(\!EOL \.\)\* EOL ;
    void:   EOL             <\- "\\n\\r" / "\\n" / "\\r" ;
    void:   EOF             <\- \!\. ;

            \# \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
    END;

## <a name='subsection1'></a>Example

Our example specifies the grammar for a basic 4\-operation calculator\.

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

Using higher\-level features of the notation, i\.e\. the character classes
\(predefined and custom\), this example can be rewritten as

    PEG calculator \(Expression\)
        Sign       <\- \[\-\+\] 						;
        Number     <\- Sign? <ddigit>\+				;
        Expression <\- '\(' Expression '\)' / \(Factor \(MulOp Factor\)\*\)	;
        MulOp      <\- \[\*/\]						;
        Factor     <\- Term \(AddOp Term\)\*				;
        AddOp      <\- \[\-\+\]						;
        Term       <\- Number					;
    END;

# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.








|

|
|

|

|
|
|
|
|
|
|
|








|
|
|
|

|
|

|
|

|
|
|



|
|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|

|






|
|
|
|
|
|
|
|
|





|
|
|
|
|
|
|
|







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
writing the specification of a grammar easy, something the other formats found
in the Parser Tools do not lend themselves too\.

It is formally specified by the grammar shown below, written in itself\. For a
tutorial / introduction to the language please go and read the *[PEG Language
Tutorial](pt\_peg\_language\.md)*\.

    PEG pe-grammar-for-peg (Grammar)

    	# --------------------------------------------------------------------
            # Syntactical constructs

            Grammar         <- WHITESPACE Header Definition* Final EOF ;

            Header          <- PEG Identifier StartExpr ;
            Definition      <- Attribute? Identifier IS Expression SEMICOLON ;
            Attribute       <- (VOID / LEAF) COLON ;
            Expression      <- Sequence (SLASH Sequence)* ;
            Sequence        <- Prefix+ ;
            Prefix          <- (AND / NOT)? Suffix ;
            Suffix          <- Primary (QUESTION / STAR / PLUS)? ;
            Primary         <- ALNUM / ALPHA / ASCII / CONTROL / DDIGIT / DIGIT
                            /  GRAPH / LOWER / PRINTABLE / PUNCT / SPACE / UPPER
                            /  WORDCHAR / XDIGIT
                            / Identifier
                            /  OPEN Expression CLOSE
                            /  Literal
                            /  Class
                            /  DOT
                            ;
            Literal         <- APOSTROPH  (!APOSTROPH  Char)* APOSTROPH  WHITESPACE
                            /  DAPOSTROPH (!DAPOSTROPH Char)* DAPOSTROPH WHITESPACE ;
            Class           <- OPENB (!CLOSEB Range)* CLOSEB WHITESPACE ;
            Range           <- Char TO Char / Char ;

            StartExpr       <- OPEN Expression CLOSE ;
    void:   Final           <- "END" WHITESPACE SEMICOLON WHITESPACE ;

            # --------------------------------------------------------------------
            # Lexing constructs

            Identifier      <- Ident WHITESPACE ;
    leaf:   Ident           <- ([_:] / <alpha>) ([_:] / <alnum>)* ;
            Char            <- CharSpecial / CharOctalFull / CharOctalPart
                            /  CharUnicode / CharUnescaped
                            ;

    leaf:   CharSpecial     <- "\\" [nrt'"\[\]\\] ;
    leaf:   CharOctalFull   <- "\\" [0-2][0-7][0-7] ;
    leaf:   CharOctalPart   <- "\\" [0-7][0-7]? ;
    leaf:   CharUnicode     <- "\\" 'u' HexDigit (HexDigit (HexDigit HexDigit?)?)? ;
    leaf:   CharUnescaped   <- !"\\" . ;

    void:   HexDigit        <- [0-9a-fA-F] ;

    void:   TO              <- '-'           ;
    void:   OPENB           <- "["           ;
    void:   CLOSEB          <- "]"           ;
    void:   APOSTROPH       <- "'"           ;
    void:   DAPOSTROPH      <- '"'           ;
    void:   PEG             <- "PEG" !([_:] / <alnum>) WHITESPACE ;
    void:   IS              <- "<-"    WHITESPACE ;
    leaf:   VOID            <- "void"  WHITESPACE ; # Implies that definition has no semantic value.
    leaf:   LEAF            <- "leaf"  WHITESPACE ; # Implies that definition has no terminals.
    void:   SEMICOLON       <- ";"     WHITESPACE ;
    void:   COLON           <- ":"     WHITESPACE ;
    void:   SLASH           <- "/"     WHITESPACE ;
    leaf:   AND             <- "&"     WHITESPACE ;
    leaf:   NOT             <- "!"     WHITESPACE ;
    leaf:   QUESTION        <- "?"     WHITESPACE ;
    leaf:   STAR            <- "*"     WHITESPACE ;
    leaf:   PLUS            <- "+"     WHITESPACE ;
    void:   OPEN            <- "("     WHITESPACE ;
    void:   CLOSE           <- ")"     WHITESPACE ;
    leaf:   DOT             <- "."     WHITESPACE ;

    leaf:   ALNUM           <- "<alnum>"    WHITESPACE ;
    leaf:   ALPHA           <- "<alpha>"    WHITESPACE ;
    leaf:   ASCII           <- "<ascii>"    WHITESPACE ;
    leaf:   CONTROL         <- "<control>"  WHITESPACE ;
    leaf:   DDIGIT          <- "<ddigit>"   WHITESPACE ;
    leaf:   DIGIT           <- "<digit>"    WHITESPACE ;
    leaf:   GRAPH           <- "<graph>"    WHITESPACE ;
    leaf:   LOWER           <- "<lower>"    WHITESPACE ;
    leaf:   PRINTABLE       <- "<print>"    WHITESPACE ;
    leaf:   PUNCT           <- "<punct>"    WHITESPACE ;
    leaf:   SPACE           <- "<space>"    WHITESPACE ;
    leaf:   UPPER           <- "<upper>"    WHITESPACE ;
    leaf:   WORDCHAR        <- "<wordchar>" WHITESPACE ;
    leaf:   XDIGIT          <- "<xdigit>"   WHITESPACE ;

    void:   WHITESPACE      <- (" " / "\t" / EOL / COMMENT)* ;
    void:   COMMENT         <- '#' (!EOL .)* EOL ;
    void:   EOL             <- "\n\r" / "\n" / "\r" ;
    void:   EOF             <- !. ;

            # --------------------------------------------------------------------
    END;

## <a name='subsection1'></a>Example

Our example specifies the grammar for a basic 4\-operation calculator\.

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

Using higher\-level features of the notation, i\.e\. the character classes
\(predefined and custom\), this example can be rewritten as

    PEG calculator (Expression)
        Sign       <- [-+] 						;
        Number     <- Sign? <ddigit>+				;
        Expression <- '(' Expression ')' / (Factor (MulOp Factor)*)	;
        MulOp      <- [*/]						;
        Factor     <- Term (AddOp Term)*				;
        AddOp      <- [-+]						;
        Term       <- Number					;
    END;

# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.

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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_from_json.md.

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
themselves are not translated further, but kept as JSON strings containing a
nested Tcl list, and there is no concept of canonicity for the JSON either\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

a JSON serialization for it is

    \{

        "pt::grammar::peg" : \{
            "rules" : \{
                "AddOp"     : \{
                    "is"   : "\\/ \{t \-\} \{t \+\}",
                    "mode" : "value"
                \},
                "Digit"     : \{
                    "is"   : "\\/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}",
                    "mode" : "value"
                \},
                "Expression" : \{
                    "is"   : "\\/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}",
                    "mode" : "value"
                \},
                "Factor"    : \{
                    "is"   : "x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}",
                    "mode" : "value"
                \},
                "MulOp"     : \{
                    "is"   : "\\/ \{t \*\} \{t \\/\}",
                    "mode" : "value"
                \},
                "Number"    : \{
                    "is"   : "x \{? \{n Sign\}\} \{\+ \{n Digit\}\}",
                    "mode" : "value"
                \},
                "Sign"      : \{
                    "is"   : "\\/ \{t \-\} \{t \+\}",
                    "mode" : "value"
                \},
                "Term"      : \{
                    "is"   : "n Number",
                    "mode" : "value"
                \}

            \},
            "start" : "n Expression"
        \}
    \}



and a Tcl serialization of the same is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


The similarity of the latter to the JSON should be quite obvious\.

# <a name='section4'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.







|
|
|
|
|
|
|
|
|




<
>
|
|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|


<
>
|

<
<
|
>
>


|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
themselves are not translated further, but kept as JSON strings containing a
nested Tcl list, and there is no concept of canonicity for the JSON either\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

a JSON serialization for it is


    {
        "pt::grammar::peg" : {
            "rules" : {
                "AddOp"     : {
                    "is"   : "\/ {t -} {t +}",
                    "mode" : "value"
                },
                "Digit"     : {
                    "is"   : "\/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}",
                    "mode" : "value"
                },
                "Expression" : {
                    "is"   : "\/ {x {t (} {n Expression} {t )}} {x {n Factor} {* {x {n MulOp} {n Factor}}}}",
                    "mode" : "value"
                },
                "Factor"    : {
                    "is"   : "x {n Term} {* {x {n AddOp} {n Term}}}",
                    "mode" : "value"
                },
                "MulOp"     : {
                    "is"   : "\/ {t *} {t \/}",
                    "mode" : "value"
                },
                "Number"    : {
                    "is"   : "x {? {n Sign}} {+ {n Digit}}",
                    "mode" : "value"
                },
                "Sign"      : {
                    "is"   : "\/ {t -} {t +}",
                    "mode" : "value"
                },
                "Term"      : {
                    "is"   : "n Number",
                    "mode" : "value"

                }
            },
            "start" : "n Expression"


        }
    }

and a Tcl serialization of the same is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

The similarity of the latter to the JSON should be quite obvious\.

# <a name='section4'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.
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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section5'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section5'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_from_peg.md.

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
writing the specification of a grammar easy, something the other formats found
in the Parser Tools do not lend themselves too\.

It is formally specified by the grammar shown below, written in itself\. For a
tutorial / introduction to the language please go and read the *[PEG Language
Tutorial](pt\_peg\_language\.md)*\.

    PEG pe\-grammar\-for\-peg \(Grammar\)

    	\# \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
            \# Syntactical constructs

            Grammar         <\- WHITESPACE Header Definition\* Final EOF ;

            Header          <\- PEG Identifier StartExpr ;
            Definition      <\- Attribute? Identifier IS Expression SEMICOLON ;
            Attribute       <\- \(VOID / LEAF\) COLON ;
            Expression      <\- Sequence \(SLASH Sequence\)\* ;
            Sequence        <\- Prefix\+ ;
            Prefix          <\- \(AND / NOT\)? Suffix ;
            Suffix          <\- Primary \(QUESTION / STAR / PLUS\)? ;
            Primary         <\- ALNUM / ALPHA / ASCII / CONTROL / DDIGIT / DIGIT
                            /  GRAPH / LOWER / PRINTABLE / PUNCT / SPACE / UPPER
                            /  WORDCHAR / XDIGIT
                            / Identifier
                            /  OPEN Expression CLOSE
                            /  Literal
                            /  Class
                            /  DOT
                            ;
            Literal         <\- APOSTROPH  \(\!APOSTROPH  Char\)\* APOSTROPH  WHITESPACE
                            /  DAPOSTROPH \(\!DAPOSTROPH Char\)\* DAPOSTROPH WHITESPACE ;
            Class           <\- OPENB \(\!CLOSEB Range\)\* CLOSEB WHITESPACE ;
            Range           <\- Char TO Char / Char ;

            StartExpr       <\- OPEN Expression CLOSE ;
    void:   Final           <\- "END" WHITESPACE SEMICOLON WHITESPACE ;

            \# \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
            \# Lexing constructs

            Identifier      <\- Ident WHITESPACE ;
    leaf:   Ident           <\- \(\[\_:\] / <alpha>\) \(\[\_:\] / <alnum>\)\* ;
            Char            <\- CharSpecial / CharOctalFull / CharOctalPart
                            /  CharUnicode / CharUnescaped
                            ;

    leaf:   CharSpecial     <\- "\\\\" \[nrt'"\\\[\\\]\\\\\] ;
    leaf:   CharOctalFull   <\- "\\\\" \[0\-2\]\[0\-7\]\[0\-7\] ;
    leaf:   CharOctalPart   <\- "\\\\" \[0\-7\]\[0\-7\]? ;
    leaf:   CharUnicode     <\- "\\\\" 'u' HexDigit \(HexDigit \(HexDigit HexDigit?\)?\)? ;
    leaf:   CharUnescaped   <\- \!"\\\\" \. ;

    void:   HexDigit        <\- \[0\-9a\-fA\-F\] ;

    void:   TO              <\- '\-'           ;
    void:   OPENB           <\- "\["           ;
    void:   CLOSEB          <\- "\]"           ;
    void:   APOSTROPH       <\- "'"           ;
    void:   DAPOSTROPH      <\- '"'           ;
    void:   PEG             <\- "PEG" \!\(\[\_:\] / <alnum>\) WHITESPACE ;
    void:   IS              <\- "<\-"    WHITESPACE ;
    leaf:   VOID            <\- "void"  WHITESPACE ; \# Implies that definition has no semantic value\.
    leaf:   LEAF            <\- "leaf"  WHITESPACE ; \# Implies that definition has no terminals\.
    void:   SEMICOLON       <\- ";"     WHITESPACE ;
    void:   COLON           <\- ":"     WHITESPACE ;
    void:   SLASH           <\- "/"     WHITESPACE ;
    leaf:   AND             <\- "&"     WHITESPACE ;
    leaf:   NOT             <\- "\!"     WHITESPACE ;
    leaf:   QUESTION        <\- "?"     WHITESPACE ;
    leaf:   STAR            <\- "\*"     WHITESPACE ;
    leaf:   PLUS            <\- "\+"     WHITESPACE ;
    void:   OPEN            <\- "\("     WHITESPACE ;
    void:   CLOSE           <\- "\)"     WHITESPACE ;
    leaf:   DOT             <\- "\."     WHITESPACE ;

    leaf:   ALNUM           <\- "<alnum>"    WHITESPACE ;
    leaf:   ALPHA           <\- "<alpha>"    WHITESPACE ;
    leaf:   ASCII           <\- "<ascii>"    WHITESPACE ;
    leaf:   CONTROL         <\- "<control>"  WHITESPACE ;
    leaf:   DDIGIT          <\- "<ddigit>"   WHITESPACE ;
    leaf:   DIGIT           <\- "<digit>"    WHITESPACE ;
    leaf:   GRAPH           <\- "<graph>"    WHITESPACE ;
    leaf:   LOWER           <\- "<lower>"    WHITESPACE ;
    leaf:   PRINTABLE       <\- "<print>"    WHITESPACE ;
    leaf:   PUNCT           <\- "<punct>"    WHITESPACE ;
    leaf:   SPACE           <\- "<space>"    WHITESPACE ;
    leaf:   UPPER           <\- "<upper>"    WHITESPACE ;
    leaf:   WORDCHAR        <\- "<wordchar>" WHITESPACE ;
    leaf:   XDIGIT          <\- "<xdigit>"   WHITESPACE ;

    void:   WHITESPACE      <\- \(" " / "\\t" / EOL / COMMENT\)\* ;
    void:   COMMENT         <\- '\#' \(\!EOL \.\)\* EOL ;
    void:   EOL             <\- "\\n\\r" / "\\n" / "\\r" ;
    void:   EOF             <\- \!\. ;

            \# \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
    END;

## <a name='subsection1'></a>Example

Our example specifies the grammar for a basic 4\-operation calculator\.

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

Using higher\-level features of the notation, i\.e\. the character classes
\(predefined and custom\), this example can be rewritten as

    PEG calculator \(Expression\)
        Sign       <\- \[\-\+\] 						;
        Number     <\- Sign? <ddigit>\+				;
        Expression <\- '\(' Expression '\)' / \(Factor \(MulOp Factor\)\*\)	;
        MulOp      <\- \[\*/\]						;
        Factor     <\- Term \(AddOp Term\)\*				;
        AddOp      <\- \[\-\+\]						;
        Term       <\- Number					;
    END;

# <a name='section4'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.








|

|
|

|

|
|
|
|
|
|
|
|








|
|
|
|

|
|

|
|

|
|
|



|
|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|

|






|
|
|
|
|
|
|
|
|





|
|
|
|
|
|
|
|







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
writing the specification of a grammar easy, something the other formats found
in the Parser Tools do not lend themselves too\.

It is formally specified by the grammar shown below, written in itself\. For a
tutorial / introduction to the language please go and read the *[PEG Language
Tutorial](pt\_peg\_language\.md)*\.

    PEG pe-grammar-for-peg (Grammar)

    	# --------------------------------------------------------------------
            # Syntactical constructs

            Grammar         <- WHITESPACE Header Definition* Final EOF ;

            Header          <- PEG Identifier StartExpr ;
            Definition      <- Attribute? Identifier IS Expression SEMICOLON ;
            Attribute       <- (VOID / LEAF) COLON ;
            Expression      <- Sequence (SLASH Sequence)* ;
            Sequence        <- Prefix+ ;
            Prefix          <- (AND / NOT)? Suffix ;
            Suffix          <- Primary (QUESTION / STAR / PLUS)? ;
            Primary         <- ALNUM / ALPHA / ASCII / CONTROL / DDIGIT / DIGIT
                            /  GRAPH / LOWER / PRINTABLE / PUNCT / SPACE / UPPER
                            /  WORDCHAR / XDIGIT
                            / Identifier
                            /  OPEN Expression CLOSE
                            /  Literal
                            /  Class
                            /  DOT
                            ;
            Literal         <- APOSTROPH  (!APOSTROPH  Char)* APOSTROPH  WHITESPACE
                            /  DAPOSTROPH (!DAPOSTROPH Char)* DAPOSTROPH WHITESPACE ;
            Class           <- OPENB (!CLOSEB Range)* CLOSEB WHITESPACE ;
            Range           <- Char TO Char / Char ;

            StartExpr       <- OPEN Expression CLOSE ;
    void:   Final           <- "END" WHITESPACE SEMICOLON WHITESPACE ;

            # --------------------------------------------------------------------
            # Lexing constructs

            Identifier      <- Ident WHITESPACE ;
    leaf:   Ident           <- ([_:] / <alpha>) ([_:] / <alnum>)* ;
            Char            <- CharSpecial / CharOctalFull / CharOctalPart
                            /  CharUnicode / CharUnescaped
                            ;

    leaf:   CharSpecial     <- "\\" [nrt'"\[\]\\] ;
    leaf:   CharOctalFull   <- "\\" [0-2][0-7][0-7] ;
    leaf:   CharOctalPart   <- "\\" [0-7][0-7]? ;
    leaf:   CharUnicode     <- "\\" 'u' HexDigit (HexDigit (HexDigit HexDigit?)?)? ;
    leaf:   CharUnescaped   <- !"\\" . ;

    void:   HexDigit        <- [0-9a-fA-F] ;

    void:   TO              <- '-'           ;
    void:   OPENB           <- "["           ;
    void:   CLOSEB          <- "]"           ;
    void:   APOSTROPH       <- "'"           ;
    void:   DAPOSTROPH      <- '"'           ;
    void:   PEG             <- "PEG" !([_:] / <alnum>) WHITESPACE ;
    void:   IS              <- "<-"    WHITESPACE ;
    leaf:   VOID            <- "void"  WHITESPACE ; # Implies that definition has no semantic value.
    leaf:   LEAF            <- "leaf"  WHITESPACE ; # Implies that definition has no terminals.
    void:   SEMICOLON       <- ";"     WHITESPACE ;
    void:   COLON           <- ":"     WHITESPACE ;
    void:   SLASH           <- "/"     WHITESPACE ;
    leaf:   AND             <- "&"     WHITESPACE ;
    leaf:   NOT             <- "!"     WHITESPACE ;
    leaf:   QUESTION        <- "?"     WHITESPACE ;
    leaf:   STAR            <- "*"     WHITESPACE ;
    leaf:   PLUS            <- "+"     WHITESPACE ;
    void:   OPEN            <- "("     WHITESPACE ;
    void:   CLOSE           <- ")"     WHITESPACE ;
    leaf:   DOT             <- "."     WHITESPACE ;

    leaf:   ALNUM           <- "<alnum>"    WHITESPACE ;
    leaf:   ALPHA           <- "<alpha>"    WHITESPACE ;
    leaf:   ASCII           <- "<ascii>"    WHITESPACE ;
    leaf:   CONTROL         <- "<control>"  WHITESPACE ;
    leaf:   DDIGIT          <- "<ddigit>"   WHITESPACE ;
    leaf:   DIGIT           <- "<digit>"    WHITESPACE ;
    leaf:   GRAPH           <- "<graph>"    WHITESPACE ;
    leaf:   LOWER           <- "<lower>"    WHITESPACE ;
    leaf:   PRINTABLE       <- "<print>"    WHITESPACE ;
    leaf:   PUNCT           <- "<punct>"    WHITESPACE ;
    leaf:   SPACE           <- "<space>"    WHITESPACE ;
    leaf:   UPPER           <- "<upper>"    WHITESPACE ;
    leaf:   WORDCHAR        <- "<wordchar>" WHITESPACE ;
    leaf:   XDIGIT          <- "<xdigit>"   WHITESPACE ;

    void:   WHITESPACE      <- (" " / "\t" / EOL / COMMENT)* ;
    void:   COMMENT         <- '#' (!EOL .)* EOL ;
    void:   EOL             <- "\n\r" / "\n" / "\r" ;
    void:   EOF             <- !. ;

            # --------------------------------------------------------------------
    END;

## <a name='subsection1'></a>Example

Our example specifies the grammar for a basic 4\-operation calculator\.

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

Using higher\-level features of the notation, i\.e\. the character classes
\(predefined and custom\), this example can be rewritten as

    PEG calculator (Expression)
        Sign       <- [-+] 						;
        Number     <- Sign? <ddigit>+				;
        Expression <- '(' Expression ')' / (Factor (MulOp Factor)*)	;
        MulOp      <- [*/]						;
        Factor     <- Term (AddOp Term)*				;
        AddOp      <- [-+]						;
        Term       <- Number					;
    END;

# <a name='section4'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.

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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section5'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section5'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_import.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (pt::peg::import \- Parser Tools)
[//000000002]: # (Generated from file 'pt\_peg\_import\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (pt::peg::import\(n\) 1 tcllib "Parser Tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>




|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (pt::peg::import \- Parser Tools)
[//000000002]: # (Generated from file 'pt\_peg\_import\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (pt::peg::import\(n\) 1\.0\.1 tcllib "Parser Tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
46
47
48
49
50
51
52

53
54
55
56
57
58
59
60
61
62
63
64
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  

package require snit  
package require configuration  
package require pt::peg  
package require pluginmgr  
package require pt::peg::import ?1?  

[__::pt::peg::import__ *objectName*](#1)  
[__objectName__ __method__ ?*arg arg \.\.\.*?](#2)  
[*objectName* __destroy__](#3)  
[*objectName* __import text__ *text* ?*format*?](#4)  
[*objectName* __import file__ *path* ?*format*?](#5)  
[*objectName* __import object text__ *object* *text* ?*format*?](#6)  







>

|


|







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require Tcl 8\.5  
package require snit  
package require fileutil::paths  
package require pt::peg  
package require pluginmgr  
package require pt::peg::import ?1\.0\.1?  

[__::pt::peg::import__ *objectName*](#1)  
[__objectName__ __method__ ?*arg arg \.\.\.*?](#2)  
[*objectName* __destroy__](#3)  
[*objectName* __import text__ *text* ?*format*?](#4)  
[*objectName* __import file__ *path* ?*format*?](#5)  
[*objectName* __import object text__ *object* *text* ?*format*?](#6)  
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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection4'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section4'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection4'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section4'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection5'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection5'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_import_json.md.

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
themselves are not translated further, but kept as JSON strings containing a
nested Tcl list, and there is no concept of canonicity for the JSON either\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

a JSON serialization for it is

    \{

        "pt::grammar::peg" : \{
            "rules" : \{
                "AddOp"     : \{
                    "is"   : "\\/ \{t \-\} \{t \+\}",
                    "mode" : "value"
                \},
                "Digit"     : \{
                    "is"   : "\\/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}",
                    "mode" : "value"
                \},
                "Expression" : \{
                    "is"   : "\\/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}",
                    "mode" : "value"
                \},
                "Factor"    : \{
                    "is"   : "x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}",
                    "mode" : "value"
                \},
                "MulOp"     : \{
                    "is"   : "\\/ \{t \*\} \{t \\/\}",
                    "mode" : "value"
                \},
                "Number"    : \{
                    "is"   : "x \{? \{n Sign\}\} \{\+ \{n Digit\}\}",
                    "mode" : "value"
                \},
                "Sign"      : \{
                    "is"   : "\\/ \{t \-\} \{t \+\}",
                    "mode" : "value"
                \},
                "Term"      : \{
                    "is"   : "n Number",
                    "mode" : "value"
                \}

            \},
            "start" : "n Expression"
        \}
    \}



and a Tcl serialization of the same is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


The similarity of the latter to the JSON should be quite obvious\.

# <a name='section4'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.







|
|
|
|
|
|
|
|
|




<
>
|
|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|


<
>
|

<
<
|
>
>


|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
themselves are not translated further, but kept as JSON strings containing a
nested Tcl list, and there is no concept of canonicity for the JSON either\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

a JSON serialization for it is


    {
        "pt::grammar::peg" : {
            "rules" : {
                "AddOp"     : {
                    "is"   : "\/ {t -} {t +}",
                    "mode" : "value"
                },
                "Digit"     : {
                    "is"   : "\/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}",
                    "mode" : "value"
                },
                "Expression" : {
                    "is"   : "\/ {x {t (} {n Expression} {t )}} {x {n Factor} {* {x {n MulOp} {n Factor}}}}",
                    "mode" : "value"
                },
                "Factor"    : {
                    "is"   : "x {n Term} {* {x {n AddOp} {n Term}}}",
                    "mode" : "value"
                },
                "MulOp"     : {
                    "is"   : "\/ {t *} {t \/}",
                    "mode" : "value"
                },
                "Number"    : {
                    "is"   : "x {? {n Sign}} {+ {n Digit}}",
                    "mode" : "value"
                },
                "Sign"      : {
                    "is"   : "\/ {t -} {t +}",
                    "mode" : "value"
                },
                "Term"      : {
                    "is"   : "n Number",
                    "mode" : "value"

                }
            },
            "start" : "n Expression"


        }
    }

and a Tcl serialization of the same is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

The similarity of the latter to the JSON should be quite obvious\.

# <a name='section4'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.
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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section5'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section5'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_import_peg.md.

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
writing the specification of a grammar easy, something the other formats found
in the Parser Tools do not lend themselves too\.

It is formally specified by the grammar shown below, written in itself\. For a
tutorial / introduction to the language please go and read the *[PEG Language
Tutorial](pt\_peg\_language\.md)*\.

    PEG pe\-grammar\-for\-peg \(Grammar\)

    	\# \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
            \# Syntactical constructs

            Grammar         <\- WHITESPACE Header Definition\* Final EOF ;

            Header          <\- PEG Identifier StartExpr ;
            Definition      <\- Attribute? Identifier IS Expression SEMICOLON ;
            Attribute       <\- \(VOID / LEAF\) COLON ;
            Expression      <\- Sequence \(SLASH Sequence\)\* ;
            Sequence        <\- Prefix\+ ;
            Prefix          <\- \(AND / NOT\)? Suffix ;
            Suffix          <\- Primary \(QUESTION / STAR / PLUS\)? ;
            Primary         <\- ALNUM / ALPHA / ASCII / CONTROL / DDIGIT / DIGIT
                            /  GRAPH / LOWER / PRINTABLE / PUNCT / SPACE / UPPER
                            /  WORDCHAR / XDIGIT
                            / Identifier
                            /  OPEN Expression CLOSE
                            /  Literal
                            /  Class
                            /  DOT
                            ;
            Literal         <\- APOSTROPH  \(\!APOSTROPH  Char\)\* APOSTROPH  WHITESPACE
                            /  DAPOSTROPH \(\!DAPOSTROPH Char\)\* DAPOSTROPH WHITESPACE ;
            Class           <\- OPENB \(\!CLOSEB Range\)\* CLOSEB WHITESPACE ;
            Range           <\- Char TO Char / Char ;

            StartExpr       <\- OPEN Expression CLOSE ;
    void:   Final           <\- "END" WHITESPACE SEMICOLON WHITESPACE ;

            \# \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
            \# Lexing constructs

            Identifier      <\- Ident WHITESPACE ;
    leaf:   Ident           <\- \(\[\_:\] / <alpha>\) \(\[\_:\] / <alnum>\)\* ;
            Char            <\- CharSpecial / CharOctalFull / CharOctalPart
                            /  CharUnicode / CharUnescaped
                            ;

    leaf:   CharSpecial     <\- "\\\\" \[nrt'"\\\[\\\]\\\\\] ;
    leaf:   CharOctalFull   <\- "\\\\" \[0\-2\]\[0\-7\]\[0\-7\] ;
    leaf:   CharOctalPart   <\- "\\\\" \[0\-7\]\[0\-7\]? ;
    leaf:   CharUnicode     <\- "\\\\" 'u' HexDigit \(HexDigit \(HexDigit HexDigit?\)?\)? ;
    leaf:   CharUnescaped   <\- \!"\\\\" \. ;

    void:   HexDigit        <\- \[0\-9a\-fA\-F\] ;

    void:   TO              <\- '\-'           ;
    void:   OPENB           <\- "\["           ;
    void:   CLOSEB          <\- "\]"           ;
    void:   APOSTROPH       <\- "'"           ;
    void:   DAPOSTROPH      <\- '"'           ;
    void:   PEG             <\- "PEG" \!\(\[\_:\] / <alnum>\) WHITESPACE ;
    void:   IS              <\- "<\-"    WHITESPACE ;
    leaf:   VOID            <\- "void"  WHITESPACE ; \# Implies that definition has no semantic value\.
    leaf:   LEAF            <\- "leaf"  WHITESPACE ; \# Implies that definition has no terminals\.
    void:   SEMICOLON       <\- ";"     WHITESPACE ;
    void:   COLON           <\- ":"     WHITESPACE ;
    void:   SLASH           <\- "/"     WHITESPACE ;
    leaf:   AND             <\- "&"     WHITESPACE ;
    leaf:   NOT             <\- "\!"     WHITESPACE ;
    leaf:   QUESTION        <\- "?"     WHITESPACE ;
    leaf:   STAR            <\- "\*"     WHITESPACE ;
    leaf:   PLUS            <\- "\+"     WHITESPACE ;
    void:   OPEN            <\- "\("     WHITESPACE ;
    void:   CLOSE           <\- "\)"     WHITESPACE ;
    leaf:   DOT             <\- "\."     WHITESPACE ;

    leaf:   ALNUM           <\- "<alnum>"    WHITESPACE ;
    leaf:   ALPHA           <\- "<alpha>"    WHITESPACE ;
    leaf:   ASCII           <\- "<ascii>"    WHITESPACE ;
    leaf:   CONTROL         <\- "<control>"  WHITESPACE ;
    leaf:   DDIGIT          <\- "<ddigit>"   WHITESPACE ;
    leaf:   DIGIT           <\- "<digit>"    WHITESPACE ;
    leaf:   GRAPH           <\- "<graph>"    WHITESPACE ;
    leaf:   LOWER           <\- "<lower>"    WHITESPACE ;
    leaf:   PRINTABLE       <\- "<print>"    WHITESPACE ;
    leaf:   PUNCT           <\- "<punct>"    WHITESPACE ;
    leaf:   SPACE           <\- "<space>"    WHITESPACE ;
    leaf:   UPPER           <\- "<upper>"    WHITESPACE ;
    leaf:   WORDCHAR        <\- "<wordchar>" WHITESPACE ;
    leaf:   XDIGIT          <\- "<xdigit>"   WHITESPACE ;

    void:   WHITESPACE      <\- \(" " / "\\t" / EOL / COMMENT\)\* ;
    void:   COMMENT         <\- '\#' \(\!EOL \.\)\* EOL ;
    void:   EOL             <\- "\\n\\r" / "\\n" / "\\r" ;
    void:   EOF             <\- \!\. ;

            \# \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
    END;

## <a name='subsection1'></a>Example

Our example specifies the grammar for a basic 4\-operation calculator\.

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

Using higher\-level features of the notation, i\.e\. the character classes
\(predefined and custom\), this example can be rewritten as

    PEG calculator \(Expression\)
        Sign       <\- \[\-\+\] 						;
        Number     <\- Sign? <ddigit>\+				;
        Expression <\- '\(' Expression '\)' / \(Factor \(MulOp Factor\)\*\)	;
        MulOp      <\- \[\*/\]						;
        Factor     <\- Term \(AddOp Term\)\*				;
        AddOp      <\- \[\-\+\]						;
        Term       <\- Number					;
    END;

# <a name='section4'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.








|

|
|

|

|
|
|
|
|
|
|
|








|
|
|
|

|
|

|
|

|
|
|



|
|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|

|






|
|
|
|
|
|
|
|
|





|
|
|
|
|
|
|
|







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
writing the specification of a grammar easy, something the other formats found
in the Parser Tools do not lend themselves too\.

It is formally specified by the grammar shown below, written in itself\. For a
tutorial / introduction to the language please go and read the *[PEG Language
Tutorial](pt\_peg\_language\.md)*\.

    PEG pe-grammar-for-peg (Grammar)

    	# --------------------------------------------------------------------
            # Syntactical constructs

            Grammar         <- WHITESPACE Header Definition* Final EOF ;

            Header          <- PEG Identifier StartExpr ;
            Definition      <- Attribute? Identifier IS Expression SEMICOLON ;
            Attribute       <- (VOID / LEAF) COLON ;
            Expression      <- Sequence (SLASH Sequence)* ;
            Sequence        <- Prefix+ ;
            Prefix          <- (AND / NOT)? Suffix ;
            Suffix          <- Primary (QUESTION / STAR / PLUS)? ;
            Primary         <- ALNUM / ALPHA / ASCII / CONTROL / DDIGIT / DIGIT
                            /  GRAPH / LOWER / PRINTABLE / PUNCT / SPACE / UPPER
                            /  WORDCHAR / XDIGIT
                            / Identifier
                            /  OPEN Expression CLOSE
                            /  Literal
                            /  Class
                            /  DOT
                            ;
            Literal         <- APOSTROPH  (!APOSTROPH  Char)* APOSTROPH  WHITESPACE
                            /  DAPOSTROPH (!DAPOSTROPH Char)* DAPOSTROPH WHITESPACE ;
            Class           <- OPENB (!CLOSEB Range)* CLOSEB WHITESPACE ;
            Range           <- Char TO Char / Char ;

            StartExpr       <- OPEN Expression CLOSE ;
    void:   Final           <- "END" WHITESPACE SEMICOLON WHITESPACE ;

            # --------------------------------------------------------------------
            # Lexing constructs

            Identifier      <- Ident WHITESPACE ;
    leaf:   Ident           <- ([_:] / <alpha>) ([_:] / <alnum>)* ;
            Char            <- CharSpecial / CharOctalFull / CharOctalPart
                            /  CharUnicode / CharUnescaped
                            ;

    leaf:   CharSpecial     <- "\\" [nrt'"\[\]\\] ;
    leaf:   CharOctalFull   <- "\\" [0-2][0-7][0-7] ;
    leaf:   CharOctalPart   <- "\\" [0-7][0-7]? ;
    leaf:   CharUnicode     <- "\\" 'u' HexDigit (HexDigit (HexDigit HexDigit?)?)? ;
    leaf:   CharUnescaped   <- !"\\" . ;

    void:   HexDigit        <- [0-9a-fA-F] ;

    void:   TO              <- '-'           ;
    void:   OPENB           <- "["           ;
    void:   CLOSEB          <- "]"           ;
    void:   APOSTROPH       <- "'"           ;
    void:   DAPOSTROPH      <- '"'           ;
    void:   PEG             <- "PEG" !([_:] / <alnum>) WHITESPACE ;
    void:   IS              <- "<-"    WHITESPACE ;
    leaf:   VOID            <- "void"  WHITESPACE ; # Implies that definition has no semantic value.
    leaf:   LEAF            <- "leaf"  WHITESPACE ; # Implies that definition has no terminals.
    void:   SEMICOLON       <- ";"     WHITESPACE ;
    void:   COLON           <- ":"     WHITESPACE ;
    void:   SLASH           <- "/"     WHITESPACE ;
    leaf:   AND             <- "&"     WHITESPACE ;
    leaf:   NOT             <- "!"     WHITESPACE ;
    leaf:   QUESTION        <- "?"     WHITESPACE ;
    leaf:   STAR            <- "*"     WHITESPACE ;
    leaf:   PLUS            <- "+"     WHITESPACE ;
    void:   OPEN            <- "("     WHITESPACE ;
    void:   CLOSE           <- ")"     WHITESPACE ;
    leaf:   DOT             <- "."     WHITESPACE ;

    leaf:   ALNUM           <- "<alnum>"    WHITESPACE ;
    leaf:   ALPHA           <- "<alpha>"    WHITESPACE ;
    leaf:   ASCII           <- "<ascii>"    WHITESPACE ;
    leaf:   CONTROL         <- "<control>"  WHITESPACE ;
    leaf:   DDIGIT          <- "<ddigit>"   WHITESPACE ;
    leaf:   DIGIT           <- "<digit>"    WHITESPACE ;
    leaf:   GRAPH           <- "<graph>"    WHITESPACE ;
    leaf:   LOWER           <- "<lower>"    WHITESPACE ;
    leaf:   PRINTABLE       <- "<print>"    WHITESPACE ;
    leaf:   PUNCT           <- "<punct>"    WHITESPACE ;
    leaf:   SPACE           <- "<space>"    WHITESPACE ;
    leaf:   UPPER           <- "<upper>"    WHITESPACE ;
    leaf:   WORDCHAR        <- "<wordchar>" WHITESPACE ;
    leaf:   XDIGIT          <- "<xdigit>"   WHITESPACE ;

    void:   WHITESPACE      <- (" " / "\t" / EOL / COMMENT)* ;
    void:   COMMENT         <- '#' (!EOL .)* EOL ;
    void:   EOL             <- "\n\r" / "\n" / "\r" ;
    void:   EOF             <- !. ;

            # --------------------------------------------------------------------
    END;

## <a name='subsection1'></a>Example

Our example specifies the grammar for a basic 4\-operation calculator\.

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

Using higher\-level features of the notation, i\.e\. the character classes
\(predefined and custom\), this example can be rewritten as

    PEG calculator (Expression)
        Sign       <- [-+] 						;
        Number     <- Sign? <ddigit>+				;
        Expression <- '(' Expression ')' / (Factor (MulOp Factor)*)	;
        MulOp      <- [*/]						;
        Factor     <- Term (AddOp Term)*				;
        AddOp      <- [-+]						;
        Term       <- Number					;
    END;

# <a name='section4'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.

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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section5'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section5'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_interp.md.

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
      1. The string representation of the value is the canonical representation
         of a pure Tcl list\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection3'></a>Example

Assuming the parsing expression grammar below

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

and the input string

    120\+5

then a parser should deliver the abstract syntax tree below \(except for
whitespace\)

    set ast \{Expression 0 4
        \{Factor 0 4
            \{Term 0 2
                \{Number 0 2
                    \{Digit 0 0\}
                    \{Digit 1 1\}
                    \{Digit 2 2\}
                \}
            \}


            \{AddOp 3 3\}
            \{Term 4 4
                \{Number 4 4
                    \{Digit 4 4\}
                \}
            \}
        \}
    \}





Or, more graphical

![](\.\./\.\./\.\./\.\./image/expr\_ast\.png)

# <a name='section3'></a>PE serialization format








|
|
|
|
|
|
|
|
|




|




|
|
|
|
|
|
|
<
<
>
>
|
|
|
|
<
<
<
<
>
>
>
>







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
      1. The string representation of the value is the canonical representation
         of a pure Tcl list\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection3'></a>Example

Assuming the parsing expression grammar below

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

and the input string

    120+5

then a parser should deliver the abstract syntax tree below \(except for
whitespace\)

    set ast {Expression 0 4
        {Factor 0 4
            {Term 0 2
                {Number 0 2
                    {Digit 0 0}
                    {Digit 1 1}
                    {Digit 2 2}


                }
            }
            {AddOp 3 3}
            {Term 4 4
                {Number 4 4
                    {Digit 4 4}




                }
            }
        }
    }

Or, more graphical

![](\.\./\.\./\.\./\.\./image/expr\_ast\.png)

# <a name='section3'></a>PE serialization format

390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection4'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection4'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_language.md.

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

# <a name='section3'></a>The elements of the language

## <a name='subsection1'></a>Basic structure

The general outline of a textual PEG is

    PEG <<name>> \(<<start\-expression>>\)
       <<rules>>
    END;

*Note*: We are using text in double angle\-brackets as place\-holders for things
not yet explained\.

## <a name='subsection2'></a>Names







|







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

# <a name='section3'></a>The elements of the language

## <a name='subsection1'></a>Basic structure

The general outline of a textual PEG is

    PEG <<name>> (<<start-expression>>)
       <<rules>>
    END;

*Note*: We are using text in double angle\-brackets as place\-holders for things
not yet explained\.

## <a name='subsection2'></a>Names
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

  1. It begins with a letter, underscore, or colon, followed by

  1. zero or more letters, digits, underscores, or colons\.

Or, in formal textual notation:

    \(\[\_:\] / <alpha>\) \(\[\_:\] / <alnum>\)\*

Examples of names:

    Hello
    ::world
    \_:submarine55\_

Examples of text which are *not* names:

    12
    \.bogus
    0wrong
    @location

## <a name='subsection3'></a>Rules

The main body of the text of a grammar specification is taken up by the rules\.
Each rule defines the sentence structure of one nonterminal symbol\. Their basic
structure is

    <<name>>  <\-  <<expression>> ;

The <name> specifies the nonterminal symbol to be defined, the <expression>
after the arrow \(<\-\) then declares its structure\.

Note that each rule ends in a single semicolon, even the last\. I\.e\. the
semicolon is a rule *terminator*, not a separator\.








|





|




|









|







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

  1. It begins with a letter, underscore, or colon, followed by

  1. zero or more letters, digits, underscores, or colons\.

Or, in formal textual notation:

    ([_:] / <alpha>) ([_:] / <alnum>)*

Examples of names:

    Hello
    ::world
    _:submarine55_

Examples of text which are *not* names:

    12
    .bogus
    0wrong
    @location

## <a name='subsection3'></a>Rules

The main body of the text of a grammar specification is taken up by the rules\.
Each rule defines the sentence structure of one nonterminal symbol\. Their basic
structure is

    <<name>>  <-  <<expression>> ;

The <name> specifies the nonterminal symbol to be defined, the <expression>
after the arrow \(<\-\) then declares its structure\.

Note that each rule ends in a single semicolon, even the last\. I\.e\. the
semicolon is a rule *terminator*, not a separator\.

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
of parts, and for look\-ahead constraints\. There is no explicit operator for the
sequencing \(also known as *concatenation*\) of parts however\. This is specified
by simply placing the parts adjacent to each other\.

Here are the operators, from highest to lowest priority \(i\.e\. strength of
binding\):

    \# Binary operators\.

    <<expression\-1>>     <<expression\-2>>  \# sequence\. parse 1, then 2\.
    <<expression\-1>>  /  <<expression\-2>>  \# alternative\. try to parse 1, and parse 2 if 1 failed to parse\.

    \# Prefix operators\. Lookahead constraints\. Same priority\.

    & <<expression>>  \# Parse expression, ok on successful parse\.
    \! <<expression>>  \# Ditto, except ok on failure to parse\.

    \# Suffix operators\. Repetition\. Same priority\.

    <<expression>> ?  \# Parse expression none, or once \(repeat 0 or 1\)\.
    <<expression>> \*  \# Parse expression zero or more times\.
    <<expression>> \+  \# Parse expression one or more times\.

    \# Expression nesting

    \( <<expression>> \) \# Put an expression in parens to change its priority\.

With this we can now deconstruct the formal expression for names given in
section [Names](#subsection2):

    \(\[\_:\] / <alpha>\) \(\[\_:\] / <alnum>\)\*

It is a sequence of two parts,

    \[\_:\] / <alpha>

and

    \(\[\_:\] / <alnum>\)\*

The parentheses around the parts kept their inner alternatives bound together
against the normally higher priority of the sequence\. Each of the two parts is
an alternative, with the second part additionally repeated zero or more times,
leaving us with the three atomic expressions

    \[\_:\]
    <alpha>
    <alnum>

And *atomic expressions* are our next topic\. They fall into three classes:

  1. names, i\.e\. nonterminal symbols,








|

|
|

|

|
|

|

|
|
|

|

|




|



|



|






|







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
of parts, and for look\-ahead constraints\. There is no explicit operator for the
sequencing \(also known as *concatenation*\) of parts however\. This is specified
by simply placing the parts adjacent to each other\.

Here are the operators, from highest to lowest priority \(i\.e\. strength of
binding\):

    # Binary operators.

    <<expression-1>>     <<expression-2>>  # sequence. parse 1, then 2.
    <<expression-1>>  /  <<expression-2>>  # alternative. try to parse 1, and parse 2 if 1 failed to parse.

    # Prefix operators. Lookahead constraints. Same priority.

    & <<expression>>  # Parse expression, ok on successful parse.
    ! <<expression>>  # Ditto, except ok on failure to parse.

    # Suffix operators. Repetition. Same priority.

    <<expression>> ?  # Parse expression none, or once (repeat 0 or 1).
    <<expression>> *  # Parse expression zero or more times.
    <<expression>> +  # Parse expression one or more times.

    # Expression nesting

    ( <<expression>> ) # Put an expression in parens to change its priority.

With this we can now deconstruct the formal expression for names given in
section [Names](#subsection2):

    ([_:] / <alpha>) ([_:] / <alnum>)*

It is a sequence of two parts,

    [_:] / <alpha>

and

    ([_:] / <alnum>)*

The parentheses around the parts kept their inner alternatives bound together
against the normally higher priority of the sequence\. Each of the two parts is
an alternative, with the second part additionally repeated zero or more times,
leaving us with the three atomic expressions

    [_:]
    <alpha>
    <alnum>

And *atomic expressions* are our next topic\. They fall into three classes:

  1. names, i\.e\. nonterminal symbols,

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

The last two examples show how to place any of the delimiters into a string\.

For the last, but not least of our atomic expressions, character classes, we
have a number of predefined classes, shown below, and the ability to construct
or own\. The predefined classes are:

    <alnum>    \# Any unicode alphabet or digit character \(string is alnum\)\.
    <alpha>    \# Any unicode alphabet character \(string is alpha\)\.
    <ascii>    \# Any unicode character below codepoint 0x80 \(string is ascii\)\.
    <control>  \# Any unicode control character \(string is control\)\.
    <ddigit>   \# The digit characters \[0\-9\]\.
    <digit>    \# Any unicode digit character \(string is digit\)\.
    <graph>    \# Any unicode printing character, except space \(string is graph\)\.
    <lower>    \# Any unicode lower\-case alphabet character \(string is lower\)\.
    <print>    \# Any unicode printing character, incl\. space \(string is print\)\.
    <punct>    \# Any unicode punctuation character \(string is punct\)\.
    <space>    \# Any unicode space character \(string is space\)\.
    <upper>    \# Any unicode upper\-case alphabet character \(string is upper\)\.
    <wordchar> \# Any unicode word character \(string is wordchar\)\.
    <xdigit>   \# The hexadecimal digit characters \[0\-9a\-fA\-F\]\.
    \.          \# Any character, except end of input\.

And the syntax of custom\-defined character classes is

    \[ <<range>>\* \]

where each range is either a single character, or of the form

    <<character>> \- <character>>

Examples for character classes we have seen already in the course of this
introduction are

    \[\_:\]
    \[0\-9\]
    \[0\-9a\-fA\-F\]

We are nearly done with expressions\. The only piece left is to tell how the
characters in character classes and string literals are specified\.

Basically characters in the input stand for themselves, and in addition to that
we several types of escape syntax to to repesent control characters, or
characters outside of the encoding the text is in\.

All the escaped forms are started with a backslash character \('\\', unicode
codepoint 0x5C\)\. This is then followed by a series of octal digits, or 'u' and
hexedecimal digits, or a regular character from a fixed set for various control
characters\. Some examples:

    \\n \\r \\t \\' \\" \\\[ \\\] \\\\ \#
    \\000 up to \\277         \# octal escape, all ascii character, leading 0's can be removed\.
    \\u2CA7                  \# hexadecimal escape, all unicode characters\.
    \#                       \# Here 2ca7 <=> Koptic Small Letter Tau

## <a name='subsection5'></a>Whitespace and comments

One issue not touched upon so far is whitespace and comments\.

Whitespace is any unicode space character, i\.e\. anything in the character class
<space>, and comments\. The latter are sequences of characters starting with a
'\#' \(hash, unicode codepoint 0x23\) and ending at the next end\-of\-line\.

Whitespace can be freely used between all syntactical elements of a grammar
specification\. It cannot be used inside of syntactical elements, like names,
string literals, predefined character classes, etc\.

## <a name='subsection6'></a>Nonterminal attributes

Lastly, a more advanced topic\. In the section [Rules](#subsection3) we gave
the structure of a rule as

    <<name>>  <\-  <<expression>> ;

This is not quite true\. It is possible to associate a semantic mode with the
nonterminal in the rule, by writing it before the name, separated from it by a
colon, i\.e\. writing

    <<mode>> : <<name>>  <\-  <<expression>> ;

is also allowed\. This mode is optional\. The known modes and their meanings are:

  - __value__

    The semantic value of the nonterminal symbol is an abstract syntax tree
    consisting of a single node node for the nonterminal itself, which has the







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|



|



|




|
|
|













|
|
|
|


















|





|







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

The last two examples show how to place any of the delimiters into a string\.

For the last, but not least of our atomic expressions, character classes, we
have a number of predefined classes, shown below, and the ability to construct
or own\. The predefined classes are:

    <alnum>    # Any unicode alphabet or digit character (string is alnum).
    <alpha>    # Any unicode alphabet character (string is alpha).
    <ascii>    # Any unicode character below codepoint 0x80 (string is ascii).
    <control>  # Any unicode control character (string is control).
    <ddigit>   # The digit characters [0-9].
    <digit>    # Any unicode digit character (string is digit).
    <graph>    # Any unicode printing character, except space (string is graph).
    <lower>    # Any unicode lower-case alphabet character (string is lower).
    <print>    # Any unicode printing character, incl. space (string is print).
    <punct>    # Any unicode punctuation character (string is punct).
    <space>    # Any unicode space character (string is space).
    <upper>    # Any unicode upper-case alphabet character (string is upper).
    <wordchar> # Any unicode word character (string is wordchar).
    <xdigit>   # The hexadecimal digit characters [0-9a-fA-F].
    .          # Any character, except end of input.

And the syntax of custom\-defined character classes is

    [ <<range>>* ]

where each range is either a single character, or of the form

    <<character>> - <character>>

Examples for character classes we have seen already in the course of this
introduction are

    [_:]
    [0-9]
    [0-9a-fA-F]

We are nearly done with expressions\. The only piece left is to tell how the
characters in character classes and string literals are specified\.

Basically characters in the input stand for themselves, and in addition to that
we several types of escape syntax to to repesent control characters, or
characters outside of the encoding the text is in\.

All the escaped forms are started with a backslash character \('\\', unicode
codepoint 0x5C\)\. This is then followed by a series of octal digits, or 'u' and
hexedecimal digits, or a regular character from a fixed set for various control
characters\. Some examples:

    \n \r \t \' \" \[ \] \\ #
    \000 up to \277         # octal escape, all ascii character, leading 0's can be removed.
    \u2CA7                  # hexadecimal escape, all unicode characters.
    #                       # Here 2ca7 <=> Koptic Small Letter Tau

## <a name='subsection5'></a>Whitespace and comments

One issue not touched upon so far is whitespace and comments\.

Whitespace is any unicode space character, i\.e\. anything in the character class
<space>, and comments\. The latter are sequences of characters starting with a
'\#' \(hash, unicode codepoint 0x23\) and ending at the next end\-of\-line\.

Whitespace can be freely used between all syntactical elements of a grammar
specification\. It cannot be used inside of syntactical elements, like names,
string literals, predefined character classes, etc\.

## <a name='subsection6'></a>Nonterminal attributes

Lastly, a more advanced topic\. In the section [Rules](#subsection3) we gave
the structure of a rule as

    <<name>>  <-  <<expression>> ;

This is not quite true\. It is possible to associate a semantic mode with the
nonterminal in the rule, by writing it before the name, separated from it by a
colon, i\.e\. writing

    <<mode>> : <<name>>  <-  <<expression>> ;

is also allowed\. This mode is optional\. The known modes and their meanings are:

  - __value__

    The semantic value of the nonterminal symbol is an abstract syntax tree
    consisting of a single node node for the nonterminal itself, which has the
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
writing the specification of a grammar easy, something the other formats found
in the Parser Tools do not lend themselves too\.

It is formally specified by the grammar shown below, written in itself\. For a
tutorial / introduction to the language please go and read the *PEG Language
Tutorial*\.

    PEG pe\-grammar\-for\-peg \(Grammar\)

    	\# \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
            \# Syntactical constructs

            Grammar         <\- WHITESPACE Header Definition\* Final EOF ;

            Header          <\- PEG Identifier StartExpr ;
            Definition      <\- Attribute? Identifier IS Expression SEMICOLON ;
            Attribute       <\- \(VOID / LEAF\) COLON ;
            Expression      <\- Sequence \(SLASH Sequence\)\* ;
            Sequence        <\- Prefix\+ ;
            Prefix          <\- \(AND / NOT\)? Suffix ;
            Suffix          <\- Primary \(QUESTION / STAR / PLUS\)? ;
            Primary         <\- ALNUM / ALPHA / ASCII / CONTROL / DDIGIT / DIGIT
                            /  GRAPH / LOWER / PRINTABLE / PUNCT / SPACE / UPPER
                            /  WORDCHAR / XDIGIT
                            / Identifier
                            /  OPEN Expression CLOSE
                            /  Literal
                            /  Class
                            /  DOT
                            ;
            Literal         <\- APOSTROPH  \(\!APOSTROPH  Char\)\* APOSTROPH  WHITESPACE
                            /  DAPOSTROPH \(\!DAPOSTROPH Char\)\* DAPOSTROPH WHITESPACE ;
            Class           <\- OPENB \(\!CLOSEB Range\)\* CLOSEB WHITESPACE ;
            Range           <\- Char TO Char / Char ;

            StartExpr       <\- OPEN Expression CLOSE ;
    void:   Final           <\- "END" WHITESPACE SEMICOLON WHITESPACE ;

            \# \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
            \# Lexing constructs

            Identifier      <\- Ident WHITESPACE ;
    leaf:   Ident           <\- \(\[\_:\] / <alpha>\) \(\[\_:\] / <alnum>\)\* ;
            Char            <\- CharSpecial / CharOctalFull / CharOctalPart
                            /  CharUnicode / CharUnescaped
                            ;

    leaf:   CharSpecial     <\- "\\\\" \[nrt'"\\\[\\\]\\\\\] ;
    leaf:   CharOctalFull   <\- "\\\\" \[0\-2\]\[0\-7\]\[0\-7\] ;
    leaf:   CharOctalPart   <\- "\\\\" \[0\-7\]\[0\-7\]? ;
    leaf:   CharUnicode     <\- "\\\\" 'u' HexDigit \(HexDigit \(HexDigit HexDigit?\)?\)? ;
    leaf:   CharUnescaped   <\- \!"\\\\" \. ;

    void:   HexDigit        <\- \[0\-9a\-fA\-F\] ;

    void:   TO              <\- '\-'           ;
    void:   OPENB           <\- "\["           ;
    void:   CLOSEB          <\- "\]"           ;
    void:   APOSTROPH       <\- "'"           ;
    void:   DAPOSTROPH      <\- '"'           ;
    void:   PEG             <\- "PEG" \!\(\[\_:\] / <alnum>\) WHITESPACE ;
    void:   IS              <\- "<\-"    WHITESPACE ;
    leaf:   VOID            <\- "void"  WHITESPACE ; \# Implies that definition has no semantic value\.
    leaf:   LEAF            <\- "leaf"  WHITESPACE ; \# Implies that definition has no terminals\.
    void:   SEMICOLON       <\- ";"     WHITESPACE ;
    void:   COLON           <\- ":"     WHITESPACE ;
    void:   SLASH           <\- "/"     WHITESPACE ;
    leaf:   AND             <\- "&"     WHITESPACE ;
    leaf:   NOT             <\- "\!"     WHITESPACE ;
    leaf:   QUESTION        <\- "?"     WHITESPACE ;
    leaf:   STAR            <\- "\*"     WHITESPACE ;
    leaf:   PLUS            <\- "\+"     WHITESPACE ;
    void:   OPEN            <\- "\("     WHITESPACE ;
    void:   CLOSE           <\- "\)"     WHITESPACE ;
    leaf:   DOT             <\- "\."     WHITESPACE ;

    leaf:   ALNUM           <\- "<alnum>"    WHITESPACE ;
    leaf:   ALPHA           <\- "<alpha>"    WHITESPACE ;
    leaf:   ASCII           <\- "<ascii>"    WHITESPACE ;
    leaf:   CONTROL         <\- "<control>"  WHITESPACE ;
    leaf:   DDIGIT          <\- "<ddigit>"   WHITESPACE ;
    leaf:   DIGIT           <\- "<digit>"    WHITESPACE ;
    leaf:   GRAPH           <\- "<graph>"    WHITESPACE ;
    leaf:   LOWER           <\- "<lower>"    WHITESPACE ;
    leaf:   PRINTABLE       <\- "<print>"    WHITESPACE ;
    leaf:   PUNCT           <\- "<punct>"    WHITESPACE ;
    leaf:   SPACE           <\- "<space>"    WHITESPACE ;
    leaf:   UPPER           <\- "<upper>"    WHITESPACE ;
    leaf:   WORDCHAR        <\- "<wordchar>" WHITESPACE ;
    leaf:   XDIGIT          <\- "<xdigit>"   WHITESPACE ;

    void:   WHITESPACE      <\- \(" " / "\\t" / EOL / COMMENT\)\* ;
    void:   COMMENT         <\- '\#' \(\!EOL \.\)\* EOL ;
    void:   EOL             <\- "\\n\\r" / "\\n" / "\\r" ;
    void:   EOF             <\- \!\. ;

            \# \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
    END;

## <a name='subsection7'></a>Example

Our example specifies the grammar for a basic 4\-operation calculator\.

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

Using higher\-level features of the notation, i\.e\. the character classes
\(predefined and custom\), this example can be rewritten as

    PEG calculator \(Expression\)
        Sign       <\- \[\-\+\] 						;
        Number     <\- Sign? <ddigit>\+				;
        Expression <\- '\(' Expression '\)' / \(Factor \(MulOp Factor\)\*\)	;
        MulOp      <\- \[\*/\]						;
        Factor     <\- Term \(AddOp Term\)\*				;
        AddOp      <\- \[\-\+\]						;
        Term       <\- Number					;
    END;

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas







|

|
|

|

|
|
|
|
|
|
|
|








|
|
|
|

|
|

|
|

|
|
|



|
|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|

|






|
|
|
|
|
|
|
|
|





|
|
|
|
|
|
|
|







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
writing the specification of a grammar easy, something the other formats found
in the Parser Tools do not lend themselves too\.

It is formally specified by the grammar shown below, written in itself\. For a
tutorial / introduction to the language please go and read the *PEG Language
Tutorial*\.

    PEG pe-grammar-for-peg (Grammar)

    	# --------------------------------------------------------------------
            # Syntactical constructs

            Grammar         <- WHITESPACE Header Definition* Final EOF ;

            Header          <- PEG Identifier StartExpr ;
            Definition      <- Attribute? Identifier IS Expression SEMICOLON ;
            Attribute       <- (VOID / LEAF) COLON ;
            Expression      <- Sequence (SLASH Sequence)* ;
            Sequence        <- Prefix+ ;
            Prefix          <- (AND / NOT)? Suffix ;
            Suffix          <- Primary (QUESTION / STAR / PLUS)? ;
            Primary         <- ALNUM / ALPHA / ASCII / CONTROL / DDIGIT / DIGIT
                            /  GRAPH / LOWER / PRINTABLE / PUNCT / SPACE / UPPER
                            /  WORDCHAR / XDIGIT
                            / Identifier
                            /  OPEN Expression CLOSE
                            /  Literal
                            /  Class
                            /  DOT
                            ;
            Literal         <- APOSTROPH  (!APOSTROPH  Char)* APOSTROPH  WHITESPACE
                            /  DAPOSTROPH (!DAPOSTROPH Char)* DAPOSTROPH WHITESPACE ;
            Class           <- OPENB (!CLOSEB Range)* CLOSEB WHITESPACE ;
            Range           <- Char TO Char / Char ;

            StartExpr       <- OPEN Expression CLOSE ;
    void:   Final           <- "END" WHITESPACE SEMICOLON WHITESPACE ;

            # --------------------------------------------------------------------
            # Lexing constructs

            Identifier      <- Ident WHITESPACE ;
    leaf:   Ident           <- ([_:] / <alpha>) ([_:] / <alnum>)* ;
            Char            <- CharSpecial / CharOctalFull / CharOctalPart
                            /  CharUnicode / CharUnescaped
                            ;

    leaf:   CharSpecial     <- "\\" [nrt'"\[\]\\] ;
    leaf:   CharOctalFull   <- "\\" [0-2][0-7][0-7] ;
    leaf:   CharOctalPart   <- "\\" [0-7][0-7]? ;
    leaf:   CharUnicode     <- "\\" 'u' HexDigit (HexDigit (HexDigit HexDigit?)?)? ;
    leaf:   CharUnescaped   <- !"\\" . ;

    void:   HexDigit        <- [0-9a-fA-F] ;

    void:   TO              <- '-'           ;
    void:   OPENB           <- "["           ;
    void:   CLOSEB          <- "]"           ;
    void:   APOSTROPH       <- "'"           ;
    void:   DAPOSTROPH      <- '"'           ;
    void:   PEG             <- "PEG" !([_:] / <alnum>) WHITESPACE ;
    void:   IS              <- "<-"    WHITESPACE ;
    leaf:   VOID            <- "void"  WHITESPACE ; # Implies that definition has no semantic value.
    leaf:   LEAF            <- "leaf"  WHITESPACE ; # Implies that definition has no terminals.
    void:   SEMICOLON       <- ";"     WHITESPACE ;
    void:   COLON           <- ":"     WHITESPACE ;
    void:   SLASH           <- "/"     WHITESPACE ;
    leaf:   AND             <- "&"     WHITESPACE ;
    leaf:   NOT             <- "!"     WHITESPACE ;
    leaf:   QUESTION        <- "?"     WHITESPACE ;
    leaf:   STAR            <- "*"     WHITESPACE ;
    leaf:   PLUS            <- "+"     WHITESPACE ;
    void:   OPEN            <- "("     WHITESPACE ;
    void:   CLOSE           <- ")"     WHITESPACE ;
    leaf:   DOT             <- "."     WHITESPACE ;

    leaf:   ALNUM           <- "<alnum>"    WHITESPACE ;
    leaf:   ALPHA           <- "<alpha>"    WHITESPACE ;
    leaf:   ASCII           <- "<ascii>"    WHITESPACE ;
    leaf:   CONTROL         <- "<control>"  WHITESPACE ;
    leaf:   DDIGIT          <- "<ddigit>"   WHITESPACE ;
    leaf:   DIGIT           <- "<digit>"    WHITESPACE ;
    leaf:   GRAPH           <- "<graph>"    WHITESPACE ;
    leaf:   LOWER           <- "<lower>"    WHITESPACE ;
    leaf:   PRINTABLE       <- "<print>"    WHITESPACE ;
    leaf:   PUNCT           <- "<punct>"    WHITESPACE ;
    leaf:   SPACE           <- "<space>"    WHITESPACE ;
    leaf:   UPPER           <- "<upper>"    WHITESPACE ;
    leaf:   WORDCHAR        <- "<wordchar>" WHITESPACE ;
    leaf:   XDIGIT          <- "<xdigit>"   WHITESPACE ;

    void:   WHITESPACE      <- (" " / "\t" / EOL / COMMENT)* ;
    void:   COMMENT         <- '#' (!EOL .)* EOL ;
    void:   EOL             <- "\n\r" / "\n" / "\r" ;
    void:   EOF             <- !. ;

            # --------------------------------------------------------------------
    END;

## <a name='subsection7'></a>Example

Our example specifies the grammar for a basic 4\-operation calculator\.

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

Using higher\-level features of the notation, i\.e\. the character classes
\(predefined and custom\), this example can be rewritten as

    PEG calculator (Expression)
        Sign       <- [-+] 						;
        Number     <- Sign? <ddigit>+				;
        Expression <- '(' Expression ')' / (Factor (MulOp Factor)*)	;
        MulOp      <- [*/]						;
        Factor     <- Term (AddOp Term)*				;
        AddOp      <- [-+]						;
        Term       <- Number					;
    END;

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_op.md.

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

  - <a name='2'></a>__::peg::peg::op__ __dechain__ *container*

    This command simplifies all symbols which just chain to a different symbol
    by inlining the right hand side of the called symbol in its callers\. This
    works if and only the modes match properly, per the decision table below\.

        caller called &#124; dechain &#124; notes
        \-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
        value  value  &#124;  yes    &#124;  value is passed
        value  leaf   &#124;  yes    &#124;  value is passed
        value  void   &#124;  yes    &#124;  caller is implied void
        leaf   value  &#124;  no     &#124;  generated value was discarded, inlined would not\. called may be implied void\.
        leaf   leaf   &#124;  no     &#124;  s\.a\.
        leaf   void   &#124;  no     &#124;  s\.a\.
        void   value  &#124;  no     &#124;  caller drops value, inlined would not\.
        void   leaf   &#124;  no     &#124;  s\.a\.
        void   void   &#124;  yes    &#124;

    The result of the command is the empty string\.

    The grammar in the container is directly modified\. If that is not wanted, a
    copy of the original container has to be used\.

    The *container* instance has to expose a method API as is provided by the







|
|
|
|
|
|
|
|
|
|
|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

  - <a name='2'></a>__::peg::peg::op__ __dechain__ *container*

    This command simplifies all symbols which just chain to a different symbol
    by inlining the right hand side of the called symbol in its callers\. This
    works if and only the modes match properly, per the decision table below\.

        caller called | dechain | notes
        --------------+---------+-----------------------
        value  value  |  yes    |  value is passed
        value  leaf   |  yes    |  value is passed
        value  void   |  yes    |  caller is implied void
        leaf   value  |  no     |  generated value was discarded, inlined would not. called may be implied void.
        leaf   leaf   |  no     |  s.a.
        leaf   void   |  no     |  s.a.
        void   value  |  no     |  caller drops value, inlined would not.
        void   leaf   |  no     |  s.a.
        void   void   |  yes    |

    The result of the command is the empty string\.

    The grammar in the container is directly modified\. If that is not wanted, a
    copy of the original container has to be used\.

    The *container* instance has to expose a method API as is provided by the

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_to_container.md.

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

It has no direct formal specification beyond what was said above\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

one possible CONTAINER serialization for it is

    snit::type a\_pe\_grammar \{
        constructor \{\} \{
            install myg using pt::peg::container $\{selfns\}::G
            $myg start \{n Expression\}
            $myg add   AddOp Digit Expression Factor MulOp Number Sign Term
            $myg modes \{
                AddOp      value
                Digit      value
                Expression value
                Factor     value
                MulOp      value
                Number     value
                Sign       value
                Term       value
            \}

            $myg rules \{
                AddOp      \{/ \{t \-\} \{t \+\}\}
                Digit      \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}
                Expression \{/ \{x \{t \\50\} \{n Expression\} \{t \\51\}\} \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}\}
                Factor     \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}
                MulOp      \{/ \{t \*\} \{t /\}\}
                Number     \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}
                Sign       \{/ \{t \-\} \{t \+\}\}
                Term       \{n Number\}
            \}

            return
        \}


        component myg
        delegate method \* to myg
    \}


# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a PEG







|
|
|
|
|
|
|
|
|




|
|
|
|

|








<
>
|
|
|
|
|
|
|
|
|
<
>

<
|
>

|
<
>







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

It has no direct formal specification beyond what was said above\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

one possible CONTAINER serialization for it is

    snit::type a_pe_grammar {
        constructor {} {
            install myg using pt::peg::container ${selfns}::G
            $myg start {n Expression}
            $myg add   AddOp Digit Expression Factor MulOp Number Sign Term
            $myg modes {
                AddOp      value
                Digit      value
                Expression value
                Factor     value
                MulOp      value
                Number     value
                Sign       value
                Term       value

            }
            $myg rules {
                AddOp      {/ {t -} {t +}}
                Digit      {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}
                Expression {/ {x {t \50} {n Expression} {t \51}} {x {n Factor} {* {x {n MulOp} {n Factor}}}}}
                Factor     {x {n Term} {* {x {n AddOp} {n Term}}}}
                MulOp      {/ {t *} {t /}}
                Number     {x {? {n Sign}} {+ {n Digit}}}
                Sign       {/ {t -} {t +}}
                Term       {n Number}

            }
            return

        }

        component myg
        delegate method * to myg

    }

# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a PEG
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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_to_cparam.md.

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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_to_json.md.

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
themselves are not translated further, but kept as JSON strings containing a
nested Tcl list, and there is no concept of canonicity for the JSON either\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

a JSON serialization for it is

    \{

        "pt::grammar::peg" : \{
            "rules" : \{
                "AddOp"     : \{
                    "is"   : "\\/ \{t \-\} \{t \+\}",
                    "mode" : "value"
                \},
                "Digit"     : \{
                    "is"   : "\\/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}",
                    "mode" : "value"
                \},
                "Expression" : \{
                    "is"   : "\\/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}",
                    "mode" : "value"
                \},
                "Factor"    : \{
                    "is"   : "x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}",
                    "mode" : "value"
                \},
                "MulOp"     : \{
                    "is"   : "\\/ \{t \*\} \{t \\/\}",
                    "mode" : "value"
                \},
                "Number"    : \{
                    "is"   : "x \{? \{n Sign\}\} \{\+ \{n Digit\}\}",
                    "mode" : "value"
                \},
                "Sign"      : \{
                    "is"   : "\\/ \{t \-\} \{t \+\}",
                    "mode" : "value"
                \},
                "Term"      : \{
                    "is"   : "n Number",
                    "mode" : "value"
                \}

            \},
            "start" : "n Expression"
        \}
    \}



and a Tcl serialization of the same is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


The similarity of the latter to the JSON should be quite obvious\.

# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.







|
|
|
|
|
|
|
|
|




<
>
|
|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|
|

|
|


<
>
|

<
<
|
>
>


|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
themselves are not translated further, but kept as JSON strings containing a
nested Tcl list, and there is no concept of canonicity for the JSON either\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

a JSON serialization for it is


    {
        "pt::grammar::peg" : {
            "rules" : {
                "AddOp"     : {
                    "is"   : "\/ {t -} {t +}",
                    "mode" : "value"
                },
                "Digit"     : {
                    "is"   : "\/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}",
                    "mode" : "value"
                },
                "Expression" : {
                    "is"   : "\/ {x {t (} {n Expression} {t )}} {x {n Factor} {* {x {n MulOp} {n Factor}}}}",
                    "mode" : "value"
                },
                "Factor"    : {
                    "is"   : "x {n Term} {* {x {n AddOp} {n Term}}}",
                    "mode" : "value"
                },
                "MulOp"     : {
                    "is"   : "\/ {t *} {t \/}",
                    "mode" : "value"
                },
                "Number"    : {
                    "is"   : "x {? {n Sign}} {+ {n Digit}}",
                    "mode" : "value"
                },
                "Sign"      : {
                    "is"   : "\/ {t -} {t +}",
                    "mode" : "value"
                },
                "Term"      : {
                    "is"   : "n Number",
                    "mode" : "value"

                }
            },
            "start" : "n Expression"


        }
    }

and a Tcl serialization of the same is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

The similarity of the latter to the JSON should be quite obvious\.

# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.
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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_to_param.md.

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

It has no direct formal specification beyond what was said above\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

one possible PARAM serialization for it is

    \# \-\*\- text \-\*\-
    \# Parsing Expression Grammar 'TEMPLATE'\.
    \# Generated for unknown, from file 'TEST'

    \#

    \# Grammar Start Expression
    \#


    <<MAIN>>:
             call              sym\_Expression
             halt

    \#

    \# value Symbol 'AddOp'
    \#


    sym\_AddOp:
    \# /
    \#     '\-'
    \#     '\+'

             symbol\_restore    AddOp
      found\! jump              found\_7
             loc\_push

             call              choice\_5

       fail\! value\_clear
         ok\! value\_leaf        AddOp
             symbol\_save       AddOp
             error\_nonterminal AddOp
             loc\_pop\_discard

    found\_7:
         ok\! ast\_value\_push
             return

    choice\_5:
    \# /
    \#     '\-'
    \#     '\+'

             error\_clear

             loc\_push
             error\_push

             input\_next        "t \-"
         ok\! test\_char         "\-"

             error\_pop\_merge
         ok\! jump              oknoast\_4

             loc\_pop\_rewind
             loc\_push
             error\_push

             input\_next        "t \+"
         ok\! test\_char         "\+"

             error\_pop\_merge
         ok\! jump              oknoast\_4

             loc\_pop\_rewind
             status\_fail
             return

    oknoast\_4:
             loc\_pop\_discard
             return
    \#

    \# value Symbol 'Digit'
    \#


    sym\_Digit:
    \# /
    \#     '0'
    \#     '1'
    \#     '2'
    \#     '3'
    \#     '4'
    \#     '5'
    \#     '6'
    \#     '7'
    \#     '8'
    \#     '9'

             symbol\_restore    Digit
      found\! jump              found\_22
             loc\_push

             call              choice\_20

       fail\! value\_clear
         ok\! value\_leaf        Digit
             symbol\_save       Digit
             error\_nonterminal Digit
             loc\_pop\_discard

    found\_22:
         ok\! ast\_value\_push
             return

    choice\_20:
    \# /
    \#     '0'
    \#     '1'
    \#     '2'
    \#     '3'
    \#     '4'
    \#     '5'
    \#     '6'
    \#     '7'
    \#     '8'
    \#     '9'

             error\_clear

             loc\_push
             error\_push

             input\_next        "t 0"
         ok\! test\_char         "0"

             error\_pop\_merge
         ok\! jump              oknoast\_19

             loc\_pop\_rewind
             loc\_push
             error\_push

             input\_next        "t 1"
         ok\! test\_char         "1"

             error\_pop\_merge
         ok\! jump              oknoast\_19

             loc\_pop\_rewind
             loc\_push
             error\_push

             input\_next        "t 2"
         ok\! test\_char         "2"

             error\_pop\_merge
         ok\! jump              oknoast\_19

             loc\_pop\_rewind
             loc\_push
             error\_push

             input\_next        "t 3"
         ok\! test\_char         "3"

             error\_pop\_merge
         ok\! jump              oknoast\_19

             loc\_pop\_rewind
             loc\_push
             error\_push

             input\_next        "t 4"
         ok\! test\_char         "4"

             error\_pop\_merge
         ok\! jump              oknoast\_19

             loc\_pop\_rewind
             loc\_push
             error\_push

             input\_next        "t 5"
         ok\! test\_char         "5"


             error\_pop\_merge
         ok\! jump              oknoast\_19

             loc\_pop\_rewind
             loc\_push
             error\_push

             input\_next        "t 6"
         ok\! test\_char         "6"

             error\_pop\_merge
         ok\! jump              oknoast\_19

             loc\_pop\_rewind
             loc\_push
             error\_push

             input\_next        "t 7"
         ok\! test\_char         "7"

             error\_pop\_merge
         ok\! jump              oknoast\_19

             loc\_pop\_rewind
             loc\_push
             error\_push

             input\_next        "t 8"
         ok\! test\_char         "8"

             error\_pop\_merge
         ok\! jump              oknoast\_19

             loc\_pop\_rewind
             loc\_push
             error\_push

             input\_next        "t 9"
         ok\! test\_char         "9"

             error\_pop\_merge
         ok\! jump              oknoast\_19

             loc\_pop\_rewind
             status\_fail
             return

    oknoast\_19:
             loc\_pop\_discard
             return
    \#

    \# value Symbol 'Expression'
    \#


    sym\_Expression:
    \# /
    \#     x
    \#         '\\\('
    \#         \(Expression\)
    \#         '\\\)'
    \#     x
    \#         \(Factor\)
    \#         \*
    \#             x
    \#                 \(MulOp\)
    \#                 \(Factor\)

             symbol\_restore    Expression
      found\! jump              found\_46
             loc\_push
             ast\_push

             call              choice\_44

       fail\! value\_clear
         ok\! value\_reduce      Expression
             symbol\_save       Expression
             error\_nonterminal Expression
             ast\_pop\_rewind
             loc\_pop\_discard

    found\_46:
         ok\! ast\_value\_push
             return

    choice\_44:
    \# /
    \#     x
    \#         '\\\('
    \#         \(Expression\)
    \#         '\\\)'
    \#     x
    \#         \(Factor\)
    \#         \*
    \#             x
    \#                 \(MulOp\)
    \#                 \(Factor\)

             error\_clear

             ast\_push
             loc\_push
             error\_push

             call              sequence\_27

             error\_pop\_merge
         ok\! jump              ok\_43

             ast\_pop\_rewind
             loc\_pop\_rewind
             ast\_push
             loc\_push
             error\_push

             call              sequence\_40


             error\_pop\_merge
         ok\! jump              ok\_43

             ast\_pop\_rewind
             loc\_pop\_rewind
             status\_fail
             return

    ok\_43:
             ast\_pop\_discard
             loc\_pop\_discard
             return

    sequence\_27:
    \# x
    \#     '\\\('
    \#     \(Expression\)
    \#     '\\\)'

             loc\_push
             error\_clear

             error\_push

             input\_next        "t \("
         ok\! test\_char         "\("

             error\_pop\_merge
       fail\! jump              failednoast\_29
             ast\_push
             error\_push

             call              sym\_Expression

             error\_pop\_merge
       fail\! jump              failed\_28
             error\_push

             input\_next        "t \)"
         ok\! test\_char         "\)"

             error\_pop\_merge
       fail\! jump              failed\_28

             ast\_pop\_discard
             loc\_pop\_discard
             return

    failed\_28:
             ast\_pop\_rewind

    failednoast\_29:
             loc\_pop\_rewind
             return

    sequence\_40:
    \# x
    \#     \(Factor\)
    \#     \*
    \#         x
    \#             \(MulOp\)
    \#             \(Factor\)

             ast\_push
             loc\_push
             error\_clear

             error\_push

             call              sym\_Factor

             error\_pop\_merge
       fail\! jump              failed\_41
             error\_push

             call              kleene\_37

             error\_pop\_merge
       fail\! jump              failed\_41

             ast\_pop\_discard
             loc\_pop\_discard
             return

    failed\_41:
             ast\_pop\_rewind
             loc\_pop\_rewind
             return

    kleene\_37:
    \# \*
    \#     x
    \#         \(MulOp\)
    \#         \(Factor\)

             loc\_push
             error\_push

             call              sequence\_34

             error\_pop\_merge
       fail\! jump              failed\_38
             loc\_pop\_discard
             jump              kleene\_37

    failed\_38:
             loc\_pop\_rewind
             status\_ok
             return

    sequence\_34:
    \# x
    \#     \(MulOp\)
    \#     \(Factor\)

             ast\_push



             loc\_push
             error\_clear

             error\_push

             call              sym\_MulOp

             error\_pop\_merge
       fail\! jump              failed\_35
             error\_push

             call              sym\_Factor

             error\_pop\_merge
       fail\! jump              failed\_35

             ast\_pop\_discard
             loc\_pop\_discard
             return

    failed\_35:
             ast\_pop\_rewind
             loc\_pop\_rewind
             return





    \#
    \# value Symbol 'Factor'
    \#

    sym\_Factor:
    \# x
    \#     \(Term\)
    \#     \*
    \#         x
    \#             \(AddOp\)
    \#             \(Term\)

             symbol\_restore    Factor
      found\! jump              found\_60
             loc\_push
             ast\_push

             call              sequence\_57

       fail\! value\_clear
         ok\! value\_reduce      Factor
             symbol\_save       Factor
             error\_nonterminal Factor
             ast\_pop\_rewind
             loc\_pop\_discard

    found\_60:
         ok\! ast\_value\_push
             return

    sequence\_57:
    \# x
    \#     \(Term\)
    \#     \*
    \#         x
    \#             \(AddOp\)
    \#             \(Term\)

             ast\_push
             loc\_push
             error\_clear

             error\_push

             call              sym\_Term

             error\_pop\_merge
       fail\! jump              failed\_58


             error\_push

             call              kleene\_54

             error\_pop\_merge
       fail\! jump              failed\_58

             ast\_pop\_discard
             loc\_pop\_discard
             return

    failed\_58:
             ast\_pop\_rewind
             loc\_pop\_rewind
             return

    kleene\_54:
    \# \*
    \#     x
    \#         \(AddOp\)
    \#         \(Term\)

             loc\_push
             error\_push

             call              sequence\_51

             error\_pop\_merge
       fail\! jump              failed\_55
             loc\_pop\_discard
             jump              kleene\_54

    failed\_55:
             loc\_pop\_rewind
             status\_ok
             return

    sequence\_51:
    \# x
    \#     \(AddOp\)
    \#     \(Term\)

             ast\_push
             loc\_push
             error\_clear

             error\_push

             call              sym\_AddOp

             error\_pop\_merge
       fail\! jump              failed\_52
             error\_push

             call              sym\_Term

             error\_pop\_merge
       fail\! jump              failed\_52

             ast\_pop\_discard
             loc\_pop\_discard
             return

    failed\_52:
             ast\_pop\_rewind
             loc\_pop\_rewind
             return
    \#
    \# value Symbol 'MulOp'
    \#




    sym\_MulOp:
    \# /
    \#     '\*'
    \#     '/'

             symbol\_restore    MulOp
      found\! jump              found\_67
             loc\_push

             call              choice\_65

       fail\! value\_clear
         ok\! value\_leaf        MulOp
             symbol\_save       MulOp
             error\_nonterminal MulOp
             loc\_pop\_discard

    found\_67:
         ok\! ast\_value\_push
             return

    choice\_65:
    \# /
    \#     '\*'
    \#     '/'

             error\_clear

             loc\_push
             error\_push

             input\_next        "t \*"
         ok\! test\_char         "\*"

             error\_pop\_merge
         ok\! jump              oknoast\_64

             loc\_pop\_rewind
             loc\_push
             error\_push

             input\_next        "t /"
         ok\! test\_char         "/"

             error\_pop\_merge
         ok\! jump              oknoast\_64

             loc\_pop\_rewind
             status\_fail
             return

    oknoast\_64:
             loc\_pop\_discard
             return
    \#

    \# value Symbol 'Number'
    \#


    sym\_Number:
    \# x
    \#     ?
    \#         \(Sign\)
    \#     \+
    \#         \(Digit\)

             symbol\_restore    Number
      found\! jump              found\_80
             loc\_push
             ast\_push

             call              sequence\_77

       fail\! value\_clear
         ok\! value\_reduce      Number
             symbol\_save       Number
             error\_nonterminal Number
             ast\_pop\_rewind
             loc\_pop\_discard

    found\_80:
         ok\! ast\_value\_push
             return

    sequence\_77:
    \# x
    \#     ?
    \#         \(Sign\)
    \#     \+
    \#         \(Digit\)

             ast\_push
             loc\_push
             error\_clear

             error\_push

             call              optional\_70

             error\_pop\_merge
       fail\! jump              failed\_78
             error\_push

             call              poskleene\_73

             error\_pop\_merge
       fail\! jump              failed\_78

             ast\_pop\_discard
             loc\_pop\_discard
             return

    failed\_78:
             ast\_pop\_rewind
             loc\_pop\_rewind
             return

    optional\_70:
    \# ?
    \#     \(Sign\)

             loc\_push
             error\_push

             call              sym\_Sign

             error\_pop\_merge
       fail\! loc\_pop\_rewind
         ok\! loc\_pop\_discard
             status\_ok
             return

    poskleene\_73:
    \# \+
    \#     \(Digit\)

             loc\_push

             call              sym\_Digit

       fail\! jump              failed\_74

    loop\_75:
             loc\_pop\_discard
             loc\_push
             error\_push

             call              sym\_Digit

             error\_pop\_merge
         ok\! jump              loop\_75
             status\_ok

    failed\_74:
             loc\_pop\_rewind
             return
    \#

    \# value Symbol 'Sign'
    \#


    sym\_Sign:
    \# /
    \#     '\-'
    \#     '\+'

             symbol\_restore    Sign
      found\! jump              found\_86
             loc\_push

             call              choice\_5

       fail\! value\_clear
         ok\! value\_leaf        Sign
             symbol\_save       Sign
             error\_nonterminal Sign
             loc\_pop\_discard

    found\_86:
         ok\! ast\_value\_push
             return
    \#

    \# value Symbol 'Term'
    \#


    sym\_Term:
    \# \(Number\)

             symbol\_restore    Term
      found\! jump              found\_89
             loc\_push
             ast\_push

             call              sym\_Number

       fail\! value\_clear
         ok\! value\_reduce      Term
             symbol\_save       Term
             error\_nonterminal Term
             ast\_pop\_rewind
             loc\_pop\_discard

    found\_89:
         ok\! ast\_value\_push
             return

    \#
    \#



# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a PEG







|
|
|
|
|
|
|
|
|




|
|
|

<
>
|
<
|
>

|


<
>
|
<
|
>
|
|
|
|

|
|
|

|

|
|
|
|
|

|
|


|
|
|
|

|

|
|

|
|

|
|

|
|
|

|
|

|
|

|
|


|
|

<
>
|
<
|
>
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|

|

|
|
|
|
|

|
|


|
|
|
|
|
|
|
|
|
|
|
|

|

|
|

|
|

|
|

|
|
|

|
|

|
|

|
|
|

|
|

|
|

|
|
|

|
|

|
|

|
|
|

|
|

|
|

|
|
|

|
|
>
|
<
|

|
|
|

|
|

|
|

|
|
|

|
|

|
|

|
|
|

|
|

|
|

|
|
|

|
|

|
|

|
|


|
|

<
>
|
<
|
>
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|

|

|
|
|
|
|
|

|
|


|
|
|
|
|
|
|
|
|
|
|
|

|

|
|
|

|

|
|

|
|
|
|
|

|
>
|
<
|

|
|
|


|
|
|


|
|
|
|
|

|
|

|

|
|

|
|
|
|

|

|
|
|

|
|

|
|

|
|


|
|

|
|


|
|
|
|
|
|
|

|
|
|

|

|

|
|
|

|

|
|

|
|


|
|
|


|
|
|
|
|

|
|

|

|
|
|
|

|
|
|


|
|
|
|

|
>
>
>
|
<

<
<
|

|
|
|

|

|
|

|
|


|
|
|

>
>
>
>
>
<
<
<
<
<
|
|
|
|
|
|

|
|
|
|

|

|
|
|
|
|
|

|
|


|
|
|
|
|
|
|

|
|
|

|

|

<
<
>
>
|

|

|
|

|
|


|
|
|


|
|
|
|
|

|
|

|

|
|
|
|

|
|
|


|
|
|
|

|
|
|

|

|

|
|
|

|

|
|

|
|


|
|
|

<
<
<
|
>
>
>
|
|
|
|

|
|
|

|

|
|
|
|
|

|
|


|
|
|
|

|

|
|

|
|

|
|

|
|
|

|
|

|
|

|
|


|
|

<
>
|
<
|
>
|
|
|
|
|
|

|
|
|
|

|

|
|
|
|
|
|

|
|


|
|
|
|
|
|

|
|
|

|

|

|
|
|

|

|
|

|
|


|
|
|


|
|
|

|
|

|

|
|
|
|


|
|
|

|

|

|

|
|
|
|

|

|
|
|

|
|

<
>
|
<
|
>
|
|
|
|

|
|
|

|

|
|
|
|
|

|
|

<
>
|
<
>

|
|

|
|
|
|

|

|
|
|
|
|
|

|
|


<
<
>
>







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

It has no direct formal specification beyond what was said above\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

one possible PARAM serialization for it is

    # -*- text -*-
    # Parsing Expression Grammar 'TEMPLATE'.
    # Generated for unknown, from file 'TEST'


    #
    # Grammar Start Expression

    #

    <<MAIN>>:
             call              sym_Expression
             halt


    #
    # value Symbol 'AddOp'

    #

    sym_AddOp:
    # /
    #     '-'
    #     '+'

             symbol_restore    AddOp
      found! jump              found_7
             loc_push

             call              choice_5

       fail! value_clear
         ok! value_leaf        AddOp
             symbol_save       AddOp
             error_nonterminal AddOp
             loc_pop_discard

    found_7:
         ok! ast_value_push
             return

    choice_5:
    # /
    #     '-'
    #     '+'

             error_clear

             loc_push
             error_push

             input_next        "t -"
         ok! test_char         "-"

             error_pop_merge
         ok! jump              oknoast_4

             loc_pop_rewind
             loc_push
             error_push

             input_next        "t +"
         ok! test_char         "+"

             error_pop_merge
         ok! jump              oknoast_4

             loc_pop_rewind
             status_fail
             return

    oknoast_4:
             loc_pop_discard
             return

    #
    # value Symbol 'Digit'

    #

    sym_Digit:
    # /
    #     '0'
    #     '1'
    #     '2'
    #     '3'
    #     '4'
    #     '5'
    #     '6'
    #     '7'
    #     '8'
    #     '9'

             symbol_restore    Digit
      found! jump              found_22
             loc_push

             call              choice_20

       fail! value_clear
         ok! value_leaf        Digit
             symbol_save       Digit
             error_nonterminal Digit
             loc_pop_discard

    found_22:
         ok! ast_value_push
             return

    choice_20:
    # /
    #     '0'
    #     '1'
    #     '2'
    #     '3'
    #     '4'
    #     '5'
    #     '6'
    #     '7'
    #     '8'
    #     '9'

             error_clear

             loc_push
             error_push

             input_next        "t 0"
         ok! test_char         "0"

             error_pop_merge
         ok! jump              oknoast_19

             loc_pop_rewind
             loc_push
             error_push

             input_next        "t 1"
         ok! test_char         "1"

             error_pop_merge
         ok! jump              oknoast_19

             loc_pop_rewind
             loc_push
             error_push

             input_next        "t 2"
         ok! test_char         "2"

             error_pop_merge
         ok! jump              oknoast_19

             loc_pop_rewind
             loc_push
             error_push

             input_next        "t 3"
         ok! test_char         "3"

             error_pop_merge
         ok! jump              oknoast_19

             loc_pop_rewind
             loc_push
             error_push

             input_next        "t 4"
         ok! test_char         "4"

             error_pop_merge
         ok! jump              oknoast_19

             loc_pop_rewind
             loc_push
             error_push

             input_next        "t 5"
         ok! test_char         "5"

             error_pop_merge

         ok! jump              oknoast_19

             loc_pop_rewind
             loc_push
             error_push

             input_next        "t 6"
         ok! test_char         "6"

             error_pop_merge
         ok! jump              oknoast_19

             loc_pop_rewind
             loc_push
             error_push

             input_next        "t 7"
         ok! test_char         "7"

             error_pop_merge
         ok! jump              oknoast_19

             loc_pop_rewind
             loc_push
             error_push

             input_next        "t 8"
         ok! test_char         "8"

             error_pop_merge
         ok! jump              oknoast_19

             loc_pop_rewind
             loc_push
             error_push

             input_next        "t 9"
         ok! test_char         "9"

             error_pop_merge
         ok! jump              oknoast_19

             loc_pop_rewind
             status_fail
             return

    oknoast_19:
             loc_pop_discard
             return

    #
    # value Symbol 'Expression'

    #

    sym_Expression:
    # /
    #     x
    #         '\('
    #         (Expression)
    #         '\)'
    #     x
    #         (Factor)
    #         *
    #             x
    #                 (MulOp)
    #                 (Factor)

             symbol_restore    Expression
      found! jump              found_46
             loc_push
             ast_push

             call              choice_44

       fail! value_clear
         ok! value_reduce      Expression
             symbol_save       Expression
             error_nonterminal Expression
             ast_pop_rewind
             loc_pop_discard

    found_46:
         ok! ast_value_push
             return

    choice_44:
    # /
    #     x
    #         '\('
    #         (Expression)
    #         '\)'
    #     x
    #         (Factor)
    #         *
    #             x
    #                 (MulOp)
    #                 (Factor)

             error_clear

             ast_push
             loc_push
             error_push

             call              sequence_27

             error_pop_merge
         ok! jump              ok_43

             ast_pop_rewind
             loc_pop_rewind
             ast_push
             loc_push
             error_push

             call              sequence_40

             error_pop_merge

         ok! jump              ok_43

             ast_pop_rewind
             loc_pop_rewind
             status_fail
             return

    ok_43:
             ast_pop_discard
             loc_pop_discard
             return

    sequence_27:
    # x
    #     '\('
    #     (Expression)
    #     '\)'

             loc_push
             error_clear

             error_push

             input_next        "t ("
         ok! test_char         "("

             error_pop_merge
       fail! jump              failednoast_29
             ast_push
             error_push

             call              sym_Expression

             error_pop_merge
       fail! jump              failed_28
             error_push

             input_next        "t )"
         ok! test_char         ")"

             error_pop_merge
       fail! jump              failed_28

             ast_pop_discard
             loc_pop_discard
             return

    failed_28:
             ast_pop_rewind

    failednoast_29:
             loc_pop_rewind
             return

    sequence_40:
    # x
    #     (Factor)
    #     *
    #         x
    #             (MulOp)
    #             (Factor)

             ast_push
             loc_push
             error_clear

             error_push

             call              sym_Factor

             error_pop_merge
       fail! jump              failed_41
             error_push

             call              kleene_37

             error_pop_merge
       fail! jump              failed_41

             ast_pop_discard
             loc_pop_discard
             return

    failed_41:
             ast_pop_rewind
             loc_pop_rewind
             return

    kleene_37:
    # *
    #     x
    #         (MulOp)
    #         (Factor)

             loc_push
             error_push

             call              sequence_34

             error_pop_merge
       fail! jump              failed_38
             loc_pop_discard
             jump              kleene_37

    failed_38:
             loc_pop_rewind
             status_ok
             return

    sequence_34:
    # x
    #     (MulOp)
    #     (Factor)

             ast_push
             loc_push
             error_clear

             error_push




             call              sym_MulOp

             error_pop_merge
       fail! jump              failed_35
             error_push

             call              sym_Factor

             error_pop_merge
       fail! jump              failed_35

             ast_pop_discard
             loc_pop_discard
             return

    failed_35:
             ast_pop_rewind
             loc_pop_rewind
             return
    #
    # value Symbol 'Factor'
    #

    sym_Factor:





    # x
    #     (Term)
    #     *
    #         x
    #             (AddOp)
    #             (Term)

             symbol_restore    Factor
      found! jump              found_60
             loc_push
             ast_push

             call              sequence_57

       fail! value_clear
         ok! value_reduce      Factor
             symbol_save       Factor
             error_nonterminal Factor
             ast_pop_rewind
             loc_pop_discard

    found_60:
         ok! ast_value_push
             return

    sequence_57:
    # x
    #     (Term)
    #     *
    #         x
    #             (AddOp)
    #             (Term)

             ast_push
             loc_push
             error_clear

             error_push

             call              sym_Term



             error_pop_merge
       fail! jump              failed_58
             error_push

             call              kleene_54

             error_pop_merge
       fail! jump              failed_58

             ast_pop_discard
             loc_pop_discard
             return

    failed_58:
             ast_pop_rewind
             loc_pop_rewind
             return

    kleene_54:
    # *
    #     x
    #         (AddOp)
    #         (Term)

             loc_push
             error_push

             call              sequence_51

             error_pop_merge
       fail! jump              failed_55
             loc_pop_discard
             jump              kleene_54

    failed_55:
             loc_pop_rewind
             status_ok
             return

    sequence_51:
    # x
    #     (AddOp)
    #     (Term)

             ast_push
             loc_push
             error_clear

             error_push

             call              sym_AddOp

             error_pop_merge
       fail! jump              failed_52
             error_push

             call              sym_Term

             error_pop_merge
       fail! jump              failed_52

             ast_pop_discard
             loc_pop_discard
             return

    failed_52:
             ast_pop_rewind
             loc_pop_rewind
             return



    #
    # value Symbol 'MulOp'
    #

    sym_MulOp:
    # /
    #     '*'
    #     '/'

             symbol_restore    MulOp
      found! jump              found_67
             loc_push

             call              choice_65

       fail! value_clear
         ok! value_leaf        MulOp
             symbol_save       MulOp
             error_nonterminal MulOp
             loc_pop_discard

    found_67:
         ok! ast_value_push
             return

    choice_65:
    # /
    #     '*'
    #     '/'

             error_clear

             loc_push
             error_push

             input_next        "t *"
         ok! test_char         "*"

             error_pop_merge
         ok! jump              oknoast_64

             loc_pop_rewind
             loc_push
             error_push

             input_next        "t /"
         ok! test_char         "/"

             error_pop_merge
         ok! jump              oknoast_64

             loc_pop_rewind
             status_fail
             return

    oknoast_64:
             loc_pop_discard
             return

    #
    # value Symbol 'Number'

    #

    sym_Number:
    # x
    #     ?
    #         (Sign)
    #     +
    #         (Digit)

             symbol_restore    Number
      found! jump              found_80
             loc_push
             ast_push

             call              sequence_77

       fail! value_clear
         ok! value_reduce      Number
             symbol_save       Number
             error_nonterminal Number
             ast_pop_rewind
             loc_pop_discard

    found_80:
         ok! ast_value_push
             return

    sequence_77:
    # x
    #     ?
    #         (Sign)
    #     +
    #         (Digit)

             ast_push
             loc_push
             error_clear

             error_push

             call              optional_70

             error_pop_merge
       fail! jump              failed_78
             error_push

             call              poskleene_73

             error_pop_merge
       fail! jump              failed_78

             ast_pop_discard
             loc_pop_discard
             return

    failed_78:
             ast_pop_rewind
             loc_pop_rewind
             return

    optional_70:
    # ?
    #     (Sign)

             loc_push
             error_push

             call              sym_Sign

             error_pop_merge
       fail! loc_pop_rewind
         ok! loc_pop_discard
             status_ok
             return

    poskleene_73:
    # +
    #     (Digit)

             loc_push

             call              sym_Digit

       fail! jump              failed_74

    loop_75:
             loc_pop_discard
             loc_push
             error_push

             call              sym_Digit

             error_pop_merge
         ok! jump              loop_75
             status_ok

    failed_74:
             loc_pop_rewind
             return

    #
    # value Symbol 'Sign'

    #

    sym_Sign:
    # /
    #     '-'
    #     '+'

             symbol_restore    Sign
      found! jump              found_86
             loc_push

             call              choice_5

       fail! value_clear
         ok! value_leaf        Sign
             symbol_save       Sign
             error_nonterminal Sign
             loc_pop_discard

    found_86:
         ok! ast_value_push
             return

    #
    # value Symbol 'Term'

    #

    sym_Term:
    # (Number)

             symbol_restore    Term
      found! jump              found_89
             loc_push
             ast_push

             call              sym_Number

       fail! value_clear
         ok! value_reduce      Term
             symbol_save       Term
             error_nonterminal Term
             ast_pop_rewind
             loc_pop_discard

    found_89:
         ok! ast_value_push
             return



    #
    #

# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a PEG
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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_to_peg.md.

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
writing the specification of a grammar easy, something the other formats found
in the Parser Tools do not lend themselves too\.

It is formally specified by the grammar shown below, written in itself\. For a
tutorial / introduction to the language please go and read the *[PEG Language
Tutorial](pt\_peg\_language\.md)*\.

    PEG pe\-grammar\-for\-peg \(Grammar\)

    	\# \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
            \# Syntactical constructs

            Grammar         <\- WHITESPACE Header Definition\* Final EOF ;

            Header          <\- PEG Identifier StartExpr ;
            Definition      <\- Attribute? Identifier IS Expression SEMICOLON ;
            Attribute       <\- \(VOID / LEAF\) COLON ;
            Expression      <\- Sequence \(SLASH Sequence\)\* ;
            Sequence        <\- Prefix\+ ;
            Prefix          <\- \(AND / NOT\)? Suffix ;
            Suffix          <\- Primary \(QUESTION / STAR / PLUS\)? ;
            Primary         <\- ALNUM / ALPHA / ASCII / CONTROL / DDIGIT / DIGIT
                            /  GRAPH / LOWER / PRINTABLE / PUNCT / SPACE / UPPER
                            /  WORDCHAR / XDIGIT
                            / Identifier
                            /  OPEN Expression CLOSE
                            /  Literal
                            /  Class
                            /  DOT
                            ;
            Literal         <\- APOSTROPH  \(\!APOSTROPH  Char\)\* APOSTROPH  WHITESPACE
                            /  DAPOSTROPH \(\!DAPOSTROPH Char\)\* DAPOSTROPH WHITESPACE ;
            Class           <\- OPENB \(\!CLOSEB Range\)\* CLOSEB WHITESPACE ;
            Range           <\- Char TO Char / Char ;

            StartExpr       <\- OPEN Expression CLOSE ;
    void:   Final           <\- "END" WHITESPACE SEMICOLON WHITESPACE ;

            \# \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
            \# Lexing constructs

            Identifier      <\- Ident WHITESPACE ;
    leaf:   Ident           <\- \(\[\_:\] / <alpha>\) \(\[\_:\] / <alnum>\)\* ;
            Char            <\- CharSpecial / CharOctalFull / CharOctalPart
                            /  CharUnicode / CharUnescaped
                            ;

    leaf:   CharSpecial     <\- "\\\\" \[nrt'"\\\[\\\]\\\\\] ;
    leaf:   CharOctalFull   <\- "\\\\" \[0\-2\]\[0\-7\]\[0\-7\] ;
    leaf:   CharOctalPart   <\- "\\\\" \[0\-7\]\[0\-7\]? ;
    leaf:   CharUnicode     <\- "\\\\" 'u' HexDigit \(HexDigit \(HexDigit HexDigit?\)?\)? ;
    leaf:   CharUnescaped   <\- \!"\\\\" \. ;

    void:   HexDigit        <\- \[0\-9a\-fA\-F\] ;

    void:   TO              <\- '\-'           ;
    void:   OPENB           <\- "\["           ;
    void:   CLOSEB          <\- "\]"           ;
    void:   APOSTROPH       <\- "'"           ;
    void:   DAPOSTROPH      <\- '"'           ;
    void:   PEG             <\- "PEG" \!\(\[\_:\] / <alnum>\) WHITESPACE ;
    void:   IS              <\- "<\-"    WHITESPACE ;
    leaf:   VOID            <\- "void"  WHITESPACE ; \# Implies that definition has no semantic value\.
    leaf:   LEAF            <\- "leaf"  WHITESPACE ; \# Implies that definition has no terminals\.
    void:   SEMICOLON       <\- ";"     WHITESPACE ;
    void:   COLON           <\- ":"     WHITESPACE ;
    void:   SLASH           <\- "/"     WHITESPACE ;
    leaf:   AND             <\- "&"     WHITESPACE ;
    leaf:   NOT             <\- "\!"     WHITESPACE ;
    leaf:   QUESTION        <\- "?"     WHITESPACE ;
    leaf:   STAR            <\- "\*"     WHITESPACE ;
    leaf:   PLUS            <\- "\+"     WHITESPACE ;
    void:   OPEN            <\- "\("     WHITESPACE ;
    void:   CLOSE           <\- "\)"     WHITESPACE ;
    leaf:   DOT             <\- "\."     WHITESPACE ;

    leaf:   ALNUM           <\- "<alnum>"    WHITESPACE ;
    leaf:   ALPHA           <\- "<alpha>"    WHITESPACE ;
    leaf:   ASCII           <\- "<ascii>"    WHITESPACE ;
    leaf:   CONTROL         <\- "<control>"  WHITESPACE ;
    leaf:   DDIGIT          <\- "<ddigit>"   WHITESPACE ;
    leaf:   DIGIT           <\- "<digit>"    WHITESPACE ;
    leaf:   GRAPH           <\- "<graph>"    WHITESPACE ;
    leaf:   LOWER           <\- "<lower>"    WHITESPACE ;
    leaf:   PRINTABLE       <\- "<print>"    WHITESPACE ;
    leaf:   PUNCT           <\- "<punct>"    WHITESPACE ;
    leaf:   SPACE           <\- "<space>"    WHITESPACE ;
    leaf:   UPPER           <\- "<upper>"    WHITESPACE ;
    leaf:   WORDCHAR        <\- "<wordchar>" WHITESPACE ;
    leaf:   XDIGIT          <\- "<xdigit>"   WHITESPACE ;

    void:   WHITESPACE      <\- \(" " / "\\t" / EOL / COMMENT\)\* ;
    void:   COMMENT         <\- '\#' \(\!EOL \.\)\* EOL ;
    void:   EOL             <\- "\\n\\r" / "\\n" / "\\r" ;
    void:   EOF             <\- \!\. ;

            \# \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
    END;

## <a name='subsection1'></a>Example

Our example specifies the grammar for a basic 4\-operation calculator\.

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

Using higher\-level features of the notation, i\.e\. the character classes
\(predefined and custom\), this example can be rewritten as

    PEG calculator \(Expression\)
        Sign       <\- \[\-\+\] 						;
        Number     <\- Sign? <ddigit>\+				;
        Expression <\- '\(' Expression '\)' / \(Factor \(MulOp Factor\)\*\)	;
        MulOp      <\- \[\*/\]						;
        Factor     <\- Term \(AddOp Term\)\*				;
        AddOp      <\- \[\-\+\]						;
        Term       <\- Number					;
    END;

# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.








|

|
|

|

|
|
|
|
|
|
|
|








|
|
|
|

|
|

|
|

|
|
|



|
|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|

|






|
|
|
|
|
|
|
|
|





|
|
|
|
|
|
|
|







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
writing the specification of a grammar easy, something the other formats found
in the Parser Tools do not lend themselves too\.

It is formally specified by the grammar shown below, written in itself\. For a
tutorial / introduction to the language please go and read the *[PEG Language
Tutorial](pt\_peg\_language\.md)*\.

    PEG pe-grammar-for-peg (Grammar)

    	# --------------------------------------------------------------------
            # Syntactical constructs

            Grammar         <- WHITESPACE Header Definition* Final EOF ;

            Header          <- PEG Identifier StartExpr ;
            Definition      <- Attribute? Identifier IS Expression SEMICOLON ;
            Attribute       <- (VOID / LEAF) COLON ;
            Expression      <- Sequence (SLASH Sequence)* ;
            Sequence        <- Prefix+ ;
            Prefix          <- (AND / NOT)? Suffix ;
            Suffix          <- Primary (QUESTION / STAR / PLUS)? ;
            Primary         <- ALNUM / ALPHA / ASCII / CONTROL / DDIGIT / DIGIT
                            /  GRAPH / LOWER / PRINTABLE / PUNCT / SPACE / UPPER
                            /  WORDCHAR / XDIGIT
                            / Identifier
                            /  OPEN Expression CLOSE
                            /  Literal
                            /  Class
                            /  DOT
                            ;
            Literal         <- APOSTROPH  (!APOSTROPH  Char)* APOSTROPH  WHITESPACE
                            /  DAPOSTROPH (!DAPOSTROPH Char)* DAPOSTROPH WHITESPACE ;
            Class           <- OPENB (!CLOSEB Range)* CLOSEB WHITESPACE ;
            Range           <- Char TO Char / Char ;

            StartExpr       <- OPEN Expression CLOSE ;
    void:   Final           <- "END" WHITESPACE SEMICOLON WHITESPACE ;

            # --------------------------------------------------------------------
            # Lexing constructs

            Identifier      <- Ident WHITESPACE ;
    leaf:   Ident           <- ([_:] / <alpha>) ([_:] / <alnum>)* ;
            Char            <- CharSpecial / CharOctalFull / CharOctalPart
                            /  CharUnicode / CharUnescaped
                            ;

    leaf:   CharSpecial     <- "\\" [nrt'"\[\]\\] ;
    leaf:   CharOctalFull   <- "\\" [0-2][0-7][0-7] ;
    leaf:   CharOctalPart   <- "\\" [0-7][0-7]? ;
    leaf:   CharUnicode     <- "\\" 'u' HexDigit (HexDigit (HexDigit HexDigit?)?)? ;
    leaf:   CharUnescaped   <- !"\\" . ;

    void:   HexDigit        <- [0-9a-fA-F] ;

    void:   TO              <- '-'           ;
    void:   OPENB           <- "["           ;
    void:   CLOSEB          <- "]"           ;
    void:   APOSTROPH       <- "'"           ;
    void:   DAPOSTROPH      <- '"'           ;
    void:   PEG             <- "PEG" !([_:] / <alnum>) WHITESPACE ;
    void:   IS              <- "<-"    WHITESPACE ;
    leaf:   VOID            <- "void"  WHITESPACE ; # Implies that definition has no semantic value.
    leaf:   LEAF            <- "leaf"  WHITESPACE ; # Implies that definition has no terminals.
    void:   SEMICOLON       <- ";"     WHITESPACE ;
    void:   COLON           <- ":"     WHITESPACE ;
    void:   SLASH           <- "/"     WHITESPACE ;
    leaf:   AND             <- "&"     WHITESPACE ;
    leaf:   NOT             <- "!"     WHITESPACE ;
    leaf:   QUESTION        <- "?"     WHITESPACE ;
    leaf:   STAR            <- "*"     WHITESPACE ;
    leaf:   PLUS            <- "+"     WHITESPACE ;
    void:   OPEN            <- "("     WHITESPACE ;
    void:   CLOSE           <- ")"     WHITESPACE ;
    leaf:   DOT             <- "."     WHITESPACE ;

    leaf:   ALNUM           <- "<alnum>"    WHITESPACE ;
    leaf:   ALPHA           <- "<alpha>"    WHITESPACE ;
    leaf:   ASCII           <- "<ascii>"    WHITESPACE ;
    leaf:   CONTROL         <- "<control>"  WHITESPACE ;
    leaf:   DDIGIT          <- "<ddigit>"   WHITESPACE ;
    leaf:   DIGIT           <- "<digit>"    WHITESPACE ;
    leaf:   GRAPH           <- "<graph>"    WHITESPACE ;
    leaf:   LOWER           <- "<lower>"    WHITESPACE ;
    leaf:   PRINTABLE       <- "<print>"    WHITESPACE ;
    leaf:   PUNCT           <- "<punct>"    WHITESPACE ;
    leaf:   SPACE           <- "<space>"    WHITESPACE ;
    leaf:   UPPER           <- "<upper>"    WHITESPACE ;
    leaf:   WORDCHAR        <- "<wordchar>" WHITESPACE ;
    leaf:   XDIGIT          <- "<xdigit>"   WHITESPACE ;

    void:   WHITESPACE      <- (" " / "\t" / EOL / COMMENT)* ;
    void:   COMMENT         <- '#' (!EOL .)* EOL ;
    void:   EOL             <- "\n\r" / "\n" / "\r" ;
    void:   EOF             <- !. ;

            # --------------------------------------------------------------------
    END;

## <a name='subsection1'></a>Example

Our example specifies the grammar for a basic 4\-operation calculator\.

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

Using higher\-level features of the notation, i\.e\. the character classes
\(predefined and custom\), this example can be rewritten as

    PEG calculator (Expression)
        Sign       <- [-+] 						;
        Number     <- Sign? <ddigit>+				;
        Expression <- '(' Expression ')' / (Factor (MulOp Factor)*)	;
        MulOp      <- [*/]						;
        Factor     <- Term (AddOp Term)*				;
        AddOp      <- [-+]						;
        Term       <- Number					;
    END;

# <a name='section5'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.

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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection2'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection3'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_peg_to_tclparam.md.

246
247
248
249
250
251
252
253

254
255
256
257
258
259
260
  - __[pt::tclparam::configuration::snit](pt\_tclparam\_config\_snit\.md)__

    Generated parsers are classes based on the
    __[snit](\.\./snit/snit\.md)__ package, i\.e\. snit::type's\.

  - __[pt::tclparam::configuration::tcloo](pt\_tclparam\_config\_tcloo\.md)__

    Generated parsers are classes based on the __OO__ package\.


# <a name='section4'></a>Tcl/PARAM code representation of parsing expression grammars

The Tcl/PARAM representation of parsing expression grammars is Tcl code whose
execution will parse input per the grammar\. The code is based on the virtual
machine documented in the *[PackRat Machine Specification](pt\_param\.md)*,
using its instructions and a few more to handle control flow\.







|
>







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
  - __[pt::tclparam::configuration::snit](pt\_tclparam\_config\_snit\.md)__

    Generated parsers are classes based on the
    __[snit](\.\./snit/snit\.md)__ package, i\.e\. snit::type's\.

  - __[pt::tclparam::configuration::tcloo](pt\_tclparam\_config\_tcloo\.md)__

    Generated parsers are classes based on the
    __[OO](\.\./\.\./\.\./\.\./index\.md\#oo)__ package\.

# <a name='section4'></a>Tcl/PARAM code representation of parsing expression grammars

The Tcl/PARAM representation of parsing expression grammars is Tcl code whose
execution will parse input per the grammar\. The code is based on the virtual
machine documented in the *[PackRat Machine Specification](pt\_param\.md)*,
using its instructions and a few more to handle control flow\.
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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section6'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection2'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection2'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section7'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_pegrammar.md.

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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section4'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section4'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection2'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection2'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_pexpr_op.md.

237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection1'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection1'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_pexpression.md.

436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection1'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection1'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/pt/pt_pgen.md.

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
In this section we are working a complete example, starting with a PEG grammar
and ending with running the parser generated from it over some input, following
the outline shown in the figure below:

![](\.\./\.\./\.\./\.\./image/flow\.png) Our grammar, assumed to the stored in the
file "calculator\.peg" is

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

From this we create a snit\-based parser using the script "gen"

    package require Tcl 8\.5
    package require fileutil
    package require pt::pgen

    lassign $argv name
    set grammar \[fileutil::cat $name\.peg\]
    set pclass  \[pt::pgen peg $gr snit \-class $name \-file  $name\.peg \-name  $name\]
    fileutil::writeFile $name\.tcl $pclass
    exit 0

calling it like

    tclsh8\.5 gen calculator

which leaves us with the parser package and class written to the file
"calculator\.tcl"\. Assuming that this package is then properly installed in a
place where Tcl can find it we can now use this class via a script like

    package require calculator

    lassign $argv input
    set channel \[open $input r\]

    set parser \[calculator\]
    set ast \[$parser parse $channel\]
    $parser destroy
    close $channel

    \.\.\. now process the returned abstract syntax tree \.\.\.

where the abstract syntax tree stored in the variable will look like

    set ast \{Expression 0 4
        \{Factor 0 4
            \{Term 0 2
                \{Number 0 2
                    \{Digit 0 0\}
                    \{Digit 1 1\}
                    \{Digit 2 2\}
                \}
            \}


            \{AddOp 3 3\}
            \{Term 4 4
                \{Number 4 4
                    \{Digit 4 4\}
                \}
            \}
        \}
    \}





assuming that the input file and channel contained the text

    120\+5

A more graphical representation of the tree would be

![](\.\./\.\./\.\./\.\./image/expr\_ast\.png) Regardless, at this point it is the
user's responsibility to work with the tree to reach whatever goal she desires\.
I\.e\. analyze it, transform it, etc\. The package
__[pt::ast](pt\_astree\.md)__ should be of help here, providing commands







|
|
|
|
|
|
|
|
|




|




|
|
|




|








|

|
|



|



|
|
|
|
|
|
|
<
<
>
>
|
|
|
|
<
<
<
<
|
>
>
>
>


|







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
In this section we are working a complete example, starting with a PEG grammar
and ending with running the parser generated from it over some input, following
the outline shown in the figure below:

![](\.\./\.\./\.\./\.\./image/flow\.png) Our grammar, assumed to the stored in the
file "calculator\.peg" is

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

From this we create a snit\-based parser using the script "gen"

    package require Tcl 8.5
    package require fileutil
    package require pt::pgen

    lassign $argv name
    set grammar [fileutil::cat $name.peg]
    set pclass  [pt::pgen peg $gr snit -class $name -file  $name.peg -name  $name]
    fileutil::writeFile $name.tcl $pclass
    exit 0

calling it like

    tclsh8.5 gen calculator

which leaves us with the parser package and class written to the file
"calculator\.tcl"\. Assuming that this package is then properly installed in a
place where Tcl can find it we can now use this class via a script like

    package require calculator

    lassign $argv input
    set channel [open $input r]

    set parser [calculator]
    set ast [$parser parse $channel]
    $parser destroy
    close $channel

    ... now process the returned abstract syntax tree ...

where the abstract syntax tree stored in the variable will look like

    set ast {Expression 0 4
        {Factor 0 4
            {Term 0 2
                {Number 0 2
                    {Digit 0 0}
                    {Digit 1 1}
                    {Digit 2 2}


                }
            }
            {AddOp 3 3}
            {Term 4 4
                {Number 4 4
                    {Digit 4 4}




                }
            }
        }
    }

assuming that the input file and channel contained the text

    120+5

A more graphical representation of the tree would be

![](\.\./\.\./\.\./\.\./image/expr\_ast\.png) Regardless, at this point it is the
user's responsibility to work with the tree to reach whatever goal she desires\.
I\.e\. analyze it, transform it, etc\. The package
__[pt::ast](pt\_astree\.md)__ should be of help here, providing commands

Changes to embedded/md/tcllib/files/modules/pt/pt_rdengine.md.

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
     runtime internals are accessible to all instructions folded into the
     sequence\.

  - <a name='66'></a>*objectName* __si:void\_state\_push__

    This method combines

        i\_loc\_push
        i\_error\_clear
        i\_error\_push

    Parsers use it at the beginning of *void* sequences and choices with a
    *void* initial branch\.

  - <a name='67'></a>*objectName* __si:void2\_state\_push__

    This method combines

        i\_loc\_push
        i\_error\_clear
        i\_error\_push

    Parsers use it at the beginning of optional and repeated expressions\.

  - <a name='68'></a>*objectName* __si:value\_state\_push__

    This method combines

        i\_ast\_push
        i\_loc\_push
        i\_error\_clear
        i\_error\_push

    Parsers use it at the beginning of sequences generating an AST and choices
    with an initial branch generating an AST\.

  - <a name='69'></a>*objectName* __si:void\_state\_merge__

    This method combines

        i\_error\_pop\_merge
        i\_loc\_pop\_rewind/discard

    Parsers use it at the end of void sequences and choices whose last branch is
    void\.

  - <a name='70'></a>*objectName* __si:void\_state\_merge\_ok__

    This method combines

        i\_error\_pop\_merge
        i\_loc\_pop\_rewind/discard
        i\_status\_ok

    Parsers use it at the end of optional expressions

  - <a name='71'></a>*objectName* __si:value\_state\_merge__

    This method combines

        i\_error\_pop\_merge
        i\_ast\_pop\_rewind/discard
        i\_loc\_pop\_rewind/discard

    Parsers use it at the end of sequences generating ASTs and choices whose
    last branch generates an AST

  - <a name='72'></a>*objectName* __si:value\_notahead\_start__

    This method combines

        i\_loc\_push
        i\_ast\_push

    Parsers use it at the beginning of negative lookahead predicates which
    generate ASTs\.

  - <a name='73'></a>*objectName* __si:void\_notahead\_exit__

    This method combines

        i\_loc\_pop\_rewind
        i\_status\_negate

    Parsers use it at the end of void negative lookahead predicates\.

  - <a name='74'></a>*objectName* __si:value\_notahead\_exit__

    This method combines

        i\_ast\_pop\_discard/rewind
        i\_loc\_pop\_rewind
        i\_status\_negate

    Parsers use it at the end of negative lookahead predicates which generate
    ASTs\.

  - <a name='75'></a>*objectName* __si:kleene\_abort__

    This method combines

        i\_loc\_pop\_rewind/discard
        i:fail\_return

    Parsers use it to stop a positive repetition when its first, required,
    expression fails\.

  - <a name='76'></a>*objectName* __si:kleene\_close__

    This method combines

        i\_error\_pop\_merge
        i\_loc\_pop\_rewind/discard
        i:fail\_status\_ok
        i:fail\_return

    Parsers use it at the end of repetitions\.

  - <a name='77'></a>*objectName* __si:voidvoid\_branch__

    This method combines

        i\_error\_pop\_merge
        i:ok\_loc\_pop\_discard
        i:ok\_return
        i\_loc\_rewind
        i\_error\_push

    Parsers use it when transiting between branches of a choice when both are
    void\.

  - <a name='78'></a>*objectName* __si:voidvalue\_branch__

    This method combines

        i\_error\_pop\_merge
        i:ok\_loc\_pop\_discard
        i:ok\_return
        i\_ast\_push
        i\_loc\_rewind
        i\_error\_push

    Parsers use it when transiting between branches of a choice when the failing
    branch is void, and the next to test generates an AST\.

  - <a name='79'></a>*objectName* __si:valuevoid\_branch__

    This method combines

        i\_error\_pop\_merge
        i\_ast\_pop\_rewind/discard
        i:ok\_loc\_pop\_discard
        i:ok\_return
        i\_loc\_rewind
        i\_error\_push

    Parsers use it when transiting between branches of a choice when the failing
    branch generates an AST, and the next to test is void\.

  - <a name='80'></a>*objectName* __si:valuevalue\_branch__

    This method combines

        i\_error\_pop\_merge
        i\_ast\_pop\_discard
        i:ok\_loc\_pop\_discard
        i:ok\_return
        i\_ast\_rewind
        i\_loc\_rewind
        i\_error\_push

    Parsers use it when transiting between branches of a choice when both
    generate ASTs\.

  - <a name='81'></a>*objectName* __si:voidvoid\_part__

    This method combines

        i\_error\_pop\_merge
        i:fail\_loc\_pop\_rewind
        i:fail\_return
        i\_error\_push

    Parsers use it when transiting between parts of a sequence and both are
    void\.

  - <a name='82'></a>*objectName* __si:voidvalue\_part__

    This method combines

        i\_error\_pop\_merge
        i:fail\_loc\_pop\_rewind
        i:fail\_return
        i\_ast\_push
        i\_error\_push

    Parsers use it when transiting between parts of a sequence and the
    sucessfully matched part is void, and after it an AST is generated\.

  - <a name='83'></a>*objectName* __si:valuevalue\_part__

    This method combines

        i\_error\_pop\_merge
        i:fail\_ast\_pop\_rewind
        i:fail\_loc\_pop\_rewind
        i:fail\_return
        i\_error\_push

    Parsers use it when transiting between parts of a sequence and both parts
    generate ASTs\.

  - <a name='84'></a>*objectName* __si:value\_symbol\_start__ *symbol*

    This method combines

        if/found? i\_symbol\_restore $symbol
        i:found:ok\_ast\_value\_push
        i:found\_return
        i\_loc\_push
        i\_ast\_push

    Parsers use it at the beginning of a nonterminal symbol generating an AST,
    whose right\-hand side may have generated an AST as well\.

  - <a name='85'></a>*objectName* __si:value\_void\_symbol\_start__ *symbol*

    This method combines

        if/found? i\_symbol\_restore $symbol
        i:found:ok\_ast\_value\_push
        i:found\_return
        i\_loc\_push
        i\_ast\_push

    Parsers use it at the beginning of a void nonterminal symbol whose
    right\-hand side may generate an AST\.

  - <a name='86'></a>*objectName* __si:void\_symbol\_start__ *symbol*

    This method combines

        if/found? i\_symbol\_restore $symbol
        i:found\_return
        i\_loc\_push
        i\_ast\_push

    Parsers use it at the beginning of a nonterminal symbol generating an AST
    whose right\-hand side is void\.

  - <a name='87'></a>*objectName* __si:void\_void\_symbol\_start__ *symbol*

    This method combines

        if/found? i\_symbol\_restore $symbol
        i:found\_return
        i\_loc\_push

    Parsers use it at the beginning of a void nonterminal symbol whose
    right\-hand side is void as well\.

  - <a name='88'></a>*objectName* __si:reduce\_symbol\_end__ *symbol*

    This method combines

        i\_value\_clear/reduce $symbol
        i\_symbol\_save        $symbol
        i\_error\_nonterminal  $symbol
        i\_ast\_pop\_rewind
        i\_loc\_pop\_discard
        i:ok\_ast\_value\_push

    Parsers use it at the end of a non\-terminal symbol generating an AST using
    the AST generated by the right\-hand side as child\.

  - <a name='89'></a>*objectName* __si:void\_leaf\_symbol\_end__ *symbol*

    This method combines

        i\_value\_clear/leaf  $symbol
        i\_symbol\_save       $symbol
        i\_error\_nonterminal $symbol
        i\_loc\_pop\_discard
        i:ok\_ast\_value\_push

    Parsers use it at the end of a non\-terminal symbol generating an AST whose
    right\-hand side is void\.

  - <a name='90'></a>*objectName* __si:value\_leaf\_symbol\_end__ *symbol*

    This method combines

        i\_value\_clear/leaf  $symbol
        i\_symbol\_save       $symbol
        i\_error\_nonterminal $symbol
        i\_loc\_pop\_discard
        i\_ast\_pop\_rewind
        i:ok\_ast\_value\_push

    Parsers use it at the end of a non\-terminal symbol generating an AST
    discarding the AST generated by the right\-hand side\.

  - <a name='91'></a>*objectName* __si:value\_clear\_symbol\_end__ *symbol*

    This method combines

        i\_value\_clear
        i\_symbol\_save       $symbol
        i\_error\_nonterminal $symbol
        i\_loc\_pop\_discard
        i\_ast\_pop\_rewind

    Parsers use it at the end of a void non\-terminal symbol, discarding the AST
    generated by the right\-hand side\.

  - <a name='92'></a>*objectName* __si:void\_clear\_symbol\_end__ *symbol*

    This method combines

        i\_value\_clear
        i\_symbol\_save       $symbol
        i\_error\_nonterminal $symbol
        i\_loc\_pop\_discard

    Parsers use it at the end of a void non\-terminal symbol with a void
    right\-hand side\.

  - <a name='93'></a>*objectName* __si:next\_char__ *tok*

  - <a name='94'></a>*objectName* __si:next\_range__ *toks* *toke*







|
|
|








|
|
|







|
|
|
|








|
|








|
|
|







|
|
|








|
|








|
|







|
|
|








|
|








|
|
|
|







|
|
|
|
|








|
|
|
|
|
|








|
|
|
|
|
|








|
|
|
|
|
|
|








|
|
|
|








|
|
|
|
|








|
|
|
|
|








|
|
|
|
|








|
|
|
|
|








|
|
|
|








|
|
|








|
|
|
|
|
|








|
|
|
|
|








|
|
|
|
|
|








|
|
|
|
|








|
|
|
|







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
     runtime internals are accessible to all instructions folded into the
     sequence\.

  - <a name='66'></a>*objectName* __si:void\_state\_push__

    This method combines

        i_loc_push
        i_error_clear
        i_error_push

    Parsers use it at the beginning of *void* sequences and choices with a
    *void* initial branch\.

  - <a name='67'></a>*objectName* __si:void2\_state\_push__

    This method combines

        i_loc_push
        i_error_clear
        i_error_push

    Parsers use it at the beginning of optional and repeated expressions\.

  - <a name='68'></a>*objectName* __si:value\_state\_push__

    This method combines

        i_ast_push
        i_loc_push
        i_error_clear
        i_error_push

    Parsers use it at the beginning of sequences generating an AST and choices
    with an initial branch generating an AST\.

  - <a name='69'></a>*objectName* __si:void\_state\_merge__

    This method combines

        i_error_pop_merge
        i_loc_pop_rewind/discard

    Parsers use it at the end of void sequences and choices whose last branch is
    void\.

  - <a name='70'></a>*objectName* __si:void\_state\_merge\_ok__

    This method combines

        i_error_pop_merge
        i_loc_pop_rewind/discard
        i_status_ok

    Parsers use it at the end of optional expressions

  - <a name='71'></a>*objectName* __si:value\_state\_merge__

    This method combines

        i_error_pop_merge
        i_ast_pop_rewind/discard
        i_loc_pop_rewind/discard

    Parsers use it at the end of sequences generating ASTs and choices whose
    last branch generates an AST

  - <a name='72'></a>*objectName* __si:value\_notahead\_start__

    This method combines

        i_loc_push
        i_ast_push

    Parsers use it at the beginning of negative lookahead predicates which
    generate ASTs\.

  - <a name='73'></a>*objectName* __si:void\_notahead\_exit__

    This method combines

        i_loc_pop_rewind
        i_status_negate

    Parsers use it at the end of void negative lookahead predicates\.

  - <a name='74'></a>*objectName* __si:value\_notahead\_exit__

    This method combines

        i_ast_pop_discard/rewind
        i_loc_pop_rewind
        i_status_negate

    Parsers use it at the end of negative lookahead predicates which generate
    ASTs\.

  - <a name='75'></a>*objectName* __si:kleene\_abort__

    This method combines

        i_loc_pop_rewind/discard
        i:fail_return

    Parsers use it to stop a positive repetition when its first, required,
    expression fails\.

  - <a name='76'></a>*objectName* __si:kleene\_close__

    This method combines

        i_error_pop_merge
        i_loc_pop_rewind/discard
        i:fail_status_ok
        i:fail_return

    Parsers use it at the end of repetitions\.

  - <a name='77'></a>*objectName* __si:voidvoid\_branch__

    This method combines

        i_error_pop_merge
        i:ok_loc_pop_discard
        i:ok_return
        i_loc_rewind
        i_error_push

    Parsers use it when transiting between branches of a choice when both are
    void\.

  - <a name='78'></a>*objectName* __si:voidvalue\_branch__

    This method combines

        i_error_pop_merge
        i:ok_loc_pop_discard
        i:ok_return
        i_ast_push
        i_loc_rewind
        i_error_push

    Parsers use it when transiting between branches of a choice when the failing
    branch is void, and the next to test generates an AST\.

  - <a name='79'></a>*objectName* __si:valuevoid\_branch__

    This method combines

        i_error_pop_merge
        i_ast_pop_rewind/discard
        i:ok_loc_pop_discard
        i:ok_return
        i_loc_rewind
        i_error_push

    Parsers use it when transiting between branches of a choice when the failing
    branch generates an AST, and the next to test is void\.

  - <a name='80'></a>*objectName* __si:valuevalue\_branch__

    This method combines

        i_error_pop_merge
        i_ast_pop_discard
        i:ok_loc_pop_discard
        i:ok_return
        i_ast_rewind
        i_loc_rewind
        i_error_push

    Parsers use it when transiting between branches of a choice when both
    generate ASTs\.

  - <a name='81'></a>*objectName* __si:voidvoid\_part__

    This method combines

        i_error_pop_merge
        i:fail_loc_pop_rewind
        i:fail_return
        i_error_push

    Parsers use it when transiting between parts of a sequence and both are
    void\.

  - <a name='82'></a>*objectName* __si:voidvalue\_part__

    This method combines

        i_error_pop_merge
        i:fail_loc_pop_rewind
        i:fail_return
        i_ast_push
        i_error_push

    Parsers use it when transiting between parts of a sequence and the
    sucessfully matched part is void, and after it an AST is generated\.

  - <a name='83'></a>*objectName* __si:valuevalue\_part__

    This method combines

        i_error_pop_merge
        i:fail_ast_pop_rewind
        i:fail_loc_pop_rewind
        i:fail_return
        i_error_push

    Parsers use it when transiting between parts of a sequence and both parts
    generate ASTs\.

  - <a name='84'></a>*objectName* __si:value\_symbol\_start__ *symbol*

    This method combines

        if/found? i_symbol_restore $symbol
        i:found:ok_ast_value_push
        i:found_return
        i_loc_push
        i_ast_push

    Parsers use it at the beginning of a nonterminal symbol generating an AST,
    whose right\-hand side may have generated an AST as well\.

  - <a name='85'></a>*objectName* __si:value\_void\_symbol\_start__ *symbol*

    This method combines

        if/found? i_symbol_restore $symbol
        i:found:ok_ast_value_push
        i:found_return
        i_loc_push
        i_ast_push

    Parsers use it at the beginning of a void nonterminal symbol whose
    right\-hand side may generate an AST\.

  - <a name='86'></a>*objectName* __si:void\_symbol\_start__ *symbol*

    This method combines

        if/found? i_symbol_restore $symbol
        i:found_return
        i_loc_push
        i_ast_push

    Parsers use it at the beginning of a nonterminal symbol generating an AST
    whose right\-hand side is void\.

  - <a name='87'></a>*objectName* __si:void\_void\_symbol\_start__ *symbol*

    This method combines

        if/found? i_symbol_restore $symbol
        i:found_return
        i_loc_push

    Parsers use it at the beginning of a void nonterminal symbol whose
    right\-hand side is void as well\.

  - <a name='88'></a>*objectName* __si:reduce\_symbol\_end__ *symbol*

    This method combines

        i_value_clear/reduce $symbol
        i_symbol_save        $symbol
        i_error_nonterminal  $symbol
        i_ast_pop_rewind
        i_loc_pop_discard
        i:ok_ast_value_push

    Parsers use it at the end of a non\-terminal symbol generating an AST using
    the AST generated by the right\-hand side as child\.

  - <a name='89'></a>*objectName* __si:void\_leaf\_symbol\_end__ *symbol*

    This method combines

        i_value_clear/leaf  $symbol
        i_symbol_save       $symbol
        i_error_nonterminal $symbol
        i_loc_pop_discard
        i:ok_ast_value_push

    Parsers use it at the end of a non\-terminal symbol generating an AST whose
    right\-hand side is void\.

  - <a name='90'></a>*objectName* __si:value\_leaf\_symbol\_end__ *symbol*

    This method combines

        i_value_clear/leaf  $symbol
        i_symbol_save       $symbol
        i_error_nonterminal $symbol
        i_loc_pop_discard
        i_ast_pop_rewind
        i:ok_ast_value_push

    Parsers use it at the end of a non\-terminal symbol generating an AST
    discarding the AST generated by the right\-hand side\.

  - <a name='91'></a>*objectName* __si:value\_clear\_symbol\_end__ *symbol*

    This method combines

        i_value_clear
        i_symbol_save       $symbol
        i_error_nonterminal $symbol
        i_loc_pop_discard
        i_ast_pop_rewind

    Parsers use it at the end of a void non\-terminal symbol, discarding the AST
    generated by the right\-hand side\.

  - <a name='92'></a>*objectName* __si:void\_clear\_symbol\_end__ *symbol*

    This method combines

        i_value_clear
        i_symbol_save       $symbol
        i_error_nonterminal $symbol
        i_loc_pop_discard

    Parsers use it at the end of a void non\-terminal symbol with a void
    right\-hand side\.

  - <a name='93'></a>*objectName* __si:next\_char__ *tok*

  - <a name='94'></a>*objectName* __si:next\_range__ *toks* *toke*
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912

  - <a name='106'></a>*objectName* __si:next\_wordchar__

  - <a name='107'></a>*objectName* __si:next\_xdigit__

    These methods all combine

        i\_input\_next $msg
        i:fail\_return

    with the appropriate __i\_test\_xxx__ instruction\. Parsers use them for
    handling atomic expressions\.

# <a name='section2'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and







|
|







897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912

  - <a name='106'></a>*objectName* __si:next\_wordchar__

  - <a name='107'></a>*objectName* __si:next\_xdigit__

    These methods all combine

        i_input_next $msg
        i:fail_return

    with the appropriate __i\_test\_xxx__ instruction\. Parsers use them for
    handling atomic expressions\.

# <a name='section2'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and

Changes to embedded/md/tcllib/files/modules/pt/pt_tclparam_config_tcloo.md.

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
system the current package is a part of\.

This package is an adjunct to
__[pt::peg::to::tclparam](pt\_peg\_to\_tclparam\.md)__, to make the use of
this highly configurable package easier by providing a canned configuration\.
When applied this configuration causes the package
__[pt::peg::to::tclparam](pt\_peg\_to\_tclparam\.md)__ to generate
__OO__\-based parser packages\.

It is a supporting package in the Core Layer of Parser Tools\.

![](\.\./\.\./\.\./\.\./image/arch\_core\_support\.png)

# <a name='section2'></a>API

  - <a name='1'></a>__::pt::tclparam::configuration::tcloo__ __def__ *name* *pkg* *version* *cmdprefix*

    The command applies the configuration provided by this package to the
    *cmdprefix*, causing the creation of __OO__\-based parsers whose class

    is *name*, in package *pkg* with *version*\.

    The use of a command prefix as API allows application of the configuration
    to not only __[pt::peg::to::tclparam](pt\_peg\_to\_tclparam\.md)__
    \(__pt::peg::to::tclparam configure__\), but also export manager instances
    and PEG containers \(__$export configuration set__ and __\[$container
    exporter\] configuration set__ respectively\)\.








|










|
>
|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
system the current package is a part of\.

This package is an adjunct to
__[pt::peg::to::tclparam](pt\_peg\_to\_tclparam\.md)__, to make the use of
this highly configurable package easier by providing a canned configuration\.
When applied this configuration causes the package
__[pt::peg::to::tclparam](pt\_peg\_to\_tclparam\.md)__ to generate
__[OO](\.\./\.\./\.\./\.\./index\.md\#oo)__\-based parser packages\.

It is a supporting package in the Core Layer of Parser Tools\.

![](\.\./\.\./\.\./\.\./image/arch\_core\_support\.png)

# <a name='section2'></a>API

  - <a name='1'></a>__::pt::tclparam::configuration::tcloo__ __def__ *name* *pkg* *version* *cmdprefix*

    The command applies the configuration provided by this package to the
    *cmdprefix*, causing the creation of
    __[OO](\.\./\.\./\.\./\.\./index\.md\#oo)__\-based parsers whose class is
    *name*, in package *pkg* with *version*\.

    The use of a command prefix as API allows application of the configuration
    to not only __[pt::peg::to::tclparam](pt\_peg\_to\_tclparam\.md)__
    \(__pt::peg::to::tclparam configure__\), but also export manager instances
    and PEG containers \(__$export configuration set__ and __\[$container
    exporter\] configuration set__ respectively\)\.

Changes to embedded/md/tcllib/files/modules/pt/pt_to_api.md.

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
    The value of this option is the name of the user for which the command is
    run\. The default value is __unknown__\.

# <a name='section5'></a>Usage

To use a converter do

    \# Get the converter \(single command here, not class\)
    package require the\-converter\-package

    \# Provide a configuration
    theconverter configure \.\.\.

    \# Perform the conversion
    set result \[theconverter convert $thegrammarserial\]

    \.\.\. process the result \.\.\.

To use a plugin __FOO__ do

    \# Get an export plugin manager
    package require pt::peg::export
    pt::peg::export E

    \# Provide a configuration
    E configuration set \.\.\.

    \# Run the plugin, and the converter inside\.
    set result \[E export serial $grammarserial FOO\]

    \.\.\. process the result \.\.\.

# <a name='section6'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a PEG







|
|

|
|

|
|

|



|



|
|

|
|

|







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
    The value of this option is the name of the user for which the command is
    run\. The default value is __unknown__\.

# <a name='section5'></a>Usage

To use a converter do

    # Get the converter (single command here, not class)
    package require the-converter-package

    # Provide a configuration
    theconverter configure ...

    # Perform the conversion
    set result [theconverter convert $thegrammarserial]

    ... process the result ...

To use a plugin __FOO__ do

    # Get an export plugin manager
    package require pt::peg::export
    pt::peg::export E

    # Provide a configuration
    E configuration set ...

    # Run the plugin, and the converter inside.
    set result [E export serial $grammarserial FOO]

    ... process the result ...

# <a name='section6'></a>PEG serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expression Grammars as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a PEG
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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator \(Expression\)
        Digit      <\- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <\- '\-' / '\+'                                     ;
        Number     <\- Sign? Digit\+                                  ;
        Expression <\- Term \(AddOp Term\)\*                            ;
        MulOp      <\- '\*' / '/'                                     ;
        Term       <\- Factor \(MulOp Factor\)\*                        ;
        AddOp      <\- '\+'/'\-'                                       ;
        Factor     <\- '\(' Expression '\)' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg \{
        rules \{
            AddOp      \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Digit      \{is \{/ \{t 0\} \{t 1\} \{t 2\} \{t 3\} \{t 4\} \{t 5\} \{t 6\} \{t 7\} \{t 8\} \{t 9\}\}                mode value\}
            Expression \{is \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}                                        mode value\}
            Factor     \{is \{/ \{x \{t \(\} \{n Expression\} \{t \)\}\} \{n Number\}\}                                  mode value\}
            MulOp      \{is \{/ \{t \*\} \{t /\}\}                                                                mode value\}
            Number     \{is \{x \{? \{n Sign\}\} \{\+ \{n Digit\}\}\}                                                 mode value\}
            Sign       \{is \{/ \{t \-\} \{t \+\}\}                                                                mode value\}
            Term       \{is \{x \{n Factor\} \{\* \{x \{n MulOp\} \{n Factor\}\}\}\}                                    mode value\}
        \}

        start \{n Expression\}
    \}


# <a name='section7'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a







|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
<
>
|
<
>







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
      1. The string representation of the value is the canonical representation
         of a Tcl dictionary\. I\.e\. it does not contain superfluous whitespace\.

## <a name='subsection1'></a>Example

Assuming the following PEG for simple mathematical expressions

    PEG calculator (Expression)
        Digit      <- '0'/'1'/'2'/'3'/'4'/'5'/'6'/'7'/'8'/'9'       ;
        Sign       <- '-' / '+'                                     ;
        Number     <- Sign? Digit+                                  ;
        Expression <- Term (AddOp Term)*                            ;
        MulOp      <- '*' / '/'                                     ;
        Term       <- Factor (MulOp Factor)*                        ;
        AddOp      <- '+'/'-'                                       ;
        Factor     <- '(' Expression ')' / Number                   ;
    END;

then its canonical serialization \(except for whitespace\) is

    pt::grammar::peg {
        rules {
            AddOp      {is {/ {t -} {t +}}                                                                mode value}
            Digit      {is {/ {t 0} {t 1} {t 2} {t 3} {t 4} {t 5} {t 6} {t 7} {t 8} {t 9}}                mode value}
            Expression {is {x {n Term} {* {x {n AddOp} {n Term}}}}                                        mode value}
            Factor     {is {/ {x {t (} {n Expression} {t )}} {n Number}}                                  mode value}
            MulOp      {is {/ {t *} {t /}}                                                                mode value}
            Number     {is {x {? {n Sign}} {+ {n Digit}}}                                                 mode value}
            Sign       {is {/ {t -} {t +}}                                                                mode value}
            Term       {is {x {n Factor} {* {x {n MulOp} {n Factor}}}}                                    mode value}

        }
        start {n Expression}

    }

# <a name='section7'></a>PE serialization format

Here we specify the format used by the Parser Tools to serialize Parsing
Expressions as immutable values for transport, comparison, etc\.

We distinguish between *regular* and *canonical* serializations\. While a
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection2'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <\- Term \(AddOp Term\)\*

then its canonical serialization \(except for whitespace\) is

    \{x \{n Term\} \{\* \{x \{n AddOp\} \{n Term\}\}\}\}

# <a name='section8'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|



|







480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
      1. Terminals are *not* encoded as ranges \(where start and end of the
         range are identical\)\.

## <a name='subsection2'></a>Example

Assuming the parsing expression shown on the right\-hand side of the rule

    Expression <- Term (AddOp Term)*

then its canonical serialization \(except for whitespace\) is

    {x {n Term} {* {x {n AddOp} {n Term}}}}

# <a name='section8'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *pt* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/rc4/rc4.md.

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
  - <a name='4'></a>__::rc4::RC4Final__ *Key*

    This should be called to clean up resources associated with *Key*\. Once
    this function has been called the key is destroyed\.

# <a name='section4'></a>EXAMPLES

    % set keydata \[binary format H\* 0123456789abcdef\]
    % rc4::rc4 \-hex \-key $keydata HelloWorld
    3cf1ae8b7f1c670b612f
    % rc4::rc4 \-hex \-key $keydata \[binary format H\* 3cf1ae8b7f1c670b612f\]
    HelloWorld

    set Key \[rc4::RC4Init "key data"\]
    append ciphertext \[rc4::RC4 $Key $plaintext\]
    append ciphertext \[rc4::RC4 $Key $additional\_plaintext\]
    rc4::RC4Final $Key

    proc ::Finish \{myState data\} \{
        DoStuffWith $myState $data
    \}

    rc4::rc4 \-in $socket \-command \[list ::Finish $ApplicationState\]

# <a name='section5'></a>AUTHORS

Pat Thoyts

# <a name='section6'></a>Bugs, Ideas, Feedback








|
|

|


|
|
|


|

<
>
|







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
  - <a name='4'></a>__::rc4::RC4Final__ *Key*

    This should be called to clean up resources associated with *Key*\. Once
    this function has been called the key is destroyed\.

# <a name='section4'></a>EXAMPLES

    % set keydata [binary format H* 0123456789abcdef]
    % rc4::rc4 -hex -key $keydata HelloWorld
    3cf1ae8b7f1c670b612f
    % rc4::rc4 -hex -key $keydata [binary format H* 3cf1ae8b7f1c670b612f]
    HelloWorld

    set Key [rc4::RC4Init "key data"]
    append ciphertext [rc4::RC4 $Key $plaintext]
    append ciphertext [rc4::RC4 $Key $additional_plaintext]
    rc4::RC4Final $Key

    proc ::Finish {myState data} {
        DoStuffWith $myState $data

    }
    rc4::rc4 -in $socket -command [list ::Finish $ApplicationState]

# <a name='section5'></a>AUTHORS

Pat Thoyts

# <a name='section6'></a>Bugs, Ideas, Feedback

Changes to embedded/md/tcllib/files/modules/rcs/rcs.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (rcs \- RCS low level utilities)
[//000000002]: # (Generated from file 'rcs\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2005, Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>  
Copyright &copy; 2005, Colin McCormack <coldstore@users\.sourceforge\.net>)
[//000000004]: # (rcs\(n\) 2\.0\.2 tcllib "RCS low level utilities")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (rcs \- RCS low level utilities)
[//000000002]: # (Generated from file 'rcs\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2005, Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (Copyright &copy; 2005, Colin McCormack <coldstore@users\.sourceforge\.net>)
[//000000005]: # (rcs\(n\) 2\.0\.2 tcllib "RCS low level utilities")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180

    Hello World,
    how are you ?
    Fine, and you ?

for example can be represented by

    \{\{1 \{Hello World,\}\} \{2 \{how are you ?\}\} \{3 \{Fine, and you ?\}\}\}

or

    \{\{5 \{Hello World,\}\} \{8 \{how are you ?\}\} \{9 \{Fine, and you ?\}\}\}

or

    \{\{\-1 \{Hello World,
    how are you ?\}\} \{4 \{Fine, and you ?\}\}\}

The first dictionary is the *canonical* representation of the text, with line
numbers starting at __1__, increasing in steps of __1__ and without
gaps, and each value representing exactly one physical line\.

All the commands creating dictionaries from text will return the canonical
representation of their input text\. The commands taking a dictionary and







|



|



|
|







157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180

    Hello World,
    how are you ?
    Fine, and you ?

for example can be represented by

    {{1 {Hello World,}} {2 {how are you ?}} {3 {Fine, and you ?}}}

or

    {{5 {Hello World,}} {8 {how are you ?}} {9 {Fine, and you ?}}}

or

    {{-1 {Hello World,
    how are you ?}} {4 {Fine, and you ?}}}

The first dictionary is the *canonical* representation of the text, with line
numbers starting at __1__, increasing in steps of __1__ and without
gaps, and each value representing exactly one physical line\.

All the commands creating dictionaries from text will return the canonical
representation of their input text\. The commands taking a dictionary and
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
at the functional level\.

And example of a RCS patch is

    d1 2
    d4 1
    a4 2
    The named is the mother of all things\.

    a11 3
    They both may be called deep and profound\.
    Deeper and more profound,
    The door of all subtleties\!

# <a name='section5'></a>RCS PATCH COMMAND LIST

Patch command lists \(sort: PCL's\) are the data structures generated by patch
decoder command and accepted by the patch encoder and applicator commands\. They
represent RCS patches in the form of Tcl data structures\.








|


|

|







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
at the functional level\.

And example of a RCS patch is

    d1 2
    d4 1
    a4 2
    The named is the mother of all things.

    a11 3
    They both may be called deep and profound.
    Deeper and more profound,
    The door of all subtleties!

# <a name='section5'></a>RCS PATCH COMMAND LIST

Patch command lists \(sort: PCL's\) are the data structures generated by patch
decoder command and accepted by the patch encoder and applicator commands\. They
represent RCS patches in the form of Tcl data structures\.

272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

This is the format returned by the patch decoder command and accepted as input
by the patch encoder and applicator commands\.

An example for a patch command is shown below, it represents the example RCS
patch found in section [RCS PATCH FORMAT](#section4)\.

    \{\{d 1 2\} \{d 4 1\} \{a 4 \{The named is the mother of all things\.

    \}\} \{a 11 \{They both may be called deep and profound\.
    Deeper and more profound,
    The door of all subtleties\!\}\}\}

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *rcs* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|

|

|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

This is the format returned by the patch decoder command and accepted as input
by the patch encoder and applicator commands\.

An example for a patch command is shown below, it represents the example RCS
patch found in section [RCS PATCH FORMAT](#section4)\.

    {{d 1 2} {d 4 1} {a 4 {The named is the mother of all things.

    }} {a 11 {They both may be called deep and profound.
    Deeper and more profound,
    The door of all subtleties!}}}

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *rcs* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/report/report.md.

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
# <a name='section7'></a>EXAMPLES

Our examples define some generally useful report styles\.

A simple table with lines surrounding all information and vertical separators,
but without internal horizontal separators\.

        ::report::defstyle simpletable \{\} \{
    	data	set \[split "\[string repeat "&#124; "   \[columns\]\]&#124;"\]
    	top	set \[split "\[string repeat "\+ \- " \[columns\]\]\+"\]
    	bottom	set \[top get\]
    	top	enable
    	bottom	enable
        \}


An extension of a __simpletable__, see above, with a title area\.

        ::report::defstyle captionedtable \{\{n 1\}\} \{
    	simpletable
    	topdata   set \[data get\]
    	topcapsep set \[top get\]
    	topcapsep enable
    	tcaption $n
        \}


Given the definitions above now an example which actually formats a matrix into
a tabular report\. It assumes that the matrix actually contains useful data\.

    % ::struct::matrix m
    % \# \.\.\. fill m with data, assume 5 columns
    % ::report::report r 5 style captionedtable 1
    % r printmatrix m
    \+\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\+
    &#124;000&#124;VERSIONS:          &#124;2:8\.4a3&#124;1:8\.4a3&#124;1:8\.4a3%&#124;
    \+\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\+
    &#124;001&#124;CATCH return ok    &#124;7      &#124;13     &#124;53\.85   &#124;
    &#124;002&#124;CATCH return error &#124;68     &#124;91     &#124;74\.73   &#124;
    &#124;003&#124;CATCH no catch used&#124;7      &#124;14     &#124;50\.00   &#124;
    &#124;004&#124;IF if true numeric &#124;12     &#124;33     &#124;36\.36   &#124;
    &#124;005&#124;IF elseif          &#124;15     &#124;47     &#124;31\.91   &#124;
    &#124;   &#124;true numeric       &#124;       &#124;       &#124;        &#124;
    \+\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\+
    %
    % \# alternate way of doing the above
    % m format 2string r

# <a name='section8'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *report* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas







|
|
|
|


<
>



|

|
|


<
>





|


|
|
|
|
|
|
|
|
|
|

|







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
# <a name='section7'></a>EXAMPLES

Our examples define some generally useful report styles\.

A simple table with lines surrounding all information and vertical separators,
but without internal horizontal separators\.

        ::report::defstyle simpletable {} {
    	data	set [split "[string repeat "| "   [columns]]|"]
    	top	set [split "[string repeat "+ - " [columns]]+"]
    	bottom	set [top get]
    	top	enable
    	bottom	enable

        }

An extension of a __simpletable__, see above, with a title area\.

        ::report::defstyle captionedtable {{n 1}} {
    	simpletable
    	topdata   set [data get]
    	topcapsep set [top get]
    	topcapsep enable
    	tcaption $n

        }

Given the definitions above now an example which actually formats a matrix into
a tabular report\. It assumes that the matrix actually contains useful data\.

    % ::struct::matrix m
    % # ... fill m with data, assume 5 columns
    % ::report::report r 5 style captionedtable 1
    % r printmatrix m
    +---+-------------------+-------+-------+--------+
    |000|VERSIONS:          |2:8.4a3|1:8.4a3|1:8.4a3%|
    +---+-------------------+-------+-------+--------+
    |001|CATCH return ok    |7      |13     |53.85   |
    |002|CATCH return error |68     |91     |74.73   |
    |003|CATCH no catch used|7      |14     |50.00   |
    |004|IF if true numeric |12     |33     |36.36   |
    |005|IF elseif          |15     |47     |31.91   |
    |   |true numeric       |       |       |        |
    +---+-------------------+-------+-------+--------+
    %
    % # alternate way of doing the above
    % m format 2string r

# <a name='section8'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *report* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas

Changes to embedded/md/tcllib/files/modules/rest/rest.md.

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

    Two quick examples:

    Example 1, Yahoo Boss:

        set appid APPID
        set search tcl
        set res \[rest::get http://boss\.yahooapis\.com/ysearch/web/v1/$search \[list appid $appid\]\]
        set res \[rest::format\_json $res\]

    Example 2, Twitter:

        set url   http://twitter\.com/statuses/update\.json
        set query \[list status $text\]
        set res \[rest::simple $url $query \{
            method post
            auth   \{basic user password\}
            format json
        \}\]

# <a name='section3'></a>Interface usage

An interface to a REST API consists of a series of definitions of REST calls
contained in an array\. The name of that array becomes a namespace containing the
defined commands\. Each key of the array specifies the name of the call, with the
associated configuration a dictionary, i\.e\. key/value pairs\. The acceptable
keys, i\.e\. legal configuration options are described below\. After creating the
definitions in the array simply calling __rest::create\_interface__ with the
array as argument will then create the desired commands\.

Example, Yahoo Weather:

    package require rest

    set yweather\(forecast\) \{
       url      http://weather\.yahooapis\.com/forecastrss
       req\_args \{ p: \}
       opt\_args \{ u: \}
    \}

    rest::create\_interface yweather
    puts \[yweather::forecast \-p 94089\]

  - <a name='8'></a>__::rest::save__ *name* *file*

    This command saves a copy of the dynamically created procedures for all the
    API calls specified in the array variable *name* to the *file*, for
    later loading\.








|
|



|
|
|

|

|















|
|
|
|
<
>
|
|







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

    Two quick examples:

    Example 1, Yahoo Boss:

        set appid APPID
        set search tcl
        set res [rest::get http://boss.yahooapis.com/ysearch/web/v1/$search [list appid $appid]]
        set res [rest::format_json $res]

    Example 2, Twitter:

        set url   http://twitter.com/statuses/update.json
        set query [list status $text]
        set res [rest::simple $url $query {
            method post
            auth   {basic user password}
            format json
        }]

# <a name='section3'></a>Interface usage

An interface to a REST API consists of a series of definitions of REST calls
contained in an array\. The name of that array becomes a namespace containing the
defined commands\. Each key of the array specifies the name of the call, with the
associated configuration a dictionary, i\.e\. key/value pairs\. The acceptable
keys, i\.e\. legal configuration options are described below\. After creating the
definitions in the array simply calling __rest::create\_interface__ with the
array as argument will then create the desired commands\.

Example, Yahoo Weather:

    package require rest

    set yweather(forecast) {
       url      http://weather.yahooapis.com/forecastrss
       req_args { p: }
       opt_args { u: }

    }
    rest::create_interface yweather
    puts [yweather::forecast -p 94089]

  - <a name='8'></a>__::rest::save__ *name* *file*

    This command saves a copy of the dynamically created procedures for all the
    API calls specified in the array variable *name* to the *file*, for
    later loading\.

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

        See __callback__ above for more information\.

# <a name='section4'></a>Examples

Yahoo Geo:

    set ygeo\(parse\) \{
        url http://wherein\.yahooapis\.com/v1/document
        method post
        body \{ arg documentContent \}
    \}

    ygeo::parse "san jose ca"
    \# "san jose ca" will be interpreted as if it were specified as the \-documentContent option

Google Docs:

    set gdocs\(upload\) \{
        url http://docs\.google\.com/feeds/default/private/full
        body mime\_multipart
    \}

    gdocs::upload \[list \{Content\-Type application/atom\+xml\} $xml\] \[list \{Content\-Type image/jpeg\} $filedata\]

Delicious:

    set delicious\(updated\) \{
        url https://api\.del\.icio\.us/v1/posts/update
        auth basic
    \}


    rest::create\_interface flickr

    flickr::basic\_auth username password

Flickr:

    set flickr\(auth\.getToken\) \{
       url http://api\.flickr\.com/services/rest/
       req\_args \{ api\_key: secret: \}
       auth \{ sign do\_signature \}
    \}


    rest::create\_interface flickr

    proc ::flickr::do\_signature \{query\} \{
        \# perform some operations on the query here
        return $query
    \}


# <a name='section5'></a>INCLUDED

The package provides functional but incomplete implementations for the following
services:

  - __del\.icio\.us__







|
|

|
<
>

|



|
|
|
<
>
|



|
|

<
|
>
|

|



|
|
|
|
<
|
>
|

|
|

<
>







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

        See __callback__ above for more information\.

# <a name='section4'></a>Examples

Yahoo Geo:

    set ygeo(parse) {
        url http://wherein.yahooapis.com/v1/document
        method post
        body { arg documentContent }

    }
    ygeo::parse "san jose ca"
    # "san jose ca" will be interpreted as if it were specified as the -documentContent option

Google Docs:

    set gdocs(upload) {
        url http://docs.google.com/feeds/default/private/full
        body mime_multipart

    }
    gdocs::upload [list {Content-Type application/atom+xml} $xml] [list {Content-Type image/jpeg} $filedata]

Delicious:

    set delicious(updated) {
        url https://api.del.icio.us/v1/posts/update
        auth basic

    }

    rest::create_interface flickr

    flickr::basic_auth username password

Flickr:

    set flickr(auth.getToken) {
       url http://api.flickr.com/services/rest/
       req_args { api_key: secret: }
       auth { sign do_signature }

    }

    rest::create_interface flickr

    proc ::flickr::do_signature {query} {
        # perform some operations on the query here
        return $query

    }

# <a name='section5'></a>INCLUDED

The package provides functional but incomplete implementations for the following
services:

  - __del\.icio\.us__
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init \-tls1 1 ;\# forcibly activate support for the TLS1 protocol

    \.\.\. your own application code \.\.\.

# <a name='section8'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *rest* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|

|







555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol

    ... your own application code ...

# <a name='section8'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *rest* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/ripemd/ripemd128.md.

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

  - <a name='8'></a>__::ripemd::RIPEHMAC128Final__ *token*

    These commands are identical to the RIPEMD128 equivalent commands\.

# <a name='section4'></a>EXAMPLES

    % ripemd::ripemd128 \-hex "Tcl does RIPEMD\-128"
    3cab177bae65205d81e7978f63556c63

    % ripemd::hmac128 \-hex \-key Sekret "Tcl does RIPEMD\-128"
    b359dc5971a05beea0be7b106b30e389

    % set tok \[ripemd::RIPEMD128Init\]
    ::ripemd::1
    % ripemd::RIPEMD128Update $tok "Tcl "
    % ripemd::RIPEMD128Update $tok "does "
    % ripemd::RIPEMD128Update $tok "RIPEMD\-128"
    % ripemd::Hex \[ripemd::RIPEMD128Final $tok\]
    3cab177bae65205d81e7978f63556c63

# <a name='section5'></a>REFERENCES

  1. H\. Dobbertin, A\. Bosselaers, B\. Preneel, "RIPEMD\-160, a strengthened
     version of RIPEMD"
     [http://www\.esat\.kuleuven\.ac\.be/~cosicart/pdf/AB\-9601/AB\-9601\.pdf](http://www\.esat\.kuleuven\.ac\.be/~cosicart/pdf/AB\-9601/AB\-9601\.pdf)







|


|


|



|
|







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

  - <a name='8'></a>__::ripemd::RIPEHMAC128Final__ *token*

    These commands are identical to the RIPEMD128 equivalent commands\.

# <a name='section4'></a>EXAMPLES

    % ripemd::ripemd128 -hex "Tcl does RIPEMD-128"
    3cab177bae65205d81e7978f63556c63

    % ripemd::hmac128 -hex -key Sekret "Tcl does RIPEMD-128"
    b359dc5971a05beea0be7b106b30e389

    % set tok [ripemd::RIPEMD128Init]
    ::ripemd::1
    % ripemd::RIPEMD128Update $tok "Tcl "
    % ripemd::RIPEMD128Update $tok "does "
    % ripemd::RIPEMD128Update $tok "RIPEMD-128"
    % ripemd::Hex [ripemd::RIPEMD128Final $tok]
    3cab177bae65205d81e7978f63556c63

# <a name='section5'></a>REFERENCES

  1. H\. Dobbertin, A\. Bosselaers, B\. Preneel, "RIPEMD\-160, a strengthened
     version of RIPEMD"
     [http://www\.esat\.kuleuven\.ac\.be/~cosicart/pdf/AB\-9601/AB\-9601\.pdf](http://www\.esat\.kuleuven\.ac\.be/~cosicart/pdf/AB\-9601/AB\-9601\.pdf)

Changes to embedded/md/tcllib/files/modules/ripemd/ripemd160.md.

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

  - <a name='8'></a>__::ripemd::RIPEHMAC160Final__ *token*

    These commands are identical to the RIPEMD160 equivalent commands\.

# <a name='section4'></a>EXAMPLES

    % ripemd::ripemd160 \-hex "Tcl does RIPEMD\-160"
    0829dea75a1a7074c702896723fe37763481a0a7

    % ripemd::hmac160 \-hex \-key Sekret "Tcl does RIPEMD\-160"
    bf0c927231733686731dddb470b64a9c23f7f53b

    % set tok \[ripemd::RIPEMD160Init\]
    ::ripemd::1
    % ripemd::RIPEMD160Update $tok "Tcl "
    % ripemd::RIPEMD160Update $tok "does "
    % ripemd::RIPEMD160Update $tok "RIPEMD\-160"
    % ripemd::Hex \[ripemd::RIPEMD160Final $tok\]
    0829dea75a1a7074c702896723fe37763481a0a7

# <a name='section5'></a>REFERENCES

  1. H\. Dobbertin, A\. Bosselaers, B\. Preneel, "RIPEMD\-160, a strengthened
     version of RIPEMD"
     [http://www\.esat\.kuleuven\.ac\.be/~cosicart/pdf/AB\-9601/AB\-9601\.pdf](http://www\.esat\.kuleuven\.ac\.be/~cosicart/pdf/AB\-9601/AB\-9601\.pdf)







|


|


|



|
|







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

  - <a name='8'></a>__::ripemd::RIPEHMAC160Final__ *token*

    These commands are identical to the RIPEMD160 equivalent commands\.

# <a name='section4'></a>EXAMPLES

    % ripemd::ripemd160 -hex "Tcl does RIPEMD-160"
    0829dea75a1a7074c702896723fe37763481a0a7

    % ripemd::hmac160 -hex -key Sekret "Tcl does RIPEMD-160"
    bf0c927231733686731dddb470b64a9c23f7f53b

    % set tok [ripemd::RIPEMD160Init]
    ::ripemd::1
    % ripemd::RIPEMD160Update $tok "Tcl "
    % ripemd::RIPEMD160Update $tok "does "
    % ripemd::RIPEMD160Update $tok "RIPEMD-160"
    % ripemd::Hex [ripemd::RIPEMD160Final $tok]
    0829dea75a1a7074c702896723fe37763481a0a7

# <a name='section5'></a>REFERENCES

  1. H\. Dobbertin, A\. Bosselaers, B\. Preneel, "RIPEMD\-160, a strengthened
     version of RIPEMD"
     [http://www\.esat\.kuleuven\.ac\.be/~cosicart/pdf/AB\-9601/AB\-9601\.pdf](http://www\.esat\.kuleuven\.ac\.be/~cosicart/pdf/AB\-9601/AB\-9601\.pdf)

Changes to embedded/md/tcllib/files/modules/sasl/gtoken.md.

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init \-tls1 1 ;\# forcibly activate support for the TLS1 protocol

    \.\.\. your own application code \.\.\.

# <a name='section3'></a>AUTHORS

Pat Thoyts

# <a name='section4'></a>Bugs, Ideas, Feedback








|

|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol

    ... your own application code ...

# <a name='section3'></a>AUTHORS

Pat Thoyts

# <a name='section4'></a>Bugs, Ideas, Feedback

Changes to embedded/md/tcllib/files/modules/sasl/sasl.md.

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

See the examples subdirectory for more complete samples using SASL with network
protocols\. The following should give an idea how the SASL commands are to be
used\. In reality this should be event driven\. Each time the __step__ command
is called, the last server response should be provided as the command argument
so that the SASL mechanism can take appropriate action\.

    proc ClientCallback \{context command args\} \{
        switch \-exact \-\- $command \{
            login    \{ return "" \}
            username \{ return $::tcl\_platform\(user\) \}
            password \{ return "SecRet" \}
            realm    \{ return "" \}
            hostname \{ return \[info host\] \}
            default  \{ return \-code error unxpected \}
        \}
    \}



    proc Demo \{\{mech PLAIN\}\} \{
        set ctx \[SASL::new \-mechanism $mech \-callback ClientCallback\]
        set challenge ""
        while \{1\} \{
            set more\_steps \[SASL::step $ctx challenge\]
            puts "Send '\[SASL::response $ctx\]'"
            puts "Read server response into challenge var"
            if \{\!$more\_steps\} \{break\}
        \}

        SASL::cleanup $ctx
    \}


# <a name='section7'></a>REFERENCES

  1. Myers, J\. "Simple Authentication and Security Layer \(SASL\)", RFC 2222,
     October 1997\.
     \([http://www\.ietf\.org/rfc/rfc2222\.txt](http://www\.ietf\.org/rfc/rfc2222\.txt)\)








|
|
|
|
|
|
|
|
<
<
|
>
>
|
|

|
|
|

|
<
>

<
>







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

See the examples subdirectory for more complete samples using SASL with network
protocols\. The following should give an idea how the SASL commands are to be
used\. In reality this should be event driven\. Each time the __step__ command
is called, the last server response should be provided as the command argument
so that the SASL mechanism can take appropriate action\.

    proc ClientCallback {context command args} {
        switch -exact -- $command {
            login    { return "" }
            username { return $::tcl_platform(user) }
            password { return "SecRet" }
            realm    { return "" }
            hostname { return [info host] }
            default  { return -code error unxpected }


        }
    }

    proc Demo {{mech PLAIN}} {
        set ctx [SASL::new -mechanism $mech -callback ClientCallback]
        set challenge ""
        while {1} {
            set more_steps [SASL::step $ctx challenge]
            puts "Send '[SASL::response $ctx]'"
            puts "Read server response into challenge var"
            if {!$more_steps} {break}

        }
        SASL::cleanup $ctx

    }

# <a name='section7'></a>REFERENCES

  1. Myers, J\. "Simple Authentication and Security Layer \(SASL\)", RFC 2222,
     October 1997\.
     \([http://www\.ietf\.org/rfc/rfc2222\.txt](http://www\.ietf\.org/rfc/rfc2222\.txt)\)

Changes to embedded/md/tcllib/files/modules/sha1/sha1.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (sha1 \- SHA\-x Message\-Digest Algorithm)
[//000000002]: # (Generated from file 'sha1\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2005, Pat Thoyts <patthoyts@users\.sourceforge\.net>)
[//000000004]: # (sha1\(n\) 2\.0\.3 tcllib "SHA\-x Message\-Digest Algorithm")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>




|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (sha1 \- SHA\-x Message\-Digest Algorithm)
[//000000002]: # (Generated from file 'sha1\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2005, Pat Thoyts <patthoyts@users\.sourceforge\.net>)
[//000000004]: # (sha1\(n\) 2\.0\.4 tcllib "SHA\-x Message\-Digest Algorithm")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require sha1 ?2\.0\.3?  

[__::sha1::sha1__ ?__\-hex&#124;\-bin__? \[ __\-channel channel__ &#124; __\-file filename__ &#124; ?__\-\-__? *string* \]](#1)  
[__::sha1::hmac__ *key* *string*](#2)  
[__::sha1::hmac__ ?__\-hex&#124;\-bin__? __\-key key__ \[ __\-channel channel__ &#124; __\-file filename__ &#124; ?__\-\-__? *string* \]](#3)  
[__::sha1::SHA1Init__](#4)  
[__::sha1::SHA1Update__ *token* *data*](#5)  
[__::sha1::SHA1Final__ *token*](#6)  







|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require sha1 ?2\.0\.4?  

[__::sha1::sha1__ ?__\-hex&#124;\-bin__? \[ __\-channel channel__ &#124; __\-file filename__ &#124; ?__\-\-__? *string* \]](#1)  
[__::sha1::hmac__ *key* *string*](#2)  
[__::sha1::hmac__ ?__\-hex&#124;\-bin__? __\-key key__ \[ __\-channel channel__ &#124; __\-file filename__ &#124; ?__\-\-__? *string* \]](#3)  
[__::sha1::SHA1Init__](#4)  
[__::sha1::SHA1Update__ *token* *data*](#5)  
[__::sha1::SHA1Final__ *token*](#6)  
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

    % sha1::sha1 "Tcl does SHA1"
    285a6a91c45a9066bf39fcf24425796ef0b2a8bf

    % sha1::hmac Sekret "Tcl does SHA1"
    ae6251fa51b95b18cba2be95eb031d07475ff03c

    % set tok \[sha1::SHA1Init\]
    ::sha1::1
    % sha1::SHA1Update $tok "Tcl "
    % sha1::SHA1Update $tok "does "
    % sha1::SHA1Update $tok "SHA1"
    % sha1::Hex \[sha1::SHA1Final $tok\]
    285a6a91c45a9066bf39fcf24425796ef0b2a8bf

# <a name='section5'></a>REFERENCES

  1. "Secure Hash Standard", National Institute of Standards and Technology,
     U\.S\. Department Of Commerce, April 1995\.
     \([http://www\.itl\.nist\.gov/fipspubs/fip180\-1\.htm](http://www\.itl\.nist\.gov/fipspubs/fip180\-1\.htm)\)







|




|







154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

    % sha1::sha1 "Tcl does SHA1"
    285a6a91c45a9066bf39fcf24425796ef0b2a8bf

    % sha1::hmac Sekret "Tcl does SHA1"
    ae6251fa51b95b18cba2be95eb031d07475ff03c

    % set tok [sha1::SHA1Init]
    ::sha1::1
    % sha1::SHA1Update $tok "Tcl "
    % sha1::SHA1Update $tok "does "
    % sha1::SHA1Update $tok "SHA1"
    % sha1::Hex [sha1::SHA1Final $tok]
    285a6a91c45a9066bf39fcf24425796ef0b2a8bf

# <a name='section5'></a>REFERENCES

  1. "Secure Hash Standard", National Institute of Standards and Technology,
     U\.S\. Department Of Commerce, April 1995\.
     \([http://www\.itl\.nist\.gov/fipspubs/fip180\-1\.htm](http://www\.itl\.nist\.gov/fipspubs/fip180\-1\.htm)\)

Changes to embedded/md/tcllib/files/modules/sha1/sha256.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (sha256 \- SHA\-x Message\-Digest Algorithm)
[//000000002]: # (Generated from file 'sha256\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2008, Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (sha256\(n\) 1\.0\.3 tcllib "SHA\-x Message\-Digest Algorithm")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>




|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (sha256 \- SHA\-x Message\-Digest Algorithm)
[//000000002]: # (Generated from file 'sha256\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2008, Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (sha256\(n\) 1\.0\.4 tcllib "SHA\-x Message\-Digest Algorithm")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require sha256 ?1\.0\.3?  

[__::sha2::sha256__ ?__\-hex&#124;\-bin__? \[ __\-channel channel__ &#124; __\-file filename__ &#124; ?__\-\-__? *string* \]](#1)  
[__::sha2::sha224__ ?__\-hex&#124;\-bin__? \[ __\-channel channel__ &#124; __\-file filename__ &#124; ?__\-\-__? *string* \]](#2)  
[__::sha2::hmac__ *key* *string*](#3)  
[__::sha2::hmac__ ?__\-hex&#124;\-bin__? __\-key key__ \[ __\-channel channel__ &#124; __\-file filename__ &#124; ?__\-\-__? *string* \]](#4)  
[__::sha2::SHA256Init__](#5)  
[__::sha2::SHA224Init__](#6)  







|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require sha256 ?1\.0\.4?  

[__::sha2::sha256__ ?__\-hex&#124;\-bin__? \[ __\-channel channel__ &#124; __\-file filename__ &#124; ?__\-\-__? *string* \]](#1)  
[__::sha2::sha224__ ?__\-hex&#124;\-bin__? \[ __\-channel channel__ &#124; __\-file filename__ &#124; ?__\-\-__? *string* \]](#2)  
[__::sha2::hmac__ *key* *string*](#3)  
[__::sha2::hmac__ ?__\-hex&#124;\-bin__? __\-key key__ \[ __\-channel channel__ &#124; __\-file filename__ &#124; ?__\-\-__? *string* \]](#4)  
[__::sha2::SHA256Init__](#5)  
[__::sha2::SHA224Init__](#6)  
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

    % sha2::sha256 "Tcl does SHA256"
    0b91043ee484abd83c3e4b08d6034d71b937026379f0f59bda6e625e6e214789

    % sha2::hmac Sekret "Tcl does SHA256"
    4f9352c64d655e8a36abe73e6163a9d7a54039877c1c92ec90b07d48d4e854e0

    % set tok \[sha2::SHA256Init\]
    ::sha2::1
    % sha2::SHA256Update $tok "Tcl "
    % sha2::SHA256Update $tok "does "
    % sha2::SHA256Update $tok "SHA256"
    % sha2::Hex \[sha2::SHA256Final $tok\]
    0b91043ee484abd83c3e4b08d6034d71b937026379f0f59bda6e625e6e214789

# <a name='section5'></a>REFERENCES

  1. "Secure Hash Standard", National Institute of Standards and Technology,
     U\.S\. Department Of Commerce, April 1995\.
     \([http://www\.itl\.nist\.gov/fipspubs/fip180\-1\.htm](http://www\.itl\.nist\.gov/fipspubs/fip180\-1\.htm)\)







|




|







165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

    % sha2::sha256 "Tcl does SHA256"
    0b91043ee484abd83c3e4b08d6034d71b937026379f0f59bda6e625e6e214789

    % sha2::hmac Sekret "Tcl does SHA256"
    4f9352c64d655e8a36abe73e6163a9d7a54039877c1c92ec90b07d48d4e854e0

    % set tok [sha2::SHA256Init]
    ::sha2::1
    % sha2::SHA256Update $tok "Tcl "
    % sha2::SHA256Update $tok "does "
    % sha2::SHA256Update $tok "SHA256"
    % sha2::Hex [sha2::SHA256Final $tok]
    0b91043ee484abd83c3e4b08d6034d71b937026379f0f59bda6e625e6e214789

# <a name='section5'></a>REFERENCES

  1. "Secure Hash Standard", National Institute of Standards and Technology,
     U\.S\. Department Of Commerce, April 1995\.
     \([http://www\.itl\.nist\.gov/fipspubs/fip180\-1\.htm](http://www\.itl\.nist\.gov/fipspubs/fip180\-1\.htm)\)

Changes to embedded/md/tcllib/files/modules/simulation/annealing.md.

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
    stuck in a local optimum and theoretically it is capable of finding the
    global optimum within the search space\.

The method resembles the cooling of material, hence the name\.

The package *simulation::annealing* offers the command *findMinimum*:

    puts \[::simulation::annealing::findMinimum  \-trials 300  \-parameters \{x \-5\.0 5\.0 y \-5\.0 5\.0\}  \-function \{$x\*$x\+$y\*$y\+sin\(10\.0\*$x\)\+4\.0\*cos\(20\.0\*$y\)\}\]

prints the estimated minimum value of the function f\(x,y\) =
*x\*\*2\+y\*\*2\+sin\(10\*x\)\+4\*cos\(20\*y\)* and the values of x and y where the minimum
was attained:

    result \-4\.9112922923 x \-0\.181647676593 y 0\.155743646974

# <a name='section2'></a>PROCEDURES

The package defines the following auxiliary procedures:

  - <a name='1'></a>__::simulation::annealing::getOption__ *keyword*








|





|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
    stuck in a local optimum and theoretically it is capable of finding the
    global optimum within the search space\.

The method resembles the cooling of material, hence the name\.

The package *simulation::annealing* offers the command *findMinimum*:

    puts [::simulation::annealing::findMinimum  -trials 300  -parameters {x -5.0 5.0 y -5.0 5.0}  -function {$x*$x+$y*$y+sin(10.0*$x)+4.0*cos(20.0*$y)}]

prints the estimated minimum value of the function f\(x,y\) =
*x\*\*2\+y\*\*2\+sin\(10\*x\)\+4\*cos\(20\*y\)* and the values of x and y where the minimum
was attained:

    result -4.9112922923 x -0.181647676593 y 0.155743646974

# <a name='section2'></a>PROCEDURES

The package defines the following auxiliary procedures:

  - <a name='1'></a>__::simulation::annealing::getOption__ *keyword*

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

  - This does mean that the automatic determination of a scale factor is out of
    the question \- the high function values that force the point inside the
    region would distort the estimation\.

Here is an example of finding an optimum inside a circle:

    puts \[::simulation::annealing::findMinimum  \-trials 3000  \-reduce 0\.98  \-parameters \{x \-5\.0 5\.0 y \-5\.0 5\.0\}  \-code \{
            if \{ hypot\($x\-5\.0,$y\-5\.0\) < 4\.0 \} \{
                set result \[expr \{$x\*$x\+$y\*$y\+sin\(10\.0\*$x\)\+4\.0\*cos\(20\.0\*$y\)\}\]
            \} else \{
                set result 1\.0e100

            \}
        \}\]

The method is theoretically capable of determining the global optimum, but often
you need to use a large number of trials and a slow reduction of temperature to
get reliable and repeatable estimates\.

You can use the *\-final* option to use a deterministic optimization method,
once you are sure you are near the required optimum\.

The *findCombinatorialMinimum* procedure is suited for situations where the
parameters have the values 0 or 1 \(and there can be many of them\)\. Here is an
example:

  - We have a function that attains an absolute minimum if the first ten numbers
    are 1 and the rest is 0:

    proc cost \{params\} \{
        set cost 0
        foreach p \[lrange $params 0 9\] \{
            if \{ $p == 0 \} \{
                incr cost
            \}
        \}


        foreach p \[lrange $params 10 end\] \{
            if \{ $p == 1 \} \{
                incr cost
            \}
        \}


        return $cost
    \}


  - We want to find the solution that gives this minimum for various lengths of
    the solution vector *params*:

    foreach n \{100 1000 10000\} \{
        break
        puts "Problem size: $n"
        puts \[::simulation::annealing::findCombinatorialMinimum  \-trials 300  \-verbose 0  \-number\-params $n  \-code \{set result \[cost $params\]\}\]
    \}


  - As the vector grows, the computation time increases, but the procedure will
    stop if some kind of equilibrium is reached\. To achieve a useful solution
    you may want to try different values of the trials parameter for instance\.
    Also ensure that the function to be minimized depends on all or most
    parameters \- see the source code for a counter example and run that\.








|
|
|
|
|
>
|
<















|

|
|

<
<
>
>
|
|

<
<
>
>

<
>




|


|
<
>







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

  - This does mean that the automatic determination of a scale factor is out of
    the question \- the high function values that force the point inside the
    region would distort the estimation\.

Here is an example of finding an optimum inside a circle:

    puts [::simulation::annealing::findMinimum  -trials 3000  -reduce 0.98  -parameters {x -5.0 5.0 y -5.0 5.0}  -code {
            if { hypot($x-5.0,$y-5.0) < 4.0 } {
                set result [expr {$x*$x+$y*$y+sin(10.0*$x)+4.0*cos(20.0*$y)}]
            } else {
                set result 1.0e100
            }
        }]


The method is theoretically capable of determining the global optimum, but often
you need to use a large number of trials and a slow reduction of temperature to
get reliable and repeatable estimates\.

You can use the *\-final* option to use a deterministic optimization method,
once you are sure you are near the required optimum\.

The *findCombinatorialMinimum* procedure is suited for situations where the
parameters have the values 0 or 1 \(and there can be many of them\)\. Here is an
example:

  - We have a function that attains an absolute minimum if the first ten numbers
    are 1 and the rest is 0:

    proc cost {params} {
        set cost 0
        foreach p [lrange $params 0 9] {
            if { $p == 0 } {
                incr cost


            }
        }
        foreach p [lrange $params 10 end] {
            if { $p == 1 } {
                incr cost


            }
        }
        return $cost

    }

  - We want to find the solution that gives this minimum for various lengths of
    the solution vector *params*:

    foreach n {100 1000 10000} {
        break
        puts "Problem size: $n"
        puts [::simulation::annealing::findCombinatorialMinimum  -trials 300  -verbose 0  -number-params $n  -code {set result [cost $params]}]

    }

  - As the vector grows, the computation time increases, but the procedure will
    stop if some kind of equilibrium is reached\. To achieve a useful solution
    you may want to try different values of the trials parameter for instance\.
    Also ensure that the function to be minimized depends on all or most
    parameters \- see the source code for a counter example and run that\.

Changes to embedded/md/tcllib/files/modules/simulation/montecarlo.md.

66
67
68
69
70
71
72
73

74
75
76

77
78
79
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
You can think of a model of a network of computers, an ecosystem of some kind or
in fact anything that can be quantitatively described and has some stochastic
element in it\.

The package *simulation::montecarlo* offers a basic framework for such a
modelling technique:

    \#

    \# MC experiments:
    \# Determine the mean and median of a set of points and compare them
    \#

    ::simulation::montecarlo::singleExperiment \-init \{
        package require math::statistics

        set prng \[::simulation::random::prng\_Normal 0\.0 1\.0\]
    \} \-loop \{
        set numbers \{\}
        for \{ set i 0 \} \{ $i < \[getOption samples\] \} \{ incr i \} \{
            lappend numbers \[$prng\]
        \}

        set mean   \[::math::statistics::mean $numbers\]
        set median \[::math::statistics::median $numbers\] ;\# ? Exists?
        setTrialResult \[list $mean $median\]
    \} \-final \{
        set result \[getTrialResults\]
        set means   \{\}
        set medians \{\}
        foreach r $result \{
            foreach \{m M\} $r break
            lappend means   $m
            lappend medians $M
        \}

        puts \[getOption reportfile\] "Correlation: \[::math::statistics::corr $means $medians\]"

    \} \-trials 100 \-samples 10 \-verbose 1 \-columns \{Mean Median\}

This example attemps to find out how well the median value and the mean value of
a random set of numbers correlate\. Sometimes a median value is a more robust
characteristic than a mean value \- especially if you have a statistical
distribution with "fat" tails\.

# <a name='section2'></a>PROCEDURES







<
>
|
|
<
>
|


|
|
|
|
|
<
>
|
|
|
|
|
|
|
|
|


<
>
|

|







66
67
68
69
70
71
72

73
74
75

76
77
78
79
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
You can think of a model of a network of computers, an ecosystem of some kind or
in fact anything that can be quantitatively described and has some stochastic
element in it\.

The package *simulation::montecarlo* offers a basic framework for such a
modelling technique:


    #
    # MC experiments:
    # Determine the mean and median of a set of points and compare them

    #
    ::simulation::montecarlo::singleExperiment -init {
        package require math::statistics

        set prng [::simulation::random::prng_Normal 0.0 1.0]
    } -loop {
        set numbers {}
        for { set i 0 } { $i < [getOption samples] } { incr i } {
            lappend numbers [$prng]

        }
        set mean   [::math::statistics::mean $numbers]
        set median [::math::statistics::median $numbers] ;# ? Exists?
        setTrialResult [list $mean $median]
    } -final {
        set result [getTrialResults]
        set means   {}
        set medians {}
        foreach r $result {
            foreach {m M} $r break
            lappend means   $m
            lappend medians $M

        }
        puts [getOption reportfile] "Correlation: [::math::statistics::corr $means $medians]"

    } -trials 100 -samples 10 -verbose 1 -columns {Mean Median}

This example attemps to find out how well the median value and the mean value of
a random set of numbers correlate\. Sometimes a median value is a more robust
characteristic than a mean value \- especially if you have a statistical
distribution with "fat" tails\.

# <a name='section2'></a>PROCEDURES

Changes to embedded/md/tcllib/files/modules/simulation/simulation_random.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (simulation::random \- Tcl Simulation Tools)
[//000000002]: # (Generated from file 'simulation\_random\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Arjen Markus <arjenmarkus@users\.sourceforge\.net>)
[//000000004]: # (simulation::random\(n\) 0\.1 tcllib "Tcl Simulation Tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>




|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (simulation::random \- Tcl Simulation Tools)
[//000000002]: # (Generated from file 'simulation\_random\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Arjen Markus <arjenmarkus@users\.sourceforge\.net>)
[//000000004]: # (simulation::random\(n\) 0\.4 tcllib "Tcl Simulation Tools")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
30
31
32
33
34
35
36
37
38
39
40
41
42


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl ?8\.4?  
package require simulation::random 0\.1  

[__::simulation::random::prng\_Bernoulli__ *p*](#1)  
[__::simulation::random::prng\_Discrete__ *n*](#2)  
[__::simulation::random::prng\_Poisson__ *lambda*](#3)  
[__::simulation::random::prng\_Uniform__ *min* *max*](#4)  


[__::simulation::random::prng\_Exponential__ *min* *mean*](#5)  
[__::simulation::random::prng\_Normal__ *mean* *stdev*](#6)  
[__::simulation::random::prng\_Pareto__ *min* *steep*](#7)  
[__::simulation::random::prng\_Gumbel__ *min* *f*](#8)  
[__::simulation::random::prng\_chiSquared__ *df*](#9)  
[__::simulation::random::prng\_Disk__ *rad*](#10)  
[__::simulation::random::prng\_Sphere__ *rad*](#11)  
[__::simulation::random::prng\_Ball__ *rad*](#12)  
[__::simulation::random::prng\_Rectangle__ *length* *width*](#13)  
[__::simulation::random::prng\_Block__ *length* *width* *depth*](#14)  

# <a name='description'></a>DESCRIPTION

This package consists of commands to generate pseudo\-random number generators\.
These new commands deliver

  - numbers that are distributed normally, uniformly, according to a Pareto or
    Gumbel distribution and so on

  - coordinates of points uniformly spread inside a sphere or a rectangle

For example:

    set p \[::simulation::random::prng\_Normal \-1\.0 10\.0\]

produces a new command \(whose name is stored in the variable "p"\) that generates
normally distributed numbers with a mean of \-1\.0 and a standard deviation of
10\.0\.

# <a name='section2'></a>PROCEDURES








|





>
>
|
|
|
|
|
|
|
|
|
|













|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl ?8\.4?  
package require simulation::random 0\.4  

[__::simulation::random::prng\_Bernoulli__ *p*](#1)  
[__::simulation::random::prng\_Discrete__ *n*](#2)  
[__::simulation::random::prng\_Poisson__ *lambda*](#3)  
[__::simulation::random::prng\_Uniform__ *min* *max*](#4)  
[__::simulation::random::prng\_Triangular__ *min* *max*](#5)  
[__::simulation::random::prng\_SymmTriangular__ *min* *max*](#6)  
[__::simulation::random::prng\_Exponential__ *min* *mean*](#7)  
[__::simulation::random::prng\_Normal__ *mean* *stdev*](#8)  
[__::simulation::random::prng\_Pareto__ *min* *steep*](#9)  
[__::simulation::random::prng\_Gumbel__ *min* *f*](#10)  
[__::simulation::random::prng\_chiSquared__ *df*](#11)  
[__::simulation::random::prng\_Disk__ *rad*](#12)  
[__::simulation::random::prng\_Sphere__ *rad*](#13)  
[__::simulation::random::prng\_Ball__ *rad*](#14)  
[__::simulation::random::prng\_Rectangle__ *length* *width*](#15)  
[__::simulation::random::prng\_Block__ *length* *width* *depth*](#16)  

# <a name='description'></a>DESCRIPTION

This package consists of commands to generate pseudo\-random number generators\.
These new commands deliver

  - numbers that are distributed normally, uniformly, according to a Pareto or
    Gumbel distribution and so on

  - coordinates of points uniformly spread inside a sphere or a rectangle

For example:

    set p [::simulation::random::prng_Normal -1.0 10.0]

produces a new command \(whose name is stored in the variable "p"\) that generates
normally distributed numbers with a mean of \-1\.0 and a standard deviation of
10\.0\.

# <a name='section2'></a>PROCEDURES

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

        Minimum number that will be generated

      * float *max*

        Maximum number that will be generated

  - <a name='5'></a>__::simulation::random::prng\_Exponential__ *min* *mean*






























    Create a command \(PRNG\) that generates exponentially distributed numbers
    with a given minimum value and a given mean value\.

      * float *min*

        Minimum number that will be generated

      * float *mean*

        Mean value for the numbers

  - <a name='6'></a>__::simulation::random::prng\_Normal__ *mean* *stdev*

    Create a command \(PRNG\) that generates normally distributed numbers with a
    given mean value and a given standard deviation\.

      * float *mean*

        Mean value for the numbers

      * float *stdev*

        Standard deviation

  - <a name='7'></a>__::simulation::random::prng\_Pareto__ *min* *steep*

    Create a command \(PRNG\) that generates numbers distributed according to
    Pareto with a given minimum value and a given distribution steepness\.

      * float *min*

        Minimum number that will be generated

      * float *steep*

        Steepness of the distribution

  - <a name='8'></a>__::simulation::random::prng\_Gumbel__ *min* *f*

    Create a command \(PRNG\) that generates numbers distributed according to
    Gumbel with a given minimum value and a given scale factor\. The probability
    density function is:

    P\(v\) = exp\( \-exp\(f\*\(v\-min\)\)\)

      * float *min*

        Minimum number that will be generated

      * float *f*

        Scale factor for the values

  - <a name='9'></a>__::simulation::random::prng\_chiSquared__ *df*

    Create a command \(PRNG\) that generates numbers distributed according to the
    chi\-squared distribution with df degrees of freedom\. The mean is 0 and the
    standard deviation is 1\.

      * float *df*

        Degrees of freedom

The package defines the following public procedures for random point sets:

  - <a name='10'></a>__::simulation::random::prng\_Disk__ *rad*

    Create a command \(PRNG\) that generates \(x,y\)\-coordinates for points
    uniformly spread over a disk of given radius\.

      * float *rad*

        Radius of the disk

  - <a name='11'></a>__::simulation::random::prng\_Sphere__ *rad*

    Create a command \(PRNG\) that generates \(x,y,z\)\-coordinates for points
    uniformly spread over the surface of a sphere of given radius\.

      * float *rad*

        Radius of the disk

  - <a name='12'></a>__::simulation::random::prng\_Ball__ *rad*

    Create a command \(PRNG\) that generates \(x,y,z\)\-coordinates for points
    uniformly spread within a ball of given radius\.

      * float *rad*

        Radius of the ball

  - <a name='13'></a>__::simulation::random::prng\_Rectangle__ *length* *width*

    Create a command \(PRNG\) that generates \(x,y\)\-coordinates for points
    uniformly spread over a rectangle\.

      * float *length*

        Length of the rectangle \(x\-direction\)

      * float *width*

        Width of the rectangle \(y\-direction\)

  - <a name='14'></a>__::simulation::random::prng\_Block__ *length* *width* *depth*

    Create a command \(PRNG\) that generates \(x,y,z\)\-coordinates for points
    uniformly spread over a block

      * float *length*

        Length of the block \(x\-direction\)







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












|












|












|





|









|











|








|








|








|












|







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

        Minimum number that will be generated

      * float *max*

        Maximum number that will be generated

  - <a name='5'></a>__::simulation::random::prng\_Triangular__ *min* *max*

    Create a command \(PRNG\) that generates triangularly distributed numbers
    between "min" and "max"\. If the argument min is lower than the argument max,
    then smaller values have higher probability and vice versa\. In the first
    case the probability density function is of the form *f\(x\) = 2\(1\-x\)* and
    the other case it is of the form *f\(x\) = 2x*\.

      * float *min*

        Minimum number that will be generated

      * float *max*

        Maximum number that will be generated

  - <a name='6'></a>__::simulation::random::prng\_SymmTriangular__ *min* *max*

    Create a command \(PRNG\) that generates numbers distributed according to a
    symmetric triangle around the mean of "min" and "max"\.

      * float *min*

        Minimum number that will be generated

      * float *max*

        Maximum number that will be generated

  - <a name='7'></a>__::simulation::random::prng\_Exponential__ *min* *mean*

    Create a command \(PRNG\) that generates exponentially distributed numbers
    with a given minimum value and a given mean value\.

      * float *min*

        Minimum number that will be generated

      * float *mean*

        Mean value for the numbers

  - <a name='8'></a>__::simulation::random::prng\_Normal__ *mean* *stdev*

    Create a command \(PRNG\) that generates normally distributed numbers with a
    given mean value and a given standard deviation\.

      * float *mean*

        Mean value for the numbers

      * float *stdev*

        Standard deviation

  - <a name='9'></a>__::simulation::random::prng\_Pareto__ *min* *steep*

    Create a command \(PRNG\) that generates numbers distributed according to
    Pareto with a given minimum value and a given distribution steepness\.

      * float *min*

        Minimum number that will be generated

      * float *steep*

        Steepness of the distribution

  - <a name='10'></a>__::simulation::random::prng\_Gumbel__ *min* *f*

    Create a command \(PRNG\) that generates numbers distributed according to
    Gumbel with a given minimum value and a given scale factor\. The probability
    density function is:

    P(v) = exp( -exp(f*(v-min)))

      * float *min*

        Minimum number that will be generated

      * float *f*

        Scale factor for the values

  - <a name='11'></a>__::simulation::random::prng\_chiSquared__ *df*

    Create a command \(PRNG\) that generates numbers distributed according to the
    chi\-squared distribution with df degrees of freedom\. The mean is 0 and the
    standard deviation is 1\.

      * float *df*

        Degrees of freedom

The package defines the following public procedures for random point sets:

  - <a name='12'></a>__::simulation::random::prng\_Disk__ *rad*

    Create a command \(PRNG\) that generates \(x,y\)\-coordinates for points
    uniformly spread over a disk of given radius\.

      * float *rad*

        Radius of the disk

  - <a name='13'></a>__::simulation::random::prng\_Sphere__ *rad*

    Create a command \(PRNG\) that generates \(x,y,z\)\-coordinates for points
    uniformly spread over the surface of a sphere of given radius\.

      * float *rad*

        Radius of the disk

  - <a name='14'></a>__::simulation::random::prng\_Ball__ *rad*

    Create a command \(PRNG\) that generates \(x,y,z\)\-coordinates for points
    uniformly spread within a ball of given radius\.

      * float *rad*

        Radius of the ball

  - <a name='15'></a>__::simulation::random::prng\_Rectangle__ *length* *width*

    Create a command \(PRNG\) that generates \(x,y\)\-coordinates for points
    uniformly spread over a rectangle\.

      * float *length*

        Length of the rectangle \(x\-direction\)

      * float *width*

        Width of the rectangle \(y\-direction\)

  - <a name='16'></a>__::simulation::random::prng\_Block__ *length* *width* *depth*

    Create a command \(PRNG\) that generates \(x,y,z\)\-coordinates for points
    uniformly spread over a block

      * float *length*

        Length of the block \(x\-direction\)

Changes to embedded/md/tcllib/files/modules/smtpd/smtpd.md.

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
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init \-tls1 1 ;\# forcibly activate support for the TLS1 protocol

    \.\.\. your own application code \.\.\.

# <a name='section4'></a>COMMANDS

  - <a name='1'></a>__::smtpd::start__ ?*myaddr*? ?*port*?

    Start the service listening on *port* or the default port 25\. If
    *myaddr* is given as a domain\-style name or numerical dotted\-quad IP
    address then the server socket will be bound to that network interface\. By
    default the server is bound to all network interfaces\. For example:

    set sock \[::smtpd::start \[info hostname\] 0\]

    will bind to the hosts internet interface on the first available port\.

    At present the package only supports a single instance of a SMTP server\.
    This could be changed if required at the cost of making the package a little
    more complicated to read\. If there is a good reason for running multiple
    SMTP services then it will only be necessary to fix the __options__







|

|










|







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
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol

    ... your own application code ...

# <a name='section4'></a>COMMANDS

  - <a name='1'></a>__::smtpd::start__ ?*myaddr*? ?*port*?

    Start the service listening on *port* or the default port 25\. If
    *myaddr* is given as a domain\-style name or numerical dotted\-quad IP
    address then the server socket will be bound to that network interface\. By
    default the server is bound to all network interfaces\. For example:

    set sock [::smtpd::start [info hostname] 0]

    will bind to the hosts internet interface on the first available port\.

    At present the package only supports a single instance of a SMTP server\.
    This could be changed if required at the cost of making the package a little
    more complicated to read\. If there is a good reason for running multiple
    SMTP services then it will only be necessary to fix the __options__
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
  - __validate\_host__ callback

    This procedure is called with the clients ip address as soon as a connection
    request has been accepted and before any protocol commands are processed\. If
    you wish to deny access to a specific host then an error should be returned
    by this callback\. For example:

    proc validate\_host \{ipnum\} \{
       if \{\[string match "192\.168\.1\.\*" $ipnum\]\} \{
          error "go away\!"
       \}
    \}



    If access is denied the client will receive a standard message that includes
    the text of your error, such as:

    550 Access denied: I hate you\.

    As per the SMTP protocol, the connection is not closed but we wait for the
    client to send a QUIT command\. Any other commands cause a __503 Bad
    Sequence__ error\.

  - __validate\_sender__ callback

    The validate\_sender callback is called with the senders mail address during
    processing of a MAIL command to allow you to accept or reject mail based
    upon the declared sender\. To reject mail you should throw an error\. For
    example, to reject mail from user "denied":

    proc validate\_sender \{address\} \{
       eval array set addr \[mime::parseaddress $address\]
       if \{\[string match "denied" $addr\(local\)\]\} \{
            error "mailbox $addr\(local\) denied"
       \}

       return
    \}


    The content of any error message will not be passed back to the client\.

  - __validate\_recipient__ callback

    The validate\_recipient callback is similar to the validate\_sender callback
    and permits you to verify a local mailbox and accept mail for a local user
    address during RCPT command handling\. To reject mail, throw an error as
    above\. The error message is ignored\.

  - __deliverMIME__ callback

    The deliverMIME callback is called once a mail message has been successfully
    passed to the server\. A mime token is constructed from the sender,
    recipients and data and the users procedure it called with this single
    argument\. When the call returns, the mime token is cleaned up so if the user
    wishes to preserve the data she must make a copy\.

    proc deliverMIME \{token\} \{
        set sender \[lindex \[mime::getheader $token From\] 0\]
        set recipients \[lindex \[mime::getheader $token To\] 0\]
        set mail "From $sender \[clock format \[clock seconds\]\]"
        append mail "\\n" \[mime::buildmessage $token\]
        puts $mail
    \}


  - __deliver__ callback

    The deliver callback is called once a mail message has been successfully
    passed to the server and there is no \-deliverMIME option set\. The procedure
    is called with the sender, a list of recipients and the text of the mail as
    a list of lines\. For example:

    proc deliver \{sender recipients data\} \{
       set mail "From $sender  \[clock format \[clock seconds\]\]"
       append mail "\\n" \[join $data "\\n"\]
       puts "$mail"
    \}


    Note that the DATA command will return an error if no sender or recipient
    has yet been defined\.

# <a name='section6'></a>VARIABLES

  - __::smtpd::stopped__







|
|
|
<
<
>
>




|












|
|
|
|
<
>

<
>


















|
|
|
|
|

<
>








|
|
|

<
>







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
  - __validate\_host__ callback

    This procedure is called with the clients ip address as soon as a connection
    request has been accepted and before any protocol commands are processed\. If
    you wish to deny access to a specific host then an error should be returned
    by this callback\. For example:

    proc validate_host {ipnum} {
       if {[string match "192.168.1.*" $ipnum]} {
          error "go away!"


       }
    }

    If access is denied the client will receive a standard message that includes
    the text of your error, such as:

    550 Access denied: I hate you.

    As per the SMTP protocol, the connection is not closed but we wait for the
    client to send a QUIT command\. Any other commands cause a __503 Bad
    Sequence__ error\.

  - __validate\_sender__ callback

    The validate\_sender callback is called with the senders mail address during
    processing of a MAIL command to allow you to accept or reject mail based
    upon the declared sender\. To reject mail you should throw an error\. For
    example, to reject mail from user "denied":

    proc validate_sender {address} {
       eval array set addr [mime::parseaddress $address]
       if {[string match "denied" $addr(local)]} {
            error "mailbox $addr(local) denied"

       }
       return

    }

    The content of any error message will not be passed back to the client\.

  - __validate\_recipient__ callback

    The validate\_recipient callback is similar to the validate\_sender callback
    and permits you to verify a local mailbox and accept mail for a local user
    address during RCPT command handling\. To reject mail, throw an error as
    above\. The error message is ignored\.

  - __deliverMIME__ callback

    The deliverMIME callback is called once a mail message has been successfully
    passed to the server\. A mime token is constructed from the sender,
    recipients and data and the users procedure it called with this single
    argument\. When the call returns, the mime token is cleaned up so if the user
    wishes to preserve the data she must make a copy\.

    proc deliverMIME {token} {
        set sender [lindex [mime::getheader $token From] 0]
        set recipients [lindex [mime::getheader $token To] 0]
        set mail "From $sender [clock format [clock seconds]]"
        append mail "\n" [mime::buildmessage $token]
        puts $mail

    }

  - __deliver__ callback

    The deliver callback is called once a mail message has been successfully
    passed to the server and there is no \-deliverMIME option set\. The procedure
    is called with the sender, a list of recipients and the text of the mail as
    a list of lines\. For example:

    proc deliver {sender recipients data} {
       set mail "From $sender  [clock format [clock seconds]]"
       append mail "\n" [join $data "\n"]
       puts "$mail"

    }

    Note that the DATA command will return an error if no sender or recipient
    has yet been defined\.

# <a name='section6'></a>VARIABLES

  - __::smtpd::stopped__

Changes to embedded/md/tcllib/files/modules/snit/snit.md.

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
        The variable __type__ is automatically defined in the *body* to
        the type's fully\-qualified name\. In addition, type variables are
        automatically visible in the *body* of every type method\.

        If the *name* consists of two or more tokens, Snit handles it
        specially:

            typemethod \{a b\} \{arg\} \{ puts "Got $arg" \}

        This statement implicitly defines a type method called __a__ which
        has a subcommand __b__\. __b__ is called like this:

            $type a b "Hello, world\!"

        __a__ may have any number of subcommands\. This makes it possible to
        define a hierarchical command structure; see
        __[method](\.\./\.\./\.\./\.\./index\.md\#method)__, below, for more
        examples\.

        Type methods can call commands from the namespace in which the type is
        defined without importing them, e\.g\., if the type name is
        __::parentns::typename__, then the type's type methods can call
        __::parentns::someproc__ just as __someproc__\. *Snit 1\.x
        Incompatibility:* This does not work in Snit 1\.x, as it depends on
        __namespace path__, a new command in Tcl 8\.5\.

        *Snit 1\.x Incompatibility:* In Snit 1\.x, the following following two
        calls to this type method are equivalent:

            $type a b "Hello, world\!"
            $type \{a b\} "Hello, world\!"

        In Snit 2\.2, the second form is invalid\.

      * <a name='4'></a>__typeconstructor__ *body*

        The type constructor's *body* is executed once when the type is first
        defined; it is typically used to initialize array\-valued type variables







|




|
















|
|







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
        The variable __type__ is automatically defined in the *body* to
        the type's fully\-qualified name\. In addition, type variables are
        automatically visible in the *body* of every type method\.

        If the *name* consists of two or more tokens, Snit handles it
        specially:

            typemethod {a b} {arg} { puts "Got $arg" }

        This statement implicitly defines a type method called __a__ which
        has a subcommand __b__\. __b__ is called like this:

            $type a b "Hello, world!"

        __a__ may have any number of subcommands\. This makes it possible to
        define a hierarchical command structure; see
        __[method](\.\./\.\./\.\./\.\./index\.md\#method)__, below, for more
        examples\.

        Type methods can call commands from the namespace in which the type is
        defined without importing them, e\.g\., if the type name is
        __::parentns::typename__, then the type's type methods can call
        __::parentns::someproc__ just as __someproc__\. *Snit 1\.x
        Incompatibility:* This does not work in Snit 1\.x, as it depends on
        __namespace path__, a new command in Tcl 8\.5\.

        *Snit 1\.x Incompatibility:* In Snit 1\.x, the following following two
        calls to this type method are equivalent:

            $type a b "Hello, world!"
            $type {a b} "Hello, world!"

        In Snit 2\.2, the second form is invalid\.

      * <a name='4'></a>__typeconstructor__ *body*

        The type constructor's *body* is executed once when the type is first
        defined; it is typically used to initialize array\-valued type variables
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
        Type and instance variables are automatically visible in all instance
        methods\. If the type has locally defined options, the __options__
        array is also visible\.

        If the *name* consists of two or more tokens, Snit handles it
        specially:

            method \{a b\} \{\} \{ \.\.\. \}

        This statement implicitly defines a method called __a__ which has a
        subcommand __b__\. __b__ is called like this:

            $self a b "Hello, world\!"

        __a__ may have any number of subcommands\. This makes it possible to
        define a hierarchical command structure:

            % snit::type dog \{
                method \{tail wag\}   \{\} \{return "Wag, wag"\}
                method \{tail droop\} \{\} \{return "Droop, droop"\}
            \}

            ::dog
            % dog spot
            ::spot
            % spot tail wag
            Wag, wag
            % spot tail droop
            Droop, droop







|




|




|
|
|
<
>







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
        Type and instance variables are automatically visible in all instance
        methods\. If the type has locally defined options, the __options__
        array is also visible\.

        If the *name* consists of two or more tokens, Snit handles it
        specially:

            method {a b} {} { ... }

        This statement implicitly defines a method called __a__ which has a
        subcommand __b__\. __b__ is called like this:

            $self a b "Hello, world!"

        __a__ may have any number of subcommands\. This makes it possible to
        define a hierarchical command structure:

            % snit::type dog {
                method {tail wag}   {} {return "Wag, wag"}
                method {tail droop} {} {return "Droop, droop"}

            }
            ::dog
            % dog spot
            ::spot
            % spot tail wag
            Wag, wag
            % spot tail droop
            Droop, droop
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
        __::parentns::someproc__ just as __someproc__\. *Snit 1\.x
        Incompatibility:* This does not work in Snit 1\.x, as it depends on
        __namespace path__, a new command in Tcl 8\.5\.

        *Snit 1\.x Incompatibility:* In Snit 1\.x, the following following two
        calls to this method are equivalent:

            $self a b "Hello, world\!"
            $self \{a b\} "Hello, world\!"

        In Snit 2\.2, the second form is invalid\.

      * <a name='7'></a>__option__ *namespec* ?*defaultValue*?

      * <a name='8'></a>__option__ *namespec* ?*options\.\.\.*?

        Defines an option for instances of this type, and optionally gives it an
        initial value\. The initial value defaults to the empty string if no
        *defaultValue* is specified\.

        An option defined in this way is said to be *locally defined*\.

        The *namespec* is a list defining the option's name, resource name,
        and class name, e\.g\.:

            option \{\-font font Font\} \{Courier 12\}

        The option name must begin with a hyphen, and must not contain any upper
        case letters\. The resource name and class name are optional; if not
        specified, the resource name defaults to the option name, minus the
        hyphen, and the class name defaults to the resource name with the first
        letter capitalized\. Thus, the following statement is equivalent to the
        previous example:

            option \-font \{Courier 12\}

        See [The Tk Option Database](#subsection9) for more information
        about resource and class names\.

        Options are normally set and retrieved using the standard instance
        methods __configure__ and __cget__; within instance code \(method
        bodies, etc\.\), option values are available through the __options__
        array:

            set myfont $options\(\-font\)

        If the type defines any option handlers \(e\.g\.,
        __\-configuremethod__\), then it should probably use __configure__
        and __cget__ to access its options to avoid subtle errors\.

        The __option__ statement may include the following options:








|
|
















|








|









|







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
        __::parentns::someproc__ just as __someproc__\. *Snit 1\.x
        Incompatibility:* This does not work in Snit 1\.x, as it depends on
        __namespace path__, a new command in Tcl 8\.5\.

        *Snit 1\.x Incompatibility:* In Snit 1\.x, the following following two
        calls to this method are equivalent:

            $self a b "Hello, world!"
            $self {a b} "Hello, world!"

        In Snit 2\.2, the second form is invalid\.

      * <a name='7'></a>__option__ *namespec* ?*defaultValue*?

      * <a name='8'></a>__option__ *namespec* ?*options\.\.\.*?

        Defines an option for instances of this type, and optionally gives it an
        initial value\. The initial value defaults to the empty string if no
        *defaultValue* is specified\.

        An option defined in this way is said to be *locally defined*\.

        The *namespec* is a list defining the option's name, resource name,
        and class name, e\.g\.:

            option {-font font Font} {Courier 12}

        The option name must begin with a hyphen, and must not contain any upper
        case letters\. The resource name and class name are optional; if not
        specified, the resource name defaults to the option name, minus the
        hyphen, and the class name defaults to the resource name with the first
        letter capitalized\. Thus, the following statement is equivalent to the
        previous example:

            option -font {Courier 12}

        See [The Tk Option Database](#subsection9) for more information
        about resource and class names\.

        Options are normally set and retrieved using the standard instance
        methods __configure__ and __cget__; within instance code \(method
        bodies, etc\.\), option values are available through the __options__
        array:

            set myfont $options(-font)

        If the type defines any option handlers \(e\.g\.,
        __\-configuremethod__\), then it should probably use __configure__
        and __cget__ to access its options to avoid subtle errors\.

        The __option__ statement may include the following options:

409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
            Every locally\-defined option may define its validation type, which
            may be either the name of a validation type or a specification for a
            validation subtype

            For example, an option may declare that its value must be an integer
            by specifying __snit::integer__ as its validation type:

                option \-number \-type snit::integer

            It may also declare that its value is an integer between 1 and 10 by
            specifying a validation subtype:

                option \-number \-type \{snit::integer \-min 1 \-max 10\}

            If a validation type or subtype is defined for an option, then it
            will be used to validate the option's value whenever it is changed
            by the object's __configure__ or __configurelist__ methods\.
            In addition, all such options will have their values validated
            automatically immediately after the constructor executes\.








|




|







409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
            Every locally\-defined option may define its validation type, which
            may be either the name of a validation type or a specification for a
            validation subtype

            For example, an option may declare that its value must be an integer
            by specifying __snit::integer__ as its validation type:

                option -number -type snit::integer

            It may also declare that its value is an integer between 1 and 10 by
            specifying a validation subtype:

                option -number -type {snit::integer -min 1 -max 10}

            If a validation type or subtype is defined for an option, then it
            will be used to validate the option's value whenever it is changed
            by the object's __configure__ or __configurelist__ methods\.
            In addition, all such options will have their values validated
            automatically immediately after the constructor executes\.

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
            method\. Whatever the method's *body* returns will be the return
            value of the call to __cget__\.

            The named method must take one argument, the option name\. For
            example, this code is equivalent to \(though slower than\) Snit's
            default handling of __cget__:

                option \-font \-cgetmethod GetOption
                method GetOption \{option\} \{
                    return $options\($option\)
                \}


            Note that it's possible for any number of options to share a
            __\-cgetmethod__\.

          + __\-configuremethod__ *methodName*

            Every locally\-defined option may define a __\-configuremethod__;
            it is called when the option's value is set using the
            __configure__ or __configurelist__ methods\. It is the named
            method's responsibility to save the option's value; in other words,
            the value will not be saved to the __options\(\)__ array unless
            the method saves it there\.

            The named method must take two arguments, the option name and its
            new value\. For example, this code is equivalent to \(though slower
            than\) Snit's default handling of __configure__:

                option \-font \-configuremethod SetOption
                method SetOption \{option value\} \{
                    set options\($option\) $value
                \}


            Note that it's possible for any number of options to share a single
            __\-configuremethod__\.

          + __\-validatemethod__ *methodName*

            Every locally\-defined option may define a __\-validatemethod__;
            it is called when the option's value is set using the
            __configure__ or __configurelist__ methods, just before the
            __\-configuremethod__ \(if any\)\. It is the named method's
            responsibility to validate the option's new value, and to throw an
            error if the value is invalid\.

            The named method must take two arguments, the option name and its
            new value\. For example, this code verifies that __\-flag__'s
            value is a valid Boolean value:

                option \-font \-validatemethod CheckBoolean
                method CheckBoolean \{option value\} \{
                    if \{\!\[string is boolean \-strict $value\]\} \{
                        error "option $option must have a boolean value\."
                    \}
                \}



            Note that it's possible for any number of options to share a single
            __\-validatemethod__\.

      * <a name='9'></a>__constructor__ *arglist* *body*

        The constructor definition specifies a *body* of code to be executed
        when a new instance is created\. The *arglist* is a normal Tcl argument
        list and may contain default arguments and the __args__ argument\.

        As with methods, the arguments __type__, __self__,
        __selfns__, and __win__ are defined implicitly, and all type and
        instance variables are automatically visible in its *body*\.

        If the *definition* doesn't explicitly define the constructor, Snit
        defines one implicitly\. If the type declares at least one option
        \(whether locally or by delegation\), the default constructor will be
        defined as follows:

            constructor \{args\} \{
                $self configurelist $args
            \}


        For standard Tk widget behavior, the argument list should be the single
        name __args__, as shown\.

        If the *definition* defines neither a constructor nor any options, the
        default constructor is defined as follows:

            constructor \{\} \{\}

        As with methods, the constructor can call commands from the namespace in
        which the type is defined without importing them, e\.g\., if the type name
        is __::parentns::typename__, then the constructor can call
        __::parentns::someproc__ just as __someproc__\. *Snit 1\.x
        Incompatibility:* This does not work in Snit 1\.x, as it depends on
        __namespace path__, a new command in Tcl 8\.5\.







|
|
|
<
>

















|
|
|
<
>

















|
|
|
|
<
<
>
>



















|

<
>







|







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
            method\. Whatever the method's *body* returns will be the return
            value of the call to __cget__\.

            The named method must take one argument, the option name\. For
            example, this code is equivalent to \(though slower than\) Snit's
            default handling of __cget__:

                option -font -cgetmethod GetOption
                method GetOption {option} {
                    return $options($option)

                }

            Note that it's possible for any number of options to share a
            __\-cgetmethod__\.

          + __\-configuremethod__ *methodName*

            Every locally\-defined option may define a __\-configuremethod__;
            it is called when the option's value is set using the
            __configure__ or __configurelist__ methods\. It is the named
            method's responsibility to save the option's value; in other words,
            the value will not be saved to the __options\(\)__ array unless
            the method saves it there\.

            The named method must take two arguments, the option name and its
            new value\. For example, this code is equivalent to \(though slower
            than\) Snit's default handling of __configure__:

                option -font -configuremethod SetOption
                method SetOption {option value} {
                    set options($option) $value

                }

            Note that it's possible for any number of options to share a single
            __\-configuremethod__\.

          + __\-validatemethod__ *methodName*

            Every locally\-defined option may define a __\-validatemethod__;
            it is called when the option's value is set using the
            __configure__ or __configurelist__ methods, just before the
            __\-configuremethod__ \(if any\)\. It is the named method's
            responsibility to validate the option's new value, and to throw an
            error if the value is invalid\.

            The named method must take two arguments, the option name and its
            new value\. For example, this code verifies that __\-flag__'s
            value is a valid Boolean value:

                option -font -validatemethod CheckBoolean
                method CheckBoolean {option value} {
                    if {![string is boolean -strict $value]} {
                        error "option $option must have a boolean value."


                    }
                }

            Note that it's possible for any number of options to share a single
            __\-validatemethod__\.

      * <a name='9'></a>__constructor__ *arglist* *body*

        The constructor definition specifies a *body* of code to be executed
        when a new instance is created\. The *arglist* is a normal Tcl argument
        list and may contain default arguments and the __args__ argument\.

        As with methods, the arguments __type__, __self__,
        __selfns__, and __win__ are defined implicitly, and all type and
        instance variables are automatically visible in its *body*\.

        If the *definition* doesn't explicitly define the constructor, Snit
        defines one implicitly\. If the type declares at least one option
        \(whether locally or by delegation\), the default constructor will be
        defined as follows:

            constructor {args} {
                $self configurelist $args

            }

        For standard Tk widget behavior, the argument list should be the single
        name __args__, as shown\.

        If the *definition* defines neither a constructor nor any options, the
        default constructor is defined as follows:

            constructor {} {}

        As with methods, the constructor can call commands from the namespace in
        which the type is defined without importing them, e\.g\., if the type name
        is __::parentns::typename__, then the constructor can call
        __::parentns::someproc__ just as __someproc__\. *Snit 1\.x
        Incompatibility:* This does not work in Snit 1\.x, as it depends on
        __namespace path__, a new command in Tcl 8\.5\.
572
573
574
575
576
577
578
579
580
581

582
583
584
585
586
587
588
        arguments will be passed to the named component's command instead\. That
        is, the following statement

            delegate method wag to tail

        is roughly equivalent to this explicitly defined method:

            method wag \{args\} \{
                uplevel $tail wag $args
            \}


        As with methods, the *name* may have multiple tokens; in this case,
        the last token of the name is assumed to be the name of the component's
        method\.

        The optional __as__ clause allows you to specify the delegated
        method name and possibly add some arguments:







|

<
>







572
573
574
575
576
577
578
579
580

581
582
583
584
585
586
587
588
        arguments will be passed to the named component's command instead\. That
        is, the following statement

            delegate method wag to tail

        is roughly equivalent to this explicitly defined method:

            method wag {args} {
                uplevel $tail wag $args

            }

        As with methods, the *name* may have multiple tokens; in this case,
        the last token of the name is assumed to be the name of the component's
        method\.

        The optional __as__ clause allows you to specify the delegated
        method name and possibly add some arguments:
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
        delegated\. The __using__ clause is defined as given above\. In this
        form, the statement must contain the __to__ clause, the
        __using__ clause, or both\.

        In fact, the "\*" can be a list of two or more tokens whose last element
        is "\*", as in the following example:

            delegate method \{tail \*\} to tail

        This implicitly defines the method __tail__ whose subcommands will
        be delegated to the __tail__ component\.

      * <a name='15'></a>__delegate__ __option__ *namespec* __to__ *comp*

      * <a name='16'></a>__delegate__ __option__ *namespec* __to__ *comp* __as__ *target*

      * <a name='17'></a>__delegate__ __option__ __\*__ __to__ *comp*

      * <a name='18'></a>__delegate__ __option__ __\*__ __to__ *comp* __except__ *exceptions*

        Defines a delegated option; the *namespec* is defined as for the
        __option__ statement\. When the __configure__,
        __configurelist__, or __cget__ instance method is used to set or
        retrieve the option's value, the equivalent __configure__ or
        __cget__ command will be applied to the component as though the
        option was defined with the following __\-configuremethod__ and
        __\-cgetmethod__:

            method ConfigureMethod \{option value\} \{
                $comp configure $option $value
            \}


            method CgetMethod \{option\} \{
                return \[$comp cget $option\]
            \}


        Note that delegated options never appear in the __options__ array\.

        If the __as__ clause is specified, then the *target* option name
        is used in place of *name*\.

        The form __delegate option \*__ delegates all unknown options to the







|




















|

<
|
>
|
|
<
>







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
        delegated\. The __using__ clause is defined as given above\. In this
        form, the statement must contain the __to__ clause, the
        __using__ clause, or both\.

        In fact, the "\*" can be a list of two or more tokens whose last element
        is "\*", as in the following example:

            delegate method {tail *} to tail

        This implicitly defines the method __tail__ whose subcommands will
        be delegated to the __tail__ component\.

      * <a name='15'></a>__delegate__ __option__ *namespec* __to__ *comp*

      * <a name='16'></a>__delegate__ __option__ *namespec* __to__ *comp* __as__ *target*

      * <a name='17'></a>__delegate__ __option__ __\*__ __to__ *comp*

      * <a name='18'></a>__delegate__ __option__ __\*__ __to__ *comp* __except__ *exceptions*

        Defines a delegated option; the *namespec* is defined as for the
        __option__ statement\. When the __configure__,
        __configurelist__, or __cget__ instance method is used to set or
        retrieve the option's value, the equivalent __configure__ or
        __cget__ command will be applied to the component as though the
        option was defined with the following __\-configuremethod__ and
        __\-cgetmethod__:

            method ConfigureMethod {option value} {
                $comp configure $option $value

            }

            method CgetMethod {option} {
                return [$comp cget $option]

            }

        Note that delegated options never appear in the __options__ array\.

        If the __as__ clause is specified, then the *target* option name
        is used in place of *name*\.

        The form __delegate option \*__ delegates all unknown options to the
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

        If the __\-public__ option is specified, then the option is made
        public by defining a *method* whose subcommands are delegated to the
        component e\.g\., specifying __\-public mycomp__ is equivalent to the
        following:

            component mycomp
            delegate method \{mymethod \*\} to mycomp

        If the __\-inherit__ option is specified, then *flag* must be a
        Boolean value; if *flag* is true then all unknown methods and options
        will be delegated to this component\. The name __\-inherit__ implies
        that instances of this new type inherit, in a sense, the methods and
        options of the component\. That is, __\-inherit yes__ is equivalent
        to:

            component mycomp
            delegate option \* to mycomp
            delegate method \* to mycomp

      * <a name='20'></a>__delegate__ __typemethod__ *name* __to__ *comp* ?__as__ *target*?

        Delegates type method *name* to type component *comp*\. That is, when
        type method *name* is called on this type, the type method and its
        arguments will be passed to the named type component's command instead\.
        That is, the following statement

            delegate typemethod lostdogs to pound

        is roughly equivalent to this explicitly defined method:

            typemethod lostdogs \{args\} \{
                uplevel $pound lostdogs $args
            \}


        As with type methods, the *name* may have multiple tokens; in this
        case, the last token of the name is assumed to be the name of the
        component's method\.

        The optional __as__ clause allows you to specify the delegated
        method name and possibly add some arguments:







|









|
|












|

<
>







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

        If the __\-public__ option is specified, then the option is made
        public by defining a *method* whose subcommands are delegated to the
        component e\.g\., specifying __\-public mycomp__ is equivalent to the
        following:

            component mycomp
            delegate method {mymethod *} to mycomp

        If the __\-inherit__ option is specified, then *flag* must be a
        Boolean value; if *flag* is true then all unknown methods and options
        will be delegated to this component\. The name __\-inherit__ implies
        that instances of this new type inherit, in a sense, the methods and
        options of the component\. That is, __\-inherit yes__ is equivalent
        to:

            component mycomp
            delegate option * to mycomp
            delegate method * to mycomp

      * <a name='20'></a>__delegate__ __typemethod__ *name* __to__ *comp* ?__as__ *target*?

        Delegates type method *name* to type component *comp*\. That is, when
        type method *name* is called on this type, the type method and its
        arguments will be passed to the named type component's command instead\.
        That is, the following statement

            delegate typemethod lostdogs to pound

        is roughly equivalent to this explicitly defined method:

            typemethod lostdogs {args} {
                uplevel $pound lostdogs $args

            }

        As with type methods, the *name* may have multiple tokens; in this
        case, the last token of the name is assumed to be the name of the
        component's method\.

        The optional __as__ clause allows you to specify the delegated
        method name and possibly add some arguments:
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
        create foo__, where __foo__ is the name of a new instance of the
        type\. If you use __delegate typemethod \*__, then the __create__
        type method must always be used explicitly\.

        The "\*" can be a list of two or more tokens whose last element is "\*",
        as in the following example:

            delegate typemethod \{tail \*\} to tail

        This implicitly defines the type method __tail__ whose subcommands
        will be delegated to the __tail__ type component\.

      * <a name='23'></a>__typecomponent__ *comp* ?__\-public__ *typemethod*? ?__\-inherit__ *flag*?

        Explicitly declares a type component called *comp*, and automatically
        defines the component's type variable\. A type component is an arbitrary
        command to which type methods and instance methods can be delegated; the
        command's name is stored in a type variable\.

        If the __\-public__ option is specified, then the type component is
        made public by defining a *typemethod* whose subcommands are delegated
        to the type component, e\.g\., specifying __\-public mytypemethod__ is
        equivalent to the following:

            typecomponent mycomp
            delegate typemethod \{mytypemethod \*\} to mycomp

        If the __\-inherit__ option is specified, then *flag* must be a
        Boolean value; if *flag* is true then all unknown type methods will be
        delegated to this type component\. \(See the note on "delegate typemethod
        \*", above\.\) The name __\-inherit__ implies that this type inherits,
        in a sense, the behavior of the type component\. That is, __\-inherit
        yes__ is equivalent to:

            typecomponent mycomp
            delegate typemethod \* to mycomp

      * <a name='24'></a>__pragma__ ?*options\.\.\.*?

        The __pragma__ statement provides control over how Snit generates a
        type\. It takes the following options; in each case, *flag* must be a
        Boolean value recognized by Tcl, e\.g\., __0__, __1__,
        __yes__, __no__, and so on\.







|

















|









|







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
        create foo__, where __foo__ is the name of a new instance of the
        type\. If you use __delegate typemethod \*__, then the __create__
        type method must always be used explicitly\.

        The "\*" can be a list of two or more tokens whose last element is "\*",
        as in the following example:

            delegate typemethod {tail *} to tail

        This implicitly defines the type method __tail__ whose subcommands
        will be delegated to the __tail__ type component\.

      * <a name='23'></a>__typecomponent__ *comp* ?__\-public__ *typemethod*? ?__\-inherit__ *flag*?

        Explicitly declares a type component called *comp*, and automatically
        defines the component's type variable\. A type component is an arbitrary
        command to which type methods and instance methods can be delegated; the
        command's name is stored in a type variable\.

        If the __\-public__ option is specified, then the type component is
        made public by defining a *typemethod* whose subcommands are delegated
        to the type component, e\.g\., specifying __\-public mytypemethod__ is
        equivalent to the following:

            typecomponent mycomp
            delegate typemethod {mytypemethod *} to mycomp

        If the __\-inherit__ option is specified, then *flag* must be a
        Boolean value; if *flag* is true then all unknown type methods will be
        delegated to this type component\. \(See the note on "delegate typemethod
        \*", above\.\) The name __\-inherit__ implies that this type inherits,
        in a sense, the behavior of the type component\. That is, __\-inherit
        yes__ is equivalent to:

            typecomponent mycomp
            delegate typemethod * to mycomp

      * <a name='24'></a>__pragma__ ?*options\.\.\.*?

        The __pragma__ statement provides control over how Snit generates a
        type\. It takes the following options; in each case, *flag* must be a
        Boolean value recognized by Tcl, e\.g\., __0__, __1__,
        __yes__, __no__, and so on\.
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
      * <a name='27'></a>__onconfigure__ *name* *arglist* *body*

        __Deprecated\.__ Define __option__'s __\-configuremethod__
        option instead\.

        As of version 0\.95, the following definitions,

            option \-myoption
            onconfigure \-myoption \{value\} \{
                \# Code to save the option's value
            \}


        are implemented as follows:

            option \-myoption \-configuremethod \_configure\-myoption
            method \_configure\-myoption \{\_option value\} \{
                \# Code to save the option's value
            \}


      * <a name='28'></a>__oncget__ *name* *body*

        __Deprecated\.__ Define __option__'s __\-cgetmethod__ option
        instead\.

        As of version 0\.95, the following definitions,

            option \-myoption
            oncget \-myoption \{
                \# Code to return the option's value
            \}


        are implemented as follows:

            option \-myoption \-cgetmethod \_cget\-myoption
            method \_cget\-myoption \{\_option\} \{
                \# Code to return the option's value
            \}


  - <a name='29'></a>__snit::widget__ *name* *definition*

    This command defines a Snit megawidget type with the specified *name*\. The
    *definition* is defined as for __snit::type__\. A __snit::widget__
    differs from a __snit::type__ in these ways:








|
|
|
<
>



|
|
|
<
>








|
|
|
<
>



|
|
|
<
>







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
      * <a name='27'></a>__onconfigure__ *name* *arglist* *body*

        __Deprecated\.__ Define __option__'s __\-configuremethod__
        option instead\.

        As of version 0\.95, the following definitions,

            option -myoption
            onconfigure -myoption {value} {
                # Code to save the option's value

            }

        are implemented as follows:

            option -myoption -configuremethod _configure-myoption
            method _configure-myoption {_option value} {
                # Code to save the option's value

            }

      * <a name='28'></a>__oncget__ *name* *body*

        __Deprecated\.__ Define __option__'s __\-cgetmethod__ option
        instead\.

        As of version 0\.95, the following definitions,

            option -myoption
            oncget -myoption {
                # Code to return the option's value

            }

        are implemented as follows:

            option -myoption -cgetmethod _cget-myoption
            method _cget-myoption {_option} {
                # Code to return the option's value

            }

  - <a name='29'></a>__snit::widget__ *name* *definition*

    This command defines a Snit megawidget type with the specified *name*\. The
    *definition* is defined as for __snit::type__\. A __snit::widget__
    differs from a __snit::type__ in these ways:

1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127

    Furthermore, if the __\-hastypemethods__ pragma is false, then Snit type
    commands can be called with no arguments at all; in this case, the type
    command creates an instance with an automatically generated name\. In other
    words, provided that the __\-hastypemethods__ pragma is false and the
    type has instances, the following commands are equivalent:

        snit::type dog \{ \.\.\. \}

        set mydog \[dog create %AUTO%\]
        set mydog \[dog %AUTO%\]
        set mydog \[dog\]

    This doesn't work for Snit widgets, for obvious reasons\.

    *Snit 1\.x Incompatibility:* In Snit 1\.x, the above behavior is available
    whether __\-hastypemethods__ is true \(the default\) or false\.

## <a name='subsection3'></a>Standard Type Methods







|

|
|
|







1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127

    Furthermore, if the __\-hastypemethods__ pragma is false, then Snit type
    commands can be called with no arguments at all; in this case, the type
    command creates an instance with an automatically generated name\. In other
    words, provided that the __\-hastypemethods__ pragma is false and the
    type has instances, the following commands are equivalent:

        snit::type dog { ... }

        set mydog [dog create %AUTO%]
        set mydog [dog %AUTO%]
        set mydog [dog]

    This doesn't work for Snit widgets, for obvious reasons\.

    *Snit 1\.x Incompatibility:* In Snit 1\.x, the above behavior is available
    whether __\-hastypemethods__ is true \(the default\) or false\.

## <a name='subsection3'></a>Standard Type Methods
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
    The __mymethod__ command is used for formatting callback commands to be
    passed to other objects\. It returns a command that when called will invoke
    method *name* with the specified arguments, plus of course any arguments
    added by the caller\. In other words, both of the following commands will
    cause the object's __dosomething__ method to be called when the
    __$button__ is pressed:

        $button configure \-command \[list $self dosomething myargument\]

        $button configure \-command \[mymethod dosomething myargument\]

    The chief distinction between the two is that the latter form will not break
    if the object's command is renamed\.

  - <a name='61'></a>__mytypemethod__ *name* ?*args\.\.\.*?

    The __mytypemethod__ command is used for formatting callback commands to
    be passed to other objects\. It returns a command that when called will
    invoke type method *name* with the specified arguments, plus of course any
    arguments added by the caller\. In other words, both of the following
    commands will cause the object's __dosomething__ type method to be
    called when __$button__ is pressed:

        $button configure \-command \[list $type dosomething myargument\]

        $button configure \-command \[mytypemethod dosomething myargument\]

    Type commands cannot be renamed, so in practice there's little difference
    between the two forms\. __mytypemethod__ is provided for parallelism with
    __mymethod__\.

  - <a name='62'></a>__myproc__ *name* ?*args\.\.\.*?

    The __myproc__ command is used for formatting callback commands to be
    passed to other objects\. It returns a command that when called will invoke
    the type proc *name* with the specified arguments, plus of course any
    arguments added by the caller\. In other words, both of the following
    commands will cause the object's __dosomething__ proc to be called when
    __$button__ is pressed:

        $button configure \-command \[list $\{type\}::dosomething myargument\]

        $button configure \-command \[myproc dosomething myargument\]

  - <a name='63'></a>__myvar__ *name*

    Given an instance variable name, returns the fully qualified name\. Use this
    if you're passing the variable to some other object, e\.g\., as a
    __\-textvariable__ to a Tk label widget\.








|

|













|

|














|

|







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
    The __mymethod__ command is used for formatting callback commands to be
    passed to other objects\. It returns a command that when called will invoke
    method *name* with the specified arguments, plus of course any arguments
    added by the caller\. In other words, both of the following commands will
    cause the object's __dosomething__ method to be called when the
    __$button__ is pressed:

        $button configure -command [list $self dosomething myargument]

        $button configure -command [mymethod dosomething myargument]

    The chief distinction between the two is that the latter form will not break
    if the object's command is renamed\.

  - <a name='61'></a>__mytypemethod__ *name* ?*args\.\.\.*?

    The __mytypemethod__ command is used for formatting callback commands to
    be passed to other objects\. It returns a command that when called will
    invoke type method *name* with the specified arguments, plus of course any
    arguments added by the caller\. In other words, both of the following
    commands will cause the object's __dosomething__ type method to be
    called when __$button__ is pressed:

        $button configure -command [list $type dosomething myargument]

        $button configure -command [mytypemethod dosomething myargument]

    Type commands cannot be renamed, so in practice there's little difference
    between the two forms\. __mytypemethod__ is provided for parallelism with
    __mymethod__\.

  - <a name='62'></a>__myproc__ *name* ?*args\.\.\.*?

    The __myproc__ command is used for formatting callback commands to be
    passed to other objects\. It returns a command that when called will invoke
    the type proc *name* with the specified arguments, plus of course any
    arguments added by the caller\. In other words, both of the following
    commands will cause the object's __dosomething__ proc to be called when
    __$button__ is pressed:

        $button configure -command [list ${type}::dosomething myargument]

        $button configure -command [myproc dosomething myargument]

  - <a name='63'></a>__myvar__ *name*

    Given an instance variable name, returns the fully qualified name\. Use this
    if you're passing the variable to some other object, e\.g\., as a
    __\-textvariable__ to a Tk label widget\.

1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455

    Creates a new object of type *objType* called *objName* and installs it
    as component *compName*, as described in [Components and
    Delegation](#subsection7)\. Any additional *args\.\.\.* are passed along
    with the name to the *objType* command\. If this is a __snit::type__,
    then the following two commands are equivalent:

        install myComp using myObjType $self\.myComp args\.\.\.

        set myComp \[myObjType $self\.myComp args\.\.\.\]

    Note that whichever method is used, *compName* must still be declared in
    the type definition using __component__, or must be referenced in at
    least one __delegate__ statement\.

    If this is a __snit::widget__ or __snit::widgetadaptor__, and if
    options have been delegated to component *compName*, then those options







|

|







1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455

    Creates a new object of type *objType* called *objName* and installs it
    as component *compName*, as described in [Components and
    Delegation](#subsection7)\. Any additional *args\.\.\.* are passed along
    with the name to the *objType* command\. If this is a __snit::type__,
    then the following two commands are equivalent:

        install myComp using myObjType $self.myComp args...

        set myComp [myObjType $self.myComp args...]

    Note that whichever method is used, *compName* must still be declared in
    the type definition using __component__, or must be referenced in at
    least one __delegate__ statement\.

    If this is a __snit::widget__ or __snit::widgetadaptor__, and if
    options have been delegated to component *compName*, then those options
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
When an object includes other objects, as when a toolbar contains buttons or a
GUI object contains an object that references a database, the included object is
called a component\. The standard way to handle component objects owned by a Snit
object is to declare them using __component__, which creates a component
instance variable\. In the following example, a __dog__ object has a
__tail__ object:

    snit::type dog \{
        component mytail

        constructor \{args\} \{
            set mytail \[tail %AUTO% \-partof $self\]
            $self configurelist $args
        \}


        method wag \{\} \{
            $mytail wag
        \}
    \}



    snit::type tail \{
        option \-length 5
        option \-partof
        method wag \{\} \{ return "Wag, wag, wag\."\}
    \}


Because the __tail__ object's name is stored in an instance variable, it's
easily accessible in any method\.

The __install__ command provides an alternate way to create and install the
component:

    snit::type dog \{
        component mytail

        constructor \{args\} \{
            install mytail using tail %AUTO% \-partof $self
            $self configurelist $args
        \}


        method wag \{\} \{
            $mytail wag
        \}
    \}



For __snit::type__s, the two methods are equivalent; for
__snit::widget__s and __snit::widgetadaptor__s, the __install__
command properly initializes the widget's options by querying [The Tk Option
Database](#subsection9)\.

In the above examples, the __dog__ object's __wag__ method simply calls
the __tail__ component's __wag__ method\. In OO jargon, this is called
delegation\. Snit provides an easier way to do this:

    snit::type dog \{
        delegate method wag to mytail

        constructor \{args\} \{
            install mytail using tail %AUTO% \-partof $self
            $self configurelist $args
        \}
    \}



The __delegate__ statement in the type definition implicitly defines the
instance variable __mytail__ to hold the component's name \(though it's good
form to use __component__ to declare it explicitly\); it also defines the
__dog__ object's __wag__ method, delegating it to the __mytail__
component\.

If desired, all otherwise unknown methods can be delegated to a specific
component:

        snit::type dog \{
    	delegate method \* to mytail

    	constructor \{args\} \{
    	    set mytail \[tail %AUTO% \-partof $self\]
    	    $self configurelist $args
    	\}


    	method bark \{ return "Bark, bark, bark\!" \}
        \}


In this case, a __dog__ object will handle its own __bark__ method; but
__wag__ will be passed along to __mytail__\. Any other method, being
recognized by neither __dog__ nor __tail__, will simply raise an error\.

Option delegation is similar to method delegation, except for the interactions
with the Tk option database; this is described in [The Tk Option







|


|
|

<
|
>
|

<
<
|
>
>
|
|
|
|
<
>







|


|
|

<
|
>
|

<
<
>
>










|


|
|

<
<
>
>










|
|

|
|

<
|
>
|
<
>







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
When an object includes other objects, as when a toolbar contains buttons or a
GUI object contains an object that references a database, the included object is
called a component\. The standard way to handle component objects owned by a Snit
object is to declare them using __component__, which creates a component
instance variable\. In the following example, a __dog__ object has a
__tail__ object:

    snit::type dog {
        component mytail

        constructor {args} {
            set mytail [tail %AUTO% -partof $self]
            $self configurelist $args

        }

        method wag {} {
            $mytail wag


        }
    }

    snit::type tail {
        option -length 5
        option -partof
        method wag {} { return "Wag, wag, wag."}

    }

Because the __tail__ object's name is stored in an instance variable, it's
easily accessible in any method\.

The __install__ command provides an alternate way to create and install the
component:

    snit::type dog {
        component mytail

        constructor {args} {
            install mytail using tail %AUTO% -partof $self
            $self configurelist $args

        }

        method wag {} {
            $mytail wag


        }
    }

For __snit::type__s, the two methods are equivalent; for
__snit::widget__s and __snit::widgetadaptor__s, the __install__
command properly initializes the widget's options by querying [The Tk Option
Database](#subsection9)\.

In the above examples, the __dog__ object's __wag__ method simply calls
the __tail__ component's __wag__ method\. In OO jargon, this is called
delegation\. Snit provides an easier way to do this:

    snit::type dog {
        delegate method wag to mytail

        constructor {args} {
            install mytail using tail %AUTO% -partof $self
            $self configurelist $args


        }
    }

The __delegate__ statement in the type definition implicitly defines the
instance variable __mytail__ to hold the component's name \(though it's good
form to use __component__ to declare it explicitly\); it also defines the
__dog__ object's __wag__ method, delegating it to the __mytail__
component\.

If desired, all otherwise unknown methods can be delegated to a specific
component:

        snit::type dog {
    	delegate method * to mytail

    	constructor {args} {
    	    set mytail [tail %AUTO% -partof $self]
    	    $self configurelist $args

    	}

    	method bark { return "Bark, bark, bark!" }

        }

In this case, a __dog__ object will handle its own __bark__ method; but
__wag__ will be passed along to __mytail__\. Any other method, being
recognized by neither __dog__ nor __tail__, will simply raise an error\.

Option delegation is similar to method delegation, except for the interactions
with the Tk option database; this is described in [The Tk Option
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
widgets, the widget class name is the just the widget type name with an initial
capital letter, e\.g\., the widget class for __button__ widgets is "Button"\.

Similarly, the widget class of a __snit::widget__ defaults to the
unqualified type name with the first letter capitalized\. For example, the widget
class of

    snit::widget ::mylibrary::scrolledText \{ \.\.\. \}

is "ScrolledText"\. The widget class can also be set explicitly using the
__widgetclass__ statement within the __snit::widget__ definition\.

Any widget can be used as the __hulltype__ provided that it supports the
__\-class__ option for changing its widget class name\. See the discussion of
the __hulltype__ command, above\. The user may pass __\-class__ to the







|







1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
widgets, the widget class name is the just the widget type name with an initial
capital letter, e\.g\., the widget class for __button__ widgets is "Button"\.

Similarly, the widget class of a __snit::widget__ defaults to the
unqualified type name with the first letter capitalized\. For example, the widget
class of

    snit::widget ::mylibrary::scrolledText { ... }

is "ScrolledText"\. The widget class can also be set explicitly using the
__widgetclass__ statement within the __snit::widget__ definition\.

Any widget can be used as the __hulltype__ provided that it supports the
__\-class__ option for changing its widget class name\. See the discussion of
the __hulltype__ command, above\. The user may pass __\-class__ to the
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727

1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755

1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770

1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790

1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813

1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
The resource and class names are used to initialize option default values by
querying the Tk option database\. The resource name is usually just the option
name minus the hyphen, but may contain uppercase letters at word boundaries; the
class name is usually just the resource name with an initial capital, but not
always\. For example, here are the option, resource, and class names for several
__[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget options:

    \-background         background         Background
    \-borderwidth        borderWidth        BorderWidth
    \-insertborderwidth  insertBorderWidth  BorderWidth
    \-padx               padX               Pad

As is easily seen, sometimes the resource and class names can be inferred from
the option name, but not always\.

Snit options also have a resource name and a class name\. By default, these names
follow the rule given above: the resource name is the option name without the
hyphen, and the class name is the resource name with an initial capital\. This is
true for both locally\-defined options and explicitly delegated options:

        snit::widget mywidget \{
            option \-background
            delegate option \-borderwidth to hull
            delegate option \* to text
    	\# \.\.\.
        \}


In this case, the widget class name is "Mywidget"\. The widget has the following
options: __\-background__, which is locally defined, and
__\-borderwidth__, which is explicitly delegated; all other widgets are
delegated to a component called "text", which is probably a Tk
__[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget\. If so, __mywidget__
has all the same options as a __[text](\.\./\.\./\.\./\.\./index\.md\#text)__
widget\. The option, resource, and class names are as follows:

    \-background  background  Background
    \-borderwidth borderwidth Borderwidth
    \-padx        padX        Pad

Note that the locally defined option, __\-background__, happens to have the
same three names as the standard Tk __\-background__ option; and
__\-pad__, which is delegated implicitly to the __text__ component, has
the same three names for __mywidget__ as it does for the
__[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget\. __\-borderwidth__, on
the other hand, has different resource and class names than usual, because the
internal word "width" isn't capitalized\. For consistency, it should be; this is
done as follows:

        snit::widget mywidget \{
    	option \-background
    	delegate option \{\-borderwidth borderWidth\} to hull
    	delegate option \* to text
    	\# \.\.\.
        \}


The class name will default to "BorderWidth", as expected\.

Suppose, however, that __mywidget__ also delegated __\-padx__ and
__\-pady__ to the hull\. In this case, both the resource name and the class
name must be specified explicitly:

        snit::widget mywidget \{
    	option \-background
    	delegate option \{\-borderwidth borderWidth\} to hull
    	delegate option \{\-padx padX Pad\} to hull
    	delegate option \{\-pady padY Pad\} to hull
    	delegate option \* to text
    	\# \.\.\.
        \}


__Querying the option database:__ If you set your widgetclass and option
names as described above, Snit will query the option database when each instance
is created, and will generally do the right thing when it comes to querying the
option database\. The remainder of this section goes into the gory details\.

__Initializing locally defined options:__ When an instance of a snit::widget
is created, its locally defined options are initialized as follows: each
option's resource and class names are used to query the Tk option database\. If
the result is non\-empty, it is used as the option's default; otherwise, the
default hardcoded in the type definition is used\. In either case, the default
can be overridden by the caller\. For example,

        option add \*Mywidget\.texture pebbled

        snit::widget mywidget \{
    	option \-texture smooth
    	\# \.\.\.
        \}


        mywidget \.mywidget \-texture greasy

Here, __\-texture__ would normally default to "smooth", but because of the
entry added to the option database it defaults to "pebbled"\. However, the caller
has explicitly overridden the default, and so the new widget will be "greasy"\.

__Initializing options delegated to the hull:__ A __snit::widget__'s
hull is a widget, and given that its class has been set it is expected to query
the option database for itself\. The only exception concerns options that are
delegated to it with a different name\. Consider the following code:

        option add \*Mywidget\.borderWidth 5
        option add \*Mywidget\.relief sunken
        option add \*Mywidget\.hullbackground red
        option add \*Mywidget\.background green

        snit::widget mywidget \{
    	delegate option \-borderwidth to hull
    	delegate option \-hullbackground to hull as \-background
    	delegate option \* to hull
    	\# \.\.\.
        \}


        mywidget \.mywidget

        set A \[\.mywidget cget \-relief\]
        set B \[\.mywidget cget \-hullbackground\]
        set C \[\.mywidget cget \-background\]
        set D \[\.mywidget cget \-borderwidth\]

The question is, what are the values of variables A, B, C and D?

The value of A is "sunken"\. The hull is a Tk frame that has been given the
widget class "Mywidget"; it will automatically query the option database and
pick up this value\. Since the __\-relief__ option is implicitly delegated to
the hull, Snit takes no action\.







|
|
|
|









|
|
|
|
|
<
>









|
|
|










|
|
|
|
|
<
>







|
|
|
|
|
|
|
<
>













|

|
|
|
<
|
>
|










|
|
|
|

|
|
|
|
|
<
|
>
|

|
|
|
|







1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726

1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754

1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769

1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788

1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811

1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
The resource and class names are used to initialize option default values by
querying the Tk option database\. The resource name is usually just the option
name minus the hyphen, but may contain uppercase letters at word boundaries; the
class name is usually just the resource name with an initial capital, but not
always\. For example, here are the option, resource, and class names for several
__[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget options:

    -background         background         Background
    -borderwidth        borderWidth        BorderWidth
    -insertborderwidth  insertBorderWidth  BorderWidth
    -padx               padX               Pad

As is easily seen, sometimes the resource and class names can be inferred from
the option name, but not always\.

Snit options also have a resource name and a class name\. By default, these names
follow the rule given above: the resource name is the option name without the
hyphen, and the class name is the resource name with an initial capital\. This is
true for both locally\-defined options and explicitly delegated options:

        snit::widget mywidget {
            option -background
            delegate option -borderwidth to hull
            delegate option * to text
    	# ...

        }

In this case, the widget class name is "Mywidget"\. The widget has the following
options: __\-background__, which is locally defined, and
__\-borderwidth__, which is explicitly delegated; all other widgets are
delegated to a component called "text", which is probably a Tk
__[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget\. If so, __mywidget__
has all the same options as a __[text](\.\./\.\./\.\./\.\./index\.md\#text)__
widget\. The option, resource, and class names are as follows:

    -background  background  Background
    -borderwidth borderwidth Borderwidth
    -padx        padX        Pad

Note that the locally defined option, __\-background__, happens to have the
same three names as the standard Tk __\-background__ option; and
__\-pad__, which is delegated implicitly to the __text__ component, has
the same three names for __mywidget__ as it does for the
__[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget\. __\-borderwidth__, on
the other hand, has different resource and class names than usual, because the
internal word "width" isn't capitalized\. For consistency, it should be; this is
done as follows:

        snit::widget mywidget {
    	option -background
    	delegate option {-borderwidth borderWidth} to hull
    	delegate option * to text
    	# ...

        }

The class name will default to "BorderWidth", as expected\.

Suppose, however, that __mywidget__ also delegated __\-padx__ and
__\-pady__ to the hull\. In this case, both the resource name and the class
name must be specified explicitly:

        snit::widget mywidget {
    	option -background
    	delegate option {-borderwidth borderWidth} to hull
    	delegate option {-padx padX Pad} to hull
    	delegate option {-pady padY Pad} to hull
    	delegate option * to text
    	# ...

        }

__Querying the option database:__ If you set your widgetclass and option
names as described above, Snit will query the option database when each instance
is created, and will generally do the right thing when it comes to querying the
option database\. The remainder of this section goes into the gory details\.

__Initializing locally defined options:__ When an instance of a snit::widget
is created, its locally defined options are initialized as follows: each
option's resource and class names are used to query the Tk option database\. If
the result is non\-empty, it is used as the option's default; otherwise, the
default hardcoded in the type definition is used\. In either case, the default
can be overridden by the caller\. For example,

        option add *Mywidget.texture pebbled

        snit::widget mywidget {
    	option -texture smooth
    	# ...

        }

        mywidget .mywidget -texture greasy

Here, __\-texture__ would normally default to "smooth", but because of the
entry added to the option database it defaults to "pebbled"\. However, the caller
has explicitly overridden the default, and so the new widget will be "greasy"\.

__Initializing options delegated to the hull:__ A __snit::widget__'s
hull is a widget, and given that its class has been set it is expected to query
the option database for itself\. The only exception concerns options that are
delegated to it with a different name\. Consider the following code:

        option add *Mywidget.borderWidth 5
        option add *Mywidget.relief sunken
        option add *Mywidget.hullbackground red
        option add *Mywidget.background green

        snit::widget mywidget {
    	delegate option -borderwidth to hull
    	delegate option -hullbackground to hull as -background
    	delegate option * to hull
    	# ...

        }

        mywidget .mywidget

        set A [.mywidget cget -relief]
        set B [.mywidget cget -hullbackground]
        set C [.mywidget cget -background]
        set D [.mywidget cget -borderwidth]

The question is, what are the values of variables A, B, C and D?

The value of A is "sunken"\. The hull is a Tk frame that has been given the
widget class "Mywidget"; it will automatically query the option database and
pick up this value\. Since the __\-relief__ option is implicitly delegated to
the hull, Snit takes no action\.
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857


1858
1859
1860
1861

1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891


1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902


1903
1904
1905
1906
1907
1908
1909
further\.

For __snit::widgetadaptor__s, the case is somewhat altered\. Widget adaptors
retain the widget class of their hull, and the hull is not created automatically
by Snit\. Instead, the __snit::widgetadaptor__ must call __installhull__
in its constructor\. The normal way to do this is as follows:

        snit::widgetadaptor mywidget \{
    	\# \.\.\.
    	constructor \{args\} \{
    	    \# \.\.\.
    	    installhull using text \-foreground white


    	    \#
    	\}
    	\#\.\.\.
        \}


In this case, the __installhull__ command will create the hull using a
command like this:

    set hull \[text $win \-foreground white\]

The hull is a __[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget, so its
widget class is "Text"\. Just as with __snit::widget__ hulls, Snit assumes
that it will pick up all of its normal option values automatically; options
delegated from a different name are initialized from the option database in the
same way\.

__Initializing options delegated to other components:__ Non\-hull components
are matched against the option database in two ways\. First, a component widget
remains a widget still, and therefore is initialized from the option database in
the usual way\. Second, the option database is queried for all options delegated
to the component, and the component is initialized accordingly\-\-provided that
the __install__ command is used to create it\.

Before option database support was added to Snit, the usual way to create a
component was to simply create it in the constructor and assign its command name
to the component variable:

        snit::widget mywidget \{
    	delegate option \-background to myComp

    	constructor \{args\} \{
    	    set myComp \[text $win\.text \-foreground black\]
    	\}
        \}



The drawback of this method is that Snit has no opportunity to initialize the
component properly\. Hence, the following approach is now used:

        snit::widget mywidget \{
    	delegate option \-background to myComp

    	constructor \{args\} \{
    	    install myComp using text $win\.text \-foreground black
    	\}
        \}



The __install__ command does the following:

  - Builds a list of the options explicitly included in the __install__
    command \-\- in this case, __\-foreground__\.

  - Queries the option database for all options delegated explicitly to the







|
|
|
|
|
>
>
|
<
<
<
>




|


















|
|

|
|
<
<
>
>




|
|

|
|
<
<
>
>







1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860



1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889


1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900


1901
1902
1903
1904
1905
1906
1907
1908
1909
further\.

For __snit::widgetadaptor__s, the case is somewhat altered\. Widget adaptors
retain the widget class of their hull, and the hull is not created automatically
by Snit\. Instead, the __snit::widgetadaptor__ must call __installhull__
in its constructor\. The normal way to do this is as follows:

        snit::widgetadaptor mywidget {
    	# ...
    	constructor {args} {
    	    # ...
    	    installhull using text -foreground white
    	    #
    	}
    	#...



        }

In this case, the __installhull__ command will create the hull using a
command like this:

    set hull [text $win -foreground white]

The hull is a __[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget, so its
widget class is "Text"\. Just as with __snit::widget__ hulls, Snit assumes
that it will pick up all of its normal option values automatically; options
delegated from a different name are initialized from the option database in the
same way\.

__Initializing options delegated to other components:__ Non\-hull components
are matched against the option database in two ways\. First, a component widget
remains a widget still, and therefore is initialized from the option database in
the usual way\. Second, the option database is queried for all options delegated
to the component, and the component is initialized accordingly\-\-provided that
the __install__ command is used to create it\.

Before option database support was added to Snit, the usual way to create a
component was to simply create it in the constructor and assign its command name
to the component variable:

        snit::widget mywidget {
    	delegate option -background to myComp

    	constructor {args} {
    	    set myComp [text $win.text -foreground black]


    	}
        }

The drawback of this method is that Snit has no opportunity to initialize the
component properly\. Hence, the following approach is now used:

        snit::widget mywidget {
    	delegate option -background to myComp

    	constructor {args} {
    	    install myComp using text $win.text -foreground black


    	}
        }

The __install__ command does the following:

  - Builds a list of the options explicitly included in the __install__
    command \-\- in this case, __\-foreground__\.

  - Queries the option database for all options delegated explicitly to the
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944

1945
1946
1947
1948


1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959

1960
1961
1962
1963
1964
1965
1966
1967
1968
1969

1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985

1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031

2032
2033
2034

2035
2036
2037
2038
2039
2040
2041

## <a name='subsection10'></a>Macros and Meta\-programming

The __snit::macro__ command enables a certain amount of meta\-programming
with Snit classes\. For example, suppose you like to define properties: instance
variables that have set/get methods\. Your code might look like this:

    snit::type dog \{
        variable mood happy

        method getmood \{\} \{
            return $mood
        \}


        method setmood \{newmood\} \{
            set mood $newmood
        \}
    \}



That's nine lines of text per property\. Or, you could define the following
__snit::macro__:

    snit::macro property \{name initValue\} \{
        variable $name $initValue

        method get$name \{\} "return $name"

        method set$name \{value\} "set $name \\$value"
    \}


Note that a __snit::macro__ is just a normal Tcl proc defined in the slave
interpreter used to compile type and widget definitions; as a result, it has
access to all the commands used to define types and widgets\.

Given this new macro, you can define a property in one line of code:

    snit::type dog \{
        property mood happy
    \}


Within a macro, the commands __variable__ and
__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ refer to the Snit type\-definition
commands, not the standard Tcl commands\. To get the standard Tcl commands, use
__\_variable__ and __\_proc__\.

Because a single slave interpreter is used for compiling all Snit types and
widgets in the application, there's the possibility of macro name collisions\. If
you're writing a reuseable package using Snit, and you use some
__snit::macro__s, define them in your package namespace:

    snit::macro mypkg::property \{name initValue\} \{ \.\.\. \}

    snit::type dog \{
        mypkg::property mood happy
    \}


This leaves the global namespace open for application authors\.

## <a name='subsection11'></a>Validation Types

A validation type is an object that can be used to validate Tcl values of a
particular kind\. For example, __snit::integer__ is used to validate that a
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    snit::integer validate 5     ;\# Does nothing
    snit::integer validate 5\.0   ;\# Throws an error \(not an integer\!\)

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error\.

Snit defines a family of validation types, all of which are implemented as
__snit::type__'s\. They can be used as is; in addition, their instances serve
as parameterized subtypes\. For example, a probability is a number between 0\.0
and 1\.0 inclusive:

    snit::double probability \-min 0\.0 \-max 1\.0

The example above creates an instance of __snit::double__\-\-a validation
subtype\-\-called __probability__, which can be used to validate probability
values:

    probability validate 0\.5   ;\# Does nothing
    probability validate 7\.9   ;\# Throws an error

Validation subtypes can be defined explicitly, as in the above example; when a
locally\-defined option's __\-type__ is specified, they may also be created on
the fly:

    snit::enum ::dog::breed \-values \{mutt retriever sheepdog\}

    snit::type dog \{
        \# Define subtypes on the fly\.\.\.
        option \-breed \-type \{
            snit::enum \-values \{mutt retriever sheepdog\}
        \}


        \# Or use predefined subtypes\.\.\.
        option \-breed \-type ::dog::breed
    \}


Any object that has a __validate__ method with the semantics described above
can be used as a validation type; see [Defining Validation
Types](#subsection12) for information on how to define new ones\.

Snit defines the following validation types:








|


|

<
|
>
|

<
<
>
>




|


|

|
<
>







|

<
>











|

|

<
>














|
|









|





|
|





|

|
|
|
|
<
|
>
|
|
<
>







1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942

1943
1944
1945
1946


1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958

1959
1960
1961
1962
1963
1964
1965
1966
1967
1968

1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984

1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029

2030
2031
2032
2033

2034
2035
2036
2037
2038
2039
2040
2041

## <a name='subsection10'></a>Macros and Meta\-programming

The __snit::macro__ command enables a certain amount of meta\-programming
with Snit classes\. For example, suppose you like to define properties: instance
variables that have set/get methods\. Your code might look like this:

    snit::type dog {
        variable mood happy

        method getmood {} {
            return $mood

        }

        method setmood {newmood} {
            set mood $newmood


        }
    }

That's nine lines of text per property\. Or, you could define the following
__snit::macro__:

    snit::macro property {name initValue} {
        variable $name $initValue

        method get$name {} "return $name"

        method set$name {value} "set $name \$value"

    }

Note that a __snit::macro__ is just a normal Tcl proc defined in the slave
interpreter used to compile type and widget definitions; as a result, it has
access to all the commands used to define types and widgets\.

Given this new macro, you can define a property in one line of code:

    snit::type dog {
        property mood happy

    }

Within a macro, the commands __variable__ and
__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ refer to the Snit type\-definition
commands, not the standard Tcl commands\. To get the standard Tcl commands, use
__\_variable__ and __\_proc__\.

Because a single slave interpreter is used for compiling all Snit types and
widgets in the application, there's the possibility of macro name collisions\. If
you're writing a reuseable package using Snit, and you use some
__snit::macro__s, define them in your package namespace:

    snit::macro mypkg::property {name initValue} { ... }

    snit::type dog {
        mypkg::property mood happy

    }

This leaves the global namespace open for application authors\.

## <a name='subsection11'></a>Validation Types

A validation type is an object that can be used to validate Tcl values of a
particular kind\. For example, __snit::integer__ is used to validate that a
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    snit::integer validate 5     ;# Does nothing
    snit::integer validate 5.0   ;# Throws an error (not an integer!)

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error\.

Snit defines a family of validation types, all of which are implemented as
__snit::type__'s\. They can be used as is; in addition, their instances serve
as parameterized subtypes\. For example, a probability is a number between 0\.0
and 1\.0 inclusive:

    snit::double probability -min 0.0 -max 1.0

The example above creates an instance of __snit::double__\-\-a validation
subtype\-\-called __probability__, which can be used to validate probability
values:

    probability validate 0.5   ;# Does nothing
    probability validate 7.9   ;# Throws an error

Validation subtypes can be defined explicitly, as in the above example; when a
locally\-defined option's __\-type__ is specified, they may also be created on
the fly:

    snit::enum ::dog::breed -values {mutt retriever sheepdog}

    snit::type dog {
        # Define subtypes on the fly...
        option -breed -type {
            snit::enum -values {mutt retriever sheepdog}

        }

        # Or use predefined subtypes...
        option -breed -type ::dog::breed

    }

Any object that has a __validate__ method with the semantics described above
can be used as a validation type; see [Defining Validation
Types](#subsection12) for information on how to define new ones\.

Snit defines the following validation types:

2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147

2148
2149
2150
2151
2152
2153
2154
2155

2156
2157
2158
2159
2160
2161
2162

      * __\-type__ *type*

        Specifies the type of the list elements; *type* must be the name of a
        validation type or subtype\. In the following example, the value of
        __\-numbers__ must be a list of integers\.

    option \-numbers \-type \{snit::listtype \-type snit::integer\}

        Note that this option doesn't support defining new validation subtypes
        on the fly; that is, the following code will not work \(yet, anyway\):

    option \-numbers \-type \{
        snit::listtype \-type \{snit::integer \-min 5\}
    \}


        Instead, define the subtype explicitly:

    snit::integer gt4 \-min 5

    snit::type mytype \{
        option \-numbers \-type \{snit::listtype \-type gt4\}
    \}


  - <a name='86'></a>__snit::pixels__ __validate__ ?*value*?

  - <a name='87'></a>__snit::pixels__ *name* ?*option* *value*\.\.\.?

    *Tk programs only\.* Validates screen distances, in any of the forms
    accepted by __winfo pixels__\. Subtypes may be created with the following







|




|
|
<
>



|

|
|
<
>







2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146

2147
2148
2149
2150
2151
2152
2153
2154

2155
2156
2157
2158
2159
2160
2161
2162

      * __\-type__ *type*

        Specifies the type of the list elements; *type* must be the name of a
        validation type or subtype\. In the following example, the value of
        __\-numbers__ must be a list of integers\.

    option -numbers -type {snit::listtype -type snit::integer}

        Note that this option doesn't support defining new validation subtypes
        on the fly; that is, the following code will not work \(yet, anyway\):

    option -numbers -type {
        snit::listtype -type {snit::integer -min 5}

    }

        Instead, define the subtype explicitly:

    snit::integer gt4 -min 5

    snit::type mytype {
        option -numbers -type {snit::listtype -type gt4}

    }

  - <a name='86'></a>__snit::pixels__ __validate__ ?*value*?

  - <a name='87'></a>__snit::pixels__ *name* ?*option* *value*\.\.\.?

    *Tk programs only\.* Validates screen distances, in any of the forms
    accepted by __winfo pixels__\. Subtypes may be created with the following
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240

2241
2242

2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256

2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270

2271
2272
2273

2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286

2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305

2306
2307
2308
2309


2310
2311
2312
2313
2314
2315
2316
command\. A validation type is simply an object that has a __validate__
method; the __validate__ method must take one argument, a value, return the
value if it is valid, and throw an error with __\-errorcode__ INVALID if the
value is invalid\. This can be done with a simple
__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__\. For example, the
__snit::boolean__ validate type could have been implemented like this:

    proc ::snit::boolean \{"validate" value\} \{
        if \{\!\[string is boolean \-strict $value\]\} \{
            return \-code error \-errorcode INVALID  "invalid boolean \\"$value\\", should be one of: 1, 0, \.\.\."
        \}


        return $value
    \}


A validation type defined in this way cannot be subtyped, of course; but for
many applications this will be sufficient\.

Finally, one can define a full\-fledged, subtype\-able validation type as a
__snit::type__\. Here's a skeleton to get you started:

    snit::type myinteger \{
        \# First, define any options you'd like to use to define
        \# subtypes\.  Give them defaults such that they won't take
        \# effect if they aren't used, and marked them "read\-only"\.
        \# After all, you shouldn't be changing their values after
        \# a subtype is defined\.
        \#

        \# For example:

        option \-min \-default "" \-readonly 1
        option \-max \-default "" \-readonly 1

        \# Next, define a "validate" type method which should do the
        \# validation in the basic case\.  This will allow the
        \# type command to be used as a validation type\.

        typemethod validate \{value\} \{
            if \{\!\[string is integer \-strict $value\]\} \{
                return \-code error \-errorcode INVALID  "invalid value \\"$value\\", expected integer"
            \}


            return $value
        \}


        \# Next, the constructor should validate the subtype options,
        \# if any\.  Since they are all readonly, we don't need to worry
        \# about validating the options on change\.

        constructor \{args\} \{
            \# FIRST, get the options
            $self configurelist $args

            \# NEXT, validate them\.

            \# I'll leave this to your imagination\.
        \}


        \# Next, define a "validate" instance method; its job is to
        \# validate values for subtypes\.

        method validate \{value\} \{
            \# First, call the type method to do the basic validation\.
            $type validate $value

            \# Now we know it's a valid integer\.

            if \{\("" \!= $options\(\-min\) && $value < $options\(\-min\)\)  &#124;&#124;
                \("" \!= $options\(\-max\) && $value > $options\(\-max\)\)\} \{
                \# It's out of range; format a detailed message about
                \# the error, and throw it\.

                set msg "\.\.\.\."

                return \-code error \-errorcode INVALID $msg
            \}


            \# Otherwise, if it's valid just return it\.
            return $valid
        \}
    \}



And now you have a type that can be subtyped\.

The file "validate\.tcl" in the Snit distribution defines all of Snit's
validation types; you can find the complete implementation for
__snit::integer__ and the other types there, to use as examples for your own
types\.







|
|
|
<
|
>

<
>







|
|
|
|
|
|
<
>
|

|
|

|
|
|

|
|
|
<
|
>

<
|
>
|
|
|

|
|


|

|
<
|
>
|
|

|
|


|

|
|
|
|

|

|
<
|
>
|

<
<
>
>







2229
2230
2231
2232
2233
2234
2235
2236
2237
2238

2239
2240
2241

2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255

2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268

2269
2270
2271

2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284

2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303

2304
2305
2306
2307


2308
2309
2310
2311
2312
2313
2314
2315
2316
command\. A validation type is simply an object that has a __validate__
method; the __validate__ method must take one argument, a value, return the
value if it is valid, and throw an error with __\-errorcode__ INVALID if the
value is invalid\. This can be done with a simple
__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__\. For example, the
__snit::boolean__ validate type could have been implemented like this:

    proc ::snit::boolean {"validate" value} {
        if {![string is boolean -strict $value]} {
            return -code error -errorcode INVALID  "invalid boolean \"$value\", should be one of: 1, 0, ..."

        }

        return $value

    }

A validation type defined in this way cannot be subtyped, of course; but for
many applications this will be sufficient\.

Finally, one can define a full\-fledged, subtype\-able validation type as a
__snit::type__\. Here's a skeleton to get you started:

    snit::type myinteger {
        # First, define any options you'd like to use to define
        # subtypes.  Give them defaults such that they won't take
        # effect if they aren't used, and marked them "read-only".
        # After all, you shouldn't be changing their values after
        # a subtype is defined.

        #
        # For example:

        option -min -default "" -readonly 1
        option -max -default "" -readonly 1

        # Next, define a "validate" type method which should do the
        # validation in the basic case.  This will allow the
        # type command to be used as a validation type.

        typemethod validate {value} {
            if {![string is integer -strict $value]} {
                return -code error -errorcode INVALID  "invalid value \"$value\", expected integer"

            }

            return $value

        }

        # Next, the constructor should validate the subtype options,
        # if any.  Since they are all readonly, we don't need to worry
        # about validating the options on change.

        constructor {args} {
            # FIRST, get the options
            $self configurelist $args

            # NEXT, validate them.

            # I'll leave this to your imagination.

        }

        # Next, define a "validate" instance method; its job is to
        # validate values for subtypes.

        method validate {value} {
            # First, call the type method to do the basic validation.
            $type validate $value

            # Now we know it's a valid integer.

            if {("" != $options(-min) && $value < $options(-min))  ||
                ("" != $options(-max) && $value > $options(-max))} {
                # It's out of range; format a detailed message about
                # the error, and throw it.

                set msg "...."

                return -code error -errorcode INVALID $msg

            }

            # Otherwise, if it's valid just return it.
            return $valid


        }
    }

And now you have a type that can be subtyped\.

The file "validate\.tcl" in the Snit distribution defines all of Snit's
validation types; you can find the complete implementation for
__snit::integer__ and the other types there, to use as examples for your own
types\.

Changes to embedded/md/tcllib/files/modules/snit/snitfaq.md.

560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
unaffected by the minor incompatibilities between the two versions\) you can use
Snit 1\.3 for Tcl 8\.4 and Snit 2\.2 for Tcl 8\.5\.

## <a name='subsection9'></a>How do I select the version of Snit I want to use?

To always use Snit 1\.3 \(or a later version of Snit 1\.x\), invoke Snit as follows:

    package require snit 1\.3

To always use Snit 2\.2 \(or a later version of Snit 2\.x\), say this instead:

    package require snit 2\.2

Note that if you request Snit 2\.2 explicitly, your application will halt with
Tcl 8\.4, since Snit 2\.2 is unavailable for Tcl 8\.4\.

If you wish your application to always use the latest available version of Snit,
don't specify a version number:








|



|







560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
unaffected by the minor incompatibilities between the two versions\) you can use
Snit 1\.3 for Tcl 8\.4 and Snit 2\.2 for Tcl 8\.5\.

## <a name='subsection9'></a>How do I select the version of Snit I want to use?

To always use Snit 1\.3 \(or a later version of Snit 1\.x\), invoke Snit as follows:

    package require snit 1.3

To always use Snit 2\.2 \(or a later version of Snit 2\.x\), say this instead:

    package require snit 2.2

Note that if you request Snit 2\.2 explicitly, your application will halt with
Tcl 8\.4, since Snit 2\.2 is unavailable for Tcl 8\.4\.

If you wish your application to always use the latest available version of Snit,
don't specify a version number:

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

There are four specific incompatibilities between Snit 1\.3 and Snit 2\.2\.

  - Snit 1\.3 supports implicit naming of objects\. Suppose you define a new
    __snit::type__ called __dog__\. You can create instances of
    __dog__ in three ways:

    dog spot               ;\# Explicit naming
    set obj1 \[dog %AUTO%\]  ;\# Automatic naming
    set obj2 \[dog\]         ;\# Implicit naming

    In Snit 2\.2, type commands are defined using the __namespace ensemble__
    mechanism; and __namespace ensemble__ doesn't allow an ensemble command
    to be called without a subcommand\. In short, using __namespace
    ensemble__ there's no way to support implicit naming\.

    All is not lost, however\. If the type has no type methods, then the type
    command is a simple command rather than an ensemble, and __namespace
    ensemble__ is not used\. In this case, implicit naming is still possible\.

    In short, you can have implicit naming if you're willing to do without type
    methods \(including the standard type methods, like __$type info__\)\. To
    do so, use the __\-hastypemethods__ pragma:

    pragma \-hastypemethods 0

  - Hierarchical methods and type methods are implemented differently in Snit
    2\.2\.

    A hierarchical method is an instance method which has subcommands; these
    subcommands are themselves methods\. The Tk text widget's __tag__ command
    and its subcommands are examples of hierarchical methods\. You can implement
    such subcommands in Snit simply by including multiple words in the method
    names:

    method \{tag configure\} \{tag args\} \{ \.\.\. \}

    method \{tag cget\} \{tag option\} \{\.\.\.\}

    Here we've implicitly defined a __tag__ method which has two
    subcommands, __configure__ and __cget__\.

    In Snit 1\.3, hierarchical methods could be called in two ways:

    $obj tag cget \-myoption      ;\# The good way
    $obj \{tag cget\} \-myoption    ;\# The weird way

    In the second call, we see that a hierarchical method or type method is
    simply one whose name contains multiple words\.

    In Snit 2\.2 this is no longer the case, and the "weird" way of calling
    hierarchical methods and type methods no longer works\.








|
|
|














|










|

|






|
|







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

There are four specific incompatibilities between Snit 1\.3 and Snit 2\.2\.

  - Snit 1\.3 supports implicit naming of objects\. Suppose you define a new
    __snit::type__ called __dog__\. You can create instances of
    __dog__ in three ways:

    dog spot               ;# Explicit naming
    set obj1 [dog %AUTO%]  ;# Automatic naming
    set obj2 [dog]         ;# Implicit naming

    In Snit 2\.2, type commands are defined using the __namespace ensemble__
    mechanism; and __namespace ensemble__ doesn't allow an ensemble command
    to be called without a subcommand\. In short, using __namespace
    ensemble__ there's no way to support implicit naming\.

    All is not lost, however\. If the type has no type methods, then the type
    command is a simple command rather than an ensemble, and __namespace
    ensemble__ is not used\. In this case, implicit naming is still possible\.

    In short, you can have implicit naming if you're willing to do without type
    methods \(including the standard type methods, like __$type info__\)\. To
    do so, use the __\-hastypemethods__ pragma:

    pragma -hastypemethods 0

  - Hierarchical methods and type methods are implemented differently in Snit
    2\.2\.

    A hierarchical method is an instance method which has subcommands; these
    subcommands are themselves methods\. The Tk text widget's __tag__ command
    and its subcommands are examples of hierarchical methods\. You can implement
    such subcommands in Snit simply by including multiple words in the method
    names:

    method {tag configure} {tag args} { ... }

    method {tag cget} {tag option} {...}

    Here we've implicitly defined a __tag__ method which has two
    subcommands, __configure__ and __cget__\.

    In Snit 1\.3, hierarchical methods could be called in two ways:

    $obj tag cget -myoption      ;# The good way
    $obj {tag cget} -myoption    ;# The weird way

    In the second call, we see that a hierarchical method or type method is
    simply one whose name contains multiple words\.

    In Snit 2\.2 this is no longer the case, and the "weird" way of calling
    hierarchical methods and type methods no longer works\.

698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
    the type can call other commands defined by the package without any extra
    work\.

    This feature depends on the new Tcl 8\.5 __namespace path__ command,
    which is why it hasn't been implemented for V1\.x\. V1\.x code can achieve
    something similar by placing

    namespace import \[namespace parent\]::\*

    in a type constructor\. This is less useful, however, as it picks up only
    those commands which have already been exported by the parent namespace at
    the time the type is defined\.

# <a name='section4'></a>OBJECTS








|







698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
    the type can call other commands defined by the package without any extra
    work\.

    This feature depends on the new Tcl 8\.5 __namespace path__ command,
    which is why it hasn't been implemented for V1\.x\. V1\.x code can achieve
    something similar by placing

    namespace import [namespace parent]::*

    in a type constructor\. This is less useful, however, as it picks up only
    those commands which have already been exported by the parent namespace at
    the time the type is defined\.

# <a name='section4'></a>OBJECTS

741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757

Further, an *instance* is also a Tcl command\-\-a command that gives access to
the operations which are defined for that abstract data type\. Conventionally,
the operations are defined as subcommands of the instance command\. For example,
to insert text into a Tk text widget, you use the text widget's __insert__
subcommand:

    \# Create a text widget and insert some text in it\.
    text \.mytext \-width 80 \-height 24
    \.mytext insert end "Howdy\!"

In this example, __[text](\.\./\.\./\.\./\.\./index\.md\#text)__ is the
*[type](\.\./\.\./\.\./\.\./index\.md\#type)* command and __\.mytext__ is the
*instance* command\.

In Snit, object subcommands are generally called [INSTANCE
METHODS](#section5)\.







|
|
|







741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757

Further, an *instance* is also a Tcl command\-\-a command that gives access to
the operations which are defined for that abstract data type\. Conventionally,
the operations are defined as subcommands of the instance command\. For example,
to insert text into a Tk text widget, you use the text widget's __insert__
subcommand:

    # Create a text widget and insert some text in it.
    text .mytext -width 80 -height 24
    .mytext insert end "Howdy!"

In this example, __[text](\.\./\.\./\.\./\.\./index\.md\#text)__ is the
*[type](\.\./\.\./\.\./\.\./index\.md\#type)* command and __\.mytext__ is the
*instance* command\.

In Snit, object subcommands are generally called [INSTANCE
METHODS](#section5)\.
769
770
771
772
773
774
775
776
777
778

779
780
781
782
783
784
785
## <a name='subsection15'></a>What is a snit::type?

A __snit::type__ is a non\-GUI abstract data type, e\.g\., a stack or a queue\.
__snit::type__s are defined using the __snit::type__ command\. For
example, if you were designing a kennel management system for a dog breeder,
you'd need a dog type\.

    % snit::type dog \{
        \# \.\.\.
    \}

    ::dog
    %

This definition defines a new command \(__::dog__, in this case\) that can be
used to define dog objects\.

An instance of a __snit::type__ can have [INSTANCE METHODS](#section5),







|
|
<
>







769
770
771
772
773
774
775
776
777

778
779
780
781
782
783
784
785
## <a name='subsection15'></a>What is a snit::type?

A __snit::type__ is a non\-GUI abstract data type, e\.g\., a stack or a queue\.
__snit::type__s are defined using the __snit::type__ command\. For
example, if you were designing a kennel management system for a dog breeder,
you'd need a dog type\.

    % snit::type dog {
        # ...

    }
    ::dog
    %

This definition defines a new command \(__::dog__, in this case\) that can be
used to define dog objects\.

An instance of a __snit::type__ can have [INSTANCE METHODS](#section5),
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

## <a name='subsection18'></a>How do I create an instance of a snit::type?

You create an instance of a __snit::type__ by passing the new instance's
name to the type's create method\. In the following example, we create a
__dog__ object called __spot__\.

    % snit::type dog \{
        \# \.\.\.\.
    \}

    ::dog
    % dog create spot
    ::spot
    %

In general, the __create__ method name can be omitted so long as the
instance name doesn't conflict with any defined [TYPE METHODS](#section9)\.
\(See [TYPE COMPONENTS](#section15) for the special case in which this
doesn't work\.\) So the following example is identical to the previous example:

    % snit::type dog \{
        \# \.\.\.\.
    \}

    ::dog
    % dog spot
    ::spot
    %

This document generally uses the shorter form\.

If the __dog__ type defines [OPTIONS](#section7), these can usually be
given defaults at creation time:

    % snit::type dog \{
        option \-breed mongrel
        option \-color brown

        method bark \{\} \{ return "$self barks\." \}
    \}

    ::dog
    % dog create spot \-breed dalmation \-color spotted
    ::spot
    % spot cget \-breed
    dalmation
    % spot cget \-color
    spotted
    %

Once created, the instance name now names a new Tcl command that is used to
manipulate the object\. For example, the following code makes the dog bark:

    % spot bark
    ::spot barks\.
    %

## <a name='subsection19'></a>How do I refer to an object indirectly?

Some programmers prefer to save the object name in a variable, and reference it
that way\. For example,

    % snit::type dog \{ \.\.\. \}
    ::dog
    % set d \[dog spot \-breed dalmation \-color spotted\]
    ::spot
    % $d cget \-breed
    dalmation
    % $d bark
    ::spot barks\.
    %

If you prefer this style, you might prefer to have Snit generate the instance's
name automatically\.

## <a name='subsection20'></a>How can I generate the object name automatically?

If you'd like Snit to generate an object name for you, use the __%AUTO%__
keyword as the requested name:

    % snit::type dog \{ \.\.\. \}
    ::dog
    % set d \[dog %AUTO%\]
    ::dog2
    % $d bark
    ::dog2 barks\.
    %

The __%AUTO%__ keyword can be embedded in a longer string:

    % set d \[dog obj\_%AUTO%\]
    ::obj\_dog4
    % $d bark
    ::obj\_dog4 barks\.
    %

## <a name='subsection21'></a>Can types be renamed?

Tcl's __rename__ command renames other commands\. It's a common technique in
Tcl to modify an existing command by renaming it and defining a new command with
the original name; the new command usually calls the renamed command\.







|
|
<
>










|
|
<
>










|
|
|

|
<
>

|

|

|







|







|

|

|


|










|

|


|




|
|

|







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

## <a name='subsection18'></a>How do I create an instance of a snit::type?

You create an instance of a __snit::type__ by passing the new instance's
name to the type's create method\. In the following example, we create a
__dog__ object called __spot__\.

    % snit::type dog {
        # ....

    }
    ::dog
    % dog create spot
    ::spot
    %

In general, the __create__ method name can be omitted so long as the
instance name doesn't conflict with any defined [TYPE METHODS](#section9)\.
\(See [TYPE COMPONENTS](#section15) for the special case in which this
doesn't work\.\) So the following example is identical to the previous example:

    % snit::type dog {
        # ....

    }
    ::dog
    % dog spot
    ::spot
    %

This document generally uses the shorter form\.

If the __dog__ type defines [OPTIONS](#section7), these can usually be
given defaults at creation time:

    % snit::type dog {
        option -breed mongrel
        option -color brown

        method bark {} { return "$self barks." }

    }
    ::dog
    % dog create spot -breed dalmation -color spotted
    ::spot
    % spot cget -breed
    dalmation
    % spot cget -color
    spotted
    %

Once created, the instance name now names a new Tcl command that is used to
manipulate the object\. For example, the following code makes the dog bark:

    % spot bark
    ::spot barks.
    %

## <a name='subsection19'></a>How do I refer to an object indirectly?

Some programmers prefer to save the object name in a variable, and reference it
that way\. For example,

    % snit::type dog { ... }
    ::dog
    % set d [dog spot -breed dalmation -color spotted]
    ::spot
    % $d cget -breed
    dalmation
    % $d bark
    ::spot barks.
    %

If you prefer this style, you might prefer to have Snit generate the instance's
name automatically\.

## <a name='subsection20'></a>How can I generate the object name automatically?

If you'd like Snit to generate an object name for you, use the __%AUTO%__
keyword as the requested name:

    % snit::type dog { ... }
    ::dog
    % set d [dog %AUTO%]
    ::dog2
    % $d bark
    ::dog2 barks.
    %

The __%AUTO%__ keyword can be embedded in a longer string:

    % set d [dog obj_%AUTO%]
    ::obj_dog4
    % $d bark
    ::obj_dog4 barks.
    %

## <a name='subsection21'></a>Can types be renamed?

Tcl's __rename__ command renames other commands\. It's a common technique in
Tcl to modify an existing command by renaming it and defining a new command with
the original name; the new command usually calls the renamed command\.
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
    instance methods using __$self__\.

  - If the object is renamed, however, then __$self__'s value will change\.
    Therefore, don't use __$self__ for anything that will break if
    __$self__ changes\. For example, don't pass a callback command to another
    object like this:

    \.btn configure \-command \[list $self ButtonPress\]

    You'll get an error if __\.btn__ calls your command after your object is
    renamed\.

  - Instead, your object should define its callback command like this:

    \.btn configure \-command \[mymethod ButtonPress\]

    The __mymethod__ command returns code that will call the desired method
    safely; the caller of the callback can add additional arguments to the end
    of the command as usual\.

  - Every object has a private namespace; the name of this namespace is
    available in method bodies, etc\., as the value of the implicit argument







|






|







915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
    instance methods using __$self__\.

  - If the object is renamed, however, then __$self__'s value will change\.
    Therefore, don't use __$self__ for anything that will break if
    __$self__ changes\. For example, don't pass a callback command to another
    object like this:

    .btn configure -command [list $self ButtonPress]

    You'll get an error if __\.btn__ calls your command after your object is
    renamed\.

  - Instead, your object should define its callback command like this:

    .btn configure -command [mymethod ButtonPress]

    The __mymethod__ command returns code that will call the desired method
    safely; the caller of the callback can add additional arguments to the end
    of the command as usual\.

  - Every object has a private namespace; the name of this namespace is
    available in method bodies, etc\., as the value of the implicit argument
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
Snit megawidgets \(i\.e\., instances of __snit::widget__ and
__snit::widgetadaptor__\) can be destroyed like any other widget: by using
the Tk __destroy__ command on the widget or on one of its ancestors in the
window hierarchy\.

Every instance of a __snit::type__ has a __destroy__ method:

    % snit::type dog \{ \.\.\. \}
    ::dog
    % dog spot
    ::spot
    % spot bark
    ::spot barks\.
    % spot destroy
    % spot barks
    invalid command name "spot"
    %

Finally, every Snit type has a type method called __destroy__; calling it
destroys the type and all of its instances:

    % snit::type dog \{ \.\.\. \}
    ::dog
    % dog spot
    ::spot
    % spot bark
    ::spot barks\.
    % dog destroy
    % spot bark
    invalid command name "spot"
    % dog fido
    invalid command name "dog"
    %








|




|








|




|







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
Snit megawidgets \(i\.e\., instances of __snit::widget__ and
__snit::widgetadaptor__\) can be destroyed like any other widget: by using
the Tk __destroy__ command on the widget or on one of its ancestors in the
window hierarchy\.

Every instance of a __snit::type__ has a __destroy__ method:

    % snit::type dog { ... }
    ::dog
    % dog spot
    ::spot
    % spot bark
    ::spot barks.
    % spot destroy
    % spot barks
    invalid command name "spot"
    %

Finally, every Snit type has a type method called __destroy__; calling it
destroys the type and all of its instances:

    % snit::type dog { ... }
    ::dog
    % dog spot
    ::spot
    % spot bark
    ::spot barks.
    % dog destroy
    % spot bark
    invalid command name "spot"
    % dog fido
    invalid command name "dog"
    %

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

## <a name='subsection25'></a>How do I define an instance method?

Instance methods are defined in the type definition using the
__[method](\.\./\.\./\.\./\.\./index\.md\#method)__ statement\. Consider the
following code that might be used to add dogs to a computer simulation:

    % snit::type dog \{
        method bark \{\} \{
            return "$self barks\."
        \}


        method chase \{thing\} \{
            return "$self chases $thing\."
        \}
    \}


    ::dog
    %

A dog can bark, and it can chase things\.

The __[method](\.\./\.\./\.\./\.\./index\.md\#method)__ statement looks just like
a normal Tcl __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__, except that it
appears in a __snit::type__ definition\. Notice that every instance method
gets an implicit argument called __self__; this argument contains the
object's name\. \(There's more on implicit method arguments below\.\)

## <a name='subsection26'></a>How does a client call an instance method?

The method name becomes a subcommand of the object\. For example, let's put a
simulated dog through its paces:

    % dog spot
    ::spot
    % spot bark
    ::spot barks\.
    % spot chase cat
    ::spot chases cat\.
    %

## <a name='subsection27'></a>How does an instance method call another instance method?

If method A needs to call method B on the same object, it does so just as a
client does: it calls method B as a subcommand of the object itself, using the
object name stored in the implicit argument __self__\.

Suppose, for example, that our dogs never chase anything without barking at
them:

    % snit::type dog \{
        method bark \{\} \{
            return "$self barks\."
        \}


        method chase \{thing\} \{
            return "$self chases $thing\.  \[$self bark\]"
        \}
    \}


    ::dog
    % dog spot
    ::spot
    % spot bark
    ::spot barks\.
    % spot chase cat
    ::spot chases cat\.  ::spot barks\.
    %

## <a name='subsection28'></a>Are there any limitations on instance method names?

Not really, so long as you avoid the standard instance method names:
__configure__, __configurelist__, __cget__, __destroy__, and
__info__\. Also, method names consisting of multiple words define







|
|
|
<
|
>
|
|
<
<
>
>



















|

|











|
|
|
<
|
>
|
|
<
<
>
>




|

|







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

## <a name='subsection25'></a>How do I define an instance method?

Instance methods are defined in the type definition using the
__[method](\.\./\.\./\.\./\.\./index\.md\#method)__ statement\. Consider the
following code that might be used to add dogs to a computer simulation:

    % snit::type dog {
        method bark {} {
            return "$self barks."

        }

        method chase {thing} {
            return "$self chases $thing."


        }
    }
    ::dog
    %

A dog can bark, and it can chase things\.

The __[method](\.\./\.\./\.\./\.\./index\.md\#method)__ statement looks just like
a normal Tcl __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__, except that it
appears in a __snit::type__ definition\. Notice that every instance method
gets an implicit argument called __self__; this argument contains the
object's name\. \(There's more on implicit method arguments below\.\)

## <a name='subsection26'></a>How does a client call an instance method?

The method name becomes a subcommand of the object\. For example, let's put a
simulated dog through its paces:

    % dog spot
    ::spot
    % spot bark
    ::spot barks.
    % spot chase cat
    ::spot chases cat.
    %

## <a name='subsection27'></a>How does an instance method call another instance method?

If method A needs to call method B on the same object, it does so just as a
client does: it calls method B as a subcommand of the object itself, using the
object name stored in the implicit argument __self__\.

Suppose, for example, that our dogs never chase anything without barking at
them:

    % snit::type dog {
        method bark {} {
            return "$self barks."

        }

        method chase {thing} {
            return "$self chases $thing.  [$self bark]"


        }
    }
    ::dog
    % dog spot
    ::spot
    % spot bark
    ::spot barks.
    % spot chase cat
    ::spot chases cat.  ::spot barks.
    %

## <a name='subsection28'></a>Are there any limitations on instance method names?

Not really, so long as you avoid the standard instance method names:
__configure__, __configurelist__, __cget__, __destroy__, and
__info__\. Also, method names consisting of multiple words define
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

## <a name='subsection30'></a>How do I define a hierarchical method?

Define methods whose names consist of multiple words\. These words define the
hierarchy implicitly\. For example, the following code defines a __tag__
method with subcommands __cget__ and __configure__:

    snit::widget mytext \{
        method \{tag configure\} \{tag args\} \{ \.\.\. \}

        method \{tag cget\} \{tag option\} \{\.\.\.\}
    \}


Note that there is no explicit definition for the __tag__ method; it is
implicit in the definition of __tag configure__ and __tag cget__\. If you
tried to define __tag__ explicitly in this example, you'd get an error\.

## <a name='subsection31'></a>How do I call hierarchical methods?

As subcommands of subcommands\.

    % mytext \.text
    \.text
    % \.text tag configure redtext \-foreground red \-background black
    % \.text tag cget redtext \-foreground
    red
    %

## <a name='subsection32'></a>How do I make an instance method private?

It's often useful to define private methods, that is, instance methods intended
to be called only by other methods of the same object\.

Snit doesn't implement any access control on instance methods, so all methods
are *de facto* public\. Conventionally, though, the names of public methods
begin with a lower\-case letter, and the names of private methods begin with an
upper\-case letter\.

For example, suppose our simulated dogs only bark in response to other stimuli;
they never bark just for fun\. So the __bark__ method becomes __Bark__ to
indicate that it is private:

    % snit::type dog \{
        \# Private by convention: begins with uppercase letter\.
        method Bark \{\} \{
            return "$self barks\."
        \}


        method chase \{thing\} \{
            return "$self chases $thing\. \[$self Bark\]"
        \}
    \}


    ::dog
    % dog fido
    ::fido
    % fido chase cat
    ::fido chases cat\. ::fido barks\.
    %

## <a name='subsection33'></a>Are there any limitations on instance method arguments?

Method argument lists are defined just like normal Tcl
__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ argument lists; in particular,
they can include arguments with default values and the __args__ argument\.







|
|

|
<
>









|
|
|
|

















|
|
|
|
<
|
>
|
|
<
<
>
>




|







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

## <a name='subsection30'></a>How do I define a hierarchical method?

Define methods whose names consist of multiple words\. These words define the
hierarchy implicitly\. For example, the following code defines a __tag__
method with subcommands __cget__ and __configure__:

    snit::widget mytext {
        method {tag configure} {tag args} { ... }

        method {tag cget} {tag option} {...}

    }

Note that there is no explicit definition for the __tag__ method; it is
implicit in the definition of __tag configure__ and __tag cget__\. If you
tried to define __tag__ explicitly in this example, you'd get an error\.

## <a name='subsection31'></a>How do I call hierarchical methods?

As subcommands of subcommands\.

    % mytext .text
    .text
    % .text tag configure redtext -foreground red -background black
    % .text tag cget redtext -foreground
    red
    %

## <a name='subsection32'></a>How do I make an instance method private?

It's often useful to define private methods, that is, instance methods intended
to be called only by other methods of the same object\.

Snit doesn't implement any access control on instance methods, so all methods
are *de facto* public\. Conventionally, though, the names of public methods
begin with a lower\-case letter, and the names of private methods begin with an
upper\-case letter\.

For example, suppose our simulated dogs only bark in response to other stimuli;
they never bark just for fun\. So the __bark__ method becomes __Bark__ to
indicate that it is private:

    % snit::type dog {
        # Private by convention: begins with uppercase letter.
        method Bark {} {
            return "$self barks."

        }

        method chase {thing} {
            return "$self chases $thing. [$self Bark]"


        }
    }
    ::dog
    % dog fido
    ::fido
    % fido chase cat
    ::fido chases cat. ::fido barks.
    %

## <a name='subsection33'></a>Are there any limitations on instance method arguments?

Method argument lists are defined just like normal Tcl
__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ argument lists; in particular,
they can include arguments with default values and the __args__ argument\.
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
__selfns__, __win__, and __self__\.

## <a name='subsection35'></a>What is $type?

The implicit argument __type__ contains the fully qualified name of the
object's type:

    % snit::type thing \{
        method mytype \{\} \{
            return $type
        \}
    \}


    ::thing
    % thing something
    ::something
    % something mytype
    ::thing
    %

## <a name='subsection36'></a>What is $self?

The implicit argument __self__ contains the object's fully qualified name\.

If the object's command is renamed, then __$self__ will change to match in
subsequent calls\. Thus, your code should not assume that __$self__ is
constant unless you know for sure that the object will never be renamed\.

    % snit::type thing \{
        method myself \{\} \{
            return $self
        \}
    \}


    ::thing
    % thing mutt
    ::mutt
    % mutt myself
    ::mutt
    % rename mutt jeff
    % jeff myself
    ::jeff
    %

## <a name='subsection37'></a>What is $selfns?

Each Snit object has a private namespace in which to store its [INSTANCE
VARIABLES](#section6) and [OPTIONS](#section7)\. The implicit argument
__selfns__ contains the name of this namespace; its value never changes, and
is constant for the life of the object, even if the object's name changes:

    % snit::type thing \{
        method myNameSpace \{\} \{
            return $selfns
        \}
    \}


    ::thing
    % thing jeff
    ::jeff
    % jeff myNameSpace
    ::thing::Snit\_inst3
    % rename jeff mutt
    % mutt myNameSpace
    ::thing::Snit\_inst3
    %

The above example reveals how Snit names an instance's private namespace;
however, you should not write code that depends on the specific naming
convention, as it might change in future releases\.

## <a name='subsection38'></a>What is $win?







|
|

<
<
>
>















|
|

<
<
>
>

















|
|

<
<
>
>




|


|







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
__selfns__, __win__, and __self__\.

## <a name='subsection35'></a>What is $type?

The implicit argument __type__ contains the fully qualified name of the
object's type:

    % snit::type thing {
        method mytype {} {
            return $type


        }
    }
    ::thing
    % thing something
    ::something
    % something mytype
    ::thing
    %

## <a name='subsection36'></a>What is $self?

The implicit argument __self__ contains the object's fully qualified name\.

If the object's command is renamed, then __$self__ will change to match in
subsequent calls\. Thus, your code should not assume that __$self__ is
constant unless you know for sure that the object will never be renamed\.

    % snit::type thing {
        method myself {} {
            return $self


        }
    }
    ::thing
    % thing mutt
    ::mutt
    % mutt myself
    ::mutt
    % rename mutt jeff
    % jeff myself
    ::jeff
    %

## <a name='subsection37'></a>What is $selfns?

Each Snit object has a private namespace in which to store its [INSTANCE
VARIABLES](#section6) and [OPTIONS](#section7)\. The implicit argument
__selfns__ contains the name of this namespace; its value never changes, and
is constant for the life of the object, even if the object's name changes:

    % snit::type thing {
        method myNameSpace {} {
            return $selfns


        }
    }
    ::thing
    % thing jeff
    ::jeff
    % jeff myNameSpace
    ::thing::Snit_inst3
    % rename jeff mutt
    % mutt myNameSpace
    ::thing::Snit_inst3
    %

The above example reveals how Snit names an instance's private namespace;
however, you should not write code that depends on the specific naming
convention, as it might change in future releases\.

## <a name='subsection38'></a>What is $win?
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
It depends on the context\.

Suppose in my application I have a __dog__ object named __fido__, and I
want __fido__ to bark when a Tk button called __\.bark__ is pressed\. In
this case, I create the callback command in the usual way, using
__[list](\.\./\.\./\.\./\.\./index\.md\#list)__:

    button \.bark \-text "Bark\!" \-command \[list fido bark\]

In typical Tcl style, we use a callback to hook two independent components
together\. But suppose that the __dog__ object has a graphical interface and
owns the button itself? In this case, the __dog__ must pass one of its own
instance methods to the button it owns\. The obvious thing to do is this:

    % snit::widget dog \{
        constructor \{args\} \{
            \#\.\.\.
            button $win\.barkbtn \-text "Bark\!" \-command \[list $self bark\]
            \#\.\.\.
        \}
    \}


    ::dog
    %

\(Note that in this example, our __dog__ becomes a __snit::widget__,
because it has GUI behavior\. See [WIDGETS](#section17) for more\.\) Thus, if
we create a __dog__ called __\.spot__, it will create a Tk button called
__\.spot\.barkbtn__; when pressed, the button will call __$self bark__\.

Now, this will work\-\-provided that __\.spot__ is never renamed to something
else\. But surely renaming widgets is abnormal? And so it is\-\-unless
__\.spot__ is the hull component of a __snit::widgetadaptor__\. If it is,
then it will be renamed, and __\.spot__ will become the name of the
__snit::widgetadaptor__ object\. When the button is pressed, the command
__$self bark__ will be handled by the __snit::widgetadaptor__, which
might or might not do the right thing\.

There's a safer way to do it, and it looks like this:

    % snit::widget dog \{
        constructor \{args\} \{
            \#\.\.\.
            button $win\.barkbtn \-text "Bark\!" \-command \[mymethod bark\]
            \#\.\.\.
        \}
    \}


    ::dog
    %

The command __mymethod__ takes any number of arguments, and can be used like
__[list](\.\./\.\./\.\./\.\./index\.md\#list)__ to build up a callback command;
the only difference is that __mymethod__ returns a form of the command that
won't change even if the instance's name changes\.







|






|
|
|
|
|
<
<
>
>


















|
|
|
|
|
<
<
>
>







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
It depends on the context\.

Suppose in my application I have a __dog__ object named __fido__, and I
want __fido__ to bark when a Tk button called __\.bark__ is pressed\. In
this case, I create the callback command in the usual way, using
__[list](\.\./\.\./\.\./\.\./index\.md\#list)__:

    button .bark -text "Bark!" -command [list fido bark]

In typical Tcl style, we use a callback to hook two independent components
together\. But suppose that the __dog__ object has a graphical interface and
owns the button itself? In this case, the __dog__ must pass one of its own
instance methods to the button it owns\. The obvious thing to do is this:

    % snit::widget dog {
        constructor {args} {
            #...
            button $win.barkbtn -text "Bark!" -command [list $self bark]
            #...


        }
    }
    ::dog
    %

\(Note that in this example, our __dog__ becomes a __snit::widget__,
because it has GUI behavior\. See [WIDGETS](#section17) for more\.\) Thus, if
we create a __dog__ called __\.spot__, it will create a Tk button called
__\.spot\.barkbtn__; when pressed, the button will call __$self bark__\.

Now, this will work\-\-provided that __\.spot__ is never renamed to something
else\. But surely renaming widgets is abnormal? And so it is\-\-unless
__\.spot__ is the hull component of a __snit::widgetadaptor__\. If it is,
then it will be renamed, and __\.spot__ will become the name of the
__snit::widgetadaptor__ object\. When the button is pressed, the command
__$self bark__ will be handled by the __snit::widgetadaptor__, which
might or might not do the right thing\.

There's a safer way to do it, and it looks like this:

    % snit::widget dog {
        constructor {args} {
            #...
            button $win.barkbtn -text "Bark!" -command [mymethod bark]
            #...


        }
    }
    ::dog
    %

The command __mymethod__ takes any number of arguments, and can be used like
__[list](\.\./\.\./\.\./\.\./index\.md\#list)__ to build up a callback command;
the only difference is that __mymethod__ returns a form of the command that
won't change even if the instance's name changes\.
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

## <a name='subsection42'></a>How is a scalar instance variable defined?

Scalar instance variables are defined in the type definition using the
__variable__ statement\. You can simply name it, or you can initialize it
with a value:

    snit::type mytype \{
        \# Define variable "greeting" and initialize it with "Howdy\!"
        variable greeting "Howdy\!"
    \}


## <a name='subsection43'></a>How is an array instance variable defined?

Array instance variables are also defined in the type definition using the
__variable__ command\. You can initialize them at the same time by specifying
the __\-array__ option:

    snit::type mytype \{
        \# Define array variable "greetings"
        variable greetings \-array \{
            formal "Good Evening"
            casual "Howdy\!"
        \}
    \}



## <a name='subsection44'></a>What happens if I don't initialize an instance variable?

Variables do not really exist until they are given values\. If you do not
initialize a variable when you define it, then you must be sure to assign a
value to it \(in the constructor, say, or in some method\) before you reference
it\.







|
|
|
<
>







|
|
|

|
<
<
>
>







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

## <a name='subsection42'></a>How is a scalar instance variable defined?

Scalar instance variables are defined in the type definition using the
__variable__ statement\. You can simply name it, or you can initialize it
with a value:

    snit::type mytype {
        # Define variable "greeting" and initialize it with "Howdy!"
        variable greeting "Howdy!"

    }

## <a name='subsection43'></a>How is an array instance variable defined?

Array instance variables are also defined in the type definition using the
__variable__ command\. You can initialize them at the same time by specifying
the __\-array__ option:

    snit::type mytype {
        # Define array variable "greetings"
        variable greetings -array {
            formal "Good Evening"
            casual "Howdy!"


        }
    }

## <a name='subsection44'></a>What happens if I don't initialize an instance variable?

Variables do not really exist until they are given values\. If you do not
initialize a variable when you define it, then you must be sure to assign a
value to it \(in the constructor, say, or in some method\) before you reference
it\.
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
anyway\. This method breaks down if your instance variables include multiple
arrays; in Tcl 8\.5, however, the __[dict](\.\./\.\./\.\./\.\./index\.md\#dict)__
command might come to your rescue\.

The second method is to declare your instance variables explicitly in your
instance code, while *not* including them in the type definition:

    snit::type dog \{
        constructor \{\} \{
            variable mood

            set mood happy
        \}


        method setmood \{newMood\} \{
            variable mood

            set mood $newMood
        \}


        method getmood \{\} \{
            variable mood

            return $mood
        \}
    \}



This allows you to ensure that only the required variables are included in each
method, at the cost of longer code and run\-time errors when you forget to
declare a variable you need\.

## <a name='subsection47'></a>How do I pass an instance variable's name to another object?

In Tk, it's common to pass a widget a variable name; for example, Tk label
widgets have a __\-textvariable__ option which names the variable which will
contain the widget's text\. This allows the program to update the label's value
just by assigning a new value to the variable\.

If you naively pass the instance variable name to the label widget, you'll be
confused by the result; Tk will assume that the name names a global variable\.
Instead, you need to provide a fully\-qualified variable name\. From within an
instance method or a constructor, you can fully qualify the variable's name
using the __myvar__ command:

    snit::widget mywidget \{
        variable labeltext ""

        constructor \{args\} \{
            \# \.\.\.

            label $win\.label \-textvariable \[myvar labeltext\]

            \# \.\.\.
        \}
    \}



## <a name='subsection48'></a>How do I make an instance variable public?

Practically speaking, you don't\. Instead, you'll implement public variables as
[OPTIONS](#section7)\. Alternatively, you can write [INSTANCE
METHODS](#section5) to set and get the variable's value\.








|
|



<
|
>
|



<
|
>
|



<
<
>
>


















|


|
|

|

|
<
<
>
>







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
anyway\. This method breaks down if your instance variables include multiple
arrays; in Tcl 8\.5, however, the __[dict](\.\./\.\./\.\./\.\./index\.md\#dict)__
command might come to your rescue\.

The second method is to declare your instance variables explicitly in your
instance code, while *not* including them in the type definition:

    snit::type dog {
        constructor {} {
            variable mood

            set mood happy

        }

        method setmood {newMood} {
            variable mood

            set mood $newMood

        }

        method getmood {} {
            variable mood

            return $mood


        }
    }

This allows you to ensure that only the required variables are included in each
method, at the cost of longer code and run\-time errors when you forget to
declare a variable you need\.

## <a name='subsection47'></a>How do I pass an instance variable's name to another object?

In Tk, it's common to pass a widget a variable name; for example, Tk label
widgets have a __\-textvariable__ option which names the variable which will
contain the widget's text\. This allows the program to update the label's value
just by assigning a new value to the variable\.

If you naively pass the instance variable name to the label widget, you'll be
confused by the result; Tk will assume that the name names a global variable\.
Instead, you need to provide a fully\-qualified variable name\. From within an
instance method or a constructor, you can fully qualify the variable's name
using the __myvar__ command:

    snit::widget mywidget {
        variable labeltext ""

        constructor {args} {
            # ...

            label $win.label -textvariable [myvar labeltext]

            # ...


        }
    }

## <a name='subsection48'></a>How do I make an instance variable public?

Practically speaking, you don't\. Instead, you'll implement public variables as
[OPTIONS](#section7)\. Alternatively, you can write [INSTANCE
METHODS](#section5) to set and get the variable's value\.

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

## <a name='subsection50'></a>How do I define an option?

Options are defined in the type definition using the __option__ statement\.
Consider the following type, to be used in an application that manages a list of
dogs for a pet store:

    snit::type dog \{
        option \-breed \-default mongrel
        option \-color \-default brown
        option \-akc   \-default 0
        option \-shots \-default 0
    \}


According to this, a dog has four notable properties: a breed, a color, a flag
that says whether it's pedigreed with the American Kennel Club, and another flag
that says whether it has had its shots\. The default dog, evidently, is a brown
mutt\.

There are a number of options you can specify when defining an option; if
__\-default__ is the only one, you can omit the word __\-default__ as
follows:

    snit::type dog \{
        option \-breed mongrel
        option \-color brown
        option \-akc   0
        option \-shots 0
    \}


If no __\-default__ value is specified, the option's default value will be
the empty string \(but see [THE TK OPTION DATABASE](#section19)\)\.

The Snit man page refers to options like these as "locally defined" options\.

## <a name='subsection51'></a>How can a client set options at object creation?

The normal convention is that the client may pass any number of options and
their values after the object's name at object creation\. For example, the
__::dog__ command defined in the previous answer can now be used to create
individual dogs\. Any or all of the options may be set at creation time\.

    % dog spot \-breed beagle \-color "mottled" \-akc 1 \-shots 1
    ::spot
    % dog fido \-shots 1
    ::fido
    %

So __::spot__ is a pedigreed beagle; __::fido__ is a typical mutt, but
his owners evidently take care of him, because he's had his shots\.

*Note:* If the type defines a constructor, it can specify a different
object\-creation syntax\. See [CONSTRUCTORS](#section12) for more
information\.

## <a name='subsection52'></a>How can a client retrieve an option's value?

Retrieve option values using the __cget__ method:

    % spot cget \-color
    mottled
    % fido cget \-breed
    mongrel
    %

## <a name='subsection53'></a>How can a client set options after object creation?

Any number of options may be set at one time using the __configure__
instance method\. Suppose that closer inspection shows that ::fido is not a brown
mongrel, but rather a rare Arctic Boar Hound of a lovely dun color:

    % fido configure \-color dun \-breed "Arctic Boar Hound"
    % fido cget \-color
    dun
    % fido cget \-breed
    Arctic Boar Hound

Alternatively, the __configurelist__ method takes a list of options and
values; occasionally this is more convenient:

    % set features \[list \-color dun \-breed "Arctic Boar Hound"\]
    \-color dun \-breed \{Arctic Boar Hound\}
    % fido configurelist $features
    % fido cget \-color
    dun
    % fido cget \-breed
    Arctic Boar Hound
    %

In Tcl 8\.5, the __\*__ keyword can be used with __configure__ in this
case:

    % set features \[list \-color dun \-breed "Arctic Boar Hound"\]
    \-color dun \-breed \{Arctic Boar Hound\}
    % fido configure \{\*\}$features
    % fido cget \-color
    dun
    % fido cget \-breed
    Arctic Boar Hound
    %

The results are the same\.

## <a name='subsection54'></a>How should an instance method access an option value?

There are two ways an instance method can set and retrieve an option's value\.
One is to use the __configure__ and __cget__ methods, as shown below\.

    % snit::type dog \{
        option \-weight 10

        method gainWeight \{\} \{
            set wt \[$self cget \-weight\]
            incr wt
            $self configure \-weight $wt
        \}
    \}


    ::dog
    % dog fido
    ::fido
    % fido cget \-weight
    10
    % fido gainWeight
    % fido cget \-weight
    11
    %

Alternatively, Snit provides a built\-in array instance variable called
__options__\. The indices are the option names; the values are the option
values\. The method __gainWeight__ can thus be rewritten as follows:

    method gainWeight \{\} \{
        incr options\(\-weight\)
    \}


As you can see, using the __options__ variable involves considerably less
typing and is the usual way to do it\. But if you use __\-configuremethod__ or
__\-cgetmethod__ \(described in the following answers\), you might wish to use
the __configure__ and __cget__ methods anyway, just so that any special
processing you've implemented is sure to get done\. Also, if the option is
delegated to a component then __configure__ and __cget__ are the only
way to access it without accessing the component directly\. See
[DELEGATION](#section16) for more information\.

## <a name='subsection55'></a>How can I make an option read\-only?

Define the option with __\-readonly yes__\.

Suppose you've got an option that determines how instances of your type are
constructed; it must be set at creation time, after which it's constant\. For
example, a dog never changes its breed; it might or might not have had its
shots, and if not can have them at a later time\. __\-breed__ should be
read\-only, but __\-shots__ should not be\.

    % snit::type dog \{
        option \-breed \-default mongrel \-readonly yes
        option \-shots \-default no
    \}

    ::dog
    % dog fido \-breed retriever
    ::fido
    % fido configure \-shots yes
    % fido configure \-breed terrier
    option \-breed can only be set at instance creation
    %

## <a name='subsection56'></a>How can I catch accesses to an option's value?

Define a __\-cgetmethod__ for the option\.

## <a name='subsection57'></a>What is a \-cgetmethod?

A __\-cgetmethod__ is a method that's called whenever the related option's
value is queried via the __cget__ instance method\. The handler can compute
the option's value, retrieve it from a database, or do anything else you'd like
it to do\.

Here's what the default behavior would look like if written using a
__\-cgetmethod__:

    snit::type dog \{
        option \-color \-default brown \-cgetmethod GetOption

        method GetOption \{option\} \{
            return $options\($option\)
        \}
    \}



Any instance method can be used, provided that it takes one argument, the name
of the option whose value is to be retrieved\.

## <a name='subsection58'></a>How can I catch changes to an option's value?

Define a __\-configuremethod__ for the option\.

## <a name='subsection59'></a>What is a \-configuremethod?

A __\-configuremethod__ is a method that's called whenever the related option
is given a new value via the __configure__ or __configurelist__ instance
methods\. The method can pass the value on to some other object, store it in a
database, or do anything else you'd like it to do\.

Here's what the default configuration behavior would look like if written using
a __\-configuremethod__:

    snit::type dog \{
        option \-color \-default brown \-configuremethod SetOption

        method SetOption \{option value\} \{
            set options\($option\) $value
        \}
    \}



Any instance method can be used, provided that it takes two arguments, the name
of the option and the new value\.

Note that if your method doesn't store the value in the __options__ array,
the __options__ array won't get updated\.








|
|
|
|
|
<
>










|
|
|
|
|
<
>













|

|














|

|









|
|

|





|
|

|

|






|
|
|
|

|










|
|

|
|

|
<
<
>
>



|


|







|
|
<
>




















|
|
|
<
>

|

|
|
|
















|
|

|
|
<
<
>
>


















|
|

|
|
<
<
>
>







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

## <a name='subsection50'></a>How do I define an option?

Options are defined in the type definition using the __option__ statement\.
Consider the following type, to be used in an application that manages a list of
dogs for a pet store:

    snit::type dog {
        option -breed -default mongrel
        option -color -default brown
        option -akc   -default 0
        option -shots -default 0

    }

According to this, a dog has four notable properties: a breed, a color, a flag
that says whether it's pedigreed with the American Kennel Club, and another flag
that says whether it has had its shots\. The default dog, evidently, is a brown
mutt\.

There are a number of options you can specify when defining an option; if
__\-default__ is the only one, you can omit the word __\-default__ as
follows:

    snit::type dog {
        option -breed mongrel
        option -color brown
        option -akc   0
        option -shots 0

    }

If no __\-default__ value is specified, the option's default value will be
the empty string \(but see [THE TK OPTION DATABASE](#section19)\)\.

The Snit man page refers to options like these as "locally defined" options\.

## <a name='subsection51'></a>How can a client set options at object creation?

The normal convention is that the client may pass any number of options and
their values after the object's name at object creation\. For example, the
__::dog__ command defined in the previous answer can now be used to create
individual dogs\. Any or all of the options may be set at creation time\.

    % dog spot -breed beagle -color "mottled" -akc 1 -shots 1
    ::spot
    % dog fido -shots 1
    ::fido
    %

So __::spot__ is a pedigreed beagle; __::fido__ is a typical mutt, but
his owners evidently take care of him, because he's had his shots\.

*Note:* If the type defines a constructor, it can specify a different
object\-creation syntax\. See [CONSTRUCTORS](#section12) for more
information\.

## <a name='subsection52'></a>How can a client retrieve an option's value?

Retrieve option values using the __cget__ method:

    % spot cget -color
    mottled
    % fido cget -breed
    mongrel
    %

## <a name='subsection53'></a>How can a client set options after object creation?

Any number of options may be set at one time using the __configure__
instance method\. Suppose that closer inspection shows that ::fido is not a brown
mongrel, but rather a rare Arctic Boar Hound of a lovely dun color:

    % fido configure -color dun -breed "Arctic Boar Hound"
    % fido cget -color
    dun
    % fido cget -breed
    Arctic Boar Hound

Alternatively, the __configurelist__ method takes a list of options and
values; occasionally this is more convenient:

    % set features [list -color dun -breed "Arctic Boar Hound"]
    -color dun -breed {Arctic Boar Hound}
    % fido configurelist $features
    % fido cget -color
    dun
    % fido cget -breed
    Arctic Boar Hound
    %

In Tcl 8\.5, the __\*__ keyword can be used with __configure__ in this
case:

    % set features [list -color dun -breed "Arctic Boar Hound"]
    -color dun -breed {Arctic Boar Hound}
    % fido configure {*}$features
    % fido cget -color
    dun
    % fido cget -breed
    Arctic Boar Hound
    %

The results are the same\.

## <a name='subsection54'></a>How should an instance method access an option value?

There are two ways an instance method can set and retrieve an option's value\.
One is to use the __configure__ and __cget__ methods, as shown below\.

    % snit::type dog {
        option -weight 10

        method gainWeight {} {
            set wt [$self cget -weight]
            incr wt
            $self configure -weight $wt


        }
    }
    ::dog
    % dog fido
    ::fido
    % fido cget -weight
    10
    % fido gainWeight
    % fido cget -weight
    11
    %

Alternatively, Snit provides a built\-in array instance variable called
__options__\. The indices are the option names; the values are the option
values\. The method __gainWeight__ can thus be rewritten as follows:

    method gainWeight {} {
        incr options(-weight)

    }

As you can see, using the __options__ variable involves considerably less
typing and is the usual way to do it\. But if you use __\-configuremethod__ or
__\-cgetmethod__ \(described in the following answers\), you might wish to use
the __configure__ and __cget__ methods anyway, just so that any special
processing you've implemented is sure to get done\. Also, if the option is
delegated to a component then __configure__ and __cget__ are the only
way to access it without accessing the component directly\. See
[DELEGATION](#section16) for more information\.

## <a name='subsection55'></a>How can I make an option read\-only?

Define the option with __\-readonly yes__\.

Suppose you've got an option that determines how instances of your type are
constructed; it must be set at creation time, after which it's constant\. For
example, a dog never changes its breed; it might or might not have had its
shots, and if not can have them at a later time\. __\-breed__ should be
read\-only, but __\-shots__ should not be\.

    % snit::type dog {
        option -breed -default mongrel -readonly yes
        option -shots -default no

    }
    ::dog
    % dog fido -breed retriever
    ::fido
    % fido configure -shots yes
    % fido configure -breed terrier
    option -breed can only be set at instance creation
    %

## <a name='subsection56'></a>How can I catch accesses to an option's value?

Define a __\-cgetmethod__ for the option\.

## <a name='subsection57'></a>What is a \-cgetmethod?

A __\-cgetmethod__ is a method that's called whenever the related option's
value is queried via the __cget__ instance method\. The handler can compute
the option's value, retrieve it from a database, or do anything else you'd like
it to do\.

Here's what the default behavior would look like if written using a
__\-cgetmethod__:

    snit::type dog {
        option -color -default brown -cgetmethod GetOption

        method GetOption {option} {
            return $options($option)


        }
    }

Any instance method can be used, provided that it takes one argument, the name
of the option whose value is to be retrieved\.

## <a name='subsection58'></a>How can I catch changes to an option's value?

Define a __\-configuremethod__ for the option\.

## <a name='subsection59'></a>What is a \-configuremethod?

A __\-configuremethod__ is a method that's called whenever the related option
is given a new value via the __configure__ or __configurelist__ instance
methods\. The method can pass the value on to some other object, store it in a
database, or do anything else you'd like it to do\.

Here's what the default configuration behavior would look like if written using
a __\-configuremethod__:

    snit::type dog {
        option -color -default brown -configuremethod SetOption

        method SetOption {option value} {
            set options($option) $value


        }
    }

Any instance method can be used, provided that it takes two arguments, the name
of the option and the new value\.

Note that if your method doesn't store the value in the __options__ array,
the __options__ array won't get updated\.

1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686



1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
valid, and throw an error if it isn't\. The __\-validatemethod__, if any, is
called before the value is stored in the __options__ array; in particular,
it's called before the __\-configuremethod__, if any\.

For example, suppose an option always takes a Boolean value\. You can ensure that
the value is in fact a valid Boolean like this:

    % snit::type dog \{
        option \-shots \-default no \-validatemethod BooleanOption

        method BooleanOption \{option value\} \{
            if \{\!\[string is boolean \-strict $value\]\} \{
                error "expected a boolean value, got \\"$value\\""
            \}
        \}
    \}



    ::dog
    % dog fido
    % fido configure \-shots yes
    % fido configure \-shots NotABooleanValue
    expected a boolean value, got "NotABooleanValue"
    %

Note that the same __\-validatemethod__ can be used to validate any number of
boolean options\.

Any method can be a __\-validatemethod__ provided that it takes two







|
|

|
|
|
<
<
<
>
>
>


|
|







1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683



1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
valid, and throw an error if it isn't\. The __\-validatemethod__, if any, is
called before the value is stored in the __options__ array; in particular,
it's called before the __\-configuremethod__, if any\.

For example, suppose an option always takes a Boolean value\. You can ensure that
the value is in fact a valid Boolean like this:

    % snit::type dog {
        option -shots -default no -validatemethod BooleanOption

        method BooleanOption {option value} {
            if {![string is boolean -strict $value]} {
                error "expected a boolean value, got \"$value\""



            }
        }
    }
    ::dog
    % dog fido
    % fido configure -shots yes
    % fido configure -shots NotABooleanValue
    expected a boolean value, got "NotABooleanValue"
    %

Note that the same __\-validatemethod__ can be used to validate any number of
boolean options\.

Any method can be a __\-validatemethod__ provided that it takes two
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718

1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734


1735
1736
1737
1738
1739
1740
1741

## <a name='subsection63'></a>How is a scalar type variable defined?

Scalar type variables are defined in the type definition using the
__typevariable__ statement\. You can simply name it, or you can initialize it
with a value:

    snit::type mytype \{
        \# Define variable "greeting" and initialize it with "Howdy\!"
        typevariable greeting "Howdy\!"
    \}


Every object of type __mytype__ now has access to a single variable called
__greeting__\.

## <a name='subsection64'></a>How is an array\-valued type variable defined?

Array\-valued type variables are also defined using the __typevariable__
command; to initialize them, include the __\-array__ option:

    snit::type mytype \{
        \# Define typearray variable "greetings"
        typevariable greetings \-array \{
            formal "Good Evening"
            casual "Howdy\!"
        \}
    \}



## <a name='subsection65'></a>What happens if I don't initialize a type variable?

Variables do not really exist until they are given values\. If you do not
initialize a variable when you define it, then you must be sure to assign a
value to it \(in the type constructor, say\) before you reference it\.








|
|
|
<
>









|
|
|

|
<
<
>
>







1708
1709
1710
1711
1712
1713
1714
1715
1716
1717

1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732


1733
1734
1735
1736
1737
1738
1739
1740
1741

## <a name='subsection63'></a>How is a scalar type variable defined?

Scalar type variables are defined in the type definition using the
__typevariable__ statement\. You can simply name it, or you can initialize it
with a value:

    snit::type mytype {
        # Define variable "greeting" and initialize it with "Howdy!"
        typevariable greeting "Howdy!"

    }

Every object of type __mytype__ now has access to a single variable called
__greeting__\.

## <a name='subsection64'></a>How is an array\-valued type variable defined?

Array\-valued type variables are also defined using the __typevariable__
command; to initialize them, include the __\-array__ option:

    snit::type mytype {
        # Define typearray variable "greetings"
        typevariable greetings -array {
            formal "Good Evening"
            casual "Howdy!"


        }
    }

## <a name='subsection65'></a>What happens if I don't initialize a type variable?

Variables do not really exist until they are given values\. If you do not
initialize a variable when you define it, then you must be sure to assign a
value to it \(in the type constructor, say\) before you reference it\.

1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781


1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794

1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818


1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845

1846

1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857

If you naively pass a type variable name to the label widget, you'll be confused
by the result; Tk will assume that the name names a global variable\. Instead,
you need to provide a fully\-qualified variable name\. From within an instance
method or a constructor, you can fully qualify the type variable's name using
the __mytypevar__ command:

    snit::widget mywidget \{
        typevariable labeltext ""

        constructor \{args\} \{
            \# \.\.\.

            label $win\.label \-textvariable \[mytypevar labeltext\]

            \# \.\.\.
        \}
    \}



## <a name='subsection69'></a>How do I make a type variable public?

There are two ways to do this\. The preferred way is to write a pair of [TYPE
METHODS](#section9) to set and query the type variable's value\.

Type variables are stored in the type's namespace, which has the same name as
the type itself\. Thus, you can also publicize the type variable's name in your
documentation so that clients can access it directly\. For example,

    snit::type mytype \{
        typevariable myvariable
    \}


    set ::mytype::myvariable "New Value"

# <a name='section9'></a>TYPE METHODS

## <a name='subsection70'></a>What is a type method?

A type method is a procedure associated with the type itself rather than with
any specific instance of the type, and called as a subcommand of the type
command\.

## <a name='subsection71'></a>How do I define a type method?

Type methods are defined in the type definition using the __typemethod__
statement:

    snit::type dog \{
        \# List of pedigreed dogs
        typevariable pedigreed

        typemethod pedigreedDogs \{\} \{
            return $pedigreed
        \}
    \}



Suppose the __dog__ type maintains a list of the names of the dogs that have
pedigrees\. The __pedigreedDogs__ type method returns this list\.

The __typemethod__ statement looks just like a normal Tcl
__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__, except that it appears in a
__snit::type__ definition\. Notice that every type method gets an implicit
argument called __type__, which contains the fully\-qualified type name\.

## <a name='subsection72'></a>How does a client call a type method?

The type method name becomes a subcommand of the type's command\. For example,
assuming that the constructor adds each pedigreed dog to the list of
__pedigreedDogs__,

    snit::type dog \{
        option \-pedigreed 0

        \# List of pedigreed dogs
        typevariable pedigreed

        typemethod pedigreedDogs \{\} \{
            return $pedigreed
        \}

        \# \.\.\.
    \}



    dog spot \-pedigreed 1
    dog fido

    foreach dog \[dog pedigreedDogs\] \{ \.\.\. \}

## <a name='subsection73'></a>Are there any limitations on type method names?

Not really, so long as you avoid the standard type method names: __create__,
__destroy__, and __info__\.

## <a name='subsection74'></a>How do I make a type method private?







|


|
|

|

|
<
<
>
>










|

<
>
















|
|


|

<
<
>
>















|
|

|


|

<
|
|
<
>
|
>
|


|







1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779


1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793

1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816


1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841

1842
1843

1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857

If you naively pass a type variable name to the label widget, you'll be confused
by the result; Tk will assume that the name names a global variable\. Instead,
you need to provide a fully\-qualified variable name\. From within an instance
method or a constructor, you can fully qualify the type variable's name using
the __mytypevar__ command:

    snit::widget mywidget {
        typevariable labeltext ""

        constructor {args} {
            # ...

            label $win.label -textvariable [mytypevar labeltext]

            # ...


        }
    }

## <a name='subsection69'></a>How do I make a type variable public?

There are two ways to do this\. The preferred way is to write a pair of [TYPE
METHODS](#section9) to set and query the type variable's value\.

Type variables are stored in the type's namespace, which has the same name as
the type itself\. Thus, you can also publicize the type variable's name in your
documentation so that clients can access it directly\. For example,

    snit::type mytype {
        typevariable myvariable

    }

    set ::mytype::myvariable "New Value"

# <a name='section9'></a>TYPE METHODS

## <a name='subsection70'></a>What is a type method?

A type method is a procedure associated with the type itself rather than with
any specific instance of the type, and called as a subcommand of the type
command\.

## <a name='subsection71'></a>How do I define a type method?

Type methods are defined in the type definition using the __typemethod__
statement:

    snit::type dog {
        # List of pedigreed dogs
        typevariable pedigreed

        typemethod pedigreedDogs {} {
            return $pedigreed


        }
    }

Suppose the __dog__ type maintains a list of the names of the dogs that have
pedigrees\. The __pedigreedDogs__ type method returns this list\.

The __typemethod__ statement looks just like a normal Tcl
__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__, except that it appears in a
__snit::type__ definition\. Notice that every type method gets an implicit
argument called __type__, which contains the fully\-qualified type name\.

## <a name='subsection72'></a>How does a client call a type method?

The type method name becomes a subcommand of the type's command\. For example,
assuming that the constructor adds each pedigreed dog to the list of
__pedigreedDogs__,

    snit::type dog {
        option -pedigreed 0

        # List of pedigreed dogs
        typevariable pedigreed

        typemethod pedigreedDogs {} {
            return $pedigreed

        }


        # ...
    }

    dog spot -pedigreed 1
    dog fido

    foreach dog [dog pedigreedDogs] { ... }

## <a name='subsection73'></a>Are there any limitations on type method names?

Not really, so long as you avoid the standard type method names: __create__,
__destroy__, and __info__\.

## <a name='subsection74'></a>How do I make a type method private?
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892


1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
defined for [INSTANCE METHODS](#section5)\.

## <a name='subsection76'></a>How does an instance or type method call a type method?

If an instance or type method needs to call a type method, it should use
__$type__ to do so:

    snit::type dog \{

        typemethod pedigreedDogs \{\} \{ \.\.\. \}

        typemethod printPedigrees \{\} \{
            foreach obj \[$type pedigreedDogs\] \{ \.\.\. \}
        \}
    \}



## <a name='subsection77'></a>How do I pass a type method as a callback?

It's common in Tcl to pass a snippet of code to another object, for it to call
later\. Because types cannot be renamed, you can just use the type name, or, if
the callback is registered from within a type method, __type__\. For example,
suppose we want to print a list of pedigreed dogs when a Tk button is pushed:

    button \.btn \-text "Pedigrees" \-command \[list dog printPedigrees\]
    pack \.btn

Alternatively, from a method or type method you can use the __mytypemethod__
command, just as you would use __mymethod__ to define a callback command for
[INSTANCE METHODS](#section5)\.

## <a name='subsection78'></a>Can type methods be hierarchical?








|

|

|
|
<
<
>
>








|
|







1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890


1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
defined for [INSTANCE METHODS](#section5)\.

## <a name='subsection76'></a>How does an instance or type method call a type method?

If an instance or type method needs to call a type method, it should use
__$type__ to do so:

    snit::type dog {

        typemethod pedigreedDogs {} { ... }

        typemethod printPedigrees {} {
            foreach obj [$type pedigreedDogs] { ... }


        }
    }

## <a name='subsection77'></a>How do I pass a type method as a callback?

It's common in Tcl to pass a snippet of code to another object, for it to call
later\. Because types cannot be renamed, you can just use the type name, or, if
the callback is registered from within a type method, __type__\. For example,
suppose we want to print a list of pedigreed dogs when a Tk button is pushed:

    button .btn -text "Pedigrees" -command [list dog printPedigrees]
    pack .btn

Alternatively, from a method or type method you can use the __mytypemethod__
command, just as you would use __mymethod__ to define a callback command for
[INSTANCE METHODS](#section5)\.

## <a name='subsection78'></a>Can type methods be hierarchical?

1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933

1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964


1965
1966
1967
1968
1969
1970
1971
isn't related to any particular instance\.

## <a name='subsection80'></a>How do I define a proc?

Procs are defined by including a __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__
statement in the type definition:

    snit::type mytype \{
        \# Pops and returns the first item from the list stored in the
        \# listvar, updating the listvar
       proc pop \{listvar\} \{ \.\.\. \}

       \# \.\.\.
    \}


## <a name='subsection81'></a>Are there any limitations on proc names?

Any name can be used, so long as it does not begin with __Snit\___; names
beginning with __Snit\___ are reserved for Snit's own use\. However, the wise
programmer will avoid __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ names
\(__[set](\.\./\.\./\.\./\.\./index\.md\#set)__,
__[list](\.\./\.\./\.\./\.\./index\.md\#list)__, __if__, etc\.\) that would
shadow standard Tcl command names\.

__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ names, being private, should begin
with a capital letter according to convention; however, as there are typically
no public __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__s in the type's namespace
it doesn't matter much either way\.

## <a name='subsection82'></a>How does a method call a proc?

Just like it calls any Tcl command\. For example,

    snit::type mytype \{
        \# Pops and returns the first item from the list stored in the
        \# listvar, updating the listvar
        proc pop \{listvar\} \{ \.\.\. \}

        variable requestQueue \{\}

        \# Get one request from the queue and process it\.
        method processRequest \{\} \{
            set req \[pop requestQueue\]
        \}
    \}



## <a name='subsection83'></a>How can I pass a proc to another object as a callback?

The __myproc__ command returns a callback command for the
__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__, just as __mymethod__ does for
a method\.








|
|
|
|

|
<
>



















|
|
|
|

|

|
|
|
<
<
>
>







1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932

1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962


1963
1964
1965
1966
1967
1968
1969
1970
1971
isn't related to any particular instance\.

## <a name='subsection80'></a>How do I define a proc?

Procs are defined by including a __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__
statement in the type definition:

    snit::type mytype {
        # Pops and returns the first item from the list stored in the
        # listvar, updating the listvar
       proc pop {listvar} { ... }

       # ...

    }

## <a name='subsection81'></a>Are there any limitations on proc names?

Any name can be used, so long as it does not begin with __Snit\___; names
beginning with __Snit\___ are reserved for Snit's own use\. However, the wise
programmer will avoid __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ names
\(__[set](\.\./\.\./\.\./\.\./index\.md\#set)__,
__[list](\.\./\.\./\.\./\.\./index\.md\#list)__, __if__, etc\.\) that would
shadow standard Tcl command names\.

__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ names, being private, should begin
with a capital letter according to convention; however, as there are typically
no public __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__s in the type's namespace
it doesn't matter much either way\.

## <a name='subsection82'></a>How does a method call a proc?

Just like it calls any Tcl command\. For example,

    snit::type mytype {
        # Pops and returns the first item from the list stored in the
        # listvar, updating the listvar
        proc pop {listvar} { ... }

        variable requestQueue {}

        # Get one request from the queue and process it.
        method processRequest {} {
            set req [pop requestQueue]


        }
    }

## <a name='subsection83'></a>How can I pass a proc to another object as a callback?

The __myproc__ command returns a callback command for the
__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__, just as __mymethod__ does for
a method\.

1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995


1996
1997
1998
1999
2000
2001
2002
## <a name='subsection85'></a>How do I define a type constructor?

A type constructor is defined by using the __typeconstructor__ statement in
the type definition\. For example, suppose the type uses an array\-valued type
variable as a look\-up table, and the values in the array have to be computed at
start\-up\.

    % snit::type mytype \{
        typevariable lookupTable

        typeconstructor \{
            array set lookupTable \{key value\.\.\.\}
        \}
    \}



# <a name='section12'></a>CONSTRUCTORS

## <a name='subsection86'></a>What is a constructor?

In object\-oriented programming, an object's constructor is responsible for
initializing the object completely at creation time\. The constructor receives







|


|
|
<
<
>
>







1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993


1994
1995
1996
1997
1998
1999
2000
2001
2002
## <a name='subsection85'></a>How do I define a type constructor?

A type constructor is defined by using the __typeconstructor__ statement in
the type definition\. For example, suppose the type uses an array\-valued type
variable as a look\-up table, and the values in the array have to be computed at
start\-up\.

    % snit::type mytype {
        typevariable lookupTable

        typeconstructor {
            array set lookupTable {key value...}


        }
    }

# <a name='section12'></a>CONSTRUCTORS

## <a name='subsection86'></a>What is a constructor?

In object\-oriented programming, an object's constructor is responsible for
initializing the object completely at creation time\. The constructor receives
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030


2031
2032
2033
2034


2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053


2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078

2079
2080

2081
2082
2083
2084
2085
2086
2087
2088
2089

A constructor is defined by using the __constructor__ statement in the type
definition\. Suppose that it's desired to keep a list of all pedigreed dogs\. The
list can be maintained in a type variable and retrieved by a type method\.
Whenever a dog is created, it can add itself to the list\-\-provided that it's
registered with the American Kennel Club\.

    % snit::type dog \{
        option \-akc 0

        typevariable akcList \{\}

        constructor \{args\} \{
            $self configurelist $args

            if \{$options\(\-akc\)\} \{
                lappend akcList $self
            \}
        \}



        typemethod akclist \{\} \{
            return $akcList
        \}
    \}


    ::dog
    % dog spot \-akc 1
    ::spot
    % dog fido
    ::fido
    % dog akclist
    ::spot
    %

## <a name='subsection88'></a>What does the default constructor do?

If you don't provide a constructor explicitly, you get the default constructor,
which is identical to the explicitly\-defined constructor shown here:

    snit::type dog \{
        constructor \{args\} \{
            $self configurelist $args
        \}
    \}



When the constructor is called, __args__ will be set to the list of
arguments that follow the object's name\. The constructor is allowed to interpret
this list any way it chooses; the normal convention is to assume that it's a
list of option names and values, as shown in the example above\. If you simply
want to save the option values, you should use the __configurelist__ method,
as shown\.

## <a name='subsection89'></a>Can I choose a different set of arguments for the constructor?

Yes, you can\. For example, suppose we wanted to be sure that the breed was
explicitly stated for every dog at creation time, and couldn't be changed
thereafter\. One way to do that is as follows:

    % snit::type dog \{
        variable breed

        option \-color brown
        option \-akc 0

        constructor \{theBreed args\} \{
            set breed $theBreed
            $self configurelist $args
        \}


        method breed \{\} \{ return $breed \}
    \}

    ::dog
    % dog spot dalmatian \-color spotted \-akc 1
    ::spot
    % spot breed
    dalmatian

The drawback is that this syntax is non\-standard, and may limit the
compatibility of your new type with other people's code\. For example, Snit
assumes that it can create [COMPONENTS](#section14) using the standard







|
|

|

|


|

<
<
|
>
>
|

<
<
>
>

|












|
|

<
<
>
>














|


|
|

|


<
|
>
|
<
>

|







2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027


2028
2029
2030
2031
2032


2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051


2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076

2077
2078
2079

2080
2081
2082
2083
2084
2085
2086
2087
2088
2089

A constructor is defined by using the __constructor__ statement in the type
definition\. Suppose that it's desired to keep a list of all pedigreed dogs\. The
list can be maintained in a type variable and retrieved by a type method\.
Whenever a dog is created, it can add itself to the list\-\-provided that it's
registered with the American Kennel Club\.

    % snit::type dog {
        option -akc 0

        typevariable akcList {}

        constructor {args} {
            $self configurelist $args

            if {$options(-akc)} {
                lappend akcList $self


            }
        }

        typemethod akclist {} {
            return $akcList


        }
    }
    ::dog
    % dog spot -akc 1
    ::spot
    % dog fido
    ::fido
    % dog akclist
    ::spot
    %

## <a name='subsection88'></a>What does the default constructor do?

If you don't provide a constructor explicitly, you get the default constructor,
which is identical to the explicitly\-defined constructor shown here:

    snit::type dog {
        constructor {args} {
            $self configurelist $args


        }
    }

When the constructor is called, __args__ will be set to the list of
arguments that follow the object's name\. The constructor is allowed to interpret
this list any way it chooses; the normal convention is to assume that it's a
list of option names and values, as shown in the example above\. If you simply
want to save the option values, you should use the __configurelist__ method,
as shown\.

## <a name='subsection89'></a>Can I choose a different set of arguments for the constructor?

Yes, you can\. For example, suppose we wanted to be sure that the breed was
explicitly stated for every dog at creation time, and couldn't be changed
thereafter\. One way to do that is as follows:

    % snit::type dog {
        variable breed

        option -color brown
        option -akc 0

        constructor {theBreed args} {
            set breed $theBreed
            $self configurelist $args

        }

        method breed {} { return $breed }

    }
    ::dog
    % dog spot dalmatian -color spotted -akc 1
    ::spot
    % spot breed
    dalmatian

The drawback is that this syntax is non\-standard, and may limit the
compatibility of your new type with other people's code\. For example, Snit
assumes that it can create [COMPONENTS](#section14) using the standard
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135


2136
2137
2138
2139
2140
2141
2142
2143


2144
2145
2146
2147


2148
2149
2150
2151
2152
2153
2154

Destructors are defined by using the __destructor__ statement in the type
definition\.

Suppose we're maintaining a list of pedigreed dogs; then we'll want to remove
dogs from it when they are destroyed\.

    snit::type dog \{
        option \-akc 0

        typevariable akcList \{\}

        constructor \{args\} \{
            $self configurelist $args

            if \{$options\(\-akc\)\} \{
                lappend akcList $self
            \}
        \}



        destructor \{
            set ndx \[lsearch $akcList $self\]

            if \{$ndx \!= \-1\} \{
                set akcList \[lreplace $akcList $ndx $ndx\]
            \}
        \}



        typemethod akclist \{\} \{
            return $akcList
        \}
    \}



## <a name='subsection94'></a>Are there any limitations on destructor arguments?

Yes; a destructor has no explicit arguments\.

## <a name='subsection95'></a>What implicit arguments are passed to the destructor?








|
|

|

|


|

<
<
|
>
>
|
|

|
|
<
<
|
>
>
|

<
<
>
>







2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132


2133
2134
2135
2136
2137
2138
2139
2140


2141
2142
2143
2144
2145


2146
2147
2148
2149
2150
2151
2152
2153
2154

Destructors are defined by using the __destructor__ statement in the type
definition\.

Suppose we're maintaining a list of pedigreed dogs; then we'll want to remove
dogs from it when they are destroyed\.

    snit::type dog {
        option -akc 0

        typevariable akcList {}

        constructor {args} {
            $self configurelist $args

            if {$options(-akc)} {
                lappend akcList $self


            }
        }

        destructor {
            set ndx [lsearch $akcList $self]

            if {$ndx != -1} {
                set akcList [lreplace $akcList $ndx $ndx]


            }
        }

        typemethod akclist {} {
            return $akcList


        }
    }

## <a name='subsection94'></a>Are there any limitations on destructor arguments?

Yes; a destructor has no explicit arguments\.

## <a name='subsection95'></a>What implicit arguments are passed to the destructor?

2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195

2196
2197
2198
2199


2200
2201
2202
2203
2204
2205
2206

For example, a __dog__ might create a __tail__ component; the component
will need to be destroyed\. But suppose there's an error while processing the
creation options\-\-the destructor will be called, and there will be no
__tail__ to destroy\. The simplest solution is generally to catch and ignore
any errors while destroying components\.

    snit::type dog \{
        component tail

        constructor \{args\} \{
            $self configurelist $args

            set tail \[tail %AUTO%\]
        \}


        destructor \{
            catch \{$tail destroy\}
        \}
    \}



# <a name='section14'></a>COMPONENTS

## <a name='subsection98'></a>What is a component?

Often an object will create and manage a number of other objects\. A Snit
megawidget, for example, will often create a number of Tk widgets\. These objects







|


|


|
<
|
>
|
|
<
<
>
>







2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193

2194
2195
2196
2197


2198
2199
2200
2201
2202
2203
2204
2205
2206

For example, a __dog__ might create a __tail__ component; the component
will need to be destroyed\. But suppose there's an error while processing the
creation options\-\-the destructor will be called, and there will be no
__tail__ to destroy\. The simplest solution is generally to catch and ignore
any errors while destroying components\.

    snit::type dog {
        component tail

        constructor {args} {
            $self configurelist $args

            set tail [tail %AUTO%]

        }

        destructor {
            catch {$tail destroy}


        }
    }

# <a name='section14'></a>COMPONENTS

## <a name='subsection98'></a>What is a component?

Often an object will create and manage a number of other objects\. A Snit
megawidget, for example, will often create a number of Tk widgets\. These objects
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234

2235
2236
2237
2238


2239
2240
2241
2242
2243
2244
2245
__component__ statement\. The __component__ statement declares an
*instance variable* which is used to store the component's command name when
the component is created\.

For example, suppose your __dog__ object creates a __tail__ object \(the
better to wag with, no doubt\):

    snit::type dog \{
        component mytail

        constructor \{args\} \{
            \# Create and save the component's command
            set mytail \[tail %AUTO% \-partof $self\]
            $self configurelist $args
        \}


        method wag \{\} \{
            $mytail wag
        \}
    \}



As shown here, it doesn't matter what the __tail__ object's real name is;
the __dog__ object refers to it by its component name\.

The above example shows one way to delegate the __wag__ method to the
__mytail__ component; see [DELEGATION](#section16) for an easier way\.








|


|
|
|

<
|
>
|

<
<
>
>







2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232

2233
2234
2235
2236


2237
2238
2239
2240
2241
2242
2243
2244
2245
__component__ statement\. The __component__ statement declares an
*instance variable* which is used to store the component's command name when
the component is created\.

For example, suppose your __dog__ object creates a __tail__ object \(the
better to wag with, no doubt\):

    snit::type dog {
        component mytail

        constructor {args} {
            # Create and save the component's command
            set mytail [tail %AUTO% -partof $self]
            $self configurelist $args

        }

        method wag {} {
            $mytail wag


        }
    }

As shown here, it doesn't matter what the __tail__ object's real name is;
the __dog__ object refers to it by its component name\.

The above example shows one way to delegate the __wag__ method to the
__mytail__ component; see [DELEGATION](#section16) for an easier way\.

2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285

2286
2287
2288

2289
2290
2291
2292
2293
2294
2295
2296


2297
2298
2299
2300
2301
2302
2303
2304
2305

2306
2307
2308
2309

2310
2311
2312
2313


2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334


2335
2336
2337
2338
2339
2340
2341
controlled by the __snit::type__ or __snit::widget__\.

As stated above, a component is an object to which our object can delegate
methods or options\. Under this definition, our object will usually create its
component objects, but not necessarily\. Consider the following: a dog object has
a tail component; but tail knows that it's part of the dog:

    snit::type dog \{
        component mytail

        constructor \{args\} \{
            set mytail \[tail %AUTO% \-partof $self\]
            $self configurelist $args
        \}


        destructor \{
            catch \{$mytail destroy\}
        \}


        delegate method wagtail to mytail as wag

        method bark \{\} \{
            return "$self barked\."
        \}
    \}



     snit::type tail \{
         component mydog
         option \-partof \-readonly yes

         constructor \{args\} \{
             $self configurelist $args
             set mydog $options\(\-partof\)
         \}


         method wag \{\} \{
             return "Wag, wag\."
         \}


         method pull \{\} \{
             $mydog bark
         \}
     \}



Thus, if you ask a dog to wag its tail, it tells its tail to wag; and if you
pull the dog's tail, the tail tells the dog to bark\. In this scenario, the tail
is a component of the dog, and the dog is a component of the tail, but the dog
owns the tail and not the other way around\.

## <a name='subsection103'></a>What does the install command do?

The __install__ command creates an owned component using a specified
command, and assigns the result to the component's instance variable\. For
example:

    snit::type dog \{
        component mytail

        constructor \{args\} \{
            \# set mytail \[tail %AUTO% \-partof $self\]
            install mytail using tail %AUTO% \-partof $self
            $self configurelist $args
        \}
    \}



In a __snit::type__'s code, the __install__ command shown above is
equivalent to the __set mytail__ command that's commented out\. In a
__snit::widget__'s or __snit::widgetadaptor__'s, code, however, the
__install__ command also queries [THE TK OPTION DATABASE](#section19)
and initializes the new component's options accordingly\. For consistency, it's a
good idea to get in the habit of using __install__ for all owned components\.







|


|
|

<
|
>
|
|
<
>



|
|
<
<
|
>
>
|

|

|

|
<
|
>
|
|
<
|
>
|

<
<
>
>












|


|
|
|

<
<
>
>







2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283

2284
2285
2286
2287

2288
2289
2290
2291
2292
2293


2294
2295
2296
2297
2298
2299
2300
2301
2302
2303

2304
2305
2306
2307

2308
2309
2310
2311


2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332


2333
2334
2335
2336
2337
2338
2339
2340
2341
controlled by the __snit::type__ or __snit::widget__\.

As stated above, a component is an object to which our object can delegate
methods or options\. Under this definition, our object will usually create its
component objects, but not necessarily\. Consider the following: a dog object has
a tail component; but tail knows that it's part of the dog:

    snit::type dog {
        component mytail

        constructor {args} {
            set mytail [tail %AUTO% -partof $self]
            $self configurelist $args

        }

        destructor {
            catch {$mytail destroy}

        }

        delegate method wagtail to mytail as wag

        method bark {} {
            return "$self barked."


        }
    }

     snit::type tail {
         component mydog
         option -partof -readonly yes

         constructor {args} {
             $self configurelist $args
             set mydog $options(-partof)

         }

         method wag {} {
             return "Wag, wag."

         }

         method pull {} {
             $mydog bark


         }
     }

Thus, if you ask a dog to wag its tail, it tells its tail to wag; and if you
pull the dog's tail, the tail tells the dog to bark\. In this scenario, the tail
is a component of the dog, and the dog is a component of the tail, but the dog
owns the tail and not the other way around\.

## <a name='subsection103'></a>What does the install command do?

The __install__ command creates an owned component using a specified
command, and assigns the result to the component's instance variable\. For
example:

    snit::type dog {
        component mytail

        constructor {args} {
            # set mytail [tail %AUTO% -partof $self]
            install mytail using tail %AUTO% -partof $self
            $self configurelist $args


        }
    }

In a __snit::type__'s code, the __install__ command shown above is
equivalent to the __set mytail__ command that's commented out\. In a
__snit::widget__'s or __snit::widgetadaptor__'s, code, however, the
__install__ command also queries [THE TK OPTION DATABASE](#section19)
and initializes the new component's options accordingly\. For consistency, it's a
good idea to get in the habit of using __install__ for all owned components\.
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371


2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
command names, i\.e\., names which include the full namespace of the command\. Note
that Snit always creates objects with fully qualified names\.

Next, the object names of components and owned by your object must be unique\.
This is no problem for widget components, since widget names are always unique;
but consider the following code:

    snit::type tail \{ \.\.\. \}

    snit::type dog \{
        delegate method wag to mytail

        constructor \{\} \{
            install mytail using tail mytail
        \}
    \}



This code uses the component name, __mytail__, as the component object name\.
This is not good, and here's why: Snit instance code executes in the Snit type's
namespace\. In this case, the __mytail__ component is created in the
__::dog::__ namespace, and will thus have the name __::dog::mytail__\.

Now, suppose you create two dogs\. Both dogs will attempt to create a tail called
__::dog::mytail__\. The first will succeed, and the second will fail, since
Snit won't let you create an object if its name is already a command\. Here are
two ways to avoid this situation:

First, if the component type is a __snit::type__ you can specify
__%AUTO%__ as its name, and be guaranteed to get a unique name\. This is the
safest thing to do:

    install mytail using tail %AUTO%

If the component type isn't a __snit::type__ you can create the component in
the object's instance namespace:

    install mytail using tail $\{selfns\}::mytail

Make sure you pick a unique name within the instance namespace\.

## <a name='subsection106'></a>Must I destroy the components I own?

That depends\. When a parent widget is destroyed, all child widgets are destroyed
automatically\. Thus, if your object is a __snit::widget__ or







|

|


|

<
<
>
>




















|







2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369


2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
command names, i\.e\., names which include the full namespace of the command\. Note
that Snit always creates objects with fully qualified names\.

Next, the object names of components and owned by your object must be unique\.
This is no problem for widget components, since widget names are always unique;
but consider the following code:

    snit::type tail { ... }

    snit::type dog {
        delegate method wag to mytail

        constructor {} {
            install mytail using tail mytail


        }
    }

This code uses the component name, __mytail__, as the component object name\.
This is not good, and here's why: Snit instance code executes in the Snit type's
namespace\. In this case, the __mytail__ component is created in the
__::dog::__ namespace, and will thus have the name __::dog::mytail__\.

Now, suppose you create two dogs\. Both dogs will attempt to create a tail called
__::dog::mytail__\. The first will succeed, and the second will fail, since
Snit won't let you create an object if its name is already a command\. Here are
two ways to avoid this situation:

First, if the component type is a __snit::type__ you can specify
__%AUTO%__ as its name, and be guaranteed to get a unique name\. This is the
safest thing to do:

    install mytail using tail %AUTO%

If the component type isn't a __snit::type__ you can create the component in
the object's instance namespace:

    install mytail using tail ${selfns}::mytail

Make sure you pick a unique name within the instance namespace\.

## <a name='subsection106'></a>Must I destroy the components I own?

That depends\. When a parent widget is destroyed, all child widgets are destroyed
automatically\. Thus, if your object is a __snit::widget__ or
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436


2437
2438
2439
2440
2441
2442
2443
2444
2445
__\-public__ option\. The value of this option is the name of a method which
will be delegated to your component's object command\.

For example, supposed you've written a combobox megawidget which owns a listbox
widget, and you want to make the listbox's entire interface public\. You can do
it like this:

    snit::widget combobox \{
         component listbox \-public listbox

         constructor \{args\} \{
             install listbox using listbox $win\.listbox \.\.\.\.
         \}
    \}



    combobox \.mycombo
    \.mycombo listbox configure \-width 30

Your comobox widget, __\.mycombo__, now has a __listbox__ method which
has all of the same subcommands as the listbox widget itself\. Thus, the above
code sets the listbox component's width to 30\.

Usually you'll let the method name be the same as the component name; however,
you can name it anything you like\.







|
|

|
|
<
<
|
>
>
|
|







2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433


2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
__\-public__ option\. The value of this option is the name of a method which
will be delegated to your component's object command\.

For example, supposed you've written a combobox megawidget which owns a listbox
widget, and you want to make the listbox's entire interface public\. You can do
it like this:

    snit::widget combobox {
         component listbox -public listbox

         constructor {args} {
             install listbox using listbox $win.listbox ....


         }
    }

    combobox .mycombo
    .mycombo listbox configure -width 30

Your comobox widget, __\.mycombo__, now has a __listbox__ method which
has all of the same subcommands as the listbox widget itself\. Thus, the above
code sets the listbox component's width to 30\.

Usually you'll let the method name be the same as the component name; however,
you can name it anything you like\.
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477

2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496


2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521

2522
2523
2524
2525

2526
2527
2528
2529

2530
2531
2532
2533
2534
2535

2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562


2563
2564
2565
2566

2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598


2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611

2612
2613
2614
2615

2616
2617

2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637

2638
2639
2640
2641
2642
2643
2644
same options \(__\-inherit__ and __\-public__\) as the __component__
statement does, and defines a type variable to hold the type component's object
command\.

Suppose in your model you've got many dogs, but only one veterinarian\. You might
make the veterinarian a type component\.

    snit::type veterinarian \{ \.\.\. \}

    snit::type dog \{
        typecomponent vet

        \# \.\.\.
    \}


## <a name='subsection111'></a>How do I install a type component?

Just use the __[set](\.\./\.\./\.\./\.\./index\.md\#set)__ command to assign the
component's object command to the type component\. Because types \(even
__snit::widget__ types\) are not widgets, and do not have options anyway, the
extra features of the __install__ command are not needed\.

You'll usually install type components in the type constructor, as shown here:

    snit::type veterinarian \{ \.\.\. \}

    snit::type dog \{
        typecomponent vet

        typeconstructor \{
            set vet \[veterinarian %AUTO%\]
        \}
    \}



## <a name='subsection112'></a>Are there any limitations on type component names?

Yes, the same as on [INSTANCE VARIABLES](#section6), [TYPE
VARIABLES](#section8), and normal [COMPONENTS](#section14)\.

# <a name='section16'></a>DELEGATION

## <a name='subsection113'></a>What is delegation?

Delegation, simply put, is when you pass a task you've been given to one of your
assistants\. \(You do have assistants, don't you?\) Snit objects can do the same
thing\. The following example shows one way in which the __dog__ object can
delegate its __wag__ method and its __\-taillength__ option to its
__tail__ component\.

    snit::type dog \{
        variable mytail

        option \-taillength \-configuremethod SetTailOption \-cgetmethod GetTailOption

        method SetTailOption \{option value\} \{
             $mytail configure $option $value
        \}


        method GetTailOption \{option\} \{
             $mytail cget $option
        \}


        method wag \{\} \{
            $mytail wag
        \}


        constructor \{args\} \{
            install mytail using tail %AUTO% \-partof $self
            $self configurelist $args
        \}

    \}


This is the hard way to do it, by it demonstrates what delegation is all about\.
See the following answers for the easy way to do it\.

Note that the constructor calls the __configurelist__ method
__[after](\.\./\.\./\.\./\.\./index\.md\#after)__ it creates its __tail__;
otherwise, if __\-taillength__ appeared in the list of __args__ we'd get
an error\.

## <a name='subsection114'></a>How can I delegate a method to a component object?

Delegation occurs frequently enough that Snit makes it easy\. Any method can be
delegated to any component or type component by placing a single
__delegate__ statement in the type definition\. \(See
[COMPONENTS](#section14) and [TYPE COMPONENTS](#section15) for more
information about component names\.\)

For example, here's a much better way to delegate the __dog__ object's
__wag__ method:

    % snit::type dog \{
        delegate method wag to mytail

        constructor \{\} \{
            install mytail using tail %AUTO%
        \}
    \}


    ::dog
    % snit::type tail \{
        method wag \{\} \{ return "Wag, wag, wag\."\}
    \}

    ::tail
    % dog spot
    ::spot
    % spot wag
    Wag, wag, wag\.

This code has the same effect as the code shown under the previous question:
when a __dog__'s __wag__ method is called, the call and its arguments
are passed along automatically to the __tail__ object\.

Note that when a component is mentioned in a __delegate__ statement, the
component's instance variable is defined implicitly\. However, it's still good
practice to declare it explicitly using the __component__ statement\.

Note also that you can define a method name using the
__[method](\.\./\.\./\.\./\.\./index\.md\#method)__ statement, or you can define
it using __delegate__; you can't do both\.

## <a name='subsection115'></a>Can I delegate to a method with a different name?

Suppose you wanted to delegate the __dog__'s __wagtail__ method to the
__tail__'s __wag__ method\. After all you wag the tail, not the dog\. It's
easily done:

    snit::type dog \{
        delegate method wagtail to mytail as wag

        constructor \{args\} \{
            install mytail using tail %AUTO% \-partof $self
            $self configurelist $args
        \}
    \}



## <a name='subsection116'></a>Can I delegate to a method with additional arguments?

Suppose the __tail__'s __wag__ method takes as an argument the number of
times the tail should be wagged\. You want to delegate the __dog__'s
__wagtail__ method to the __tail__'s __wag__ method, specifying that
the tail should be wagged exactly three times\. This is easily done, too:

    snit::type dog \{
        delegate method wagtail to mytail as \{wag 3\}
        \# \.\.\.
    \}


    snit::type tail \{
        method wag \{count\} \{
            return \[string repeat "Wag " $count\]
        \}

        \# \.\.\.
    \}


## <a name='subsection117'></a>Can I delegate a method to something other than an object?

Normal method delegation assumes that you're delegating a method \(a subcommand
of an object command\) to a method of another object \(a subcommand of a different
object command\)\. But not all Tcl objects follow Tk conventions, and not
everything you'd to which you'd like to delegate a method is necessary an
object\. Consequently, Snit makes it easy to delegate a method to pretty much
anything you like using the __delegate__ statement's __using__ clause\.

Suppose your dog simulation stores dogs in a database, each dog as a single
record\. The database API you're using provides a number of commands to manage
records; each takes the record ID \(a string you choose\) as its first argument\.
For example, __saverec__ saves a record\. If you let the record ID be the
name of the dog object, you can delegate the dog's __save__ method to the
__saverec__ command as follows:

    snit::type dog \{
        delegate method save using \{saverec %s\}
    \}


The __%s__ is replaced with the instance name when the __save__ method
is called; any additional arguments are the appended to the resulting command\.

The __using__ clause understands a number of other %\-conversions; in
addition to the instance name, you can substitute in the method name
\(__%m__\), the type name \(__%t__\), the instance namespace \(__%n__\),







|

|


|
<
>










|

|


|
|
<
<
>
>
















|


|

|

<
|
>
|

<
|
>
|

<
|
>
|
|

<
|
|
>




















|


|

<
<
>
>

|
|
<
>




|



















|


|
|

<
<
>
>








|
|
|
<
|
>
|
|
|
<
>
|
<
>

















|
|
<
>







2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476

2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494


2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519

2520
2521
2522
2523

2524
2525
2526
2527

2528
2529
2530
2531
2532

2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560


2561
2562
2563
2564
2565

2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596


2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609

2610
2611
2612
2613
2614

2615
2616

2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636

2637
2638
2639
2640
2641
2642
2643
2644
same options \(__\-inherit__ and __\-public__\) as the __component__
statement does, and defines a type variable to hold the type component's object
command\.

Suppose in your model you've got many dogs, but only one veterinarian\. You might
make the veterinarian a type component\.

    snit::type veterinarian { ... }

    snit::type dog {
        typecomponent vet

        # ...

    }

## <a name='subsection111'></a>How do I install a type component?

Just use the __[set](\.\./\.\./\.\./\.\./index\.md\#set)__ command to assign the
component's object command to the type component\. Because types \(even
__snit::widget__ types\) are not widgets, and do not have options anyway, the
extra features of the __install__ command are not needed\.

You'll usually install type components in the type constructor, as shown here:

    snit::type veterinarian { ... }

    snit::type dog {
        typecomponent vet

        typeconstructor {
            set vet [veterinarian %AUTO%]


        }
    }

## <a name='subsection112'></a>Are there any limitations on type component names?

Yes, the same as on [INSTANCE VARIABLES](#section6), [TYPE
VARIABLES](#section8), and normal [COMPONENTS](#section14)\.

# <a name='section16'></a>DELEGATION

## <a name='subsection113'></a>What is delegation?

Delegation, simply put, is when you pass a task you've been given to one of your
assistants\. \(You do have assistants, don't you?\) Snit objects can do the same
thing\. The following example shows one way in which the __dog__ object can
delegate its __wag__ method and its __\-taillength__ option to its
__tail__ component\.

    snit::type dog {
        variable mytail

        option -taillength -configuremethod SetTailOption -cgetmethod GetTailOption

        method SetTailOption {option value} {
             $mytail configure $option $value

        }

        method GetTailOption {option} {
             $mytail cget $option

        }

        method wag {} {
            $mytail wag

        }

        constructor {args} {
            install mytail using tail %AUTO% -partof $self
            $self configurelist $args

        }

    }

This is the hard way to do it, by it demonstrates what delegation is all about\.
See the following answers for the easy way to do it\.

Note that the constructor calls the __configurelist__ method
__[after](\.\./\.\./\.\./\.\./index\.md\#after)__ it creates its __tail__;
otherwise, if __\-taillength__ appeared in the list of __args__ we'd get
an error\.

## <a name='subsection114'></a>How can I delegate a method to a component object?

Delegation occurs frequently enough that Snit makes it easy\. Any method can be
delegated to any component or type component by placing a single
__delegate__ statement in the type definition\. \(See
[COMPONENTS](#section14) and [TYPE COMPONENTS](#section15) for more
information about component names\.\)

For example, here's a much better way to delegate the __dog__ object's
__wag__ method:

    % snit::type dog {
        delegate method wag to mytail

        constructor {} {
            install mytail using tail %AUTO%


        }
    }
    ::dog
    % snit::type tail {
        method wag {} { return "Wag, wag, wag."}

    }
    ::tail
    % dog spot
    ::spot
    % spot wag
    Wag, wag, wag.

This code has the same effect as the code shown under the previous question:
when a __dog__'s __wag__ method is called, the call and its arguments
are passed along automatically to the __tail__ object\.

Note that when a component is mentioned in a __delegate__ statement, the
component's instance variable is defined implicitly\. However, it's still good
practice to declare it explicitly using the __component__ statement\.

Note also that you can define a method name using the
__[method](\.\./\.\./\.\./\.\./index\.md\#method)__ statement, or you can define
it using __delegate__; you can't do both\.

## <a name='subsection115'></a>Can I delegate to a method with a different name?

Suppose you wanted to delegate the __dog__'s __wagtail__ method to the
__tail__'s __wag__ method\. After all you wag the tail, not the dog\. It's
easily done:

    snit::type dog {
        delegate method wagtail to mytail as wag

        constructor {args} {
            install mytail using tail %AUTO% -partof $self
            $self configurelist $args


        }
    }

## <a name='subsection116'></a>Can I delegate to a method with additional arguments?

Suppose the __tail__'s __wag__ method takes as an argument the number of
times the tail should be wagged\. You want to delegate the __dog__'s
__wagtail__ method to the __tail__'s __wag__ method, specifying that
the tail should be wagged exactly three times\. This is easily done, too:

    snit::type dog {
        delegate method wagtail to mytail as {wag 3}
        # ...

    }

    snit::type tail {
        method wag {count} {
            return [string repeat "Wag " $count]

        }
        # ...

    }

## <a name='subsection117'></a>Can I delegate a method to something other than an object?

Normal method delegation assumes that you're delegating a method \(a subcommand
of an object command\) to a method of another object \(a subcommand of a different
object command\)\. But not all Tcl objects follow Tk conventions, and not
everything you'd to which you'd like to delegate a method is necessary an
object\. Consequently, Snit makes it easy to delegate a method to pretty much
anything you like using the __delegate__ statement's __using__ clause\.

Suppose your dog simulation stores dogs in a database, each dog as a single
record\. The database API you're using provides a number of commands to manage
records; each takes the record ID \(a string you choose\) as its first argument\.
For example, __saverec__ saves a record\. If you let the record ID be the
name of the dog object, you can delegate the dog's __save__ method to the
__saverec__ command as follows:

    snit::type dog {
        delegate method save using {saverec %s}

    }

The __%s__ is replaced with the instance name when the __save__ method
is called; any additional arguments are the appended to the resulting command\.

The __using__ clause understands a number of other %\-conversions; in
addition to the instance name, you can substitute in the method name
\(__%m__\), the type name \(__%t__\), the instance namespace \(__%n__\),
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680


2681
2682
2683
2684
2685

2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715


2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739

2740
2741
2742
2743


2744
2745
2746
2747
2748
2749
2750

The first question in this section \(see [DELEGATION](#section16)\) shows one
way to delegate an option to a component; but this pattern occurs often enough
that Snit makes it easy\. For example, every __tail__ object has a
__\-length__ option; we want to allow the creator of a __dog__ object to
set the tail's length\. We can do this:

    % snit::type dog \{
        delegate option \-length to mytail

        constructor \{args\} \{
            install mytail using tail %AUTO% \-partof $self
            $self configurelist $args
        \}
    \}


    ::dog
    % snit::type tail \{
        option \-partof
        option \-length 5
    \}

    ::tail
    % dog spot \-length 7
    ::spot
    % spot cget \-length
    7

This produces nearly the same result as the __\-configuremethod__ and
__\-cgetmethod__ shown under the first question in this section: whenever a
__dog__ object's __\-length__ option is set or retrieved, the underlying
__tail__ object's option is set or retrieved in turn\.

Note that you can define an option name using the __option__ statement, or
you can define it using __delegate__; you can't do both\.

## <a name='subsection121'></a>Can I delegate to an option with a different name?

In the previous answer we delegated the __dog__'s __\-length__ option
down to its __tail__\. This is, of course, wrong\. The dog has a length, and
the tail has a length, and they are different\. What we'd really like to do is
give the __dog__ a __\-taillength__ option, but delegate it to the
__tail__'s __\-length__ option:

    snit::type dog \{
        delegate option \-taillength to mytail as \-length

        constructor \{args\} \{
            set mytail \[tail %AUTO% \-partof $self\]
            $self configurelist $args
        \}
    \}



## <a name='subsection122'></a>How can I delegate any unrecognized method or option to a component object?

It may happen that a Snit object gets most of its behavior from one of its
components\. This often happens with __snit::widgetadaptors__, for example,
where we wish to slightly the modify the behavior of an existing widget\. To
carry on with our __dog__ example, however, suppose that we have a
__snit::type__ called __animal__ that implements a variety of animal
behaviors\-\-moving, eating, sleeping, and so forth\. We want our __dog__
objects to inherit these same behaviors, while adding dog\-like behaviors of its
own\. Here's how we can give a __dog__ methods and options of its own while
delegating all other methods and options to its __animal__ component:

    snit::type dog \{
        delegate option \* to animal
        delegate method \* to animal

        option \-akc 0

        constructor \{args\} \{
            install animal using animal %AUTO% \-name $self
            $self configurelist $args
        \}


        method wag \{\} \{
            return "$self wags its tail"
        \}
    \}



That's it\. A __dog__ is now an __animal__ that has a __\-akc__ option
and can __wag__ its tail\.

Note that we don't need to specify the full list of method names or option names
that __animal__ will receive\. It gets anything __dog__ doesn't
recognize\-\-and if it doesn't recognize it either, it will simply throw an error,







|
|

|
|

<
<
>
>

|
|
|
<
>

|

|


















|
|

|
|

<
<
>
>













|
|
|

|

|
|

<
|
>
|

<
<
>
>







2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678


2679
2680
2681
2682
2683
2684

2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713


2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737

2738
2739
2740
2741


2742
2743
2744
2745
2746
2747
2748
2749
2750

The first question in this section \(see [DELEGATION](#section16)\) shows one
way to delegate an option to a component; but this pattern occurs often enough
that Snit makes it easy\. For example, every __tail__ object has a
__\-length__ option; we want to allow the creator of a __dog__ object to
set the tail's length\. We can do this:

    % snit::type dog {
        delegate option -length to mytail

        constructor {args} {
            install mytail using tail %AUTO% -partof $self
            $self configurelist $args


        }
    }
    ::dog
    % snit::type tail {
        option -partof
        option -length 5

    }
    ::tail
    % dog spot -length 7
    ::spot
    % spot cget -length
    7

This produces nearly the same result as the __\-configuremethod__ and
__\-cgetmethod__ shown under the first question in this section: whenever a
__dog__ object's __\-length__ option is set or retrieved, the underlying
__tail__ object's option is set or retrieved in turn\.

Note that you can define an option name using the __option__ statement, or
you can define it using __delegate__; you can't do both\.

## <a name='subsection121'></a>Can I delegate to an option with a different name?

In the previous answer we delegated the __dog__'s __\-length__ option
down to its __tail__\. This is, of course, wrong\. The dog has a length, and
the tail has a length, and they are different\. What we'd really like to do is
give the __dog__ a __\-taillength__ option, but delegate it to the
__tail__'s __\-length__ option:

    snit::type dog {
        delegate option -taillength to mytail as -length

        constructor {args} {
            set mytail [tail %AUTO% -partof $self]
            $self configurelist $args


        }
    }

## <a name='subsection122'></a>How can I delegate any unrecognized method or option to a component object?

It may happen that a Snit object gets most of its behavior from one of its
components\. This often happens with __snit::widgetadaptors__, for example,
where we wish to slightly the modify the behavior of an existing widget\. To
carry on with our __dog__ example, however, suppose that we have a
__snit::type__ called __animal__ that implements a variety of animal
behaviors\-\-moving, eating, sleeping, and so forth\. We want our __dog__
objects to inherit these same behaviors, while adding dog\-like behaviors of its
own\. Here's how we can give a __dog__ methods and options of its own while
delegating all other methods and options to its __animal__ component:

    snit::type dog {
        delegate option * to animal
        delegate method * to animal

        option -akc 0

        constructor {args} {
            install animal using animal %AUTO% -name $self
            $self configurelist $args

        }

        method wag {} {
            return "$self wags its tail"


        }
    }

That's it\. A __dog__ is now an __animal__ that has a __\-akc__ option
and can __wag__ its tail\.

Note that we don't need to specify the full list of method names or option names
that __animal__ will receive\. It gets anything __dog__ doesn't
recognize\-\-and if it doesn't recognize it either, it will simply throw an error,
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779


2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794

2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807


2808
2809
2810
2811
2812
2813
2814
2815
2816

2817
2818
2819
2820
2821
2822
2823
what if the __animal__ type has some methods or options that we'd like to
suppress?

One solution is to explicitly delegate all the options and methods, and forgo
the convenience of __delegate method \*__ and __delegate option \*__\. But
if we wish to suppress only a few options or methods, there's an easier way:

    snit::type dog \{
        delegate option \* to animal except \-numlegs
        delegate method \* to animal except \{fly climb\}

        \# \.\.\.

        constructor \{args\} \{
            install animal using animal %AUTO% \-name $self \-numlegs 4
            $self configurelist $args
        \}

        \# \.\.\.
    \}



Dogs have four legs, so we specify that explicitly when we create the
__animal__ component, and explicitly exclude __\-numlegs__ from the set
of delegated options\. Similarly, dogs can neither __fly__ nor __climb__,
so we exclude those __animal__ methods as shown\.

## <a name='subsection124'></a>Can a hierarchical method be delegated?

Yes; just specify multiple words in the delegated method's name:

    snit::type tail \{
        method wag \{\} \{return "Wag, wag"\}
        method droop \{\} \{return "Droop, droop"\}
    \}


    snit::type dog \{
        delegate method \{tail wag\} to mytail
        delegate method \{tail droop\} to mytail

        \# \.\.\.

        constructor \{args\} \{
            install mytail using tail %AUTO%
            $self configurelist $args
        \}

        \# \.\.\.
    \}



Unrecognized hierarchical methods can also be delegated; the following code
delegates all subcommands of the "tail" method to the "mytail" component:

    snit::type dog \{
        delegate method \{tail \*\} to mytail

        \# \.\.\.
    \}


# <a name='section17'></a>WIDGETS

## <a name='subsection125'></a>What is a snit::widget?

A __snit::widget__ is the Snit version of what Tcl programmers usually call
a *megawidget*: a widget\-like object usually consisting of one or more Tk







|
|
|

|

|
|

<
|
|
<
>
>










|
|
|
<
|
>
|
|
|

|

|


<
|
|
<
>
>




|
|

|
<
>







2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775

2776
2777

2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792

2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803

2804
2805

2806
2807
2808
2809
2810
2811
2812
2813
2814
2815

2816
2817
2818
2819
2820
2821
2822
2823
what if the __animal__ type has some methods or options that we'd like to
suppress?

One solution is to explicitly delegate all the options and methods, and forgo
the convenience of __delegate method \*__ and __delegate option \*__\. But
if we wish to suppress only a few options or methods, there's an easier way:

    snit::type dog {
        delegate option * to animal except -numlegs
        delegate method * to animal except {fly climb}

        # ...

        constructor {args} {
            install animal using animal %AUTO% -name $self -numlegs 4
            $self configurelist $args

        }


        # ...
    }

Dogs have four legs, so we specify that explicitly when we create the
__animal__ component, and explicitly exclude __\-numlegs__ from the set
of delegated options\. Similarly, dogs can neither __fly__ nor __climb__,
so we exclude those __animal__ methods as shown\.

## <a name='subsection124'></a>Can a hierarchical method be delegated?

Yes; just specify multiple words in the delegated method's name:

    snit::type tail {
        method wag {} {return "Wag, wag"}
        method droop {} {return "Droop, droop"}

    }

    snit::type dog {
        delegate method {tail wag} to mytail
        delegate method {tail droop} to mytail

        # ...

        constructor {args} {
            install mytail using tail %AUTO%
            $self configurelist $args

        }


        # ...
    }

Unrecognized hierarchical methods can also be delegated; the following code
delegates all subcommands of the "tail" method to the "mytail" component:

    snit::type dog {
        delegate method {tail *} to mytail

        # ...

    }

# <a name='section17'></a>WIDGETS

## <a name='subsection125'></a>What is a snit::widget?

A __snit::widget__ is the Snit version of what Tcl programmers usually call
a *megawidget*: a widget\-like object usually consisting of one or more Tk
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884

2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904

2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932


2933
2934
2935
2936
2937
2938
2939

A __snit::widget__'s hull component will usually be a Tk
__[frame](\.\./\.\./\.\./\.\./index\.md\#frame)__ widget; however, it may be any
Tk widget that defines the __\-class__ option\. You can explicitly choose the
hull type you prefer by including the __hulltype__ command in the widget
definition:

    snit::widget mytoplevel \{
        hulltype toplevel

        \# \.\.\.
    \}


If no __hulltype__ command appears, the hull will be a
__[frame](\.\./\.\./\.\./\.\./index\.md\#frame)__\.

By default, Snit recognizes the following hull types: the Tk widgets
__[frame](\.\./\.\./\.\./\.\./index\.md\#frame)__, __labelframe__,
__toplevel__, and the Tile widgets __ttk::frame__,
__ttk::labelframe__, and __ttk::toplevel__\. To enable the use of some
other kind of widget as the hull type, you can __lappend__ the widget
command to the variable __snit::hulltypes__ \(always provided the widget
defines the __\-class__ option\. For example, suppose Tk gets a new widget
type called a __prettyframe__:

    lappend snit::hulltypes prettyframe

    snit::widget mywidget \{
        hulltype prettyframe

        \# \.\.\.
    \}


## <a name='subsection130'></a>How should I name widgets which are components of a snit::widget?

Every widget, whether a genuine Tk widget or a Snit megawidget, has to have a
valid Tk window name\. When a __snit::widget__ is first created, its instance
name, __self__, is a Tk window name; however, if the __snit::widget__ is
used as the hull component by a __snit::widgetadaptor__ its instance name
will be changed to something else\. For this reason, every __snit::widget__
method, constructor, destructor, and so forth is passed another implicit
argument, __win__, which is the window name of the megawidget\. Any children
should be named using __win__ as the root\.

Thus, suppose you're writing a toolbar widget, a frame consisting of a number of
buttons placed side\-by\-side\. It might look something like this:

    snit::widget toolbar \{
        delegate option \* to hull

        constructor \{args\} \{
            button $win\.open \-text Open \-command \[mymethod open\]
            button $win\.save \-text Save \-command \[mymethod save\]

            \# \.\.\.\.

            $self configurelist $args

        \}
    \}



See also the question on renaming objects, toward the top of this file\.

# <a name='section18'></a>WIDGET ADAPTORS

## <a name='subsection131'></a>What is a snit::widgetadaptor?








|


|
<
>















|


|
<
>















|
|

|
|
|

|



<
<
>
>







2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883

2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903

2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930


2931
2932
2933
2934
2935
2936
2937
2938
2939

A __snit::widget__'s hull component will usually be a Tk
__[frame](\.\./\.\./\.\./\.\./index\.md\#frame)__ widget; however, it may be any
Tk widget that defines the __\-class__ option\. You can explicitly choose the
hull type you prefer by including the __hulltype__ command in the widget
definition:

    snit::widget mytoplevel {
        hulltype toplevel

        # ...

    }

If no __hulltype__ command appears, the hull will be a
__[frame](\.\./\.\./\.\./\.\./index\.md\#frame)__\.

By default, Snit recognizes the following hull types: the Tk widgets
__[frame](\.\./\.\./\.\./\.\./index\.md\#frame)__, __labelframe__,
__toplevel__, and the Tile widgets __ttk::frame__,
__ttk::labelframe__, and __ttk::toplevel__\. To enable the use of some
other kind of widget as the hull type, you can __lappend__ the widget
command to the variable __snit::hulltypes__ \(always provided the widget
defines the __\-class__ option\. For example, suppose Tk gets a new widget
type called a __prettyframe__:

    lappend snit::hulltypes prettyframe

    snit::widget mywidget {
        hulltype prettyframe

        # ...

    }

## <a name='subsection130'></a>How should I name widgets which are components of a snit::widget?

Every widget, whether a genuine Tk widget or a Snit megawidget, has to have a
valid Tk window name\. When a __snit::widget__ is first created, its instance
name, __self__, is a Tk window name; however, if the __snit::widget__ is
used as the hull component by a __snit::widgetadaptor__ its instance name
will be changed to something else\. For this reason, every __snit::widget__
method, constructor, destructor, and so forth is passed another implicit
argument, __win__, which is the window name of the megawidget\. Any children
should be named using __win__ as the root\.

Thus, suppose you're writing a toolbar widget, a frame consisting of a number of
buttons placed side\-by\-side\. It might look something like this:

    snit::widget toolbar {
        delegate option * to hull

        constructor {args} {
            button $win.open -text Open -command [mymethod open]
            button $win.save -text Save -command [mymethod save]

            # ....

            $self configurelist $args



        }
    }

See also the question on renaming objects, toward the top of this file\.

# <a name='section18'></a>WIDGET ADAPTORS

## <a name='subsection131'></a>What is a snit::widgetadaptor?

2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971

2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986

2987
2988
2989
2990
2991
2992
2993
For example, the following code creates a read\-only text widget by the simple
device of turning its __insert__ and __delete__ methods into no\-ops\.
Then, we define new methods, __ins__ and __del__, which get delegated to
the hull component as __insert__ and __delete__\. Thus, we've adapted the
text widget and given it new behavior while still leaving it fundamentally a
text widget\.

    ::snit::widgetadaptor rotext \{

        constructor \{args\} \{
            \# Create the text widget; turn off its insert cursor
            installhull using text \-insertwidth 0

            \# Apply any options passed at creation time\.
            $self configurelist $args
        \}


        \# Disable the text widget's insert and delete methods, to
        \# make this readonly\.
        method insert \{args\} \{\}
        method delete \{args\} \{\}

        \# Enable ins and del as synonyms, so the program can insert and
        \# delete\.
        delegate method ins to hull as insert
        delegate method del to hull as delete

        \# Pass all other methods and options to the real text widget, so
        \# that the remaining behavior is as expected\.
        delegate method \* to hull
        delegate option \* to hull
    \}


The most important part is in the constructor\. Whereas __snit::widget__
creates the hull for you, __snit::widgetadaptor__ cannot \-\- it doesn't know
what kind of widget you want\. So the first thing the constructor does is create
the hull component \(a Tk text widget in this case\), and then installs it using
the __installhull__ command\.








|

|
|
|

|

<
|
>
|
|
|
|

|
|



|
|
|
|
<
>







2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969

2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985

2986
2987
2988
2989
2990
2991
2992
2993
For example, the following code creates a read\-only text widget by the simple
device of turning its __insert__ and __delete__ methods into no\-ops\.
Then, we define new methods, __ins__ and __del__, which get delegated to
the hull component as __insert__ and __delete__\. Thus, we've adapted the
text widget and given it new behavior while still leaving it fundamentally a
text widget\.

    ::snit::widgetadaptor rotext {

        constructor {args} {
            # Create the text widget; turn off its insert cursor
            installhull using text -insertwidth 0

            # Apply any options passed at creation time.
            $self configurelist $args

        }

        # Disable the text widget's insert and delete methods, to
        # make this readonly.
        method insert {args} {}
        method delete {args} {}

        # Enable ins and del as synonyms, so the program can insert and
        # delete.
        delegate method ins to hull as insert
        delegate method del to hull as delete

        # Pass all other methods and options to the real text widget, so
        # that the remaining behavior is as expected.
        delegate method * to hull
        delegate option * to hull

    }

The most important part is in the constructor\. Whereas __snit::widget__
creates the hull for you, __snit::widgetadaptor__ cannot \-\- it doesn't know
what kind of widget you want\. So the first thing the constructor does is create
the hull component \(a Tk text widget in this case\), and then installs it using
the __installhull__ command\.

3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022


3023
3024
3025
3026
3027
3028
3029
__PagesManager__ itself, using its __add__ method\. It's convenient to
adapt these frames to do what we'd like them to do\.

In a case like this, the Tk widget will already exist when the
__snit::widgetadaptor__ is created\. Snit provides an alternate form of the
__installhull__ command for this purpose:

    snit::widgetadaptor pageadaptor \{
        constructor \{args\} \{
            \# The widget already exists; just install it\.
            installhull $win

            \# \.\.\.
        \}
    \}



## <a name='subsection134'></a>Can I adapt another megawidget?

Maybe\. If the other megawidget is a __snit::widget__ or
__snit::widgetadaptor__, then yes\. If it isn't then, again, maybe\. You'll
have to try it and see\. You're most likely to have trouble with widget
destruction\-\-you have to make sure that your megawidget code receives the







|
|
|


|
<
<
>
>







3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020


3021
3022
3023
3024
3025
3026
3027
3028
3029
__PagesManager__ itself, using its __add__ method\. It's convenient to
adapt these frames to do what we'd like them to do\.

In a case like this, the Tk widget will already exist when the
__snit::widgetadaptor__ is created\. Snit provides an alternate form of the
__installhull__ command for this purpose:

    snit::widgetadaptor pageadaptor {
        constructor {args} {
            # The widget already exists; just install it.
            installhull $win

            # ...


        }
    }

## <a name='subsection134'></a>Can I adapt another megawidget?

Maybe\. If the other megawidget is a __snit::widget__ or
__snit::widgetadaptor__, then yes\. If it isn't then, again, maybe\. You'll
have to try it and see\. You're most likely to have trouble with widget
destruction\-\-you have to make sure that your megawidget code receives the
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107

3108
3109
3110
3111
3112
3113
3114
widget command name with an initial capital\. For example, the widget class of
the Tk __button__ widget is __Button__\.

Similarly, the widget class of a __snit::widget__ defaults to the
unqualified type name with the first letter capitalized\. For example, the widget
class of

    snit::widget ::mylibrary::scrolledText \{ \.\.\. \}

is __ScrolledText__\.

The widget class can also be set explicitly using the __widgetclass__
statement within the __snit::widget__ definition:

    snit::widget ::mylibrary::scrolledText \{
        widgetclass Text

        \# \.\.\.
    \}


The above definition says that a __scrolledText__ megawidget has the same
widget class as an ordinary __[text](\.\./\.\./\.\./\.\./index\.md\#text)__
widget\. This might or might not be a good idea, depending on how the rest of the
megawidget is defined, and how its options are delegated\.

## <a name='subsection138'></a>What is my snit::widgetadaptor's widget class?







|






|


|
<
>







3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106

3107
3108
3109
3110
3111
3112
3113
3114
widget command name with an initial capital\. For example, the widget class of
the Tk __button__ widget is __Button__\.

Similarly, the widget class of a __snit::widget__ defaults to the
unqualified type name with the first letter capitalized\. For example, the widget
class of

    snit::widget ::mylibrary::scrolledText { ... }

is __ScrolledText__\.

The widget class can also be set explicitly using the __widgetclass__
statement within the __snit::widget__ definition:

    snit::widget ::mylibrary::scrolledText {
        widgetclass Text

        # ...

    }

The above definition says that a __scrolledText__ megawidget has the same
widget class as an ordinary __[text](\.\./\.\./\.\./\.\./index\.md\#text)__
widget\. This might or might not be a good idea, depending on how the rest of the
megawidget is defined, and how its options are delegated\.

## <a name='subsection138'></a>What is my snit::widgetadaptor's widget class?
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165


3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193


3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212

3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233

3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263

3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
The resource and class names are used to initialize option default values by
querying the option database\. The resource name is usually just the option name
minus the hyphen, but may contain uppercase letters at word boundaries; the
class name is usually just the resource name with an initial capital, but not
always\. For example, here are the option, resource, and class names for several
Tk __[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget options:

    \-background         background         Background
    \-borderwidth        borderWidth        BorderWidth
    \-insertborderwidth  insertBorderWidth  BorderWidth
    \-padx               padX               Pad

As is easily seen, sometimes the resource and class names can be inferred from
the option name, but not always\.

## <a name='subsection140'></a>What are the resource and class names for my megawidget's options?

For options implicitly delegated to a component using __delegate option \*__,
the resource and class names will be exactly those defined by the component\. The
__configure__ method returns these names, along with the option's default
and current values:

    % snit::widget mytext \{
        delegate option \* to text

        constructor \{args\} \{
            install text using text \.text
            \# \.\.\.
        \}

        \# \.\.\.
    \}


    ::mytext
    % mytext \.text
    \.text
    % \.text configure \-padx
    \-padx padX Pad 1 1
    %

For all other options \(whether locally defined or explicitly delegated\), the
resource and class names can be defined explicitly, or they can be allowed to
have default values\.

By default, the resource name is just the option name minus the hyphen; the the
class name is just the option name with an initial capital letter\. For example,
suppose we explicitly delegate "\-padx":

    % snit::widget mytext \{
        option \-myvalue 5

        delegate option \-padx to text
        delegate option \* to text

        constructor \{args\} \{
            install text using text \.text
            \# \.\.\.
        \}

        \# \.\.\.
    \}


    ::mytext
    % mytext \.text
    \.text
    % \.text configure \-myvalue
    \-myvalue myvalue Myvalue 5 5
    % \.text configure \-padx
    \-padx padx Padx 1 1
    %

Here the resource and class names are chosen using the default rules\. Often
these rules are sufficient, but in the case of "\-padx" we'd most likely prefer
that the option's resource and class names are the same as for the built\-in Tk
widgets\. This is easily done:

    % snit::widget mytext \{
        delegate option \{\-padx padX Pad\} to text

        \# \.\.\.
    \}

    ::mytext
    % mytext \.text
    \.text
    % \.text configure \-padx
    \-padx padX Pad 1 1
    %

## <a name='subsection141'></a>How does Snit initialize my megawidget's locally\-defined options?

The option database is queried for each of the megawidget's locally\-defined
options, using the option's resource and class name\. If the result isn't "",
then it replaces the default value given in widget definition\. In either case,
the default can be overridden by the caller\. For example,

    option add \*Mywidget\.texture pebbled

    snit::widget mywidget \{
        option \-texture smooth
        \# \.\.\.
    \}


    mywidget \.mywidget \-texture greasy

Here, __\-texture__ would normally default to "smooth", but because of the
entry added to the option database it defaults to "pebbled"\. However, the caller
has explicitly overridden the default, and so the new widget will be "greasy"\.

## <a name='subsection142'></a>How does Snit initialize delegated options?

That depends on whether the options are delegated to the hull, or to some other
component\.

## <a name='subsection143'></a>How does Snit initialize options delegated to the hull?

A __snit::widget__'s hull is a widget, and given that its class has been set
it is expected to query the option database for itself\. The only exception
concerns options that are delegated to it with a different name\. Consider the
following code:

    option add \*Mywidget\.borderWidth 5
    option add \*Mywidget\.relief sunken
    option add \*Mywidget\.hullbackground red
    option add \*Mywidget\.background green

    snit::widget mywidget \{
        delegate option \-borderwidth to hull
        delegate option \-hullbackground to hull as \-background
        delegate option \* to hull
        \# \.\.\.
    \}


    mywidget \.mywidget

    set A \[\.mywidget cget \-relief\]
    set B \[\.mywidget cget \-hullbackground\]
    set C \[\.mywidget cget \-background\]
    set D \[\.mywidget cget \-borderwidth\]

The question is, what are the values of variables A, B, C and D?

The value of A is "sunken"\. The hull is a Tk frame which has been given the
widget class __Mywidget__; it will automatically query the option database
and pick up this value\. Since the __\-relief__ option is implicitly delegated
to the hull, Snit takes no action\.







|
|
|
|











|
|

|
|
|
<
|
|
<
>
>

|
|
|
|










|
|

|
|

|
|
|
<
|
|
<
>
>

|
|
|
|
|
|







|
|

|
<
>

|
|
|
|









|

|
|
|
<
|
>
|

















|
|
|
|

|
|
|
|
|
<
|
>
|

|
|
|
|







3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161

3162
3163

3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189

3190
3191

3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211

3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231

3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261

3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
The resource and class names are used to initialize option default values by
querying the option database\. The resource name is usually just the option name
minus the hyphen, but may contain uppercase letters at word boundaries; the
class name is usually just the resource name with an initial capital, but not
always\. For example, here are the option, resource, and class names for several
Tk __[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget options:

    -background         background         Background
    -borderwidth        borderWidth        BorderWidth
    -insertborderwidth  insertBorderWidth  BorderWidth
    -padx               padX               Pad

As is easily seen, sometimes the resource and class names can be inferred from
the option name, but not always\.

## <a name='subsection140'></a>What are the resource and class names for my megawidget's options?

For options implicitly delegated to a component using __delegate option \*__,
the resource and class names will be exactly those defined by the component\. The
__configure__ method returns these names, along with the option's default
and current values:

    % snit::widget mytext {
        delegate option * to text

        constructor {args} {
            install text using text .text
            # ...

        }


        # ...
    }
    ::mytext
    % mytext .text
    .text
    % .text configure -padx
    -padx padX Pad 1 1
    %

For all other options \(whether locally defined or explicitly delegated\), the
resource and class names can be defined explicitly, or they can be allowed to
have default values\.

By default, the resource name is just the option name minus the hyphen; the the
class name is just the option name with an initial capital letter\. For example,
suppose we explicitly delegate "\-padx":

    % snit::widget mytext {
        option -myvalue 5

        delegate option -padx to text
        delegate option * to text

        constructor {args} {
            install text using text .text
            # ...

        }


        # ...
    }
    ::mytext
    % mytext .text
    .text
    % .text configure -myvalue
    -myvalue myvalue Myvalue 5 5
    % .text configure -padx
    -padx padx Padx 1 1
    %

Here the resource and class names are chosen using the default rules\. Often
these rules are sufficient, but in the case of "\-padx" we'd most likely prefer
that the option's resource and class names are the same as for the built\-in Tk
widgets\. This is easily done:

    % snit::widget mytext {
        delegate option {-padx padX Pad} to text

        # ...

    }
    ::mytext
    % mytext .text
    .text
    % .text configure -padx
    -padx padX Pad 1 1
    %

## <a name='subsection141'></a>How does Snit initialize my megawidget's locally\-defined options?

The option database is queried for each of the megawidget's locally\-defined
options, using the option's resource and class name\. If the result isn't "",
then it replaces the default value given in widget definition\. In either case,
the default can be overridden by the caller\. For example,

    option add *Mywidget.texture pebbled

    snit::widget mywidget {
        option -texture smooth
        # ...

    }

    mywidget .mywidget -texture greasy

Here, __\-texture__ would normally default to "smooth", but because of the
entry added to the option database it defaults to "pebbled"\. However, the caller
has explicitly overridden the default, and so the new widget will be "greasy"\.

## <a name='subsection142'></a>How does Snit initialize delegated options?

That depends on whether the options are delegated to the hull, or to some other
component\.

## <a name='subsection143'></a>How does Snit initialize options delegated to the hull?

A __snit::widget__'s hull is a widget, and given that its class has been set
it is expected to query the option database for itself\. The only exception
concerns options that are delegated to it with a different name\. Consider the
following code:

    option add *Mywidget.borderWidth 5
    option add *Mywidget.relief sunken
    option add *Mywidget.hullbackground red
    option add *Mywidget.background green

    snit::widget mywidget {
        delegate option -borderwidth to hull
        delegate option -hullbackground to hull as -background
        delegate option * to hull
        # ...

    }

    mywidget .mywidget

    set A [.mywidget cget -relief]
    set B [.mywidget cget -hullbackground]
    set C [.mywidget cget -background]
    set D [.mywidget cget -borderwidth]

The question is, what are the values of variables A, B, C and D?

The value of A is "sunken"\. The hull is a Tk frame which has been given the
widget class __Mywidget__; it will automatically query the option database
and pick up this value\. Since the __\-relief__ option is implicitly delegated
to the hull, Snit takes no action\.
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313

3314
3315

3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
in accordance with the standard Tk naming for this option\. As with
__\-relief__, the hull picks up its own __\-borderwidth__ option before
Snit does anything\. Because the option is delegated under its own name, Snit
assumes that the correct thing has happened, and doesn't worry about it any
further\. To avoid confusion, the __\-borderwidth__ option should have been
delegated like this:

    delegate option \{\-borderwidth borderWidth BorderWidth\} to hull

For __snit::widgetadaptor__s, the case is somewhat altered\. Widget adaptors
retain the widget class of their hull, and the hull is not created automatically
by Snit\. Instead, the __snit::widgetadaptor__ must call __installhull__
in its constructor\. The normal way to do this is as follows:

    snit::widgetadaptor mywidget \{
        \# \.\.\.
        constructor \{args\} \{
            \# \.\.\.
            installhull using text \-foreground white
            \# \.\.\.
        \}

        \# \.\.\.
    \}


In this case, the __installhull__ command will create the hull using a
command like this:

    set hull \[text $win \-foreground white\]

The hull is a __[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget, so its
widget class is __Text__\. Just as with __snit::widget__ hulls, Snit
assumes that it will pick up all of its normal option values automatically,
without help from Snit\. Options delegated from a different name are initialized
from the option database in the same way as described above\.

In earlier versions of Snit, __snit::widgetadaptor__s were expected to call
__installhull__ like this:

    installhull \[text $win \-foreground white\]

This form still works\-\-but Snit will not query the option database as described
above\.

## <a name='subsection144'></a>How does Snit initialize options delegated to other components?

For hull components, Snit assumes that Tk will do most of the work







|






|
|
|
|
|
|
<
>
|
<
>




|










|







3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312

3313
3314

3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
in accordance with the standard Tk naming for this option\. As with
__\-relief__, the hull picks up its own __\-borderwidth__ option before
Snit does anything\. Because the option is delegated under its own name, Snit
assumes that the correct thing has happened, and doesn't worry about it any
further\. To avoid confusion, the __\-borderwidth__ option should have been
delegated like this:

    delegate option {-borderwidth borderWidth BorderWidth} to hull

For __snit::widgetadaptor__s, the case is somewhat altered\. Widget adaptors
retain the widget class of their hull, and the hull is not created automatically
by Snit\. Instead, the __snit::widgetadaptor__ must call __installhull__
in its constructor\. The normal way to do this is as follows:

    snit::widgetadaptor mywidget {
        # ...
        constructor {args} {
            # ...
            installhull using text -foreground white
            # ...

        }
        # ...

    }

In this case, the __installhull__ command will create the hull using a
command like this:

    set hull [text $win -foreground white]

The hull is a __[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget, so its
widget class is __Text__\. Just as with __snit::widget__ hulls, Snit
assumes that it will pick up all of its normal option values automatically,
without help from Snit\. Options delegated from a different name are initialized
from the option database in the same way as described above\.

In earlier versions of Snit, __snit::widgetadaptor__s were expected to call
__installhull__ like this:

    installhull [text $win -foreground white]

This form still works\-\-but Snit will not query the option database as described
above\.

## <a name='subsection144'></a>How does Snit initialize options delegated to other components?

For hull components, Snit assumes that Tk will do most of the work
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362


3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373


3374
3375
3376
3377
3378
3379
3380
component, and the component is initialized accordingly\-\-provided that the
__install__ command is used to create it\.

Before option database support was added to Snit, the usual way to create a
component was to simply create it in the constructor and assign its command name
to the component variable:

    snit::widget mywidget \{
        delegate option \-background to myComp

        constructor \{args\} \{
            set myComp \[text $win\.text \-foreground black\]
        \}
    \}



The drawback of this method is that Snit has no opportunity to initialize the
component properly\. Hence, the following approach is now used:

    snit::widget mywidget \{
        delegate option \-background to myComp

        constructor \{args\} \{
            install myComp using text $win\.text \-foreground black
        \}
    \}



The __install__ command does the following:

  - Builds a list of the options explicitly included in the __install__
    command\-\-in this case, __\-foreground__\.

  - Queries the option database for all options delegated explicitly to the







|
|

|
|
<
<
>
>




|
|

|
|
<
<
>
>







3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360


3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371


3372
3373
3374
3375
3376
3377
3378
3379
3380
component, and the component is initialized accordingly\-\-provided that the
__install__ command is used to create it\.

Before option database support was added to Snit, the usual way to create a
component was to simply create it in the constructor and assign its command name
to the component variable:

    snit::widget mywidget {
        delegate option -background to myComp

        constructor {args} {
            set myComp [text $win.text -foreground black]


        }
    }

The drawback of this method is that Snit has no opportunity to initialize the
component properly\. Hence, the following approach is now used:

    snit::widget mywidget {
        delegate option -background to myComp

        constructor {args} {
            install myComp using text $win.text -foreground black


        }
    }

The __install__ command does the following:

  - Builds a list of the options explicitly included in the __install__
    command\-\-in this case, __\-foreground__\.

  - Queries the option database for all options delegated explicitly to the
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442


3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468


3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492


3493
3494
3495
3496
3497
3498
3499
your ensemble command\. Then, create an instance of the type with the desired
name\.

For example, the following code uses [DELEGATION](#section16) to create a
work\-alike for the standard __[string](\.\./\.\./\.\./\.\./index\.md\#string)__
command:

    snit::type ::mynamespace::mystringtype \{
        delegate method \* to stringhandler

        constructor \{\} \{
            set stringhandler string
        \}
    \}



    ::mynamespace::mystringtype mystring

We create the type in a namespace, so that the type command is hidden; then we
create a single instance with the desired name\-\- __mystring__, in this case\.

This method has two drawbacks\. First, it leaves the type command floating about\.
More seriously, your shiny new ensemble command will have __info__ and
__destroy__ subcommands that you probably have no use for\. But read on\.

## <a name='subsection149'></a>How can I create an ensemble command using a snit::type?

Define a type whose [TYPE METHODS](#section9) are the subcommands of your
ensemble command\.

For example, the following code uses [DELEGATION](#section16) to create a
work\-alike for the standard __[string](\.\./\.\./\.\./\.\./index\.md\#string)__
command:

    snit::type mystring \{
        delegate typemethod \* to stringhandler

        typeconstructor \{
            set stringhandler string
        \}
    \}



Now the type command itself is your ensemble command\.

This method has only one drawback, and though it's major, it's also
surmountable\. Your new ensemble command will have __create__, __info__
and __destroy__ subcommands you don't want\. And worse yet, since the
__create__ method can be implicit, users of your command will accidentally
be creating instances of your __mystring__ type if they should mispell one
of the subcommands\. The command will succeed\-\-the first time\-\-but won't do
what's wanted\. This is very bad\.

The work around is to set some [PRAGMAS](#section21), as shown here:

    snit::type mystring \{
        pragma \-hastypeinfo    no
        pragma \-hastypedestroy no
        pragma \-hasinstances   no

        delegate typemethod \* to stringhandler

        typeconstructor \{
            set stringhandler string
        \}
    \}



Here we've used the __pragma__ statement to tell Snit that we don't want the
__info__ typemethod or the __destroy__ typemethod, and that our type has
no instances; this eliminates the __create__ typemethod and all related
code\. As a result, our ensemble command will be well\-behaved, with no unexpected
subcommands\.








|
|

|

<
<
>
>



















|
|

|

<
<
>
>













|
|
|
|

|

|

<
<
>
>







3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440


3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466


3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490


3491
3492
3493
3494
3495
3496
3497
3498
3499
your ensemble command\. Then, create an instance of the type with the desired
name\.

For example, the following code uses [DELEGATION](#section16) to create a
work\-alike for the standard __[string](\.\./\.\./\.\./\.\./index\.md\#string)__
command:

    snit::type ::mynamespace::mystringtype {
        delegate method * to stringhandler

        constructor {} {
            set stringhandler string


        }
    }

    ::mynamespace::mystringtype mystring

We create the type in a namespace, so that the type command is hidden; then we
create a single instance with the desired name\-\- __mystring__, in this case\.

This method has two drawbacks\. First, it leaves the type command floating about\.
More seriously, your shiny new ensemble command will have __info__ and
__destroy__ subcommands that you probably have no use for\. But read on\.

## <a name='subsection149'></a>How can I create an ensemble command using a snit::type?

Define a type whose [TYPE METHODS](#section9) are the subcommands of your
ensemble command\.

For example, the following code uses [DELEGATION](#section16) to create a
work\-alike for the standard __[string](\.\./\.\./\.\./\.\./index\.md\#string)__
command:

    snit::type mystring {
        delegate typemethod * to stringhandler

        typeconstructor {
            set stringhandler string


        }
    }

Now the type command itself is your ensemble command\.

This method has only one drawback, and though it's major, it's also
surmountable\. Your new ensemble command will have __create__, __info__
and __destroy__ subcommands you don't want\. And worse yet, since the
__create__ method can be implicit, users of your command will accidentally
be creating instances of your __mystring__ type if they should mispell one
of the subcommands\. The command will succeed\-\-the first time\-\-but won't do
what's wanted\. This is very bad\.

The work around is to set some [PRAGMAS](#section21), as shown here:

    snit::type mystring {
        pragma -hastypeinfo    no
        pragma -hastypedestroy no
        pragma -hasinstances   no

        delegate typemethod * to stringhandler

        typeconstructor {
            set stringhandler string


        }
    }

Here we've used the __pragma__ statement to tell Snit that we don't want the
__info__ typemethod or the __destroy__ typemethod, and that our type has
no instances; this eliminates the __create__ typemethod and all related
code\. As a result, our ensemble command will be well\-behaved, with no unexpected
subcommands\.

3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519

3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530

3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541

3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564

3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592

3593
3594
3595
3596
3597
3598
3599
Use the __pragma__ statement\. Each pragma is an option with a value; each
time you use the __pragma__ statement you can set one or more of them\.

## <a name='subsection152'></a>How can I get rid of the "info" type method?

Set the __\-hastypeinfo__ pragma to __no__:

    snit::type dog \{
        pragma \-hastypeinfo no
        \# \.\.\.
    \}


Snit will refrain from defining the __info__ type method\.

## <a name='subsection153'></a>How can I get rid of the "destroy" type method?

Set the __\-hastypedestroy__ pragma to __no__:

    snit::type dog \{
        pragma \-hastypedestroy no
        \# \.\.\.
    \}


Snit will refrain from defining the __destroy__ type method\.

## <a name='subsection154'></a>How can I get rid of the "create" type method?

Set the __\-hasinstances__ pragma to __no__:

    snit::type dog \{
        pragma \-hasinstances no
        \# \.\.\.
    \}


Snit will refrain from defining the __create__ type method; if you call the
type command with an unknown method name, you'll get an error instead of a new
instance of the type\.

This is useful if you wish to use a __snit::type__ to define an ensemble
command rather than a type with instances\.

Pragmas __\-hastypemethods__ and __\-hasinstances__ cannot both be false
\(or there'd be nothing left\)\.

## <a name='subsection155'></a>How can I get rid of type methods altogether?

Normal Tk widget type commands don't have subcommands; all they do is create
widgets\-\-in Snit terms, the type command calls the __create__ type method
directly\. To get the same behavior from Snit, set the __\-hastypemethods__
pragma to __no__:

    snit::type dog \{
        pragma \-hastypemethods no
        \#\.\.\.
    \}


    \# Creates ::spot
    dog spot

    \# Tries to create an instance called ::create
    dog create spot

Pragmas __\-hastypemethods__ and __\-hasinstances__ cannot both be false
\(or there'd be nothing left\)\.

## <a name='subsection156'></a>Why can't I create an object that replaces an old object with the same name?

Up until Snit 0\.95, you could use any name for an instance of a
__snit::type__, even if the name was already in use by some other object or
command\. You could do the following, for example:

    snit::type dog \{ \.\.\. \}

    dog proc

You now have a new dog named "proc", which is probably not something that you
really wanted to do\. As a result, Snit now throws an error if your chosen
instance name names an existing command\. To restore the old behavior, set the
__\-canreplace__ pragma to __yes__:

    snit::type dog \{
        pragma \-canreplace yes
        \# \.\.\.
    \}


## <a name='subsection157'></a>How can I make my simple type run faster?

In Snit 1\.x, you can set the __\-simpledispatch__ pragma to __yes__\.

Snit 1\.x method dispatch is both flexible and fast, but the flexibility comes
with a price\. If your type doesn't require the flexibility, the







|
|
|
<
>







|
|
|
<
>







|
|
|
<
>


















|
|
|
<
|
>
|


|











|








|
|
|
<
>







3509
3510
3511
3512
3513
3514
3515
3516
3517
3518

3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529

3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540

3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562

3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591

3592
3593
3594
3595
3596
3597
3598
3599
Use the __pragma__ statement\. Each pragma is an option with a value; each
time you use the __pragma__ statement you can set one or more of them\.

## <a name='subsection152'></a>How can I get rid of the "info" type method?

Set the __\-hastypeinfo__ pragma to __no__:

    snit::type dog {
        pragma -hastypeinfo no
        # ...

    }

Snit will refrain from defining the __info__ type method\.

## <a name='subsection153'></a>How can I get rid of the "destroy" type method?

Set the __\-hastypedestroy__ pragma to __no__:

    snit::type dog {
        pragma -hastypedestroy no
        # ...

    }

Snit will refrain from defining the __destroy__ type method\.

## <a name='subsection154'></a>How can I get rid of the "create" type method?

Set the __\-hasinstances__ pragma to __no__:

    snit::type dog {
        pragma -hasinstances no
        # ...

    }

Snit will refrain from defining the __create__ type method; if you call the
type command with an unknown method name, you'll get an error instead of a new
instance of the type\.

This is useful if you wish to use a __snit::type__ to define an ensemble
command rather than a type with instances\.

Pragmas __\-hastypemethods__ and __\-hasinstances__ cannot both be false
\(or there'd be nothing left\)\.

## <a name='subsection155'></a>How can I get rid of type methods altogether?

Normal Tk widget type commands don't have subcommands; all they do is create
widgets\-\-in Snit terms, the type command calls the __create__ type method
directly\. To get the same behavior from Snit, set the __\-hastypemethods__
pragma to __no__:

    snit::type dog {
        pragma -hastypemethods no
        #...

    }

    # Creates ::spot
    dog spot

    # Tries to create an instance called ::create
    dog create spot

Pragmas __\-hastypemethods__ and __\-hasinstances__ cannot both be false
\(or there'd be nothing left\)\.

## <a name='subsection156'></a>Why can't I create an object that replaces an old object with the same name?

Up until Snit 0\.95, you could use any name for an instance of a
__snit::type__, even if the name was already in use by some other object or
command\. You could do the following, for example:

    snit::type dog { ... }

    dog proc

You now have a new dog named "proc", which is probably not something that you
really wanted to do\. As a result, Snit now throws an error if your chosen
instance name names an existing command\. To restore the old behavior, set the
__\-canreplace__ pragma to __yes__:

    snit::type dog {
        pragma -canreplace yes
        # ...

    }

## <a name='subsection157'></a>How can I make my simple type run faster?

In Snit 1\.x, you can set the __\-simpledispatch__ pragma to __yes__\.

Snit 1\.x method dispatch is both flexible and fast, but the flexibility comes
with a price\. If your type doesn't require the flexibility, the
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642

3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656


3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672


3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685

3686
3687
3688

3689
3690
3691
3692
3693
3694
3695
3696
3697

3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723

3724
3725
3726
3727
3728
3729
3730
one set of methods in the first case, and another set in the second case\. But
how can your type definition know whether the fast C extension is available or
not?

It's easily done\. Outside of any type definition, define a macro that returns 1
if the extension is available, and 0 otherwise:

    if \{$gotFastExtension\} \{
        snit::macro fastcode \{\} \{return 1\}
    \} else \{
        snit::macro fastcode \{\} \{return 0\}
    \}


Then, use your macro in your type definition:

    snit::type dog \{

        if \{\[fastcode\]\} \{
            \# Fast methods
            method bark \{\} \{\.\.\.\}
            method wagtail \{\} \{\.\.\.\}
        \} else \{
            \# Slow methods
            method bark \{\} \{\.\.\.\}
            method wagtail \{\} \{\.\.\.\}
        \}
    \}



## <a name='subsection161'></a>How do I define new type definition syntax?

Use a macro\. For example, your __snit::widget__'s __\-background__ option
should be propagated to a number of component widgets\. You could implement that
like this:

    snit::widget mywidget \{
        option \-background \-default white \-configuremethod PropagateBackground

        method PropagateBackground \{option value\} \{
            $comp1 configure $option $value
            $comp2 configure $option $value
            $comp3 configure $option $value
        \}
    \}



For one option, this is fine; if you've got a number of options, it becomes
tedious and error prone\. So package it as a macro:

    snit::macro propagate \{option "to" components\} \{
        option $option \-configuremethod Propagate$option

        set body "\\n"

        foreach comp $components \{
            append body "\\$$comp configure $option \\$value\\n"
        \}


        method Propagate$option \{option value\} $body
    \}


Then you can use it like this:

    snit::widget mywidget \{
        option \-background default \-white
        option \-foreground default \-black

        propagate \-background to \{comp1 comp2 comp3\}
        propagate \-foreground to \{comp1 comp2 comp3\}
    \}


## <a name='subsection162'></a>Are there are restrictions on macro names?

Yes, there are\. You can't redefine any standard Tcl commands or Snit type
definition statements\. You can use any other command name, including the name of
a previously defined macro\.

If you're using Snit macros in your application, go ahead and name them in the
global namespace, as shown above\. But if you're using them to define types or
widgets for use by others, you should define your macros in the same namespace
as your types or widgets\. That way, they won't conflict with other people's
macros\.

If my fancy __snit::widget__ is called __::mylib::mywidget__, for
example, then I should define my __propagate__ macro as
__::mylib::propagate__:

    snit::macro mylib::propagate \{option "to" components\} \{ \.\.\. \}

    snit::widget ::mylib::mywidget \{
        option \-background default \-white
        option \-foreground default \-black

        mylib::propagate \-background to \{comp1 comp2 comp3\}
        mylib::propagate \-foreground to \{comp1 comp2 comp3\}
    \}


# <a name='section23'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *snit* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|
|
|
|
<
|
>


|

|
|
|
|
|
|
|
|
<
<
>
>







|
|

|



<
<
>
>




|
|

|

|
|
<
|
>
|
<
|
>


|
|
|

|
|
<
>

















|

|
|
|

|
|
<
>







3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640

3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654


3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670


3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683

3684
3685
3686

3687
3688
3689
3690
3691
3692
3693
3694
3695
3696

3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722

3723
3724
3725
3726
3727
3728
3729
3730
one set of methods in the first case, and another set in the second case\. But
how can your type definition know whether the fast C extension is available or
not?

It's easily done\. Outside of any type definition, define a macro that returns 1
if the extension is available, and 0 otherwise:

    if {$gotFastExtension} {
        snit::macro fastcode {} {return 1}
    } else {
        snit::macro fastcode {} {return 0}

    }

Then, use your macro in your type definition:

    snit::type dog {

        if {[fastcode]} {
            # Fast methods
            method bark {} {...}
            method wagtail {} {...}
        } else {
            # Slow methods
            method bark {} {...}
            method wagtail {} {...}


        }
    }

## <a name='subsection161'></a>How do I define new type definition syntax?

Use a macro\. For example, your __snit::widget__'s __\-background__ option
should be propagated to a number of component widgets\. You could implement that
like this:

    snit::widget mywidget {
        option -background -default white -configuremethod PropagateBackground

        method PropagateBackground {option value} {
            $comp1 configure $option $value
            $comp2 configure $option $value
            $comp3 configure $option $value


        }
    }

For one option, this is fine; if you've got a number of options, it becomes
tedious and error prone\. So package it as a macro:

    snit::macro propagate {option "to" components} {
        option $option -configuremethod Propagate$option

        set body "\n"

        foreach comp $components {
            append body "\$$comp configure $option \$value\n"

        }

        method Propagate$option {option value} $body

    }

Then you can use it like this:

    snit::widget mywidget {
        option -background default -white
        option -foreground default -black

        propagate -background to {comp1 comp2 comp3}
        propagate -foreground to {comp1 comp2 comp3}

    }

## <a name='subsection162'></a>Are there are restrictions on macro names?

Yes, there are\. You can't redefine any standard Tcl commands or Snit type
definition statements\. You can use any other command name, including the name of
a previously defined macro\.

If you're using Snit macros in your application, go ahead and name them in the
global namespace, as shown above\. But if you're using them to define types or
widgets for use by others, you should define your macros in the same namespace
as your types or widgets\. That way, they won't conflict with other people's
macros\.

If my fancy __snit::widget__ is called __::mylib::mywidget__, for
example, then I should define my __propagate__ macro as
__::mylib::propagate__:

    snit::macro mylib::propagate {option "to" components} { ... }

    snit::widget ::mylib::mywidget {
        option -background default -white
        option -foreground default -black

        mylib::propagate -background to {comp1 comp2 comp3}
        mylib::propagate -foreground to {comp1 comp2 comp3}

    }

# <a name='section23'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *snit* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/soundex/soundex.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

[//000000001]: # (soundex \- Soundex)
[//000000002]: # (Generated from file 'soundex\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; ????, Algorithm: Donald E\. Knuth  
Copyright &copy; 2003, Documentation: Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>  
Copyright &copy; 1998, Tcl port: Evan Rempel <erempel@uvic\.ca>)
[//000000004]: # (soundex\(n\) 1\.0 tcllib "Soundex")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14

[//000000001]: # (soundex \- Soundex)
[//000000002]: # (Generated from file 'soundex\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; ????, Algorithm: Donald E\. Knuth)
[//000000004]: # (Copyright &copy; 2003, Documentation: Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000005]: # (Copyright &copy; 1998, Tcl port: Evan Rempel <erempel@uvic\.ca>)
[//000000006]: # (soundex\(n\) 1\.0 tcllib "Soundex")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

Changes to embedded/md/tcllib/files/modules/stooop/stooop.md.

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

      * __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ *name* \{__this__ ?*arg arg \.\.\.*?\} *body*

        This is a member procedure of the class, as its first argument is named
        __this__\. It allows a simple access of member data for the object
        referenced by __this__ inside the procedure\. For example:

            set \($this,data\) 0

      * __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ *name* \{?*arg arg \.\.\.*?\} *body*

        This is a static \(as in C\+\+\) member procedure of the class, as its first
        argument is not named __this__\. Static \(global\) class data can be
        accessed as in:

            set \(data\) 0

      * __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ *class* \{__this copy__\} *body*

        This is the optional copy procedure for the class\. It must have the same
        name as the class and exactly 2 arguments named __this__ and
        __copy__\. It is invoked following a __new__ invocation on an
        existing object of the class\.







|







|







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

      * __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ *name* \{__this__ ?*arg arg \.\.\.*?\} *body*

        This is a member procedure of the class, as its first argument is named
        __this__\. It allows a simple access of member data for the object
        referenced by __this__ inside the procedure\. For example:

            set ($this,data) 0

      * __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ *name* \{?*arg arg \.\.\.*?\} *body*

        This is a static \(as in C\+\+\) member procedure of the class, as its first
        argument is not named __this__\. Static \(global\) class data can be
        accessed as in:

            set (data) 0

      * __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ *class* \{__this copy__\} *body*

        This is the optional copy procedure for the class\. It must have the same
        name as the class and exactly 2 arguments named __this__ and
        __copy__\. It is invoked following a __new__ invocation on an
        existing object of the class\.

Changes to embedded/md/tcllib/files/modules/stooop/switched.md.

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

61
62

63
64
65
66
67
68
69

The __switched__ class serves as base class for user classes with switch /
option configuration procedures\. It provides facilities for managing options
through a simple interface\.

For example:

    set vehicle \[new car \-length 4\.5 \-width 2 \-power 100 \-fuel diesel\]
    puts "my car was running on \[switched::cget $vehicle \-fuel\]"
    switched::configure $vehicle \-power 40 \-fuel electricity
    puts "but is now running on clean \[switched::cget $vehicle \-fuel\]"

Of course, as you might have guessed, the __car__ class is derived from the
__switched__ class\. Let us see how it works:

    class car \{
        proc car \{this args\} switched \{$args\} \{
            \# car specific initialization code here
            switched::complete $this
        \}

        \.\.\.
    \}


The switched class constructor takes the optional configuration option / value
pairs as parameters\. The switched class layer then completely manages the
switched options: it checks their validity, stores their values and provides a
clean interface to the user layer configuration setting procedures\.

The switched class members available to the programmer are:







|
|
|
|




|
|
|

<
>
|
<
>







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

60
61

62
63
64
65
66
67
68
69

The __switched__ class serves as base class for user classes with switch /
option configuration procedures\. It provides facilities for managing options
through a simple interface\.

For example:

    set vehicle [new car -length 4.5 -width 2 -power 100 -fuel diesel]
    puts "my car was running on [switched::cget $vehicle -fuel]"
    switched::configure $vehicle -power 40 -fuel electricity
    puts "but is now running on clean [switched::cget $vehicle -fuel]"

Of course, as you might have guessed, the __car__ class is derived from the
__switched__ class\. Let us see how it works:

    class car {
        proc car {this args} switched {$args} {
            # car specific initialization code here
            switched::complete $this

        }
        ...

    }

The switched class constructor takes the optional configuration option / value
pairs as parameters\. The switched class layer then completely manages the
switched options: it checks their validity, stores their values and provides a
clean interface to the user layer configuration setting procedures\.

The switched class members available to the programmer are:
84
85
86
87
88
89
90
91
92
93
94
95

96
97
98

99
100

101
102
103
104
105
106
107
    This procedure must return the configuration description for *all* options
    that the switched object will accept\. It is a pure virtual member procedure
    and therefore its implementation is *mandatory* in the derived class
    layer\. The procedure must return a list of lists\. Each list pertains to a
    single option and is composed of the switch name, the default value for the
    option and an optional initial value\. For example:

    class car \{
        \.\.\.
        proc options \{this\} \{
            return \[list \[list \-fuel petrol petrol\] \[list \-length \{\} \{\}\] \[list \-power \{\} \{\}\] \[list \-width \{\} \{\}\] \]
        \}

        proc set\-fuel \{this value\} \{
            \.\.\.
        \}

        \.\.\.
    \}


    In this case, 4 options are specified: __fuel__, __length__,
    __power__ and __width__\. The default and initial values for the
    __fuel__ option are identical and set to __petrol__\. For the other
    options, values are all empty\.

    For each option, there must be a corresponding __set\-__option____







|
|
|
|
<
>
|
|
<
>
|
<
>







84
85
86
87
88
89
90
91
92
93
94

95
96
97

98
99

100
101
102
103
104
105
106
107
    This procedure must return the configuration description for *all* options
    that the switched object will accept\. It is a pure virtual member procedure
    and therefore its implementation is *mandatory* in the derived class
    layer\. The procedure must return a list of lists\. Each list pertains to a
    single option and is composed of the switch name, the default value for the
    option and an optional initial value\. For example:

    class car {
        ...
        proc options {this} {
            return [list [list -fuel petrol petrol] [list -length {} {}] [list -power {} {}] [list -width {} {}] ]

        }
        proc set-fuel {this value} {
            ...

        }
        ...

    }

    In this case, 4 options are specified: __fuel__, __length__,
    __power__ and __width__\. The default and initial values for the
    __fuel__ option are identical and set to __petrol__\. For the other
    options, values are all empty\.

    For each option, there must be a corresponding __set\-__option____
116
117
118
119
120
121
122
123
124
125
126
127

128
129

130
131
132
133
134
135
136

    In this procedure, if the initial value differs from the default value or is
    omitted, then initial configuration is forced and the corresponding
    __set\-__option____ procedure is invoked by the switched
    __complete__ procedure located at the end of the derived class
    constructor\. For example:

    class car \{
        \.\.\.
        proc options \{this\} \{
            return \[list \[list \-fuel petrol\] \[list \-length \{\} \{\}\] \[list \-power 100 50\] \[list \-width \{\} \{\}\] \]
        \}

        \.\.\.
    \}


    In this case, configuration is forced on the __fuel__ and __power__
    options, that is the corresponding __set\-__option____ procedures
    will be invoked when the switched object is constructed \(see
    __set\-__option____ procedures documentation below\)\.

    For the __fuel__ option, since there is no initial value, the







|
|
|
|
<
>
|
<
>







116
117
118
119
120
121
122
123
124
125
126

127
128

129
130
131
132
133
134
135
136

    In this procedure, if the initial value differs from the default value or is
    omitted, then initial configuration is forced and the corresponding
    __set\-__option____ procedure is invoked by the switched
    __complete__ procedure located at the end of the derived class
    constructor\. For example:

    class car {
        ...
        proc options {this} {
            return [list [list -fuel petrol] [list -length {} {}] [list -power 100 50] [list -width {} {}] ]

        }
        ...

    }

    In this case, configuration is forced on the __fuel__ and __power__
    options, that is the corresponding __set\-__option____ procedures
    will be invoked when the switched object is constructed \(see
    __set\-__option____ procedures documentation below\)\.

    For the __fuel__ option, since there is no initial value, the
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

  - <a name='3'></a>__<switched>__ __set\-__option____ *this* *value*

    These procedures may be viewed as dynamic virtual functions\. There must be
    one implementation per supported option, as returned by the __options__
    procedure\. For example:

    class car \{
        \.\.\.
        proc options \{this\} \{
            return \[list \.\.\.
                \[list \-width \{\} \{\}\] \]
        \}

        \.\.\.
        proc set\-width \{this value\} \{
            \.\.\.
        \}

        \.\.\.
    \}


    Since the __\-width__ option was listed in the __options__ procedure,
    a __set\-width__ procedure implementation is provided, which of course
    would proceed to set the width of the car \(and would modify the looks of a
    graphical representation, for example\)\.

    As you add a supported __option__ in the list returned by the
    __options__ procedure, the corresponding __set\-__option____
    procedure may be called as soon as the switched object is complete, which
    occurs when the switched level __complete__ procedure is invoked\. For
    example:

    class car \{
        proc car \{this args\} switched \{args\} \{
            \.\.\.
            switched::complete $this
       \}

        \.\.\.
        proc options \{this\} \{
            return \[list \[list \-fuel petrol\] \[list \-length 4\.5\] \[list \-power 350\] \[list \-width 1\.8\] \]
        \}

        proc set\-fuel \{this value\} \{
            \.\.\.
        \}

        proc set\-length \{this value\} \{
            \.\.\.
        \}

        proc set\-power \{this value\} \{
            \.\.\.
        \}

        proc set\-width \{this value\} \{
            \.\.\.
        \}
    \}



    new car

    In this case, a new car is created with no options, which causes the car
    constructor to be called, which in turns calls the switched level
    __complete__ procedure after the car object layer is completely
    initialized\. At this point, since there are no initial values in any option







|
|
|
|
|
<
>
|
|
|
<
>
|
<
>












|
|
|

<
>
|
|
|
<
>
|
|
<
>
|
|
<
>
|
|
<
>
|
|
<
<
>
>







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

  - <a name='3'></a>__<switched>__ __set\-__option____ *this* *value*

    These procedures may be viewed as dynamic virtual functions\. There must be
    one implementation per supported option, as returned by the __options__
    procedure\. For example:

    class car {
        ...
        proc options {this} {
            return [list ...
                [list -width {} {}] ]

        }
        ...
        proc set-width {this value} {
            ...

        }
        ...

    }

    Since the __\-width__ option was listed in the __options__ procedure,
    a __set\-width__ procedure implementation is provided, which of course
    would proceed to set the width of the car \(and would modify the looks of a
    graphical representation, for example\)\.

    As you add a supported __option__ in the list returned by the
    __options__ procedure, the corresponding __set\-__option____
    procedure may be called as soon as the switched object is complete, which
    occurs when the switched level __complete__ procedure is invoked\. For
    example:

    class car {
        proc car {this args} switched {args} {
            ...
            switched::complete $this

       }
        ...
        proc options {this} {
            return [list [list -fuel petrol] [list -length 4.5] [list -power 350] [list -width 1.8] ]

        }
        proc set-fuel {this value} {
            ...

        }
        proc set-length {this value} {
            ...

        }
        proc set-power {this value} {
            ...

        }
        proc set-width {this value} {
            ...


        }
    }

    new car

    In this case, a new car is created with no options, which causes the car
    constructor to be called, which in turns calls the switched level
    __complete__ procedure after the car object layer is completely
    initialized\. At this point, since there are no initial values in any option
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

    The __\-option__ data member is an options current value\. There is one
    for each option listed in the options procedure\. It is a read\-only value
    which the switched layer checks against when an option is changed\. It is
    rarely used at the layer derived from switched, except in the few cases,
    such as in the following example:

    \.\.\.
    proc car::options \{this\} \{
        return \{
            \.\.\.
            \{\-manufacturer \{\} \{\}\}
            \.\.\.
        \}
    \}


    proc car::set\-manufacturer \{this value\} \{\}


    proc car::printData \{this\} \{
        puts "manufacturer: $switched::\($this,\-manufacturer\)"
        \.\.\.
    \}


    In this case, the manufacturer's name is stored at the switched layer level
    \(this is why the set\-manufacturer procedure has nothing to do\) and later
    retrieved in the printData procedure\.

  - __complete__

    The __complete__ data member \(not to be confused with the
    __complete__ procedure\) is a boolean\. Its initial value is __false__
    and it is set to __true__ at the very end of the switched
    __complete__ procedure\. It becomes useful when some options should be
    set at construction time only and not dynamically, as the following example
    shows:

    proc car::set\-width \{this value\} \{
        if \{$switched::\($this,complete\)\} \{
            error \{option \-width cannot be set dynamically\}
        \}

        \.\.\.
    \}


# <a name='section2'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *stooop* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|
|
|
|
|
|
<
<
|
>
|
>

|
|
|
<
>














|
|
|
<
>
|
<
>







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

    The __\-option__ data member is an options current value\. There is one
    for each option listed in the options procedure\. It is a read\-only value
    which the switched layer checks against when an option is changed\. It is
    rarely used at the layer derived from switched, except in the few cases,
    such as in the following example:

    ...
    proc car::options {this} {
        return {
            ...
            {-manufacturer {} {}}
            ...


        }
    }

    proc car::set-manufacturer {this value} {}

    proc car::printData {this} {
        puts "manufacturer: $switched::($this,-manufacturer)"
        ...

    }

    In this case, the manufacturer's name is stored at the switched layer level
    \(this is why the set\-manufacturer procedure has nothing to do\) and later
    retrieved in the printData procedure\.

  - __complete__

    The __complete__ data member \(not to be confused with the
    __complete__ procedure\) is a boolean\. Its initial value is __false__
    and it is set to __true__ at the very end of the switched
    __complete__ procedure\. It becomes useful when some options should be
    set at construction time only and not dynamically, as the following example
    shows:

    proc car::set-width {this value} {
        if {$switched::($this,complete)} {
            error {option -width cannot be set dynamically}

        }
        ...

    }

# <a name='section2'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *stooop* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/stringprep/stringprep.md.

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
    if *string1* is lexicographically less than *string2*, or 1 if
    *string1* is lexicographically greater than *string2*\.

# <a name='section3'></a>EXAMPLES

Nameprep profile definition \(see RFC\-3491\):

    ::stringprep::register nameprep  \-mapping \{B\.1 B\.2\}  \-normalization KC  \-prohibited \{A\.1 C\.1\.2 C\.2\.2 C\.3 C\.4 C\.5 C\.6 C\.7 C\.8 C\.9\}  \-prohibitedBidi 1

Nodeprep and resourceprep profile definitions \(see RFC\-3920\):

    ::stringprep::register nodeprep  \-mapping \{B\.1 B\.2\}  \-normalization KC  \-prohibited \{A\.1 C\.1\.1 C\.1\.2 C\.2\.1 C\.2\.2 C\.3 C\.4 C\.5 C\.6 C\.7 C\.8 C\.9\}  \-prohibitedList \{0x22 0x26 0x27 0x2f 0x3a 0x3c 0x3e 0x40\}  \-prohibitedBidi 1

    ::stringprep::register resourceprep  \-mapping \{B\.1\}  \-normalization KC  \-prohibited \{A\.1 C\.1\.2 C\.2\.1 C\.2\.2 C\.3 C\.4 C\.5 C\.6 C\.7 C\.8 C\.9\}  \-prohibitedBidi 1

# <a name='section4'></a>REFERENCES

  1. "Preparation of Internationalized Strings \('stringprep'\)",
     \([http://www\.ietf\.org/rfc/rfc3454\.txt](http://www\.ietf\.org/rfc/rfc3454\.txt)\)

  1. "Nameprep: A Stringprep Profile for Internationalized Domain Names \(IDN\)",







|



|

|







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
    if *string1* is lexicographically less than *string2*, or 1 if
    *string1* is lexicographically greater than *string2*\.

# <a name='section3'></a>EXAMPLES

Nameprep profile definition \(see RFC\-3491\):

    ::stringprep::register nameprep  -mapping {B.1 B.2}  -normalization KC  -prohibited {A.1 C.1.2 C.2.2 C.3 C.4 C.5 C.6 C.7 C.8 C.9}  -prohibitedBidi 1

Nodeprep and resourceprep profile definitions \(see RFC\-3920\):

    ::stringprep::register nodeprep  -mapping {B.1 B.2}  -normalization KC  -prohibited {A.1 C.1.1 C.1.2 C.2.1 C.2.2 C.3 C.4 C.5 C.6 C.7 C.8 C.9}  -prohibitedList {0x22 0x26 0x27 0x2f 0x3a 0x3c 0x3e 0x40}  -prohibitedBidi 1

    ::stringprep::register resourceprep  -mapping {B.1}  -normalization KC  -prohibited {A.1 C.1.2 C.2.1 C.2.2 C.3 C.4 C.5 C.6 C.7 C.8 C.9}  -prohibitedBidi 1

# <a name='section4'></a>REFERENCES

  1. "Preparation of Internationalized Strings \('stringprep'\)",
     \([http://www\.ietf\.org/rfc/rfc3454\.txt](http://www\.ietf\.org/rfc/rfc3454\.txt)\)

  1. "Nameprep: A Stringprep Profile for Internationalized Domain Names \(IDN\)",

Changes to embedded/md/tcllib/files/modules/stringprep/unicode.md.

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

    A shortcut to ::unicode::tostring \[unicode::normalize \\$form
    \[::unicode::fromstring \\$string\]\]\. Normalizes Tcl string and returns
    normalized string\.

# <a name='section3'></a>EXAMPLES

    % ::unicode::fromstring "\\u0410\\u0411\\u0412\\u0413"
    1040 1041 1042 1043
    % ::unicode::tostring \{49 50 51 52 53\}
    12345
    %

    % ::unicode::normalize D \{7692 775\}
    68 803 775
    % ::unicode::normalizeS KD "\\u1d2c"
    A
    %

# <a name='section4'></a>REFERENCES

  1. "Unicode Standard Annex \#15: Unicode Normalization Forms",
     \([http://unicode\.org/reports/tr15/](http://unicode\.org/reports/tr15/)\)







|

|



|

|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

    A shortcut to ::unicode::tostring \[unicode::normalize \\$form
    \[::unicode::fromstring \\$string\]\]\. Normalizes Tcl string and returns
    normalized string\.

# <a name='section3'></a>EXAMPLES

    % ::unicode::fromstring "\u0410\u0411\u0412\u0413"
    1040 1041 1042 1043
    % ::unicode::tostring {49 50 51 52 53}
    12345
    %

    % ::unicode::normalize D {7692 775}
    68 803 775
    % ::unicode::normalizeS KD "\u1d2c"
    A
    %

# <a name='section4'></a>REFERENCES

  1. "Unicode Standard Annex \#15: Unicode Normalization Forms",
     \([http://unicode\.org/reports/tr15/](http://unicode\.org/reports/tr15/)\)

Changes to embedded/md/tcllib/files/modules/struct/disjointset.md.

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
    covering the whole set\.

  - An alternative name for the *partitions* would be *equvalence classes*,
    and all elements in the same class are considered as equal\.

Here is a pictorial representation of the concepts listed above:

    \+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+ The outer lines are the boundaries of the set S\.
    &#124;           /     &#124; The inner regions delineated by the skewed lines
    &#124;  \*       /   \*  &#124; are the partitions P\. The \*'s denote the elements
    &#124;      \*  / \\     &#124; E in the set, each in a single partition, their
    &#124;\*       /   \\    &#124; equivalence class\.
    &#124;       /  \*  \\   &#124;
    &#124;      / \*   /    &#124;
    &#124; \*   /\\  \* /     &#124;
    &#124;    /  \\  /      &#124;
    &#124;   /    \\/  \*    &#124;
    &#124;  / \*    \\       &#124;
    &#124; /     \*  \\      &#124;
    \+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+

For more information see
[http://en\.wikipedia\.org/wiki/Disjoint\_set\_data\_structure](http://en\.wikipedia\.org/wiki/Disjoint\_set\_data\_structure)\.

# <a name='section2'></a>API

The package exports a single command, __::struct::disjointset__\. All







|
|
|
|
|
|
|
|
|
|
|
|
|







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
    covering the whole set\.

  - An alternative name for the *partitions* would be *equvalence classes*,
    and all elements in the same class are considered as equal\.

Here is a pictorial representation of the concepts listed above:

    +-----------------+ The outer lines are the boundaries of the set S.
    |           /     | The inner regions delineated by the skewed lines
    |  *       /   *  | are the partitions P. The *'s denote the elements
    |      *  / \     | E in the set, each in a single partition, their
    |*       /   \    | equivalence class.
    |       /  *  \   |
    |      / *   /    |
    | *   /\  * /     |
    |    /  \  /      |
    |   /    \/  *    |
    |  / *    \       |
    | /     *  \      |
    +-----------------+

For more information see
[http://en\.wikipedia\.org/wiki/Disjoint\_set\_data\_structure](http://en\.wikipedia\.org/wiki/Disjoint\_set\_data\_structure)\.

# <a name='section2'></a>API

The package exports a single command, __::struct::disjointset__\. All

Changes to embedded/md/tcllib/files/modules/struct/graph.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (struct::graph \- Tcl Data Structures)
[//000000002]: # (Generated from file 'graph\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2002\-2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (struct::graph\(n\) 2\.4\.1 tcllib "Tcl Data Structures")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (struct::graph \- Tcl Data Structures)
[//000000002]: # (Generated from file 'graph\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2002\-2009,2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (struct::graph\(n\) 2\.4\.3 tcllib "Tcl Data Structures")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.4  
package require struct::graph ?2\.4\.1?  
package require struct::list ?1\.5?  
package require struct::set ?2\.2\.3?  

[__::struct::graph__ ?*graphName*? ?__=__&#124;__:=__&#124;__as__&#124;__deserialize__ *source*?](#1)  
[__graphName__ *option* ?*arg arg \.\.\.*?](#2)  
[*graphName* __=__ *sourcegraph*](#3)  
[*graphName* __\-\->__ *destgraph*](#4)  







|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.4  
package require struct::graph ?2\.4\.3?  
package require struct::list ?1\.5?  
package require struct::set ?2\.2\.3?  

[__::struct::graph__ ?*graphName*? ?__=__&#124;__:=__&#124;__as__&#124;__deserialize__ *source*?](#1)  
[__graphName__ *option* ?*arg arg \.\.\.*?](#2)  
[*graphName* __=__ *sourcegraph*](#3)  
[*graphName* __\-\->__ *destgraph*](#4)  
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
    This is the *assignment* operator for graph objects\. It copies the graph
    contained in the graph object *sourcegraph* over the graph data in
    *graphName*\. The old contents of *graphName* are deleted by this
    operation\.

    This operation is in effect equivalent to

        *graphName* __deserialize__ \[*sourcegraph* __serialize__\]

    The operation assumes that the *sourcegraph* provides the method
    __serialize__ and that this method returns a valid graph serialization\.

  - <a name='4'></a>*graphName* __\-\->__ *destgraph*

    This is the *reverse assignment* operator for graph objects\. It copies the
    graph contained in the graph object *graphName* over the graph data in the
    object *destgraph*\. The old contents of *destgraph* are deleted by this
    operation\.

    This operation is in effect equivalent to

        *destgraph* __deserialize__ \[*graphName* __serialize__\]

    The operation assumes that the *destgraph* provides the method
    __deserialize__ and that this method takes a graph serialization\.

  - <a name='5'></a>*graphName* __append__ *key* *value*

    Appends a *value* to one of the keyed values associated with the graph\.







|













|







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
    This is the *assignment* operator for graph objects\. It copies the graph
    contained in the graph object *sourcegraph* over the graph data in
    *graphName*\. The old contents of *graphName* are deleted by this
    operation\.

    This operation is in effect equivalent to

    > *graphName* __deserialize__ \[*sourcegraph* __serialize__\]

    The operation assumes that the *sourcegraph* provides the method
    __serialize__ and that this method returns a valid graph serialization\.

  - <a name='4'></a>*graphName* __\-\->__ *destgraph*

    This is the *reverse assignment* operator for graph objects\. It copies the
    graph contained in the graph object *graphName* over the graph data in the
    object *destgraph*\. The old contents of *destgraph* are deleted by this
    operation\.

    This operation is in effect equivalent to

    > *destgraph* __deserialize__ \[*graphName* __serialize__\]

    The operation assumes that the *destgraph* provides the method
    __deserialize__ and that this method takes a graph serialization\.

  - <a name='5'></a>*graphName* __append__ *key* *value*

    Appends a *value* to one of the keyed values associated with the graph\.
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
    containing all arcs is returned\. Restrictions can limit the list of returned
    arcs based on the nodes that are connected by the arc, on the keyed values
    associated with the arc, or both\. A general filter command can be used as
    well\. The restrictions that involve connected nodes take a variable number
    of nodes as argument, specified after the name of the restriction itself\.

    The restrictions imposed by either __\-in__, __\-out__, __\-adj__,
    __\-inner__, or __\-embedded__ are applied first\. Specifying more than
    one of them is illegal\.

    After that the restrictions set via __\-key__ \(and __\-value__\) are
    applied\. Specifying more than one __\-key__ \(and __\-value__\) is
    illegal\. Specifying __\-value__ alone, without __\-key__ is illegal as
    well\.

    Any restriction set through __\-filter__ is applied last\. Specifying more







|
|







403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
    containing all arcs is returned\. Restrictions can limit the list of returned
    arcs based on the nodes that are connected by the arc, on the keyed values
    associated with the arc, or both\. A general filter command can be used as
    well\. The restrictions that involve connected nodes take a variable number
    of nodes as argument, specified after the name of the restriction itself\.

    The restrictions imposed by either __\-in__, __\-out__, __\-adj__,
    __\-inner__, or __\-embedding__ are applied first\. Specifying more
    than one of them is illegal\.

    After that the restrictions set via __\-key__ \(and __\-value__\) are
    applied\. Specifying more than one __\-key__ \(and __\-value__\) is
    illegal\. Specifying __\-value__ alone, without __\-key__ is illegal as
    well\.

    Any restriction set through __\-filter__ is applied last\. Specifying more
446
447
448
449
450
451
452








453
454
455
456
457
458
459
        nodes\.

      * __\-embedding__

        Return a list of all arcs adjacent to exactly one of the nodes in the
        set\. This is the set of arcs connecting the subgraph spawned by the
        specified nodes to the rest of the graph\.









      * __\-key__ *key*

        Limit the list of arcs that are returned to those arcs that have an
        associated key *key*\.

      * __\-value__ *value*







>
>
>
>
>
>
>
>







446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
        nodes\.

      * __\-embedding__

        Return a list of all arcs adjacent to exactly one of the nodes in the
        set\. This is the set of arcs connecting the subgraph spawned by the
        specified nodes to the rest of the graph\.

    *Attention*: After the above options any word with a leading dash which is
    not a valid option is treated as a node name instead of an invalid option to
    error out on\. This condition holds until either a valid option terminates
    the list of nodes, or the end of the command is reached, whichever comes
    first\.

    The remaining filter options are:

      * __\-key__ *key*

        Limit the list of arcs that are returned to those arcs that have an
        associated key *key*\.

      * __\-value__ *value*
588
589
590
591
592
593
594
595
596



597
598
599
600
601
602
603
604

    Return a list of nodes in the graph\. Restrictions can limit the list of
    returned nodes based on neighboring nodes, or based on the keyed values
    associated with the node\. The restrictions that involve neighboring nodes
    have a list of nodes as argument, specified after the name of the
    restriction itself\.

    The possible restrictions are the same as for method __arcs__\. The exact
    meanings change slightly, as they operate on nodes instead of arcs\. The



    command recognizes:

      * __\-in__

        Return a list of all nodes with at least one outgoing arc ending in a
        node found in the specified set of nodes\. Alternatively specified as the
        set of source nodes for the __\-in__ arcs of the node set\. The
        *incoming neighbours*\.







|
|
>
>
>
|







596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615

    Return a list of nodes in the graph\. Restrictions can limit the list of
    returned nodes based on neighboring nodes, or based on the keyed values
    associated with the node\. The restrictions that involve neighboring nodes
    have a list of nodes as argument, specified after the name of the
    restriction itself\.

    The possible restrictions are the same as for method __arcs__\. Note that
    while the exact meanings change slightly, as they operate on nodes instead
    of arcs, the general behaviour is the same, especially when it comes to the
    handling of words with a leading dash in node lists\.

    The command recognizes:

      * __\-in__

        Return a list of all nodes with at least one outgoing arc ending in a
        node found in the specified set of nodes\. Alternatively specified as the
        set of source nodes for the __\-in__ arcs of the node set\. The
        *incoming neighbours*\.
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

    For all attribute dictionaries they keys are the names of the attributes,
    and the values are the values for each name\.

    *Note:* The order of the nodes in the serialization has no relevance, nor
    has the order of the arcs per node\.

        \# A possible serialization for the graph structure
        \#

        \#        d \-\-\-\-\-> %2
        \#       /         ^ \\\\
        \#      /         /   \\\\
        \#     /         b     \\\\
        \#    /         /       \\\\
        \#  %1 <\- a \- %0         e
        \#    ^         \\\\      /
        \#     \\\\        c     /
        \#      \\\\        \\\\  /
        \#       \\\\        v v
        \#        f \-\-\-\-\-\- %3
        \# is
        \#

        \# %3 \{\} \{\{f 6 \{\}\}\} %0 \{\} \{\{a 6 \{\}\} \{b 9 \{\}\} \{c 0 \{\}\}\} %1 \{\} \{\{d 9 \{\}\}\} %2 \{\} \{\{e 0 \{\}\}\} \{\}
        \#

        \# This assumes that the graph has neither attribute data nor weighted arcs\.

  - <a name='64'></a>*graphName* __set__ *key* ?*value*?

    Set or get one of the keyed values associated with a graph\. A graph may have
    any number of keyed values associated with it\. If *value* is not
    specified, this command returns the current value assigned to the key; if
    *value* is specified, this command assigns that value to the key\.







|
<
>
|
|
|
|
|
|
|
|
|
|
|
|
<
>
|
<
>
|







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

    For all attribute dictionaries they keys are the names of the attributes,
    and the values are the values for each name\.

    *Note:* The order of the nodes in the serialization has no relevance, nor
    has the order of the arcs per node\.

        # A possible serialization for the graph structure

        #
        #        d -----> %2
        #       /         ^ \
        #      /         /   \
        #     /         b     \
        #    /         /       \
        #  %1 <- a - %0         e
        #    ^         \\      /
        #     \\        c     /
        #      \\        \\  /
        #       \\        v v
        #        f ------ %3
        # is

        #
        # %3 {} {{f 6 {}}} %0 {} {{a 6 {}} {b 9 {}} {c 0 {}}} %1 {} {{d 9 {}}} %2 {} {{e 0 {}}} {}

        #
        # This assumes that the graph has neither attribute data nor weighted arcs.

  - <a name='64'></a>*graphName* __set__ *key* ?*value*?

    Set or get one of the keyed values associated with a graph\. A graph may have
    any number of keyed values associated with it\. If *value* is not
    specified, this command returns the current value assigned to the key; if
    *value* is specified, this command assigns that value to the key\.
867
868
869
870
871
872
873
874

# <a name='category'></a>CATEGORY

Data structures

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2002\-2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
878
879
880
881
882
883
884
885

# <a name='category'></a>CATEGORY

Data structures

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2002\-2009,2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/struct/graphops.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

[//000000001]: # (struct::graph::op \- Tcl Data Structures)
[//000000002]: # (Generated from file 'graphops\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2008 Alejandro Paz <vidriloco@gmail\.com>  
Copyright &copy; 2008 \(docs\) Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>  
Copyright &copy; 2009 Michal Antoniewski <antoniewski\.m@gmail\.com>)
[//000000004]: # (struct::graph::op\(n\) 0\.11\.3 tcllib "Tcl Data Structures")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14

[//000000001]: # (struct::graph::op \- Tcl Data Structures)
[//000000002]: # (Generated from file 'graphops\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2008 Alejandro Paz <vidriloco@gmail\.com>)
[//000000004]: # (Copyright &copy; 2008 \(docs\) Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000005]: # (Copyright &copy; 2009 Michal Antoniewski <antoniewski\.m@gmail\.com>)
[//000000006]: # (struct::graph::op\(n\) 0\.11\.3 tcllib "Tcl Data Structures")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

Changes to embedded/md/tcllib/files/modules/struct/matrix.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (struct::matrix \- Tcl Data Structures)
[//000000002]: # (Generated from file 'matrix\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2002\-2013 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (struct::matrix\(n\) 2\.0\.3 tcllib "Tcl Data Structures")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (struct::matrix \- Tcl Data Structures)
[//000000002]: # (Generated from file 'matrix\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2002\-2013,2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (struct::matrix\(n\) 2\.0\.4 tcllib "Tcl Data Structures")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require struct::matrix ?2\.0\.3?  

[__::struct::matrix__ ?*matrixName*? ?__=__&#124;__:=__&#124;__as__&#124;__deserialize__ *source*?](#1)  
[__matrixName__ *option* ?*arg arg \.\.\.*?](#2)  
[*matrixName* __=__ *sourcematrix*](#3)  
[*matrixName* __\-\->__ *destmatrix*](#4)  
[*matrixName* __add column__ ?*values*?](#5)  
[*matrixName* __add row__ ?*values*?](#6)  







|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require struct::matrix ?2\.0\.4?  

[__::struct::matrix__ ?*matrixName*? ?__=__&#124;__:=__&#124;__as__&#124;__deserialize__ *source*?](#1)  
[__matrixName__ *option* ?*arg arg \.\.\.*?](#2)  
[*matrixName* __=__ *sourcematrix*](#3)  
[*matrixName* __\-\->__ *destmatrix*](#4)  
[*matrixName* __add column__ ?*values*?](#5)  
[*matrixName* __add row__ ?*values*?](#6)  
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
    This is the assignment operator for matrix objects\. It copies the matrix
    contained in the matrix object *sourcematrix* over the matrix data in
    *matrixName*\. The old contents of *matrixName* are deleted by this
    operation\.

    This operation is in effect equivalent to

        *matrixName* __deserialize__ \[*sourcematrix* __serialize__\]

  - <a name='4'></a>*matrixName* __\-\->__ *destmatrix*

    This is the reverse assignment operator for matrix objects\. It copies the
    matrix contained in the matrix object *matrixName* over the matrix data in
    the object *destmatrix*\. The old contents of *destmatrix* are deleted by
    this operation\.

    This operation is in effect equivalent to

        *destmatrix* __deserialize__ \[*matrixName* __serialize__\]

  - <a name='5'></a>*matrixName* __add column__ ?*values*?

    Extends the matrix by one column and then acts like __set column__ \(see
    below\) on this new column if there were *values* supplied\. Without
    *values* the new cells will be set to the empty string\. The new column is
    appended immediately behind the last existing column\.







|










|







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
    This is the assignment operator for matrix objects\. It copies the matrix
    contained in the matrix object *sourcematrix* over the matrix data in
    *matrixName*\. The old contents of *matrixName* are deleted by this
    operation\.

    This operation is in effect equivalent to

    > *matrixName* __deserialize__ \[*sourcematrix* __serialize__\]

  - <a name='4'></a>*matrixName* __\-\->__ *destmatrix*

    This is the reverse assignment operator for matrix objects\. It copies the
    matrix contained in the matrix object *matrixName* over the matrix data in
    the object *destmatrix*\. The old contents of *destmatrix* are deleted by
    this operation\.

    This operation is in effect equivalent to

    > *destmatrix* __deserialize__ \[*matrixName* __serialize__\]

  - <a name='5'></a>*matrixName* __add column__ ?*values*?

    Extends the matrix by one column and then acts like __set column__ \(see
    below\) on this new column if there were *values* supplied\. Without
    *values* the new cells will be set to the empty string\. The new column is
    appended immediately behind the last existing column\.
390
391
392
393
394
395
396
397
398

399
400
401
402

403
404

405
406
407
408
409
410
411
412
    The last element of the list contains the values of the matrix cells we have
    serialized, in the form of a value like it is returned by the __get
    rect__\. However empty cells to the right and bottom of the matrix can be
    left out of that value as the size information in the serialization allows
    the receiver the creation of a matrix with the proper size despite the
    missing values\.

        \# A possible serialization for the matrix structure
        \#

        \# &#124; a b d g &#124;
        \# &#124; c e     &#124;
        \# &#124; f       &#124;
        \#

        \# is
        \#

        \# 3 4 \{\{a b d g\} \{c e\} \{f\}\}

  - <a name='36'></a>*matrixName* __set cell__ *column row value*

    Sets the value in the cell identified by row and column index to the data in
    the third argument\.

  - <a name='37'></a>*matrixName* __set column__ *column values*







|
<
>
|
|
|
<
>
|
<
>
|







390
391
392
393
394
395
396
397

398
399
400
401

402
403

404
405
406
407
408
409
410
411
412
    The last element of the list contains the values of the matrix cells we have
    serialized, in the form of a value like it is returned by the __get
    rect__\. However empty cells to the right and bottom of the matrix can be
    left out of that value as the size information in the serialization allows
    the receiver the creation of a matrix with the proper size despite the
    missing values\.

        # A possible serialization for the matrix structure

        #
        # | a b d g |
        # | c e     |
        # | f       |

        #
        # is

        #
        # 3 4 {{a b d g} {c e} {f}}

  - <a name='36'></a>*matrixName* __set cell__ *column row value*

    Sets the value in the cell identified by row and column index to the data in
    the third argument\.

  - <a name='37'></a>*matrixName* __set column__ *column values*
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
# <a name='section2'></a>EXAMPLES

The examples below assume a 5x5 matrix M with the first row containing the
values 1 to 5, with 1 in the top\-left cell\. Each other row contains the contents
of the row above it, rotated by one cell to the right\.

    % M get rect 0 0 4 4
    \{\{1 2 3 4 5\} \{5 1 2 3 4\} \{4 5 1 2 3\} \{3 4 5 1 2\} \{2 3 4 5 1\}\}

    % M set rect 1 1 \{\{0 0 0\} \{0 0 0\} \{0 0 0\}\}
    % M get rect 0 0 4 4
    \{\{1 2 3 4 5\} \{5 0 0 0 4\} \{4 0 0 0 3\} \{3 0 0 0 2\} \{2 3 4 5 1\}\}

Assuming that the style definitions in the example section of the manpage for
the package __[report](\.\./report/report\.md)__ are loaded into the
interpreter now an example which formats a matrix into a tabular report\. The
code filling the matrix with data is not shown\. contains useful data\.

    % ::struct::matrix m
    % \# \.\.\. fill m with data, assume 5 columns
    % ::report::report r 5 style captionedtable 1
    % m format 2string r
    \+\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\+
    &#124;000&#124;VERSIONS:          &#124;2:8\.4a3&#124;1:8\.4a3&#124;1:8\.4a3%&#124;
    \+\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\+
    &#124;001&#124;CATCH return ok    &#124;7      &#124;13     &#124;53\.85   &#124;
    &#124;002&#124;CATCH return error &#124;68     &#124;91     &#124;74\.73   &#124;
    &#124;003&#124;CATCH no catch used&#124;7      &#124;14     &#124;50\.00   &#124;
    &#124;004&#124;IF if true numeric &#124;12     &#124;33     &#124;36\.36   &#124;
    &#124;005&#124;IF elseif          &#124;15     &#124;47     &#124;31\.91   &#124;
    &#124;   &#124;true numeric       &#124;       &#124;       &#124;        &#124;
    \+\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\+
    %
    % \# alternate way of doing the above
    % r printmatrix m

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *struct :: matrix* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report







|

|

|







|


|
|
|
|
|
|
|
|
|
|

|







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
# <a name='section2'></a>EXAMPLES

The examples below assume a 5x5 matrix M with the first row containing the
values 1 to 5, with 1 in the top\-left cell\. Each other row contains the contents
of the row above it, rotated by one cell to the right\.

    % M get rect 0 0 4 4
    {{1 2 3 4 5} {5 1 2 3 4} {4 5 1 2 3} {3 4 5 1 2} {2 3 4 5 1}}

    % M set rect 1 1 {{0 0 0} {0 0 0} {0 0 0}}
    % M get rect 0 0 4 4
    {{1 2 3 4 5} {5 0 0 0 4} {4 0 0 0 3} {3 0 0 0 2} {2 3 4 5 1}}

Assuming that the style definitions in the example section of the manpage for
the package __[report](\.\./report/report\.md)__ are loaded into the
interpreter now an example which formats a matrix into a tabular report\. The
code filling the matrix with data is not shown\. contains useful data\.

    % ::struct::matrix m
    % # ... fill m with data, assume 5 columns
    % ::report::report r 5 style captionedtable 1
    % m format 2string r
    +---+-------------------+-------+-------+--------+
    |000|VERSIONS:          |2:8.4a3|1:8.4a3|1:8.4a3%|
    +---+-------------------+-------+-------+--------+
    |001|CATCH return ok    |7      |13     |53.85   |
    |002|CATCH return error |68     |91     |74.73   |
    |003|CATCH no catch used|7      |14     |50.00   |
    |004|IF if true numeric |12     |33     |36.36   |
    |005|IF elseif          |15     |47     |31.91   |
    |   |true numeric       |       |       |        |
    +---+-------------------+-------+-------+--------+
    %
    % # alternate way of doing the above
    % r printmatrix m

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *struct :: matrix* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report
529
530
531
532
533
534
535
536

# <a name='category'></a>CATEGORY

Data structures

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2002\-2013 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
529
530
531
532
533
534
535
536

# <a name='category'></a>CATEGORY

Data structures

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2002\-2013,2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/struct/matrix1.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (struct::matrix\_v1 \- Tcl Data Structures)
[//000000002]: # (Generated from file 'matrix1\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2002 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (struct::matrix\_v1\(n\) 1\.2\.1 tcllib "Tcl Data Structures")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (struct::matrix\_v1 \- Tcl Data Structures)
[//000000002]: # (Generated from file 'matrix1\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2002,2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (struct::matrix\_v1\(n\) 1\.2\.2 tcllib "Tcl Data Structures")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require struct::matrix ?1\.2\.1?  

[__matrixName__ *option* ?*arg arg \.\.\.*?](#1)  
[*matrixName* __add column__ ?*values*?](#2)  
[*matrixName* __add row__ ?*values*?](#3)  
[*matrixName* __add columns__ *n*](#4)  
[*matrixName* __add rows__ *n*](#5)  
[*matrixName* __cells__](#6)  







|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require struct::matrix ?1\.2\.2?  

[__matrixName__ *option* ?*arg arg \.\.\.*?](#1)  
[*matrixName* __add column__ ?*values*?](#2)  
[*matrixName* __add row__ ?*values*?](#3)  
[*matrixName* __add columns__ *n*](#4)  
[*matrixName* __add rows__ *n*](#5)  
[*matrixName* __cells__](#6)  
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
# <a name='section2'></a>EXAMPLES

The examples below assume a 5x5 matrix M with the first row containing the
values 1 to 5, with 1 in the top\-left cell\. Each other row contains the contents
of the row above it, rotated by one cell to the right\.

    % M getrect 0 0 4 4
    \{\{1 2 3 4 5\} \{5 1 2 3 4\} \{4 5 1 2 3\} \{3 4 5 1 2\} \{2 3 4 5 1\}\}

    % M setrect 1 1 \{\{0 0 0\} \{0 0 0\} \{0 0 0\}\}
    % M getrect 0 0 4 4
    \{\{1 2 3 4 5\} \{5 0 0 0 4\} \{4 0 0 0 3\} \{3 0 0 0 2\} \{2 3 4 5 1\}\}

Assuming that the style definitions in the example section of the manpage for
the package __[report](\.\./report/report\.md)__ are loaded into the
interpreter now an example which formats a matrix into a tabular report\. The
code filling the matrix with data is not shown\. contains useful data\.

    % ::struct::matrix m
    % \# \.\.\. fill m with data, assume 5 columns
    % ::report::report r 5 style captionedtable 1
    % m format 2string r
    \+\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\+
    &#124;000&#124;VERSIONS:          &#124;2:8\.4a3&#124;1:8\.4a3&#124;1:8\.4a3%&#124;
    \+\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\+
    &#124;001&#124;CATCH return ok    &#124;7      &#124;13     &#124;53\.85   &#124;
    &#124;002&#124;CATCH return error &#124;68     &#124;91     &#124;74\.73   &#124;
    &#124;003&#124;CATCH no catch used&#124;7      &#124;14     &#124;50\.00   &#124;
    &#124;004&#124;IF if true numeric &#124;12     &#124;33     &#124;36\.36   &#124;
    &#124;005&#124;IF elseif          &#124;15     &#124;47     &#124;31\.91   &#124;
    &#124;   &#124;true numeric       &#124;       &#124;       &#124;        &#124;
    \+\-\-\-\+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\+\-\-\-\-\-\-\-\-\+
    %
    % \# alternate way of doing the above
    % r printmatrix m

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *struct :: matrix* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report







|

|

|







|


|
|
|
|
|
|
|
|
|
|

|







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
# <a name='section2'></a>EXAMPLES

The examples below assume a 5x5 matrix M with the first row containing the
values 1 to 5, with 1 in the top\-left cell\. Each other row contains the contents
of the row above it, rotated by one cell to the right\.

    % M getrect 0 0 4 4
    {{1 2 3 4 5} {5 1 2 3 4} {4 5 1 2 3} {3 4 5 1 2} {2 3 4 5 1}}

    % M setrect 1 1 {{0 0 0} {0 0 0} {0 0 0}}
    % M getrect 0 0 4 4
    {{1 2 3 4 5} {5 0 0 0 4} {4 0 0 0 3} {3 0 0 0 2} {2 3 4 5 1}}

Assuming that the style definitions in the example section of the manpage for
the package __[report](\.\./report/report\.md)__ are loaded into the
interpreter now an example which formats a matrix into a tabular report\. The
code filling the matrix with data is not shown\. contains useful data\.

    % ::struct::matrix m
    % # ... fill m with data, assume 5 columns
    % ::report::report r 5 style captionedtable 1
    % m format 2string r
    +---+-------------------+-------+-------+--------+
    |000|VERSIONS:          |2:8.4a3|1:8.4a3|1:8.4a3%|
    +---+-------------------+-------+-------+--------+
    |001|CATCH return ok    |7      |13     |53.85   |
    |002|CATCH return error |68     |91     |74.73   |
    |003|CATCH no catch used|7      |14     |50.00   |
    |004|IF if true numeric |12     |33     |36.36   |
    |005|IF elseif          |15     |47     |31.91   |
    |   |true numeric       |       |       |        |
    +---+-------------------+-------+-------+--------+
    %
    % # alternate way of doing the above
    % r printmatrix m

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *struct :: matrix* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report
410
411
412
413
414
415
416
417

# <a name='category'></a>CATEGORY

Data structures

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2002 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
410
411
412
413
414
415
416
417

# <a name='category'></a>CATEGORY

Data structures

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2002,2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/struct/pool.md.

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
In this example, brand names are used to label the various items\. However, a
brand name could be regarded as a property of an item\. Because the pool command
is not designed to manage properties of items, they need to be managed
separately\. In the latter case the items should be labeled with more neutral
names such as: car1, car2, car3 , etc \.\.\. and a separate database or array
should hold the brand names associated with the car labels\.

    1\. Load the package into an interpreter
    % package require pool
    0\.1

    2\. Create a pool object called \`CarPool' with a maximum size of 55 items \(cars\):
    % pool CarPool 55
    CarPool

    4\. Add items to the pool:
    % CarPool add Toyota Trabant Chrysler1 Chrysler2 Volkswagen

    5\. Somebody crashed the Toyota\. Remove it from the pool as follows:
    % CarPool remove Toyota

    6\. Acquired a new car for the pool\. Add it as follows:
    % CarPool add Nissan

    7\. Check whether the pool was adjusted correctly:
    % CarPool info allitems
    Trabant Chrysler1 Chrysler2 Volkswagen Nissan

Suspend the interactive session temporarily, and show the programmatic use of
the request subcommand:

    \# Mrs\. Swift needs a car\. She doesn't have a preference for a
    \# particular car\. We'll issue a request on her behalf as follows:
    if \{ \[CarPool request car \-allocID "Mrs\. Swift"\] \}  \{
        \# request was honoured, process the variable \`car'
        puts "$car has been allocated to \[CarPool info allocID $car\]\."
    \} else \{
        \# request was denied
         puts "No car available\."
    \}


Note how the __if__ command uses the value returned by the __request__
subcommand\.

    \# Suppose Mr\. Wiggly has a preference for the Trabant:
    if \{ \[CarPool request car \-allocID "Mr\. Wiggly" \-prefer Trabant\] \}  \{
        \# request was honoured, process the variable \`car'
        puts "$car has been allocated to \[CarPool info allocID $car\]\."
    \} else \{
        \# request was denied
         puts "The Trabant was not available\."
    \}


Resume the interactive session:

    8\. When the car is returned then you can render it available by:
    % CarPool release Trabant

    9\. When done, you delete the pool\.
    % CarPool destroy
    Couldn't destroy \`CarPool' because some items are still allocated\.

    Oops, forgot that Mrs\. Swift still occupies a car\.

    10\. We force the destruction of the pool as follows:
    % CarPool destroy \-force

*Example 2*

This example describes the case from which the author's need for pool management
originated\. It is an example of a server application that receives requests from
client applications\. The client requests are dispatched onto a back\-end
application before being returned to the client application\. In many cases there
are a few equivalent instances of back\-end applications to which a client
request may be passed along\. The file descriptors that identify the channels to
these back\-end instances make up a pool of connections\. A particular connection
may be allocated to just one client request at a time\.

    \# Create the pool of connections \(pipes\)
    set maxpipes 10
    pool Pipes $maxpipes
    for \{set i 0\} \{$i < $maxpipes\} \{incr i\} \{
        set fd \[open "&#124;backendApplication" w\+\]
        Pipes add $fd
    \}


    \# A client request comes in\. The request is identified as \`clientX'\.
    \# Dispatch it onto an instance of a back\-end application
    if \{ \[Pipes request fd \-allocID clientX\] \} \{
        \# a connection was allocated
        \# communicate to the back\-end application via the variable \`fd'
        puts $fd "someInstruction"
        \# \.\.\.\.\.\. etc\.
    \} else \{
        \# all connections are currently occupied
        \# store the client request in a queue for later processing,
        \# or return a 'Server busy' message to the client\.
    \}


# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *struct :: pool* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report
any ideas for enhancements you may have for either package and/or documentation\.







|

|

|



|


|


|


|






|
|
|
|
|
|
|
|
<
|
>



|
|
|
|
|
|
|
<
>



|


|

|

|

|
|












|


|
|

<
|
>
|
|
|
|
|

|
|
|
|
|
<
>







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
In this example, brand names are used to label the various items\. However, a
brand name could be regarded as a property of an item\. Because the pool command
is not designed to manage properties of items, they need to be managed
separately\. In the latter case the items should be labeled with more neutral
names such as: car1, car2, car3 , etc \.\.\. and a separate database or array
should hold the brand names associated with the car labels\.

    1. Load the package into an interpreter
    % package require pool
    0.1

    2. Create a pool object called `CarPool' with a maximum size of 55 items (cars):
    % pool CarPool 55
    CarPool

    4. Add items to the pool:
    % CarPool add Toyota Trabant Chrysler1 Chrysler2 Volkswagen

    5. Somebody crashed the Toyota. Remove it from the pool as follows:
    % CarPool remove Toyota

    6. Acquired a new car for the pool. Add it as follows:
    % CarPool add Nissan

    7. Check whether the pool was adjusted correctly:
    % CarPool info allitems
    Trabant Chrysler1 Chrysler2 Volkswagen Nissan

Suspend the interactive session temporarily, and show the programmatic use of
the request subcommand:

    # Mrs. Swift needs a car. She doesn't have a preference for a
    # particular car. We'll issue a request on her behalf as follows:
    if { [CarPool request car -allocID "Mrs. Swift"] }  {
        # request was honoured, process the variable `car'
        puts "$car has been allocated to [CarPool info allocID $car]."
    } else {
        # request was denied
         puts "No car available."

    }

Note how the __if__ command uses the value returned by the __request__
subcommand\.

    # Suppose Mr. Wiggly has a preference for the Trabant:
    if { [CarPool request car -allocID "Mr. Wiggly" -prefer Trabant] }  {
        # request was honoured, process the variable `car'
        puts "$car has been allocated to [CarPool info allocID $car]."
    } else {
        # request was denied
         puts "The Trabant was not available."

    }

Resume the interactive session:

    8. When the car is returned then you can render it available by:
    % CarPool release Trabant

    9. When done, you delete the pool.
    % CarPool destroy
    Couldn't destroy `CarPool' because some items are still allocated.

    Oops, forgot that Mrs. Swift still occupies a car.

    10. We force the destruction of the pool as follows:
    % CarPool destroy -force

*Example 2*

This example describes the case from which the author's need for pool management
originated\. It is an example of a server application that receives requests from
client applications\. The client requests are dispatched onto a back\-end
application before being returned to the client application\. In many cases there
are a few equivalent instances of back\-end applications to which a client
request may be passed along\. The file descriptors that identify the channels to
these back\-end instances make up a pool of connections\. A particular connection
may be allocated to just one client request at a time\.

    # Create the pool of connections (pipes)
    set maxpipes 10
    pool Pipes $maxpipes
    for {set i 0} {$i < $maxpipes} {incr i} {
        set fd [open "|backendApplication" w+]
        Pipes add $fd

    }

    # A client request comes in. The request is identified as `clientX'.
    # Dispatch it onto an instance of a back-end application
    if { [Pipes request fd -allocID clientX] } {
        # a connection was allocated
        # communicate to the back-end application via the variable `fd'
        puts $fd "someInstruction"
        # ...... etc.
    } else {
        # all connections are currently occupied
        # store the client request in a queue for later processing,
        # or return a 'Server busy' message to the client.

    }

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *struct :: pool* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report
any ideas for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/struct/record.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (struct::record \- Tcl Data Structures)
[//000000002]: # (Generated from file 'record\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2002, Brett Schwarz <brett\_schwarz@yahoo\.com>)
[//000000004]: # (struct::record\(n\) 1\.2\.1 tcllib "Tcl Data Structures")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>




|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (struct::record \- Tcl Data Structures)
[//000000002]: # (Generated from file 'record\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2002, Brett Schwarz <brett\_schwarz@yahoo\.com>)
[//000000004]: # (struct::record\(n\) 1\.2\.2 tcllib "Tcl Data Structures")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
21
22
23
24
25
26
27






28
29
30
31
32




33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55







56
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

  - [Synopsis](#synopsis)

  - [Description](#section1)

  - [RECORD MEMBERS](#section2)







  - [RECORD COMMAND](#section3)

  - [INSTANCE COMMAND](#section4)

  - [EXAMPLES](#section5)





  - [Bugs, Ideas, Feedback](#section6)

  - [Keywords](#keywords)

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require struct::record ?1\.2\.1?  

[__record define__ *recordName* *recordMembers* ?*instanceName1 instanceName2 \.\.\.*?](#1)  
[__record show__ *record*](#2)  
[__record show__ *instances* *recordName*](#3)  
[__record show__ *members* *recordName*](#4)  
[__record show__ *values* *instanceName*](#5)  
[__record exists__ *record* *recordName*](#6)  
[__record exists__ *instance* *instanceName*](#7)  
[__record delete__ *record* *recordName*](#8)  
[__record delete__ *instance* *instanceName*](#9)  







[*recordName* __*instanceName&#124;\#auto*__ ?*\-member1 value1 \-member2 value2 \.\.\.*?](#10)  
[*instanceName* __cget__ ?*\-member1 \-member2 \.\.\.*?](#11)  
[*instanceName* __configure__ ?*\-member1 value1 \-member2 value2 \.\.\.*?](#12)  

# <a name='description'></a>DESCRIPTION

The __::struct::record__ package provides a mechanism to group variables
together as one data structure, similar to a 'C' structure\. The members of a
record can be variables or other records\. However, a record can not contain
circular record, i\.e\. records that contain the same record as a member\.


This package was structured so that it is very similar to how Tk objects work\.
Each record definition creates a record object that encompasses that definition\.
Subsequently, that record object can create instances of that record\. These
instances can then be manipulated with the __cget__ and __configure__
methods\.

The package only contains one top level command, but several sub commands \(see
below\)\. It also obeys the namespace in which the record was define, hence the
objects returned are fully qualified\.

  - <a name='1'></a>__record define__ *recordName* *recordMembers* ?*instanceName1 instanceName2 \.\.\.*?

    Defines a record\. *recordName* is the name of the record, and is also used
    as an object command\. This object command is used to create instances of the
    record definition\. *recordMembers* are the members of the record that make
    up the record definition\. These are variables and other record\. If optional
    *instanceName* args are given, then an instance is generated after the
    definition is created for each *instanceName*\.

  - <a name='2'></a>__record show__ *record*

    Returns a list of records that have been defined\.

  - <a name='3'></a>__record show__ *instances* *recordName*








>
>
>
>
>
>





>
>
>
>












|










>
>
>
>
>
>
>
|
|
|




|
|
|
>








|






|
|
|
|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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

  - [Synopsis](#synopsis)

  - [Description](#section1)

  - [RECORD MEMBERS](#section2)

      - [Getting Values](#subsection1)

      - [Setting Values](#subsection2)

      - [Alias access](#subsection3)

  - [RECORD COMMAND](#section3)

  - [INSTANCE COMMAND](#section4)

  - [EXAMPLES](#section5)

      - [Example 1 \- Contact Information](#subsection4)

      - [Example 2 \- Linked List](#subsection5)

  - [Bugs, Ideas, Feedback](#section6)

  - [Keywords](#keywords)

  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require struct::record ?1\.2\.2?  

[__record define__ *recordName* *recordMembers* ?*instanceName1 instanceName2 \.\.\.*?](#1)  
[__record show__ *record*](#2)  
[__record show__ *instances* *recordName*](#3)  
[__record show__ *members* *recordName*](#4)  
[__record show__ *values* *instanceName*](#5)  
[__record exists__ *record* *recordName*](#6)  
[__record exists__ *instance* *instanceName*](#7)  
[__record delete__ *record* *recordName*](#8)  
[__record delete__ *instance* *instanceName*](#9)  
[*instanceName* __cget__ \-*member*](#10)  
[*instanceName* __cget__ \-*member1* \-*member2*](#11)  
[*instanceName* __cget__](#12)  
[*instanceName* __configure__](#13)  
[*instanceName*](#14)  
[*instanceName* __configure__ \-*member* *value*](#15)  
[*instanceName* __configure__ \-*member1* *value1* \-*member2* *value2*](#16)  
[*recordName* *instanceName*&#124;__\#auto__ ?*\-member1 value1 \-member2 value2 \.\.\.*?](#17)  
[*instanceName* __cget__ ?*\-member1 \-member2 \.\.\.*?](#18)  
[*instanceName* __configure__ ?*\-member1 value1 \-member2 value2 \.\.\.*?](#19)  

# <a name='description'></a>DESCRIPTION

The __::struct::record__ package provides a mechanism to group variables
together as one data structure, similar to a *[C](\.\./\.\./\.\./\.\./index\.md\#c)*
structure\. The members of a record can be variables or other records\. However, a
record can not contain circular records, i\.e\. records that contain the same
record as a member\.

This package was structured so that it is very similar to how Tk objects work\.
Each record definition creates a record object that encompasses that definition\.
Subsequently, that record object can create instances of that record\. These
instances can then be manipulated with the __cget__ and __configure__
methods\.

The package only contains one top level command, but several sub commands \(see
below\)\. It also obeys the namespace in which the record was defined, hence the
objects returned are fully qualified\.

  - <a name='1'></a>__record define__ *recordName* *recordMembers* ?*instanceName1 instanceName2 \.\.\.*?

    Defines a record\. *recordName* is the name of the record, and is also used
    as an object command\. This object command is used to create instances of the
    record definition\. The *recordMembers* are the members of the record that
    make up the record definition\. These are variables and other records\. If
    optional *instanceName* args are specified, then an instance is generated
    after the definition is created for each *instanceName*\.

  - <a name='2'></a>__record show__ *record*

    Returns a list of records that have been defined\.

  - <a name='3'></a>__record show__ *instances* *recordName*

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

    Deletes *recordName*, and all instances of *recordName*\. It will return
    an error if the record does not exist\.

  - <a name='9'></a>__record delete__ *instance* *instanceName*

    Deletes *instance* with the name of *instanceName*\. It will return an
    error if the instance does not exist\.


# <a name='section2'></a>RECORD MEMBERS

Record members can either be variables, or other records, However, the same
record can not be nested witin itself \(circular\)\. To define a nested record, you
need to specify the __record__ keyword, along the with name of the record,
and the name of the instance of that nested record\. For example, it would look
like this:

    \# this is the nested record
    record define mynestedrecord \{
        nest1
        nest2
    \}


    \# This is the main record
    record define myrecord \{
        mem1
        mem2
        \{record mynestedrecord mem3\}
    \}


You can also assign default or initial values to the members of a record, by
enclosing the member entry in braces:

    record define myrecord \{
        mem1
        \{mem2 5\}
    \}


All instances created from this record definition, will initially have 5 as the
value for *mem2*\. If no default is given, then the value will be the empty
string\.

*Getting Values*

To get a value of a member, there are several ways to do this\.

  1. To get a member value, then use the instance built\-in __cget__ method:

     *instanceName* __cget__ \-mem1


  1. To get multiple member values, you can specify them all in one command:

     *instanceName* __cget__ \-mem1 \-mem2


  1. To get a list of the key/value of all of the members, there are 3 ways:




     \- *instanceName* __cget__

     \- *instanceName* __configure__

     \- *instanceName*

  1. To get a value of a nested member, then use the dot notation:

     *instanceName* __cget__ \-mem3\.nest1


*Setting Values*

To set a value of a member, there are several ways to do this\.

  1. To set a member value, then use the instance built\-in __configure__
     method:

     *instanceName* __configure__ \-mem1 val1


  1. To set multiple member values, you can specify them all in one command:

     *instanceName* __configure__ \-mem1 va1 \-mem2 val2

  1. To set a value of a nested member, then use the dot notation:

     *instanceName* __configure__ \-mem3\.nest1 value


*Alias access*

In the original implementation, access was done by using dot notation similar to
how 'C' structures are accessed\. However, there was a concensus to make the
interface more Tcl like, which made sense\. However, the original alias access
still exists\. It might prove to be helpful to some\.

Basically, for every member of every instance, an alias is created\. This alias
is used to get and set values for that member\. An example will illustrate the
point, using the above defined records:

    \# Create an instance first
    % myrecord inst1
    ::inst1

    % \# To get a member of an instance, just use the
    % \# alias \(it behaves like a Tcl command\):
    % inst1\.mem1
    %
    % \# To set a member via the alias, just include
    % \# a value \(optionally the equal sign \- syntactic sugar\)
    % inst1\.mem1 = 5
    5

    % inst1\.mem1
    5

    % \# For nested records, just continue with the
    % \# dot notation \(note no equal sign\)
    % inst1\.mem3\.nest1 10
    10

    % inst1\.mem3\.nest1
    10

    % \# just the instance by itself gives all
    % \# member/values pairs for that instance
    % inst1

    \-mem1 5 \-mem2 \{\} \-mem3 \{\-nest1 10 \-nest2 \{\}\}
    % \# and to get all members within the nested record
    % inst1\.mem3
    \-nest1 10 \-nest2 \{\}
    %

# <a name='section3'></a>RECORD COMMAND

The following subcommands and corresponding arguments are available to any
record command:

  - <a name='10'></a>*recordName* __*instanceName&#124;\#auto*__ ?*\-member1 value1 \-member2 value2 \.\.\.*?

    Using the *recordName* object command that was created from the record
    definition, instances of the record definition can be created\. Once a
    instance is created, then it inherits the members of the record definition,
    very similar to how objects work\. During instance generation, an object
    command for the instance is created as well, using *instanceName*\. This

    object command is used to access the data members of the instance\. During
    the instantiation, values for that instance can be given, *but* all values
    must be given, and be given in key/value pairs\. Nested records, need to be
    in list format\.

    Optionally, *\#auto* can be used in place of *instanceName*\. When \#auto
    is used, then a instance name will automatically be generated, of the form
    recordName<integer>, where <integer> is a unique integer \(starting at 0\)
    that is generated\.

# <a name='section4'></a>INSTANCE COMMAND

The following subcommands and corresponding arguments are available to any
record instance command:

  - <a name='11'></a>*instanceName* __cget__ ?*\-member1 \-member2 \.\.\.*?

    Each instance has the sub command __cget__ associated with it\. This is
    very similar to how Tk widget's cget command works\. It queries the values of
    the member for that particular instance\. If no arguments are given, then a
    key/value list is returned\.

  - <a name='12'></a>*instanceName* __configure__ ?*\-member1 value1 \-member2 value2 \.\.\.*?

    Each instance has the sub command __configure__ associated with it\. This
    is very similar to how Tk widget's configure command works\. It sets the
    values of the particular member for that particular instance\. If no
    arguments are given, then a key/value list is returned\.

# <a name='section5'></a>EXAMPLES

Two examples are provided to give an good illustration on how to use this
package\.

*Example 1*

Probably the most obvious example would be to hold contact information, such as
addresses, phone numbers, comments, etc\. Since a person can have multiple phone
numbers, multiple email addresses, etc, we will use nested records to define
these\. So, the first thing we do is define the nested records:

    \#\#
    \#\#  This is an interactive example, to see what is
    \#\#  returned by each command as well\.
    \#\#

    % namespace import ::struct::record::\*

    % \# define a nested record\. Notice that country has default 'USA'\.
    % record define locations \{
        street
        street2
        city
        state
        zipcode
        \{country USA\}
        phone
    \}

    ::locations
    % \# Define the main record\. Notice that it uses the location record twice\.
    % record define contacts \{
        first
        middle
        last
        \{record locations home\}
        \{record locations work\}
    \}

    ::contacts
    % \# Create an instance for the contacts record\.
    % contacts cont1
    ::cont1
    % \# Display some introspection values
    % record show records
    ::contacts ::locations
    % \#
    % record show values cont1
    \-first \{\} \-middle \{\} \-last \{\} \-home \{\-street \{\} \-street2 \{\} \-city \{\} \-state \{\} \-zipcode \{\} \-country USA \-phone \{\}\} \-work \{\-street \{\} \-street2 \{\} \-city \{\} \-state \{\} \-zipcode \{\} \-country USA \-phone \{\}\}
    % \#
    % record show instances contacts
    ::cont1
    % \#
    % cont1 config
    \-first \{\} \-middle \{\} \-last \{\} \-home \{\-street \{\} \-street2 \{\} \-city \{\} \-state \{\} \-zipcode \{\} \-country USA \-phone \{\}\} \-work \{\-street \{\} \-street2 \{\} \-city \{\} \-state \{\} \-zipcode \{\} \-country USA \-phone \{\}\}
    % \#
    % cont1 cget
    \-first \{\} \-middle \{\} \-last \{\} \-home \{\-street \{\} \-street2 \{\} \-city \{\} \-state \{\} \-zipcode \{\} \-country USA \-phone \{\}\} \-work \{\-street \{\} \-street2 \{\} \-city \{\} \-state \{\} \-zipcode \{\} \-country USA \-phone \{\}\}
    % \# copy one record to another record
    % record define contacts2 \[record show members contacts\]
    ::contacts2
    % record show members contacts2
    first middle last \{record locations home\} \{record locations work\}
    % record show members contacts
    first middle last \{record locations home\} \{record locations work\}
    %

*Example 1*

This next example just illustrates a simple linked list

    % \# define a very simple record for linked list
    % record define llist \{
        value
        next
    \}

    ::llist
    % llist lstart
    ::lstart
    % lstart config \-value 1 \-next \[llist \#auto\]
    % \[lstart cget \-next\] config \-value 2 \-next \[llist \#auto\]
    % \[\[lstart cget \-next\] cget \-next\] config \-value 3 \-next "end"
    % set next lstart
    lstart
    % while 1 \{
    lappend values \[$next cget \-value\]
    set next \[$next cget \-next\]
    if \{\[string match "end" $next\]\} \{break\}
    \}

    % puts "$values"
    1 2 3
    % \# cleanup linked list
    % \# We could just use delete record llist also
    % foreach I \[record show instances llist\] \{
    record delete instance $I
    \}

    % record show instances llist
    %

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *struct :: record* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report







|
>






|
|

|
|


<
|
>
|
|


|
<
>




|

|
<
|
>
|
|
|

|



|

|
>

|

|

>
|
>
>
>

|

|

|

<
|
<
>

|



|
<

|
>

|

|

|

|
>

|


|
|
|





|


>
|
|
|
|
|
|
|

>
|

>
|
|
|

>
|

>
|
|

>
|
|
|
|
<






|


|
|
|
|
>
|
|
|
|

|
|
|
|






|

|
|
|
|

|

|
|
|
|



|


|






|
|
|
|

|

|
|





|

<
>

|
|



|
|
<
>

|


|


|

|
|


|

|
|

|
|
|


|

|


|



|
|


<
>
|
|

|
|
|


|
|
|
|
<
>


|
|
|
|
<
>
|







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

    Deletes *recordName*, and all instances of *recordName*\. It will return
    an error if the record does not exist\.

  - <a name='9'></a>__record delete__ *instance* *instanceName*

    Deletes *instance* with the name of *instanceName*\. It will return an
    error if the instance does not exist\. Note that this recursively deletes any
    nested instances as well\.

# <a name='section2'></a>RECORD MEMBERS

Record members can either be variables, or other records, However, the same
record can not be nested witin itself \(circular\)\. To define a nested record, you
need to specify the __record__ keyword, along the with name of the record,
and the name of the instance of that nested record \(within the container\)\. For
example, it would look like this:

    # this is the nested record
    record define mynestedrecord {
        nest1
        nest2

    }

    # This is the main record
    record define myrecord {
        mem1
        mem2
        {record mynestedrecord mem3}

    }

You can also assign default or initial values to the members of a record, by
enclosing the member entry in braces:

    record define myrecord {
        mem1
        {mem2 5}

    }

All instances created from this record definition will initially have __5__
as the value for member *mem2*\. If no default is given, then the value will be
the empty string\.

## <a name='subsection1'></a>Getting Values

To get a value of a member, there are several ways to do this\.

  - <a name='10'></a>*instanceName* __cget__ \-*member*

    In this form the built\-in __cget__ instance method returns the value of
    the specified *member*\. Note the leading dash\.

    To reach a nested member use *dot notation*:

    > *instanceName* __cget__ \-mem3\.nest1

  - <a name='11'></a>*instanceName* __cget__ \-*member1* \-*member2*

    In this form the built\-in __cget__ instance method returns a list
    containing the values of both specified members, in the order of
    specification\.

  - <a name='12'></a>*instanceName* __cget__

  - <a name='13'></a>*instanceName* __configure__

  - <a name='14'></a>*instanceName*


    These forms are all equivalent\. They return a dictionary of all members and

    the associated values\.

## <a name='subsection2'></a>Setting Values

To set a value of a member, there are several ways to do this\.

  - <a name='15'></a>*instanceName* __configure__ \-*member* *value*


    In this form the built\-in __configure__ instance method sets the
    specified *member* to the given *value*\. Note the leading dash\.

    To reach a nested member use *dot notation*:

    > *instanceName* __configure__ \-mem3\.nest1 value

  - <a name='16'></a>*instanceName* __configure__ \-*member1* *value1* \-*member2* *value2*

    In this form the built\-in __configure__ instance method sets all
    specified members to the associated values\.

## <a name='subsection3'></a>Alias access

In the original implementation, access was done by using dot notation similar to
how *[C](\.\./\.\./\.\./\.\./index\.md\#c)* structures are accessed\. However, there
was a concensus to make the interface more Tcl like, which made sense\. However,
the original alias access still exists\. It might prove to be helpful to some\.

Basically, for every member of every instance, an alias is created\. This alias
is used to get and set values for that member\. An example will illustrate the
point, using the above defined records:

    % # Create an instance first
    % myrecord inst1
    ::inst1

    % # To get a member of an instance, just use the alias. It behaves
    % # like a Tcl command:
    % inst1.mem1

    % # To set a member via the alias, just include a value. And optionally
    % # the equal sign - syntactic sugar.
    % inst1.mem1 = 5
    5

    % inst1.mem1
    5

    % # For nested records, just continue with the dot notation.
    % # note, no equal sign.
    % inst1.mem3.nest1 10
    10

    % inst1.mem3.nest1
    10

    % # just the instance by itself gives all member/values pairs for that
    % # instance
    % inst1
    -mem1 5 -mem2 {} -mem3 {-nest1 10 -nest2 {}}

    % # and to get all members within the nested record
    % inst1.mem3
    -nest1 10 -nest2 {}


# <a name='section3'></a>RECORD COMMAND

The following subcommands and corresponding arguments are available to any
record command:

  - <a name='17'></a>*recordName* *instanceName*&#124;__\#auto__ ?*\-member1 value1 \-member2 value2 \.\.\.*?

    Using the *recordName* object command that was created from the record
    definition, instances of the record definition can be created\. Once an
    instance is created, it inherits the members of the record definition, very
    similar to how objects work\. During instance generation, an object command
    for the instance is created as well, using *instanceName*\.

    This object command is used to access the data members of the instance\.
    During the instantiation, while values for that instance may be given, when
    done, *all* values must be given, and be given as key/value pairs, like
    for method __configure__\. Nested records have to be in list format\.

    Optionally, __\#auto__ can be used in place of *instanceName*\. When
    __\#auto__ is used, the instance name will be automatically generated,
    and of the form __recordName__N____, where __N__ is a unique
    integer \(starting at 0\) that is generated\.

# <a name='section4'></a>INSTANCE COMMAND

The following subcommands and corresponding arguments are available to any
record instance command:

  - <a name='18'></a>*instanceName* __cget__ ?*\-member1 \-member2 \.\.\.*?

    Each instance has the method __cget__\. This is very similar to how Tk
    widget's __cget__ command works\. It queries the values of the members
    for that particular instance\. If no arguments are given, then a dictionary
    is returned\.

  - <a name='19'></a>*instanceName* __configure__ ?*\-member1 value1 \-member2 value2 \.\.\.*?

    Each instance has the method __configure__\. This is very similar to how
    Tk widget's __configure__ command works\. It sets the values of the
    particular members for that particular instance\. If no arguments are given,
    then a dictionary list is returned\.

# <a name='section5'></a>EXAMPLES

Two examples are provided to give a good illustration on how to use this
package\.

## <a name='subsection4'></a>Example 1 \- Contact Information

Probably the most obvious example would be to hold contact information, such as
addresses, phone numbers, comments, etc\. Since a person can have multiple phone
numbers, multiple email addresses, etc, we will use nested records to define
these\. So, the first thing we do is define the nested records:

    ##
    ##  This is an interactive example, to see what is returned by
    ##  each command as well.
    ##

    % namespace import ::struct::record::*

    % # define a nested record. Notice that country has default 'USA'.
    % record define locations {
        street
        street2
        city
        state
        zipcode
        {country USA}
        phone

    }
    ::locations
    % # Define the main record. Notice that it uses the location record twice.
    % record define contacts {
        first
        middle
        last
        {record locations home}
        {record locations work}

    }
    ::contacts
    % # Create an instance for the contacts record.
    % contacts cont1
    ::cont1
    % # Display some introspection values
    % record show records
    ::contacts ::locations
    % #
    % record show values cont1
    -first {} -middle {} -last {} -home {-street {} -street2 {} -city {} -state {} -zipcode {} -country USA -phone {}} -work {-street {} -street2 {} -city {} -state {} -zipcode {} -country USA -phone {}}
    % #
    % record show instances contacts
    ::cont1
    % #
    % cont1 config
    -first {} -middle {} -last {} -home {-street {} -street2 {} -city {} -state {} -zipcode {} -country USA -phone {}} -work {-street {} -street2 {} -city {} -state {} -zipcode {} -country USA -phone {}}
    % #
    % cont1 cget
    -first {} -middle {} -last {} -home {-street {} -street2 {} -city {} -state {} -zipcode {} -country USA -phone {}} -work {-street {} -street2 {} -city {} -state {} -zipcode {} -country USA -phone {}}
    % # copy one record to another record
    % record define contacts2 [record show members contacts]
    ::contacts2
    % record show members contacts2
    first middle last {record locations home} {record locations work}
    % record show members contacts
    first middle last {record locations home} {record locations work}
    %

## <a name='subsection5'></a>Example 2 \- Linked List

This next example just illustrates a simple linked list

    % # define a very simple record for linked list
    % record define linkedlist {
        value
        next

    }
    ::linkedlist
    % linkedlist lstart
    ::lstart
    % lstart config -value 1 -next [linkedlist #auto]
    % [lstart cget -next] config -value 2 -next [linkedlist #auto]
    % [[lstart cget -next] cget -next] config -value 3 -next "end"
    % set next lstart
    lstart
    % while 1 {
        lappend values [$next cget -value]
        set next [$next cget -next]
        if {[string match "end" $next]} break

    }
    % puts "$values"
    1 2 3
    % # cleanup linked list
    % # We could just use delete record linkedlist also
    % foreach I [record show instances linkedlist] {
        record delete instance $I

    }
    % record show instances linkedlist
    %

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *struct :: record* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report

Changes to embedded/md/tcllib/files/modules/struct/struct_list.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (struct::list \- Tcl Data Structures)
[//000000002]: # (Generated from file 'struct\_list\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2003\-2005 by Kevin B\. Kenny\. All rights reserved  
Copyright &copy; 2003\-2012 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (struct::list\(n\) 1\.8\.4 tcllib "Tcl Data Structures")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (struct::list \- Tcl Data Structures)
[//000000002]: # (Generated from file 'struct\_list\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2003\-2005 by Kevin B\. Kenny\. All rights reserved)
[//000000004]: # (Copyright &copy; 2003\-2012 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000005]: # (struct::list\(n\) 1\.8\.4 tcllib "Tcl Data Structures")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
        of indices into *sequence1* describes the range of items which has
        been replaced\. The first index refers to the first item in the range,
        and the second index refers to the last item in the range\. The pair of
        indices into *sequence2* describes the range of items replacing the
        original range\. Again the first index refers to the first item in the
        range, and the second index refers to the last item in the range\.

        sequence 1 = \{a b r a c a d a b r a\}
        lcs 1      =   \{1 2   4 5     8 9 10\}
        lcs 2      =   \{0 1   3 4     5 6 7\}
        sequence 2 =   \{b r i c a     b r a c\}

        Inversion  = \{\{deleted  \{0  0\} \{\-1 0\}\}
                      \{changed  \{3  3\}  \{2 2\}\}
                      \{deleted  \{6  7\}  \{4 5\}\}
                      \{added   \{10 11\}  \{8 8\}\}\}

    *Notes:*

      * An index of __\-1__ in a *deleted* chunk refers to just before the
        first element of the second sequence\.

      * Also an index equal to the length of the first sequence in an *added*







|
|
|
|

|
|
|
|







160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
        of indices into *sequence1* describes the range of items which has
        been replaced\. The first index refers to the first item in the range,
        and the second index refers to the last item in the range\. The pair of
        indices into *sequence2* describes the range of items replacing the
        original range\. Again the first index refers to the first item in the
        range, and the second index refers to the last item in the range\.

        sequence 1 = {a b r a c a d a b r a}
        lcs 1      =   {1 2   4 5     8 9 10}
        lcs 2      =   {0 1   3 4     5 6 7}
        sequence 2 =   {b r i c a     b r a c}

        Inversion  = {{deleted  {0  0} {-1 0}}
                      {changed  {3  3}  {2 2}}
                      {deleted  {6  7}  {4 5}}
                      {added   {10 11}  {8 8}}}

    *Notes:*

      * An index of __\-1__ in a *deleted* chunk refers to just before the
        first element of the second sequence\.

      * Also an index equal to the length of the first sequence in an *added*
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
    that command, except that it may contain chunks of type __unchanged__
    too\.

    These new chunks describe the parts which are unchanged between the two
    sequences\. This means that the result of this command describes both the
    changed and unchanged parts of the two sequences in one structure\.

        sequence 1 = \{a b r a c a d a b r a\}
        lcs 1      =   \{1 2   4 5     8 9 10\}
        lcs 2      =   \{0 1   3 4     5 6 7\}
        sequence 2 =   \{b r i c a     b r a c\}

        Inversion/Merge  = \{\{deleted   \{0  0\} \{\-1 0\}\}
                            \{unchanged \{1  2\}  \{0 1\}\}
                            \{changed   \{3  3\}  \{2 2\}\}
                            \{unchanged \{4  5\}  \{3 4\}\}
                            \{deleted   \{6  7\}  \{4 5\}\}
                            \{unchanged \{8 10\}  \{5 7\}\}
                            \{added    \{10 11\}  \{8 8\}\}\}

  - <a name='6'></a>__::struct::list__ __lcsInvertMerge2__ *lcs1* *lcs2* *len1* *len2*

    Similar to __lcsInvertMerge__\. Instead of directly taking the result of
    a call to __longestCommonSubsequence__ this subcommand expects the
    indices for the two sequences in two separate lists\.








|
|
|
|

|
|
|
|
|
|
|







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
    that command, except that it may contain chunks of type __unchanged__
    too\.

    These new chunks describe the parts which are unchanged between the two
    sequences\. This means that the result of this command describes both the
    changed and unchanged parts of the two sequences in one structure\.

        sequence 1 = {a b r a c a d a b r a}
        lcs 1      =   {1 2   4 5     8 9 10}
        lcs 2      =   {0 1   3 4     5 6 7}
        sequence 2 =   {b r i c a     b r a c}

        Inversion/Merge  = {{deleted   {0  0} {-1 0}}
                            {unchanged {1  2}  {0 1}}
                            {changed   {3  3}  {2 2}}
                            {unchanged {4  5}  {3 4}}
                            {deleted   {6  7}  {4 5}}
                            {unchanged {8 10}  {5 7}}
                            {added    {10 11}  {8 8}}}

  - <a name='6'></a>__::struct::list__ __lcsInvertMerge2__ *lcs1* *lcs2* *len1* *len2*

    Similar to __lcsInvertMerge__\. Instead of directly taking the result of
    a call to __longestCommonSubsequence__ this subcommand expects the
    indices for the two sequences in two separate lists\.

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
    If there are more variables specified than there are elements in the
    *sequence* the empty string will be assigned to the superfluous variables\.

    If there are more elements in the *sequence* than variable names specified
    the subcommand returns a list containing the unassigned elements\. Else an
    empty list is returned\.

        tclsh> ::struct::list assign \{a b c d e\} foo bar
        c d e
        tclsh> set foo
        a
        tclsh> set bar
        b

  - <a name='10'></a>__::struct::list__ __flatten__ ?__\-full__? ?__\-\-__? *sequence*

    The subcommand takes a single *sequence* and returns a new sequence where
    one level of nesting was removed from the input sequence\. In other words,
    the sublists in the input sequence are replaced by their elements\.

    The subcommand will remove any nesting it finds if the option __\-full__
    is specified\.

        tclsh> ::struct::list flatten \{1 2 3 \{4 5\} \{6 7\} \{\{8 9\}\} 10\}
        1 2 3 4 5 6 7 \{8 9\} 10
        tclsh> ::struct::list flatten \-full \{1 2 3 \{4 5\} \{6 7\} \{\{8 9\}\} 10\}
        1 2 3 4 5 6 7 8 9 10

  - <a name='11'></a>__::struct::list__ __map__ *sequence* *cmdprefix*

    The subcommand takes a *sequence* to operate on and a command prefix
    \(*cmdprefix*\) specifying an operation, applies the command prefix to each
    element of the sequence and returns a sequence consisting of the results of
    that application\.

    The command prefix will be evaluated with a single word appended to it\. The
    evaluation takes place in the context of the caller of the subcommand\.

        tclsh> \# squaring all elements in a list

        tclsh> proc sqr \{x\} \{expr \{$x\*$x\}\}
        tclsh> ::struct::list map \{1 2 3 4 5\} sqr
        1 4 9 16 25

        tclsh> \# Retrieving the second column from a matrix
        tclsh> \# given as list of lists\.

        tclsh> proc projection \{n list\} \{::lindex $list $n\}
        tclsh> ::struct::list map \{\{a b c\} \{1 2 3\} \{d f g\}\} \{projection 1\}
        b 2 f

  - <a name='12'></a>__::struct::list__ __mapfor__ *var* *sequence* *script*

    The subcommand takes a *sequence* to operate on and a tcl *script*,
    applies the script to each element of the sequence and returns a sequence
    consisting of the results of that application\.

    The script will be evaluated as is, and has access to the current list
    element through the specified iteration variable *var*\. The evaluation
    takes place in the context of the caller of the subcommand\.

            tclsh> \# squaring all elements in a list

            tclsh> ::struct::list mapfor x \{1 2 3 4 5\} \{
        	expr \{$x \* $x\}
            \}

            1 4 9 16 25

            tclsh> \# Retrieving the second column from a matrix
            tclsh> \# given as list of lists\.

            tclsh> ::struct::list mapfor x \{\{a b c\} \{1 2 3\} \{d f g\}\} \{
        	lindex $x 1
            \}

            b 2 f

  - <a name='13'></a>__::struct::list__ __filter__ *sequence* *cmdprefix*

    The subcommand takes a *sequence* to operate on and a command prefix
    \(*cmdprefix*\) specifying an operation, applies the command prefix to each
    element of the sequence and returns a sequence consisting of all elements of
    the *sequence* for which the command prefix returned __true__\. In
    other words, this command filters out all elements of the input *sequence*
    which fail the test the *cmdprefix* represents, and returns the remaining
    elements\.

    The command prefix will be evaluated with a single word appended to it\. The
    evaluation takes place in the context of the caller of the subcommand\.

        tclsh> \# removing all odd numbers from the input

        tclsh> proc even \{x\} \{expr \{\($x % 2\) == 0\}\}
        tclsh> ::struct::list filter \{1 2 3 4 5\} even
        2 4

    *Note:* The __filter__ is a specialized application of __fold__
    where the result is extended with the current item or not, depending o nthe
    result of the test\.

  - <a name='14'></a>__::struct::list__ __filterfor__ *var* *sequence* *expr*

    The subcommand takes a *sequence* to operate on and a tcl expression
    \(*expr*\) specifying a condition, applies the conditionto each element of
    the sequence and returns a sequence consisting of all elements of the
    *sequence* for which the expression returned __true__\. In other words,
    this command filters out all elements of the input *sequence* which fail
    the test the condition *expr* represents, and returns the remaining
    elements\.

    The expression will be evaluated as is, and has access to the current list
    element through the specified iteration variable *var*\. The evaluation
    takes place in the context of the caller of the subcommand\.

        tclsh> \# removing all odd numbers from the input

        tclsh> ::struct::list filterfor x \{1 2 3 4 5\} \{\($x % 2\) == 0\}
        2 4

  - <a name='15'></a>__::struct::list__ __split__ *sequence* *cmdprefix* ?*passVar* *failVar*?

    This is a variant of method __filter__, see above\. Instead of returning
    just the elements passing the test we get lists of both passing and failing
    elements\.







|















|
|
|












|

|
|


|
|

|
|












|

|
|
<
>


|
|

|

<
>















|

|
|




















|

|







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
    If there are more variables specified than there are elements in the
    *sequence* the empty string will be assigned to the superfluous variables\.

    If there are more elements in the *sequence* than variable names specified
    the subcommand returns a list containing the unassigned elements\. Else an
    empty list is returned\.

        tclsh> ::struct::list assign {a b c d e} foo bar
        c d e
        tclsh> set foo
        a
        tclsh> set bar
        b

  - <a name='10'></a>__::struct::list__ __flatten__ ?__\-full__? ?__\-\-__? *sequence*

    The subcommand takes a single *sequence* and returns a new sequence where
    one level of nesting was removed from the input sequence\. In other words,
    the sublists in the input sequence are replaced by their elements\.

    The subcommand will remove any nesting it finds if the option __\-full__
    is specified\.

        tclsh> ::struct::list flatten {1 2 3 {4 5} {6 7} {{8 9}} 10}
        1 2 3 4 5 6 7 {8 9} 10
        tclsh> ::struct::list flatten -full {1 2 3 {4 5} {6 7} {{8 9}} 10}
        1 2 3 4 5 6 7 8 9 10

  - <a name='11'></a>__::struct::list__ __map__ *sequence* *cmdprefix*

    The subcommand takes a *sequence* to operate on and a command prefix
    \(*cmdprefix*\) specifying an operation, applies the command prefix to each
    element of the sequence and returns a sequence consisting of the results of
    that application\.

    The command prefix will be evaluated with a single word appended to it\. The
    evaluation takes place in the context of the caller of the subcommand\.

        tclsh> # squaring all elements in a list

        tclsh> proc sqr {x} {expr {$x*$x}}
        tclsh> ::struct::list map {1 2 3 4 5} sqr
        1 4 9 16 25

        tclsh> # Retrieving the second column from a matrix
        tclsh> # given as list of lists.

        tclsh> proc projection {n list} {::lindex $list $n}
        tclsh> ::struct::list map {{a b c} {1 2 3} {d f g}} {projection 1}
        b 2 f

  - <a name='12'></a>__::struct::list__ __mapfor__ *var* *sequence* *script*

    The subcommand takes a *sequence* to operate on and a tcl *script*,
    applies the script to each element of the sequence and returns a sequence
    consisting of the results of that application\.

    The script will be evaluated as is, and has access to the current list
    element through the specified iteration variable *var*\. The evaluation
    takes place in the context of the caller of the subcommand\.

            tclsh> # squaring all elements in a list

            tclsh> ::struct::list mapfor x {1 2 3 4 5} {
        	expr {$x * $x}

            }
            1 4 9 16 25

            tclsh> # Retrieving the second column from a matrix
            tclsh> # given as list of lists.

            tclsh> ::struct::list mapfor x {{a b c} {1 2 3} {d f g}} {
        	lindex $x 1

            }
            b 2 f

  - <a name='13'></a>__::struct::list__ __filter__ *sequence* *cmdprefix*

    The subcommand takes a *sequence* to operate on and a command prefix
    \(*cmdprefix*\) specifying an operation, applies the command prefix to each
    element of the sequence and returns a sequence consisting of all elements of
    the *sequence* for which the command prefix returned __true__\. In
    other words, this command filters out all elements of the input *sequence*
    which fail the test the *cmdprefix* represents, and returns the remaining
    elements\.

    The command prefix will be evaluated with a single word appended to it\. The
    evaluation takes place in the context of the caller of the subcommand\.

        tclsh> # removing all odd numbers from the input

        tclsh> proc even {x} {expr {($x % 2) == 0}}
        tclsh> ::struct::list filter {1 2 3 4 5} even
        2 4

    *Note:* The __filter__ is a specialized application of __fold__
    where the result is extended with the current item or not, depending o nthe
    result of the test\.

  - <a name='14'></a>__::struct::list__ __filterfor__ *var* *sequence* *expr*

    The subcommand takes a *sequence* to operate on and a tcl expression
    \(*expr*\) specifying a condition, applies the conditionto each element of
    the sequence and returns a sequence consisting of all elements of the
    *sequence* for which the expression returned __true__\. In other words,
    this command filters out all elements of the input *sequence* which fail
    the test the condition *expr* represents, and returns the remaining
    elements\.

    The expression will be evaluated as is, and has access to the current list
    element through the specified iteration variable *var*\. The evaluation
    takes place in the context of the caller of the subcommand\.

        tclsh> # removing all odd numbers from the input

        tclsh> ::struct::list filterfor x {1 2 3 4 5} {($x % 2) == 0}
        2 4

  - <a name='15'></a>__::struct::list__ __split__ *sequence* *cmdprefix* ?*passVar* *failVar*?

    This is a variant of method __filter__, see above\. Instead of returning
    just the elements passing the test we get lists of both passing and failing
    elements\.
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419

      * __end__

        Application of the command to the result of the last call and the last
        element of the list\. The result of this call is returned as the result
        of the subcommand\.

        tclsh> \# summing the elements in a list\.
        tclsh> proc \+ \{a b\} \{expr \{$a \+ $b\}\}
        tclsh> ::struct::list fold \{1 2 3 4 5\} 0 \+
        15

  - <a name='17'></a>__::struct::list__ __shift__ *listvar*

    The subcommand takes the list contained in the variable named by *listvar*
    and shifts it down one element\. After the call *listvar* will contain a
    list containing the second to last elements of the input list\. The first







|
|
|







403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419

      * __end__

        Application of the command to the result of the last call and the last
        element of the list\. The result of this call is returned as the result
        of the subcommand\.

        tclsh> # summing the elements in a list.
        tclsh> proc + {a b} {expr {$a + $b}}
        tclsh> ::struct::list fold {1 2 3 4 5} 0 +
        15

  - <a name='17'></a>__::struct::list__ __shift__ *listvar*

    The subcommand takes the list contained in the variable named by *listvar*
    and shifts it down one element\. After the call *listvar* will contain a
    list containing the second to last elements of the input list\. The first
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
    \.\.\.__ is identical to __list arg \.\.\.__, though the *arg* is required
    with __repeat__\.

    *Examples:*

        tclsh> ::struct::list repeat 3 a
        a a a
        tclsh> ::struct::list repeat 3 \[::struct::list repeat 3 0\]
        \{0 0 0\} \{0 0 0\} \{0 0 0\}
        tclsh> ::struct::list repeat 3 a b c
        a b c a b c a b c
        tclsh> ::struct::list repeat 3 \[::struct::list repeat 2 a\] b c
        \{a a\} b c \{a a\} b c \{a a\} b c

  - <a name='21'></a>__::struct::list__ __repeatn__ *value* *size*\.\.\.

    The subcommand creates a \(nested\) list containing the *value* in all
    positions\. The exact size and degree of nesting is determined by the
    *size* arguments, all of which have to be integer numbers greater than or
    equal to zero\.







|
|


|
|







447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
    \.\.\.__ is identical to __list arg \.\.\.__, though the *arg* is required
    with __repeat__\.

    *Examples:*

        tclsh> ::struct::list repeat 3 a
        a a a
        tclsh> ::struct::list repeat 3 [::struct::list repeat 3 0]
        {0 0 0} {0 0 0} {0 0 0}
        tclsh> ::struct::list repeat 3 a b c
        a b c a b c a b c
        tclsh> ::struct::list repeat 3 [::struct::list repeat 2 a] b c
        {a a} b c {a a} b c {a a} b c

  - <a name='21'></a>__::struct::list__ __repeatn__ *value* *size*\.\.\.

    The subcommand creates a \(nested\) list containing the *value* in all
    positions\. The exact size and degree of nesting is determined by the
    *size* arguments, all of which have to be integer numbers greater than or
    equal to zero\.
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
    of the length specified by the last *size* argument given to it\. The
    elements of that list are defined as the result of __Repeat__ for the
    same arguments, but with the last *size* value removed\.

    An empty list will be returned if no *size* arguments are present\.

        tclsh> ::struct::list repeatn  0 3 4
        \{0 0 0\} \{0 0 0\} \{0 0 0\} \{0 0 0\}
        tclsh> ::struct::list repeatn  0 \{3 4\}
        \{0 0 0\} \{0 0 0\} \{0 0 0\} \{0 0 0\}
        tclsh> ::struct::list repeatn  0 \{3 4 5\}
        \{\{0 0 0\} \{0 0 0\} \{0 0 0\} \{0 0 0\}\} \{\{0 0 0\} \{0 0 0\} \{0 0 0\} \{0 0 0\}\} \{\{0 0 0\} \{0 0 0\} \{0 0 0\} \{0 0 0\}\} \{\{0 0 0\} \{0 0 0\} \{0 0 0\} \{0 0 0\}\} \{\{0 0 0\} \{0 0 0\} \{0 0 0\} \{0 0 0\}\}

  - <a name='22'></a>__::struct::list__ __dbJoin__ ?__\-inner__&#124;__\-left__&#124;__\-right__&#124;__\-full__? ?__\-keys__ *varname*? \{*keycol* *table*\}\.\.\.

    The method performs a table join according to relational algebra\. The
    execution of any of the possible outer join operation is triggered by the
    presence of either option __\-left__, __\-right__, or __\-full__\.
    If none of these options is present a regular inner join will be performed\.







|
|
|
|
|







474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
    of the length specified by the last *size* argument given to it\. The
    elements of that list are defined as the result of __Repeat__ for the
    same arguments, but with the last *size* value removed\.

    An empty list will be returned if no *size* arguments are present\.

        tclsh> ::struct::list repeatn  0 3 4
        {0 0 0} {0 0 0} {0 0 0} {0 0 0}
        tclsh> ::struct::list repeatn  0 {3 4}
        {0 0 0} {0 0 0} {0 0 0} {0 0 0}
        tclsh> ::struct::list repeatn  0 {3 4 5}
        {{0 0 0} {0 0 0} {0 0 0} {0 0 0}} {{0 0 0} {0 0 0} {0 0 0} {0 0 0}} {{0 0 0} {0 0 0} {0 0 0} {0 0 0}} {{0 0 0} {0 0 0} {0 0 0} {0 0 0}} {{0 0 0} {0 0 0} {0 0 0} {0 0 0}}

  - <a name='22'></a>__::struct::list__ __dbJoin__ ?__\-inner__&#124;__\-left__&#124;__\-right__&#124;__\-full__? ?__\-keys__ *varname*? \{*keycol* *table*\}\.\.\.

    The method performs a table join according to relational algebra\. The
    execution of any of the possible outer join operation is triggered by the
    presence of either option __\-left__, __\-right__, or __\-full__\.
    If none of these options is present a regular inner join will be performed\.
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
  1. The full outer join combines both left and right outer join\. In other
     words, the additional rows are as defined for left outer join, and right
     outer join, combined\.

We extend all the joins from two to __n__ tables \(__n__ > 2\) by
executing

    \(\.\.\.\(\(table1 join table2\) join table3\) \.\.\.\) join tableN

Examples for all the joins:

    Inner Join

    \{0 foo\}              \{0 bagel\}    \{0 foo   0 bagel\}
    \{1 snarf\} inner join \{1 snatz\}  = \{1 snarf 1 snatz\}
    \{2 blue\}             \{3 driver\}

    Left Outer Join

    \{0 foo\}                   \{0 bagel\}    \{0 foo   0 bagel\}
    \{1 snarf\} left outer join \{1 snatz\}  = \{1 snarf 1 snatz\}
    \{2 blue\}                  \{3 driver\}   \{2 blue  \{\} \{\}\}

    Right Outer Join

    \{0 foo\}                    \{0 bagel\}    \{0 foo   0 bagel\}
    \{1 snarf\} right outer join \{1 snatz\}  = \{1 snarf 1 snatz\}
    \{2 blue\}                   \{3 driver\}   \{\{\} \{\}   3 driver\}

    Full Outer Join

    \{0 foo\}                   \{0 bagel\}    \{0 foo   0 bagel\}
    \{1 snarf\} full outer join \{1 snatz\}  = \{1 snarf 1 snatz\}
    \{2 blue\}                  \{3 driver\}   \{2 blue  \{\} \{\}\}
                                           \{\{\} \{\}   3 driver\}

# <a name='section5'></a>REFERENCES

  1. J\. W\. Hunt and M\. D\. McIlroy, "An algorithm for differential file
     comparison," Comp\. Sci\. Tech\. Rep\. \#41, Bell Telephone Laboratories \(1976\)\.
     Available on the Web at the second author's personal site:
     [http://www\.cs\.dartmouth\.edu/~doug/](http://www\.cs\.dartmouth\.edu/~doug/)







|





|
|
|



|
|
|



|
|
|



|
|
|
|







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
  1. The full outer join combines both left and right outer join\. In other
     words, the additional rows are as defined for left outer join, and right
     outer join, combined\.

We extend all the joins from two to __n__ tables \(__n__ > 2\) by
executing

    (...((table1 join table2) join table3) ...) join tableN

Examples for all the joins:

    Inner Join

    {0 foo}              {0 bagel}    {0 foo   0 bagel}
    {1 snarf} inner join {1 snatz}  = {1 snarf 1 snatz}
    {2 blue}             {3 driver}

    Left Outer Join

    {0 foo}                   {0 bagel}    {0 foo   0 bagel}
    {1 snarf} left outer join {1 snatz}  = {1 snarf 1 snatz}
    {2 blue}                  {3 driver}   {2 blue  {} {}}

    Right Outer Join

    {0 foo}                    {0 bagel}    {0 foo   0 bagel}
    {1 snarf} right outer join {1 snatz}  = {1 snarf 1 snatz}
    {2 blue}                   {3 driver}   {{} {}   3 driver}

    Full Outer Join

    {0 foo}                   {0 bagel}    {0 foo   0 bagel}
    {1 snarf} full outer join {1 snatz}  = {1 snarf 1 snatz}
    {2 blue}                  {3 driver}   {2 blue  {} {}}
                                           {{} {}   3 driver}

# <a name='section5'></a>REFERENCES

  1. J\. W\. Hunt and M\. D\. McIlroy, "An algorithm for differential file
     comparison," Comp\. Sci\. Tech\. Rep\. \#41, Bell Telephone Laboratories \(1976\)\.
     Available on the Web at the second author's personal site:
     [http://www\.cs\.dartmouth\.edu/~doug/](http://www\.cs\.dartmouth\.edu/~doug/)

Added embedded/md/tcllib/files/modules/struct/struct_map.md.





































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

[//000000001]: # (struct::map \- )
[//000000002]: # (Generated from file 'struct\_map\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (struct::map\(n\) 1 tcllib "")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

# NAME

struct::map \- Manage key/value maps

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Synopsis](#synopsis)

  - [Description](#section1)

  - [API](#section2)

  - [Bugs, Ideas, Feedback](#section3)

# <a name='synopsis'></a>SYNOPSIS

package require struct::map ?1?  

[__::struct::map__ *mapName*](#1)  
[__mapName__ __method__ ?*arg arg \.\.\.*?](#2)  
[*mapName* __get__](#3)  
[*mapName* __names__](#4)  
[*mapName* __set__ *name* ?*value*?](#5)  
[*mapName* __unset__ ?*pattern*\.\.\.?](#6)  

# <a name='description'></a>DESCRIPTION

Provides a snit class whose instances manage a key/value map\. In other words, an
object wrapper around Tcl arrays\.

# <a name='section2'></a>API

The main command provides construction of maps:

  - <a name='1'></a>__::struct::map__ *mapName*

    Creates a new, empty map with an associated global Tcl command whose name is
    *mapName*\. It may be used to invoke various operations on the map\. It has
    the following general form:

      * <a name='2'></a>__mapName__ __method__ ?*arg arg \.\.\.*?

        __method__ and *arg*uments determine the exact behavior of the
        command\.

    If *mapName* is specified as __%AUTO%__ a unique name will be
    generated by the package itself\. The result of the command is the
    fully\-qualified name of the instance command\.

The following commands are possible for map objects:

  - <a name='3'></a>*mapName* __get__

    Returns the entire map as a Tcl dictionary\.

  - <a name='4'></a>*mapName* __names__

    Returns the list of all keys known to the map, in arbitrary order\.

  - <a name='5'></a>*mapName* __set__ *name* ?*value*?

    Sets key *name* to the specified *value*, if the value specified\.
    Returns the value for the key\. Throws an error if the key is not known\.

  - <a name='6'></a>*mapName* __unset__ ?*pattern*\.\.\.?

    Removes all keys matching at least one of the glob *pattern*s from the
    map\. If no pattern is specified all keys are removed\. In other words, the
    default pattern is __\*__\. The result of the command is the empty string\.

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *struct :: list* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report
any ideas for enhancements you may have for either package and/or documentation\.

When proposing code changes, please provide *unified diffs*, i\.e the output of
__diff \-u__\.

Note further that *attachments* are strongly preferred over inlined patches\.
Attachments can be made by going to the __Edit__ form of the ticket
immediately after its creation, and then using the left\-most button in the
secondary navigation bar\.

Changes to embedded/md/tcllib/files/modules/struct/struct_tree.md.

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
    This is the assignment operator for tree objects\. It copies the tree
    contained in the tree object *sourcetree* over the tree data in
    *treeName*\. The old contents of *treeName* are deleted by this
    operation\.

    This operation is in effect equivalent to

        *treeName* __deserialize__ \[*sourcetree* __serialize__\]

  - <a name='5'></a>*treeName* __\-\->__ *desttree*

    This is the reverse assignment operator for tree objects\. It copies the tree
    contained in the tree object *treeName* over the tree data in the object
    *desttree*\. The old contents of *desttree* are deleted by this
    operation\.

    This operation is in effect equivalent to

        *desttree* __deserialize__ \[*treeName* __serialize__\]

  - <a name='6'></a>*treeName* __ancestors__ *node*

    This method extends the method __parent__ and returns a list containing
    all ancestor nodes to the specified *node*\. The immediate ancestor, in
    other words, parent node, is the first element in that list, its parent the
    second element, and so on until the root node is reached, making it the last







|










|







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
    This is the assignment operator for tree objects\. It copies the tree
    contained in the tree object *sourcetree* over the tree data in
    *treeName*\. The old contents of *treeName* are deleted by this
    operation\.

    This operation is in effect equivalent to

    > *treeName* __deserialize__ \[*sourcetree* __serialize__\]

  - <a name='5'></a>*treeName* __\-\->__ *desttree*

    This is the reverse assignment operator for tree objects\. It copies the tree
    contained in the tree object *treeName* over the tree data in the object
    *desttree*\. The old contents of *desttree* are deleted by this
    operation\.

    This operation is in effect equivalent to

    > *desttree* __deserialize__ \[*treeName* __serialize__\]

  - <a name='6'></a>*treeName* __ancestors__ *node*

    This method extends the method __parent__ and returns a list containing
    all ancestor nodes to the specified *node*\. The immediate ancestor, in
    other words, parent node, is the first element in that list, its parent the
    second element, and so on until the root node is reached, making it the last
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
            mytree insert root end 1
            mytree insert root end 2
            mytree insert 0    end 3
            mytree insert 0    end 4
            mytree insert 4    end 5 ; mytree set 5 volume 50
            mytree insert 4    end 6

            proc vol \{t n\} \{
        	$t keyexists $n volume
            \}

            proc vgt40 \{t n\} \{
        	if \{\!\[$t keyexists $n volume\]\} \{return 0\}
        	expr \{\[$t get $n volume\] > 40\}
            \}


            tclsh> lsort \[mytree children \-all root filter vol\]
            0 5

            tclsh> lsort \[mytree children \-all root filter vgt40\]
            5

            tclsh> lsort \[mytree children root filter vol\]
            0

            tclsh> puts \(\[lsort \[mytree children root filter vgt40\]\]\)
            \(\)

  - <a name='13'></a>*treeName* __cut__ *node*

    Removes the node specified by *node* from the tree, but not its children\.
    The children of *node* are made children of the parent of the *node*, at
    the index at which *node* was located\.








|

<
>
|
|
|
<
|
>
|


|


|


|
|







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
            mytree insert root end 1
            mytree insert root end 2
            mytree insert 0    end 3
            mytree insert 0    end 4
            mytree insert 4    end 5 ; mytree set 5 volume 50
            mytree insert 4    end 6

            proc vol {t n} {
        	$t keyexists $n volume

            }
            proc vgt40 {t n} {
        	if {![$t keyexists $n volume]} {return 0}
        	expr {[$t get $n volume] > 40}

            }

            tclsh> lsort [mytree children -all root filter vol]
            0 5

            tclsh> lsort [mytree children -all root filter vgt40]
            5

            tclsh> lsort [mytree children root filter vol]
            0

            tclsh> puts ([lsort [mytree children root filter vgt40]])
            ()

  - <a name='13'></a>*treeName* __cut__ *node*

    Removes the node specified by *node* from the tree, but not its children\.
    The children of *node* are made children of the parent of the *node*, at
    the index at which *node* was located\.

479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
    rely on for the structure of the tree is that the root node is signaled by
    the empty string for the parent reference, that all other nodes refer to
    their parent through the index in the list, and that children occur in the
    same order as in their parent\.

        A possible serialization for the tree structure

                    \+\- d
              \+\- a \-\+
        root \-\+\- b  \+\- e
              \+\- c
        is

        \{root \{\} \{\} a 0 \{\} d 3 \{\} e 3 \{\} b 0 \{\} c 0 \{\}\}

        The above assumes that none of the nodes have attributes\.

  - <a name='38'></a>*treeName* __set__ *node* *key* ?*value*?

    Set or get one of the keyed values associated with a node\. A node may have
    any number of keyed values associated with it\. If *value* is not
    specified, this command returns the current value assigned to the key; if
    *value* is specified, this command assigns that value to the key, and







|
|
|
|


|

|







479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
    rely on for the structure of the tree is that the root node is signaled by
    the empty string for the parent reference, that all other nodes refer to
    their parent through the index in the list, and that children occur in the
    same order as in their parent\.

        A possible serialization for the tree structure

                    +- d
              +- a -+
        root -+- b  +- e
              +- c
        is

        {root {} {} a 0 {} d 3 {} e 3 {} b 0 {} c 0 {}}

        The above assumes that none of the nodes have attributes.

  - <a name='38'></a>*treeName* __set__ *node* *key* ?*value*?

    Set or get one of the keyed values associated with a node\. A node may have
    any number of keyed values associated with it\. If *value* is not
    specified, this command returns the current value assigned to the key; if
    *value* is specified, this command assigns that value to the key, and
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
    visited\), or upon leaving will have undefined results\. They may succeed,
    error out, silently compute the wrong result, or anything in between\.

    At last a small table showing the relationship between the various options
    and the possible actions\.

        order       type    actions         notes
        \-\-\-\-\-       \-\-\-\-    \-\-\-\-\-           \-\-\-\-\-
        pre         dfs     enter           parent before children
        post        dfs     leave           parent after children
        in          dfs     visit           parent between first and second child\.
        both        dfs     enter, leave    parent before and after children
        \-\-\-\-\-       \-\-\-\-    \-\-\-\-\-           \-\-\-\-\-
        pre         bfs     enter           parent before children
        post        bfs     leave           parent after children
        in          bfs             \-\- illegal \-\-
        both        bfs     enter, leave    parent before and after children
        \-\-\-\-\-       \-\-\-\-    \-\-\-\-\-           \-\-\-\-\-

    Note the command __::struct::tree::prune__\. This command can be used in
    the walk script to force the command to ignore the children of the node we
    are currently at\. It will throw an error if the order of traversal is either
    __post__ or __in__ as these modes visit the children before their
    parent, making pruning non\-sensical\.








|


|

|


|

|







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
    visited\), or upon leaving will have undefined results\. They may succeed,
    error out, silently compute the wrong result, or anything in between\.

    At last a small table showing the relationship between the various options
    and the possible actions\.

        order       type    actions         notes
        -----       ----    -----           -----
        pre         dfs     enter           parent before children
        post        dfs     leave           parent after children
        in          dfs     visit           parent between first and second child.
        both        dfs     enter, leave    parent before and after children
        -----       ----    -----           -----
        pre         bfs     enter           parent before children
        post        bfs     leave           parent after children
        in          bfs             -- illegal --
        both        bfs     enter, leave    parent before and after children
        -----       ----    -----           -----

    Note the command __::struct::tree::prune__\. This command can be used in
    the walk script to force the command to ignore the children of the node we
    are currently at\. It will throw an error if the order of traversal is either
    __post__ or __in__ as these modes visit the children before their
    parent, making pruning non\-sensical\.

667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
     Another extension is the ability to look not only at the immediate children
     of the node, but the whole tree below it\.

# <a name='section3'></a>EXAMPLES

The following example demonstrates the creation of new nodes:

    mytree insert root end 0   ; \# Create node 0, as child of the root
    mytree insert root end 1 2 ; \# Ditto nodes 1 & 2
    mytree insert 0    end 3   ; \# Now create node 3 as child of node 0
    mytree insert 0    end     ; \# Create another child of 0, with a
    \#                              generated name\. The name is returned
    \#                              as the result of the command\.

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *struct :: tree* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report
any ideas for enhancements you may have for either package and/or documentation\.







|
|
|
|
|
|







667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
     Another extension is the ability to look not only at the immediate children
     of the node, but the whole tree below it\.

# <a name='section3'></a>EXAMPLES

The following example demonstrates the creation of new nodes:

    mytree insert root end 0   ; # Create node 0, as child of the root
    mytree insert root end 1 2 ; # Ditto nodes 1 & 2
    mytree insert 0    end 3   ; # Now create node 3 as child of node 0
    mytree insert 0    end     ; # Create another child of 0, with a
    #                              generated name. The name is returned
    #                              as the result of the command.

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *struct :: tree* of the
[Tcllib Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report
any ideas for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/tar/tar.md.

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    Returns a nested dict containing information on the named ?file? in
    *tarball*, or all files if none is specified\. The top level are pairs of
    filename and info\. The info is a dict with the keys "__mode__
    __uid__ __gid__ __size__ __mtime__ __type__
    __linkname__ __uname__ __gname__ __devmajor__
    __devminor__"

        % ::tar::stat tarball\.tar
        foo\.jpg \{mode 0644 uid 1000 gid 0 size 7580 mtime 811903867 type file linkname \{\} uname user gname wheel devmajor 0 devminor 0\}

    If the option __\-chan__ is present *tarball* is interpreted as an open
    channel\. It is assumed that the channel was opened for reading, and
    configured for binary input\. The command will *not* close the channel\.

  - <a name='3'></a>__::tar::untar__ *tarball* *args*








|
|







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    Returns a nested dict containing information on the named ?file? in
    *tarball*, or all files if none is specified\. The top level are pairs of
    filename and info\. The info is a dict with the keys "__mode__
    __uid__ __gid__ __size__ __mtime__ __type__
    __linkname__ __uname__ __gname__ __devmajor__
    __devminor__"

        % ::tar::stat tarball.tar
        foo.jpg {mode 0644 uid 1000 gid 0 size 7580 mtime 811903867 type file linkname {} uname user gname wheel devmajor 0 devminor 0}

    If the option __\-chan__ is present *tarball* is interpreted as an open
    channel\. It is assumed that the channel was opened for reading, and
    configured for binary input\. The command will *not* close the channel\.

  - <a name='3'></a>__::tar::untar__ *tarball* *args*

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

      * __\-chan__

        If this option is present *tarball* is interpreted as an open channel\.
        It is assumed that the channel was opened for reading, and configured
        for binary input\. The command will *not* close the channel\.

        % foreach \{file size\} \[::tar::untar tarball\.tar \-glob \*\.jpg\] \{
        puts "Extracted $file \($size bytes\)"
        \}


  - <a name='4'></a>__::tar::get__ *tarball* *fileName* ?__\-chan__?

    Returns the contents of *fileName* from the *tarball*\.

        % set readme \[::tar::get tarball\.tar doc/README\] \{
        % puts $readme
        \}


    If the option __\-chan__ is present *tarball* is interpreted as an open
    channel\. It is assumed that the channel was opened for reading, and
    configured for binary input\. The command will *not* close the channel\.

    An error is thrown when *fileName* is not found in the tar archive\.








|
|
<
>





|

<
>







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

      * __\-chan__

        If this option is present *tarball* is interpreted as an open channel\.
        It is assumed that the channel was opened for reading, and configured
        for binary input\. The command will *not* close the channel\.

        % foreach {file size} [::tar::untar tarball.tar -glob *.jpg] {
        puts "Extracted $file ($size bytes)"

        }

  - <a name='4'></a>__::tar::get__ *tarball* *fileName* ?__\-chan__?

    Returns the contents of *fileName* from the *tarball*\.

        % set readme [::tar::get tarball.tar doc/README] {
        % puts $readme

        }

    If the option __\-chan__ is present *tarball* is interpreted as an open
    channel\. It is assumed that the channel was opened for reading, and
    configured for binary input\. The command will *not* close the channel\.

    An error is thrown when *fileName* is not found in the tar archive\.

144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

      * __\-chan__

        If this option is present *tarball* is interpreted as an open channel\.
        It is assumed that the channel was opened for writing, and configured
        for binary output\. The command will *not* close the channel\.

        % ::tar::create new\.tar \[glob \-nocomplain file\*\]
        % ::tar::contents new\.tar
        file1 file2 file3

  - <a name='6'></a>__::tar::add__ *tarball* *files* *args*

    Appends *files* to the end of the existing *tarball*\. *files* must be
    specified as a single argument which is a proper list of filenames\.








|
|







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

      * __\-chan__

        If this option is present *tarball* is interpreted as an open channel\.
        It is assumed that the channel was opened for writing, and configured
        for binary output\. The command will *not* close the channel\.

        % ::tar::create new.tar [glob -nocomplain file*]
        % ::tar::contents new.tar
        file1 file2 file3

  - <a name='6'></a>__::tar::add__ *tarball* *files* *args*

    Appends *files* to the end of the existing *tarball*\. *files* must be
    specified as a single argument which is a proper list of filenames\.

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194

  - <a name='7'></a>__::tar::remove__ *tarball* *files*

    Removes *files* from the *tarball*\. No error will result if the file
    does not exist in the tarball\. Directory write permission and free disk
    space equivalent to at least the size of the tarball will be needed\.

        % ::tar::remove new\.tar \{file2 file3\}
        % ::tar::contents new\.tar
        file3

# <a name='section2'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *tar* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas







|
|







179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194

  - <a name='7'></a>__::tar::remove__ *tarball* *files*

    Removes *files* from the *tarball*\. No error will result if the file
    does not exist in the tarball\. Directory write permission and free disk
    space equivalent to at least the size of the tarball will be needed\.

        % ::tar::remove new.tar {file2 file3}
        % ::tar::contents new.tar
        file3

# <a name='section2'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *tar* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas

Changes to embedded/md/tcllib/files/modules/tepam/tepam_argument_dialogbox.md.

77
78
79
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
    been acknowledged \(via the *OK* button\) and validated by a data checker\.
    If the entered data have been rejected \(via the *Cancel* button\) the
    __argument\_dialogbox__ returns __cancel__\.

    A small example illustrates how the __argument\_dialogbox__ can be
    employed:

        set DialogResult \[__tepam::argument\_dialogbox__ \\
           __\-title__ "Itinerary selection" \\
           __\-file__ \{*\-label "Itinerary report" \-variable report\_file*\} \\
           __\-frame__ \{*\-label "Itinerary start"*\} \\
              __\-comment__ \{*\-text "Specify your itinerary start location"*\} \\
              __\-entry__ \{*\-label "City" \-variable start\_city \-type string*\} \\
              __\-entry__ \{*\-label "Street" \-variable start\_street \-type string \-optional 1*\} \\
              __\-entry__ \{*\-label "Street number" \-variable start\_street\_nbr \-type integer \-optional 1*\} \\
           __\-frame__ \{*\-label "Itinerary destination"*\} \\
              __\-comment__ \{*\-text "Specify your itinerary destination"*\} \\
              __\-entry__ \{*\-label "City" \-variable dest\_city \-type string*\} \\
              __\-entry__ \{*\-label "Street" \-variable dest\_street \-type string \-optional 1*\} \\
              __\-entry__ \{*\-label "Street number" \-variable dest\_street\_nbr \-type integer \-optional 1*\} \\
           __\-frame__ \{\} \\
           __\-checkbutton__ \{*\-label "Don't use highways" \-variable no\_highway*\}

    \] This example opens a dialog box that has the title *Itinerary
    selection*\. A first entry widget in this box allows selecting a report
    file\. It follows two frames to define respectively an itinerary start and
    end location\. Each of these locations that are described with a comment has
    three entry widgets to specify respectively the city, street and the street
    number\. Bellow the second frame there is a check button that allows
    specifying if eventual highways should be ignored\.

  - <a name='2'></a>__tepam::argument\_dialogbox__ \{*item\_name item\_attributes ?item\_name item\_attributes? ?\.\.\.?*\}

    Sometimes it is simpler to provide all the data entry item definitions in
    form of a single list to __argument\_dialogbox__, and not as individual
    arguments\. The second format that is supported by __argument\_dialogbox__
    corresponds exactly to the first one, except that all item definitions are
    packed into a single list that is provided to __argument\_dialogbox__\.
    The previous example can therefore also be written in the following way:

        set DialogResult \[__tepam::argument\_dialogbox \{__
           __\-title__ "Itinerary selection"
           __\-file__ \{*\-label "Itinerary report" \-variable report\_file*\}
           \.\.\.
           __\-checkbutton__ \{*\-label "Don't use highways" \-variable no\_highway*\}

    __\}__\]

The commands __argument\_dialogbox__ as well as
__[procedure](\.\./\.\./\.\./\.\./index\.md\#procedure)__ are exported from the
namespace __tepam__\. To use these commands without the __tepam::__
namespace prefix, it is sufficient to import them into the main namespace:

    __namespace import tepam::\*__

    set DialogResult \[__argument\_dialogbox__ \\
       \-title "Itinerary selection"
       \.\.\.

The following subsections explain the different argument item types that are
accepted by the __argument\_dialogbox__, classified into three groups\. The
first data entry item definition format will be used in the remaining document,
knowing that this format can always be transformed into the second format by
putting all arguments into a single list that is then provided to
__argument\_dialogbox__\.

## <a name='subsection1'></a>Context Definition Items

The first item group allows specifying some context aspects of an argument
dialog box\. These items are taking a simple character string as item attribute:

    tepam::argument\_dialogbox \\
       __\-<argument\_name>__ *string* \\
       \.\.\.

The following items are classified into this group:

  - \-title *string*

    The dialog box window title which is by default *Dialog* can be changed
    with the *\-title* item:

    tepam::argument\_dialogbox \\
       __\-title__ "System configuration" \\
       \.\.\.

  - \-window *string*

    The argument dialog box uses by default *\.dialog* as dialog top level
    window\. This path can be changed with the *\-window* item:

    tepam::argument\_dialogbox \\
       __\-window__ \.dialog \\
       \.\.\.

  - \-parent *string*

    By defining a parent window, the argument dialog box will be displayed
    beside this one\. Without explicit parent window definition, the top\-level
    window will be considered as parent window\.

    tepam::argument\_dialogbox \\
       __\-parent__ \.my\_appl \\
       \.\.\.

  - \-context *string*

    If a context is defined the dialog box state, e\.g\. the entered data as well
    as the window size and position, is restored the next time the argument
    dialog box is called\. The assignment of a context allows saving the dialog
    box state in its context to distinguish between different usages of the
    argument dialog box\.

    tepam::argument\_dialogbox \\
       __\-context__ destination\_definitions \\
       \.\.\.

## <a name='subsection2'></a>Formatting and Display Options

Especially for big, complex forms it becomes important that the different data
entry widgets are graphically well organized and commented to provide an
immediate and clear overview to the user\. A couple of items allow structuring
and commenting the dialog boxes\.

The items of this classification group require as item attributes a definition
list, which contains itself attribute name and value pairs:

    tepam::argument\_dialogbox \\
       \.\.\.
       __\-<argument\_name>__ \{ *
          ?\-<attribute\_name> <attribute\_value>?
          ?\-<attribute\_name> <attribute\_value>?
          ?\.\.\.?*

       \}
       \.\.\.

The following items are classified into this group:

  - \-frame *list*

    The *\-frame* item allows packing all following entry widgets into a
    labeled frame, until a next frame item is defined or until the last entry
    widget has been defined\. It recognizes the following attributes inside the
    item attribute list:

      * \-label *string*

        An optional frame label can be specified with the *\-label* statement\.

    Example:

    tepam::argument\_dialogbox \\
       \.\.\.
       __\-frame__ \{*\-label "Destination address"*\}
       \.\.\.

    To close an open frame without opening a new one, an empty list has to be
    provided to the *\-frame* statement\.

    tepam::argument\_dialogbox \\
       \.\.\.
       __\-frame__ \{\}
       \.\.\.

  - \-sep \[const \{\{\}\}\]

    Entry widgets can be separated with the *\-sep* statement which doesn't
    require additional definitions\. The related definition list has to exist,
    but its content is ignored\.

    tepam::argument\_dialogbox \\
       \.\.\.
       __\-sep__ \{\}
       \.\.\.

  - \-comment *string*

    Comments and descriptions can be added with the *\-text* attribute of the
    *\-comment* item\. Please note that each entry widget itself can also
    contain a *\-text* attribute for comments and descriptions\. But the
    *\-comment* item allows for example adding a description between two
    frames\.

    tepam::argument\_dialogbox \\
       \.\.\.
       __\-comment__ \{*\-text "Specify bellow the destination address"*\}
       \.\.\.

  - \-yscroll __0__&#124;__1__&#124;__auto__

    This attribute allows controlling an eventual vertical scrollbar\. Setting it
    to __0__ will permanently disable the scrollbar, setting it to __1__
    will enable it\. By default it is set to __auto__\. The scrollbar is
    enabled in this mode only if the vertical data entry form size exceeds 66%
    of the screen height\.

    tepam::argument\_dialogbox \\
       \.\.\.
       __\-yscroll__ __auto__
       \.\.\.

## <a name='subsection3'></a>Global Custom Data Validation

This item group allows specifying global custom checks to validate the entered
data\.

  - \-validatecommand *script*

    Custom data checks can be performed via validation commands that are defined
    with the *\-validatecommand* item\. Example:

    tepam::argument\_dialogbox \\
       \-entry \{\-label "Your comment" \-variable YourCom\} \\
       __\-validatecommand__ \{IllegalWordDetector $YourCom\}

    The validation command is executed in the context of the calling procedure,
    once all the basic data checks have been performed and data variables are
    assigned\. All data is accessed via the data variables\. Note that there is
    also an entry widget specific attribute *\-validatecommand* that allows
    declaring custom checks for specific data entries\.








|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|










|
|
|
|
|
<
<






|
|
|
|
|













|
|
|








|
|
|






|
|
|







|
|
|









|
|
|











|
|
|
|
|
|
>
|
|
















|
|
|
|




|
|
|
|







|
|
|
|









|
|
|
|









|
|
|
|











|
|
|







77
78
79
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
    been acknowledged \(via the *OK* button\) and validated by a data checker\.
    If the entered data have been rejected \(via the *Cancel* button\) the
    __argument\_dialogbox__ returns __cancel__\.

    A small example illustrates how the __argument\_dialogbox__ can be
    employed:

    > set DialogResult \[__tepam::argument\_dialogbox__ \\  
    > &nbsp;&nbsp;&nbsp;__\-title__ "Itinerary selection" \\  
    > &nbsp;&nbsp;&nbsp;__\-file__ \{*\-label "Itinerary report" \-variable report\_file*\} \\  
    > &nbsp;&nbsp;&nbsp;__\-frame__ \{*\-label "Itinerary start"*\} \\  
    > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-comment__ \{*\-text "Specify your itinerary start location"*\} \\  
    > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-entry__ \{*\-label "City" \-variable start\_city \-type string*\} \\  
    > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-entry__ \{*\-label "Street" \-variable start\_street \-type string \-optional 1*\} \\  
    > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-entry__ \{*\-label "Street number" \-variable start\_street\_nbr \-type integer \-optional 1*\} \\  
    > &nbsp;&nbsp;&nbsp;__\-frame__ \{*\-label "Itinerary destination"*\} \\  
    > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-comment__ \{*\-text "Specify your itinerary destination"*\} \\  
    > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-entry__ \{*\-label "City" \-variable dest\_city \-type string*\} \\  
    > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-entry__ \{*\-label "Street" \-variable dest\_street \-type string \-optional 1*\} \\  
    > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-entry__ \{*\-label "Street number" \-variable dest\_street\_nbr \-type integer \-optional 1*\} \\  
    > &nbsp;&nbsp;&nbsp;__\-frame__ \{\} \\  
    > &nbsp;&nbsp;&nbsp;__\-checkbutton__ \{*\-label "Don't use highways" \-variable no\_highway*\}\]

    This example opens a dialog box that has the title *Itinerary selection*\.
    A first entry widget in this box allows selecting a report file\. It follows
    two frames to define respectively an itinerary start and end location\. Each
    of these locations that are described with a comment has three entry widgets
    to specify respectively the city, street and the street number\. Bellow the
    second frame there is a check button that allows specifying if eventual
    highways should be ignored\.

  - <a name='2'></a>__tepam::argument\_dialogbox__ \{*item\_name item\_attributes ?item\_name item\_attributes? ?\.\.\.?*\}

    Sometimes it is simpler to provide all the data entry item definitions in
    form of a single list to __argument\_dialogbox__, and not as individual
    arguments\. The second format that is supported by __argument\_dialogbox__
    corresponds exactly to the first one, except that all item definitions are
    packed into a single list that is provided to __argument\_dialogbox__\.
    The previous example can therefore also be written in the following way:

    > set DialogResult \[__tepam::argument\_dialogbox \{__  
    > &nbsp;&nbsp;&nbsp;__\-title__ "Itinerary selection"  
    > &nbsp;&nbsp;&nbsp;__\-file__ \{*\-label "Itinerary report" \-variable report\_file*\}  
    > &nbsp;&nbsp;&nbsp;\.\.\.  
    > &nbsp;&nbsp;&nbsp;__\-checkbutton__ \{*\-label "Don't use highways" \-variable no\_highway*\} __\}__\]



The commands __argument\_dialogbox__ as well as
__[procedure](\.\./\.\./\.\./\.\./index\.md\#procedure)__ are exported from the
namespace __tepam__\. To use these commands without the __tepam::__
namespace prefix, it is sufficient to import them into the main namespace:

> __namespace import tepam::\*__  
>   
> set DialogResult \[__argument\_dialogbox__ \\  
> &nbsp;&nbsp;&nbsp;\-title "Itinerary selection"  
> &nbsp;&nbsp;&nbsp;\.\.\.

The following subsections explain the different argument item types that are
accepted by the __argument\_dialogbox__, classified into three groups\. The
first data entry item definition format will be used in the remaining document,
knowing that this format can always be transformed into the second format by
putting all arguments into a single list that is then provided to
__argument\_dialogbox__\.

## <a name='subsection1'></a>Context Definition Items

The first item group allows specifying some context aspects of an argument
dialog box\. These items are taking a simple character string as item attribute:

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-<argument\_name>__ *string* \\  
> &nbsp;&nbsp;&nbsp;\.\.\.

The following items are classified into this group:

  - \-title *string*

    The dialog box window title which is by default *Dialog* can be changed
    with the *\-title* item:

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-title__ "System configuration" \\  
> &nbsp;&nbsp;&nbsp;\.\.\.

  - \-window *string*

    The argument dialog box uses by default *\.dialog* as dialog top level
    window\. This path can be changed with the *\-window* item:

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-window__ \.dialog \\  
> &nbsp;&nbsp;&nbsp;\.\.\.

  - \-parent *string*

    By defining a parent window, the argument dialog box will be displayed
    beside this one\. Without explicit parent window definition, the top\-level
    window will be considered as parent window\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-parent__ \.my\_appl \\  
> &nbsp;&nbsp;&nbsp;\.\.\.

  - \-context *string*

    If a context is defined the dialog box state, e\.g\. the entered data as well
    as the window size and position, is restored the next time the argument
    dialog box is called\. The assignment of a context allows saving the dialog
    box state in its context to distinguish between different usages of the
    argument dialog box\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-context__ destination\_definitions \\  
> &nbsp;&nbsp;&nbsp;\.\.\.

## <a name='subsection2'></a>Formatting and Display Options

Especially for big, complex forms it becomes important that the different data
entry widgets are graphically well organized and commented to provide an
immediate and clear overview to the user\. A couple of items allow structuring
and commenting the dialog boxes\.

The items of this classification group require as item attributes a definition
list, which contains itself attribute name and value pairs:

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;&nbsp;__\-<argument\_name>__ \{   
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*?\-<attribute\_name> <attribute\_value>?*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*?\-<attribute\_name> <attribute\_value>?*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*?\.\.\.?*  
>   
> &nbsp;&nbsp;&nbsp;\}  
> &nbsp;&nbsp;&nbsp;\.\.\.

The following items are classified into this group:

  - \-frame *list*

    The *\-frame* item allows packing all following entry widgets into a
    labeled frame, until a next frame item is defined or until the last entry
    widget has been defined\. It recognizes the following attributes inside the
    item attribute list:

      * \-label *string*

        An optional frame label can be specified with the *\-label* statement\.

    Example:

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;&nbsp;__\-frame__ \{*\-label "Destination address"*\}  
> &nbsp;&nbsp;&nbsp;\.\.\.

    To close an open frame without opening a new one, an empty list has to be
    provided to the *\-frame* statement\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;&nbsp;__\-frame__ \{\}  
> &nbsp;&nbsp;&nbsp;\.\.\.

  - \-sep \[const \{\{\}\}\]

    Entry widgets can be separated with the *\-sep* statement which doesn't
    require additional definitions\. The related definition list has to exist,
    but its content is ignored\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;&nbsp;__\-sep__ \{\}  
> &nbsp;&nbsp;&nbsp;\.\.\.

  - \-comment *string*

    Comments and descriptions can be added with the *\-text* attribute of the
    *\-comment* item\. Please note that each entry widget itself can also
    contain a *\-text* attribute for comments and descriptions\. But the
    *\-comment* item allows for example adding a description between two
    frames\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;&nbsp;__\-comment__ \{*\-text "Specify bellow the destination address"*\}  
> &nbsp;&nbsp;&nbsp;\.\.\.

  - \-yscroll __0__&#124;__1__&#124;__auto__

    This attribute allows controlling an eventual vertical scrollbar\. Setting it
    to __0__ will permanently disable the scrollbar, setting it to __1__
    will enable it\. By default it is set to __auto__\. The scrollbar is
    enabled in this mode only if the vertical data entry form size exceeds 66%
    of the screen height\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;&nbsp;__\-yscroll__ __auto__  
> &nbsp;&nbsp;&nbsp;\.\.\.

## <a name='subsection3'></a>Global Custom Data Validation

This item group allows specifying global custom checks to validate the entered
data\.

  - \-validatecommand *script*

    Custom data checks can be performed via validation commands that are defined
    with the *\-validatecommand* item\. Example:

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-entry \{\-label "Your comment" \-variable YourCom\} \\  
> &nbsp;&nbsp;&nbsp;__\-validatecommand__ \{IllegalWordDetector $YourCom\}

    The validation command is executed in the context of the calling procedure,
    once all the basic data checks have been performed and data variables are
    assigned\. All data is accessed via the data variables\. Note that there is
    also an entry widget specific attribute *\-validatecommand* that allows
    declaring custom checks for specific data entries\.

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

## <a name='subsection4'></a>Data Entry Widget Items

Data entry widgets are created with the widget items\. These items require as
item attributes a definition list, which contains itself attribute name and
value pairs:

    tepam::argument\_dialogbox \\
       \.\.\.
       __\-<argument\_name>__ \{ *
          ?\-<attribute\_name> <attribute\_value>?
          ?\-<attribute\_name> <attribute\_value>?
          ?\.\.\.?*

       \}
       \.\.\.

The attribute list can contain various attributes to describe and comment an
entry widget and to constrain its entered value\. All entry widgets are accepting
a common set of attributes that are described in the section [Entry Widget Item
Attributes](#subsection5)\.

TEPAM defines a rich set of entry widgets\. If necessary, this set can be
extended with additional application specific entry widgets \(see [APPLICATION
SPECIFIC ENTRY WIDGETS](#section3)\):

  - \-entry *list*

    The *\-entry* item generates the simplest but most universal data entry
    widget\. It allows entering any kind of data in form of single line strings\.

    tepam::argument\_dialogbox \\
       __\-entry__ \{\-label Name \-variable Entry\}

  - \-text *list*

    The *\-text* item generates a multi line text entry widget\. The widget
    height can be selected with the *\-height* attribute\.

    tepam::argument\_dialogbox \\
       __\-text__ \{\-label Name \-variable Text \-height 5\}

  - \-checkbox *list*

    A group of check boxes is created with the *\-checkbox* item\. The number of
    check boxes and their option values are specified with a list assigned to
    the *\-choices* attribute or via a variable declared with the
    *\-choicevariable* attribute:

    tepam::argument\_dialogbox \\
       __\-checkbox__ \{\-label "Font sytle" \-variable FontStyle \\
                   \-choices \{bold italic underline\} \-default italic\}

    If the labels of the check boxes should differ from the option values, their
    labels can be defined with the *\-choicelabels* attribute:

    tepam::argument\_dialogbox \\
       __\-checkbox__ \{\-label "Font sytle" \-variable FontStyle \\
                  \-choices \{bold italic underline\} \\
                  \-choicelabels \{Bold Italic Underline\} \\
                  \-default italic\}

    In contrast to a radio box group, a check box group allows selecting
    simultaneously several choice options\. The selection is stored for this
    reason inside the defined variable in form of a list, even if only one
    choice option has been selected\.

  - \-radiobox *list*

    A group of radio boxes is created with the *\-radiobox* item\. The number of
    radio boxes and their option values are specified with a list assigned to
    the *\-choices* attribute or via a variable declared with the
    *\-choicevariable* attribute\.

    In contrast to a check box group, a radio box group allows selecting
    simultaneously only one choice option\. The selected option value is stored
    directly, and not in form of a list, inside the defined variable\.

    tepam::argument\_dialogbox \\
       __\-radiobox__ \{\-label "Text adjustment" \-variable Adjustment \\
                  \-choices \{left center right\} \-default left\}

    If the labels of the radio boxes should differ from the option values, their
    labels can be defined with the *\-choicelabels* attribute:

    tepam::argument\_dialogbox \\
       __\-radiobox__ \{\-label "Text adjustment" \-variable Adjustment \\
                  \-choices \{left center right\} \\
                  \-choicelabels \{Left Center Right\} \-default left\}

  - \-checkbutton *list*

    The *\-checkbutton* entry widget allows activating or deactivating a single
    choice option\. The result written into the variable will either be __0__
    if the check button was not activated or __1__ if it was activated\. An
    eventually provided default value has also to be either __0__ or
    __1__\.

    tepam::argument\_dialogbox \\
       __\-checkbutton__ \{\-label Capitalize \-variable Capitalize \-default 1\}

Several types of list and combo boxes are available to handle selection lists\.

  - \-combobox *list*

    The combobox is a combination of a normal entry widget together with a
    drop\-down list box\. The combobox allows selecting from this drop\-down list
    box a single element\. The list of the available elements can be provided
    either as a list to the *\-choices* attribute, or via a variable that is
    specified with the *\-choicevariable* attribute\.

    tepam::argument\_dialogbox \\
       __\-combobox__ \{\-label "Text size" \-variable Size \-choices \{8 9 10 12 15 18\} \-default 12\}

    And here is an example of using a variable to define the selection list:

    set TextSizes \{8 9 10 12 15 18\}
    tepam::argument\_dialogbox \\
       __\-combobox__ \{\-label "Text size" \-variable Size \-choicevariable TextSizes \-default 12\}

  - \-listbox *list*

    In contrast to the combo box, the list box is always displayed by the
    *listbox* entry widget\. Only one element is selectable unless the
    *\-multiple\_selection* attribute is set\. The list box height can be
    selected with the *\-height* attribute\. If the height is not explicitly
    defined, the list box height is automatically adapted to the argument dialog
    box size\. The first example uses a variable to define the available choices:

    set set AvailableSizes
    for \{set k 0\} \{$k<16\} \{incr k\} \{lappend AvailableSizes \[expr 1<<$k\]\}

    tepam::argument\_dialogbox \\
       __\-listbox__ \{\-label "Distance" \-variable Distance \\
                 \-choicevariable AvailableSizes \-default 6 \-height 5\}

    Here is a multi\-element selection example\. Please note that also the default
    selection can contain multiple elements:

    tepam::argument\_dialogbox \\
       __\-listbox__ \{\-label "Text styles" \-variable Styles \\
                 \-choices \{bold italic underline overstrike\} \\
                 \-choicelabels \{Bold Italic Underline Overstrike\} \\
                 \-default \{bold underline\} \-multiple\_selection 1 \\
                 \-height 3\}

  - \-disjointlistbox *list*

    A disjoint list box has to be used instead of a normal list box if the
    selection order is important\. The disjoint list box entry widget has in fact
    two list boxes, one to select elements and one to display the selected
    elements in the chosen order\.

    Disjoint listboxes allow always selecting multiple elements\. With the
    exception of the *\-multiple\_selection* attribute, disjointed list boxes
    are accepting the same attributes as the normal listbox, e\.g\. *\-height,
    \-choices, \-choicevariable, \-default*\.

    tepam::argument\_dialogbox \\
       __\-disjointlistbox__ \{\-label "Preferred scripting languages" \-variable Languages \\
                 \-comment "Please select your preferred languages in the order" \\
                 \-choices \{JavaScript Lisp Lua Octave PHP Perl Python Ruby Scheme Tcl\} \\
                 \-default \{Tcl Perl Python\}\}

The file and directory selectors are building a next group of data entry
widgets\. A paragraph of section [Entry Widget Item
Attributes](#subsection5) explains the widget specific attributes that allow
specifying the targeted file types, active directory etc\.

  - \-file *list*

    The item *\-file* creates a group composed by an entry widget together with
    a button that allows opening a file browser\. The data type *file* is
    automatically selected for this entry if no data type has been explicitly
    defined with the *\-type* attribute\.

    tepam::argument\_dialogbox \\
       __\-file__ \{\-label "Image file" \-variable ImageF \\
              \-filetypes \{\{"GIF" \{\*\.gif\}\} \{"JPG" \{\*\.jpg\}\}\} \\
              \-initialfile "picture\.gif"\}

  - \-existingfile *list*

    The item *\-existingfile* creates a group composed by an entry widget
    together with a button that allows opening a browser to select an existing
    file\. The data type *existingfile* is automatically selected for this
    entry if no data type has been explicitly defined with the *\-type*
    attribute\.

    tepam::argument\_dialogbox \\
       __\-existingfile__ \{\-label "Image file" \-variable ImageF \\
                      \-filetypes \{\{"GIF" \{\*\.gif\}\} \{"JPG" \{\*\.jpg\}\}\} \\
                      \-initialfile "picture\.gif"\}

  - \-directory *list*

    The item *\-directory* creates a group composed by an entry widget together
    with a button that allows opening a directory browser\. The data type
    *directory* is automatically selected for this entry if no data type has
    been explicitly defined with the *\-type* attribute\.

    tepam::argument\_dialogbox \\
       __\-directory__ \{\-label "Report directory" \-variable ReportDir\}

  - \-existingdirectory *list*

    The item *\-existingdirectory* creates a group composed by an entry widget
    together with a button that allows opening a browser to select an existing
    directory\. The data type *existingdirectory* is automatically selected for
    this entry if no data type has been explicitly defined with the *\-type*
    attribute\.

    tepam::argument\_dialogbox \\
       __\-existingdirectory__ \{\-label "Report directory" \-variable ReportDir\}

Finally, there is a last group of some other special data entry widgets\.

  - \-color *list*

    The color selector is composed by an entry widget together with a button
    that allows opening a color browser\. The data type *color* is
    automatically selected for this entry widget type if no data type has been
    explicitly defined with the *\-type* attribute\.

    tepam::argument\_dialogbox \\
       __\-color__ \{\-label "Background color" \-variable Color \-default red\}

  - \-font *list*

    The font selector is composed by an entry widget together with a button that
    allows opening a font browser\. The data type *font* is automatically
    selected for this entry widget type if no data type has been explicitly
    defined with the *\-type* attribute\. The entry widget displays an example







|
|
|
|
|
|
>
|
|















|
|






|
|








|
|
|




|
|
|
|
|

















|
|
|




|
|
|
|









|
|











|
|



|
|
|










|
|
|
|
|
|




|
|
|
|
|
|













|
|
|
|
|













|
|
|
|









|
|
|
|








|
|









|
|










|
|







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

## <a name='subsection4'></a>Data Entry Widget Items

Data entry widgets are created with the widget items\. These items require as
item attributes a definition list, which contains itself attribute name and
value pairs:

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\.\.\.  
> &nbsp;&nbsp;&nbsp;__\-<argument\_name>__ \{   
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*?\-<attribute\_name> <attribute\_value>?*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*?\-<attribute\_name> <attribute\_value>?*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*?\.\.\.?*  
>   
> &nbsp;&nbsp;&nbsp;\}  
> &nbsp;&nbsp;&nbsp;\.\.\.

The attribute list can contain various attributes to describe and comment an
entry widget and to constrain its entered value\. All entry widgets are accepting
a common set of attributes that are described in the section [Entry Widget Item
Attributes](#subsection5)\.

TEPAM defines a rich set of entry widgets\. If necessary, this set can be
extended with additional application specific entry widgets \(see [APPLICATION
SPECIFIC ENTRY WIDGETS](#section3)\):

  - \-entry *list*

    The *\-entry* item generates the simplest but most universal data entry
    widget\. It allows entering any kind of data in form of single line strings\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-entry__ \{\-label Name \-variable Entry\}

  - \-text *list*

    The *\-text* item generates a multi line text entry widget\. The widget
    height can be selected with the *\-height* attribute\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-text__ \{\-label Name \-variable Text \-height 5\}

  - \-checkbox *list*

    A group of check boxes is created with the *\-checkbox* item\. The number of
    check boxes and their option values are specified with a list assigned to
    the *\-choices* attribute or via a variable declared with the
    *\-choicevariable* attribute:

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-checkbox__ \{\-label "Font sytle" \-variable FontStyle \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choices \{bold italic underline\} \-default italic\}

    If the labels of the check boxes should differ from the option values, their
    labels can be defined with the *\-choicelabels* attribute:

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-checkbox__ \{\-label "Font sytle" \-variable FontStyle \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choices \{bold italic underline\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choicelabels \{Bold Italic Underline\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-default italic\}

    In contrast to a radio box group, a check box group allows selecting
    simultaneously several choice options\. The selection is stored for this
    reason inside the defined variable in form of a list, even if only one
    choice option has been selected\.

  - \-radiobox *list*

    A group of radio boxes is created with the *\-radiobox* item\. The number of
    radio boxes and their option values are specified with a list assigned to
    the *\-choices* attribute or via a variable declared with the
    *\-choicevariable* attribute\.

    In contrast to a check box group, a radio box group allows selecting
    simultaneously only one choice option\. The selected option value is stored
    directly, and not in form of a list, inside the defined variable\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-radiobox__ \{\-label "Text adjustment" \-variable Adjustment \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choices \{left center right\} \-default left\}

    If the labels of the radio boxes should differ from the option values, their
    labels can be defined with the *\-choicelabels* attribute:

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-radiobox__ \{\-label "Text adjustment" \-variable Adjustment \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choices \{left center right\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choicelabels \{Left Center Right\} \-default left\}

  - \-checkbutton *list*

    The *\-checkbutton* entry widget allows activating or deactivating a single
    choice option\. The result written into the variable will either be __0__
    if the check button was not activated or __1__ if it was activated\. An
    eventually provided default value has also to be either __0__ or
    __1__\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-checkbutton__ \{\-label Capitalize \-variable Capitalize \-default 1\}

Several types of list and combo boxes are available to handle selection lists\.

  - \-combobox *list*

    The combobox is a combination of a normal entry widget together with a
    drop\-down list box\. The combobox allows selecting from this drop\-down list
    box a single element\. The list of the available elements can be provided
    either as a list to the *\-choices* attribute, or via a variable that is
    specified with the *\-choicevariable* attribute\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-combobox__ \{\-label "Text size" \-variable Size \-choices \{8 9 10 12 15 18\} \-default 12\}

    And here is an example of using a variable to define the selection list:

> set TextSizes \{8 9 10 12 15 18\}  
> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-combobox__ \{\-label "Text size" \-variable Size \-choicevariable TextSizes \-default 12\}

  - \-listbox *list*

    In contrast to the combo box, the list box is always displayed by the
    *listbox* entry widget\. Only one element is selectable unless the
    *\-multiple\_selection* attribute is set\. The list box height can be
    selected with the *\-height* attribute\. If the height is not explicitly
    defined, the list box height is automatically adapted to the argument dialog
    box size\. The first example uses a variable to define the available choices:

> set set AvailableSizes  
> for \{set k 0\} \{$k<16\} \{incr k\} \{lappend AvailableSizes \[expr 1<<$k\]\}  
>   
> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-listbox__ \{\-label "Distance" \-variable Distance \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choicevariable AvailableSizes \-default 6 \-height 5\}

    Here is a multi\-element selection example\. Please note that also the default
    selection can contain multiple elements:

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-listbox__ \{\-label "Text styles" \-variable Styles \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choices \{bold italic underline overstrike\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choicelabels \{Bold Italic Underline Overstrike\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-default \{bold underline\} \-multiple\_selection 1 \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-height 3\}

  - \-disjointlistbox *list*

    A disjoint list box has to be used instead of a normal list box if the
    selection order is important\. The disjoint list box entry widget has in fact
    two list boxes, one to select elements and one to display the selected
    elements in the chosen order\.

    Disjoint listboxes allow always selecting multiple elements\. With the
    exception of the *\-multiple\_selection* attribute, disjointed list boxes
    are accepting the same attributes as the normal listbox, e\.g\. *\-height,
    \-choices, \-choicevariable, \-default*\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-disjointlistbox__ \{\-label "Preferred scripting languages" \-variable Languages \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-comment "Please select your preferred languages in the order" \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choices \{JavaScript Lisp Lua Octave PHP Perl Python Ruby Scheme Tcl\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-default \{Tcl Perl Python\}\}

The file and directory selectors are building a next group of data entry
widgets\. A paragraph of section [Entry Widget Item
Attributes](#subsection5) explains the widget specific attributes that allow
specifying the targeted file types, active directory etc\.

  - \-file *list*

    The item *\-file* creates a group composed by an entry widget together with
    a button that allows opening a file browser\. The data type *file* is
    automatically selected for this entry if no data type has been explicitly
    defined with the *\-type* attribute\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-file__ \{\-label "Image file" \-variable ImageF \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-filetypes \{\{"GIF" \{\*\.gif\}\} \{"JPG" \{\*\.jpg\}\}\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-initialfile "picture\.gif"\}

  - \-existingfile *list*

    The item *\-existingfile* creates a group composed by an entry widget
    together with a button that allows opening a browser to select an existing
    file\. The data type *existingfile* is automatically selected for this
    entry if no data type has been explicitly defined with the *\-type*
    attribute\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-existingfile__ \{\-label "Image file" \-variable ImageF \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-filetypes \{\{"GIF" \{\*\.gif\}\} \{"JPG" \{\*\.jpg\}\}\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-initialfile "picture\.gif"\}

  - \-directory *list*

    The item *\-directory* creates a group composed by an entry widget together
    with a button that allows opening a directory browser\. The data type
    *directory* is automatically selected for this entry if no data type has
    been explicitly defined with the *\-type* attribute\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-directory__ \{\-label "Report directory" \-variable ReportDir\}

  - \-existingdirectory *list*

    The item *\-existingdirectory* creates a group composed by an entry widget
    together with a button that allows opening a browser to select an existing
    directory\. The data type *existingdirectory* is automatically selected for
    this entry if no data type has been explicitly defined with the *\-type*
    attribute\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-existingdirectory__ \{\-label "Report directory" \-variable ReportDir\}

Finally, there is a last group of some other special data entry widgets\.

  - \-color *list*

    The color selector is composed by an entry widget together with a button
    that allows opening a color browser\. The data type *color* is
    automatically selected for this entry widget type if no data type has been
    explicitly defined with the *\-type* attribute\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-color__ \{\-label "Background color" \-variable Color \-default red\}

  - \-font *list*

    The font selector is composed by an entry widget together with a button that
    allows opening a font browser\. The data type *font* is automatically
    selected for this entry widget type if no data type has been explicitly
    defined with the *\-type* attribute\. The entry widget displays an example
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
    If no default font is provided via the *\-default* attribute, the default
    font of the label widget to display the selected font will be used as
    default selected font\. If the font family of this label widget is not part
    of the available families the first available family is used as default\. If
    the font size of this label widget is not part of the available sizes the
    next close available size is selected as default size\.

    tepam::argument\_dialogbox \\
       __\-font__ \{\-label "Font" \-variable Font \\
              \-font\_sizes \{8 10 12 16\} \\
              \-default \{Arial 20 italic\}\}

## <a name='subsection5'></a>Entry Widget Item Attributes

All the entry widget items are accepting the following attributes:

  - \-text *string*

    Eventual descriptions and comments specified with the *\-text* attribute
    are displayed above the entry widget\.

    tepam::argument\_dialogbox \\
       \-entry \{__\-text "Please enter your name bellow"__ \-variable Name\}

  - \-label *string*

    The label attribute creates left to the entry widget a label using the
    provided string as label text:

    tepam::argument\_dialogbox \\
       \-entry \{__\-label Name__ \-variable Name\}

  - \-variable *string*

    All entry widgets require a specified variable\. After accepting the entered
    information with the OK button, the entry widget data is stored inside the
    defined variables\.

    tepam::argument\_dialogbox \\
       \-existingdirectory \{\-label "Report directory" __\-variable ReportDir__\}

  - \-default *string*

    Eventual default data for the entry widgets can be provided via the
    *\-default* attribute\. The default value is overridden if an argument
    dialog box with a defined context is called another time\. The value
    acknowledged in a previous call will be used in this case as default value\.

    tepam::argument\_dialogbox \\
       \-checkbox \{\-label "Font sytle" \-variable FontStyle \\
                   \-choices \{bold italic underline\} __\-default italic__\}

  - \-optional __0__&#124;__1__

    Data can be specified as optional or mandatory with the *\-optional*
    attribute that requires either __0__ \(mandatory\) or __1__ \(optional\)
    as attribute data\.

    In case an entry is optional and no data has been entered, e\.g\. the entry
    contains an empty character string, the entry will be considered as
    undefined and the assigned variable will not be defined\.

    tepam::argument\_dialogbox \\
       \-entry \{\-label "City" \-variable start\_city \-type string\} \\
       \-entry \{\-label "Street" \-variable start\_street \-type string __\-optional 0__\} \\
       \-entry \{\-label "Street number" \-variable start\_street\_nbr \-type integer __\-optional 1__\} \\

  - \-type *string*

    If the data type is defined with the *\-type* attribute the argument dialog
    box will automatically perform a data type check after acknowledging the
    entered values and before the dialog box is closed\. If a type incompatible
    value is found an error message box appears and the user can correct the
    value\.

    The argument dialog box accepts all types that have been specified by the
    TEPAM package and that are also used by
    __[tepam::procedure](tepam\_procedure\.md)__ \(see the
    *tepam::procedure reference manual*\)\.

    Some entry widgets like the file and directory widgets, as well as the color
    and font widgets are specifying automatically the default data type if no
    type has been specified explicitly with the *\-type* attribute\.

    tepam::argument\_dialogbox \\
       __\-entry__ \{\-label "Street number" \-variable start\_street\_nbr __\-type integer__\} \\

  - \-range *string*

    Values can be constrained with the *\-range* attribute\. The valid range is
    defined with a list containing the minimum valid value and a maximum valid
    value\.

    The *\-range* attribute has to be used only for numerical arguments, like
    integers and doubles\.

    tepam::argument\_dialogbox \\
       \-entry \{\-label Month \-variable Month \-type integer __\-range \{1 12\}__\}

  - \-validatecommand *string*

    Custom argument value validations can be performed via specific validation
    commands that are defined with the *\-validatecommand* attribute\. The
    provided validation command can be a complete script in which the pattern
    *%P* is placeholder for the argument value that has to be validated\.

    tepam::argument\_dialogbox \\
       \-entry \{\-label "Your comment" \-variable YourCom \\
               __\-validatecommand__ "IllegalWordDetector %P"\}

    While the purpose of this custom argument validation attribute is the
    validation of a specific argument, there is also a global data validation
    attribute *\-validatecommand* that allows performing validation that
    involves multiple arguments\.

  - \-validatecommand\_error\_text *string*

    This attribute allows overriding the default error message for a custom
    argument validation \(defined by *\-validatecommand*\)\.

Some other attributes are supported by the list and combo boxes as well as by
the radio and check buttons\.

  - \-choices *string*

    Choice lists can directly be defined with the *\-choices* attribute\. This
    way to define choice lists is especially adapted for smaller, fixed
    selection lists\.

    tepam::argument\_dialogbox \\
       \-listbox \{\-label "Text styles" \-variable Styles \\
                 __\-choices \{bold italic underline\}__ \-default underline

  - \-choicelabels *string* *\(only check and radio buttons\)*

    If the labels of the check and radio boxes should differ from the option
    values, they can be defined with the *\-choicelabels* attribute:

    tepam::argument\_dialogbox \\
       \-checkbox \{\-label "Font sytle" \-variable FontStyle \\
                  \-choices \{bold italic underline\} \\
                  __\-choicelabels \{Bold Italic Underline\}__

  - \-choicevariable *string*

    Another way to define the choice lists is using the *\-choicevariable*
    attribute\. This way to define choice lists is especially adapted for huge
    and eventually variable selection lists\.

    set TextSizes \{8 9 10 12 15 18\}
    tepam::argument\_dialogbox \\
       \-combobox \{\-label "Text size" \-variable Size __\-choicevariable TextSizes__\}

  - \-multiple\_selection __0__&#124;__1__

    The list box item \(__\-listbox__\) allows by default selecting only one
    list element\. By setting the *\-multiple\_selection* attribute to __1__,
    multiple elements can be selected\.

    tepam::argument\_dialogbox \\
       \-listbox \{\-label "Text styles" \-variable Styles \\
                 \-choices \{bold italic underline\} \-default underline \\
                 __\-multiple\_selection 1__ \-height 3\}

Some additional attributes are supported by the file and directory selection
widgets\.

  - \-filetypes *string*

    The file type attribute is used by the __\-file__ and
    __\-existingfile__ items to define the file endings that are searched by
    the file browser\.

    tepam::argument\_dialogbox \\
       \-file \{\-label "Image file" \-variable ImageF \\
              __\-filetypes \{\{"GIF" \{\*\.gif\}\} \{"JPG" \{\*\.jpg\}\}\}__\}

  - \-initialfile *string*

    The initial file used by the file browsers of the __\-file__ and
    __\-existingfile__ widgets are by default the file defined with the
    *\-default* attribute, unless a file is specified with the *\-initialfile*
    attribute\.

    tepam::argument\_dialogbox \\
       \-file \{\-variable ImageF __\-initialfile "picture\.gif"__\}

  - \-activedir *string*

    The *\-activedir* attribute will override the default active search
    directory used by the file browsers of all file and directory entry widgets\.
    The default active search directory is defined by the directory of a
    specified initial file \(*\-initialfile*\) if defined, and otherwise by the
    directory of the default file/directory, specified with the *\-default*
    attribute\.

    tepam::argument\_dialogbox \\
       \-file "\-variable ImageF __\-activedir $pwd__"

Finally, there is a last attribute supported by some widgets:

  - \-height *string*

    All widgets containing a selection list \(__\-listbox__,
    __\-disjointlistbox__, __\-font__\) as well as the multi line
    __\-text__ widget are accepting the *\-height* attribute that defines
    the number of displayed rows of the selection lists\.

    tepam::argument\_dialogbox \\
       \-listbox \{\-label "Text size" \-variable Size \\
                 \-choices \{8 9 10 12 15 18\} \-default 12 __\-height 3__\}

    If the no height has been explicitly specified the height of the widget will
    be dynamically adapted to the argument dialog box size\.

# <a name='section3'></a>APPLICATION SPECIFIC ENTRY WIDGETS

An application specific entry widget can be made available to the argument
dialog box by adding a dedicated procedure to the __tepam__ namespace\. This
procedure has three arguments; the first one is the widget path, the second one
a subcommand and the third argument has various purposes:

    *proc* tepam::ad\_form\(<WidgetName>\) \{W Command \{Par ""\}\} \{
       *upvar Option Option; \# if required*
       *variable argument\_dialogbox; \# if required*
       switch $Command \{
          "create" <CreateCommandSequence>
          "set\_choice" <SetChoiceCommandSequence>
          "set" <SetCommandv>
          "get" <GetCommandSequence>
       \}
    \}

__Argument\_dialogbox__ takes care about the *\-label* and *\-text*
attributes for all entry widgets\. For any data entry widget it creates a frame
into which the data entry widget components can be placed\. The path to this
frame is provided via the *W* argument\.

The entry widget procedure has to support 3 mandatory and an optional command







|
|
|
|










|
|






|
|







|
|








|
|
|











|
|
|
|


















|
|










|
|








|
|
|




















|
|
|






|
|
|
|







|
|
|







|
|
|
|










|
|
|








|
|










|
|










|
|
|











|
|
|
|
|
|
|
|
|
|







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
    If no default font is provided via the *\-default* attribute, the default
    font of the label widget to display the selected font will be used as
    default selected font\. If the font family of this label widget is not part
    of the available families the first available family is used as default\. If
    the font size of this label widget is not part of the available sizes the
    next close available size is selected as default size\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-font__ \{\-label "Font" \-variable Font \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-font\_sizes \{8 10 12 16\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-default \{Arial 20 italic\}\}

## <a name='subsection5'></a>Entry Widget Item Attributes

All the entry widget items are accepting the following attributes:

  - \-text *string*

    Eventual descriptions and comments specified with the *\-text* attribute
    are displayed above the entry widget\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-entry \{__\-text "Please enter your name bellow"__ \-variable Name\}

  - \-label *string*

    The label attribute creates left to the entry widget a label using the
    provided string as label text:

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-entry \{__\-label Name__ \-variable Name\}

  - \-variable *string*

    All entry widgets require a specified variable\. After accepting the entered
    information with the OK button, the entry widget data is stored inside the
    defined variables\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-existingdirectory \{\-label "Report directory" __\-variable ReportDir__\}

  - \-default *string*

    Eventual default data for the entry widgets can be provided via the
    *\-default* attribute\. The default value is overridden if an argument
    dialog box with a defined context is called another time\. The value
    acknowledged in a previous call will be used in this case as default value\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-checkbox \{\-label "Font sytle" \-variable FontStyle \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choices \{bold italic underline\} __\-default italic__\}

  - \-optional __0__&#124;__1__

    Data can be specified as optional or mandatory with the *\-optional*
    attribute that requires either __0__ \(mandatory\) or __1__ \(optional\)
    as attribute data\.

    In case an entry is optional and no data has been entered, e\.g\. the entry
    contains an empty character string, the entry will be considered as
    undefined and the assigned variable will not be defined\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-entry \{\-label "City" \-variable start\_city \-type string\} \\  
> &nbsp;&nbsp;&nbsp;\-entry \{\-label "Street" \-variable start\_street \-type string __\-optional 0__\} \\  
> &nbsp;&nbsp;&nbsp;\-entry \{\-label "Street number" \-variable start\_street\_nbr \-type integer __\-optional 1__\} \\

  - \-type *string*

    If the data type is defined with the *\-type* attribute the argument dialog
    box will automatically perform a data type check after acknowledging the
    entered values and before the dialog box is closed\. If a type incompatible
    value is found an error message box appears and the user can correct the
    value\.

    The argument dialog box accepts all types that have been specified by the
    TEPAM package and that are also used by
    __[tepam::procedure](tepam\_procedure\.md)__ \(see the
    *tepam::procedure reference manual*\)\.

    Some entry widgets like the file and directory widgets, as well as the color
    and font widgets are specifying automatically the default data type if no
    type has been specified explicitly with the *\-type* attribute\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;__\-entry__ \{\-label "Street number" \-variable start\_street\_nbr __\-type integer__\} \\

  - \-range *string*

    Values can be constrained with the *\-range* attribute\. The valid range is
    defined with a list containing the minimum valid value and a maximum valid
    value\.

    The *\-range* attribute has to be used only for numerical arguments, like
    integers and doubles\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-entry \{\-label Month \-variable Month \-type integer __\-range \{1 12\}__\}

  - \-validatecommand *string*

    Custom argument value validations can be performed via specific validation
    commands that are defined with the *\-validatecommand* attribute\. The
    provided validation command can be a complete script in which the pattern
    *%P* is placeholder for the argument value that has to be validated\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-entry \{\-label "Your comment" \-variable YourCom \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-validatecommand__ "IllegalWordDetector %P"\}

    While the purpose of this custom argument validation attribute is the
    validation of a specific argument, there is also a global data validation
    attribute *\-validatecommand* that allows performing validation that
    involves multiple arguments\.

  - \-validatecommand\_error\_text *string*

    This attribute allows overriding the default error message for a custom
    argument validation \(defined by *\-validatecommand*\)\.

Some other attributes are supported by the list and combo boxes as well as by
the radio and check buttons\.

  - \-choices *string*

    Choice lists can directly be defined with the *\-choices* attribute\. This
    way to define choice lists is especially adapted for smaller, fixed
    selection lists\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-listbox \{\-label "Text styles" \-variable Styles \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-choices \{bold italic underline\}__ \-default underline

  - \-choicelabels *string* *\(only check and radio buttons\)*

    If the labels of the check and radio boxes should differ from the option
    values, they can be defined with the *\-choicelabels* attribute:

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-checkbox \{\-label "Font sytle" \-variable FontStyle \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choices \{bold italic underline\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-choicelabels \{Bold Italic Underline\}__

  - \-choicevariable *string*

    Another way to define the choice lists is using the *\-choicevariable*
    attribute\. This way to define choice lists is especially adapted for huge
    and eventually variable selection lists\.

> set TextSizes \{8 9 10 12 15 18\}  
> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-combobox \{\-label "Text size" \-variable Size __\-choicevariable TextSizes__\}

  - \-multiple\_selection __0__&#124;__1__

    The list box item \(__\-listbox__\) allows by default selecting only one
    list element\. By setting the *\-multiple\_selection* attribute to __1__,
    multiple elements can be selected\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-listbox \{\-label "Text styles" \-variable Styles \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choices \{bold italic underline\} \-default underline \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-multiple\_selection 1__ \-height 3\}

Some additional attributes are supported by the file and directory selection
widgets\.

  - \-filetypes *string*

    The file type attribute is used by the __\-file__ and
    __\-existingfile__ items to define the file endings that are searched by
    the file browser\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-file \{\-label "Image file" \-variable ImageF \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-filetypes \{\{"GIF" \{\*\.gif\}\} \{"JPG" \{\*\.jpg\}\}\}__\}

  - \-initialfile *string*

    The initial file used by the file browsers of the __\-file__ and
    __\-existingfile__ widgets are by default the file defined with the
    *\-default* attribute, unless a file is specified with the *\-initialfile*
    attribute\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-file \{\-variable ImageF __\-initialfile "picture\.gif"__\}

  - \-activedir *string*

    The *\-activedir* attribute will override the default active search
    directory used by the file browsers of all file and directory entry widgets\.
    The default active search directory is defined by the directory of a
    specified initial file \(*\-initialfile*\) if defined, and otherwise by the
    directory of the default file/directory, specified with the *\-default*
    attribute\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-file "\-variable ImageF __\-activedir $pwd__"

Finally, there is a last attribute supported by some widgets:

  - \-height *string*

    All widgets containing a selection list \(__\-listbox__,
    __\-disjointlistbox__, __\-font__\) as well as the multi line
    __\-text__ widget are accepting the *\-height* attribute that defines
    the number of displayed rows of the selection lists\.

> tepam::argument\_dialogbox \\  
> &nbsp;&nbsp;&nbsp;\-listbox \{\-label "Text size" \-variable Size \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choices \{8 9 10 12 15 18\} \-default 12 __\-height 3__\}

    If the no height has been explicitly specified the height of the widget will
    be dynamically adapted to the argument dialog box size\.

# <a name='section3'></a>APPLICATION SPECIFIC ENTRY WIDGETS

An application specific entry widget can be made available to the argument
dialog box by adding a dedicated procedure to the __tepam__ namespace\. This
procedure has three arguments; the first one is the widget path, the second one
a subcommand and the third argument has various purposes:

> *proc* tepam::ad\_form\(<WidgetName>\) \{W Command \{Par ""\}\} \{  
> &nbsp;&nbsp;&nbsp;*upvar Option Option; \# if required*  
> &nbsp;&nbsp;&nbsp;*variable argument\_dialogbox; \# if required*  
> &nbsp;&nbsp;&nbsp;switch $Command \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"create" <CreateCommandSequence>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"set\_choice" <SetChoiceCommandSequence>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"set" <SetCommandv>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"get" <GetCommandSequence>  
> &nbsp;&nbsp;&nbsp;\}  
> \}

__Argument\_dialogbox__ takes care about the *\-label* and *\-text*
attributes for all entry widgets\. For any data entry widget it creates a frame
into which the data entry widget components can be placed\. The path to this
frame is provided via the *W* argument\.

The entry widget procedure has to support 3 mandatory and an optional command
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
__argument\_dialogbox__ has to be used for this purpose together with array
indexes starting with *"$W,"*, e\.g\. *argument\_dialogbox\($W,values\)*\.

Examples of entry widget procedures are directly provided by the TEPAM package
source file that specifies the standard entry widget procedures\. The simplest
procedure is the one for the basic *entry* widget:

    proc tepam::ad\_form\(entry\) \{W Command \{Par ""\}\} \{
       switch $Command \{
          "create" \{pack \[entry \\$W\.entry\] \-fill x \\
                            \-expand yes \-pady 4 \-side left\}
          "set" \{\\$W\.entry insert 0 $Par\}
          "get" \{return \[\\$W\.entry get\]\}
       \}
    \}



It is also possible to relay on an existing entry widget procedure to derive a
new, more specific one\. The *radiobox* widget is used for example, to create a
new entry widget that allows selecting either *left*, *center* or *right*\.
The original *radiobox* widget is called with the *set\_choice* command
immediately after the *create* command, to define the fixed list of selection
options\.

    proc tepam::ad\_form\(rcl\) \{W Command \{Par ""\}\} \{
       set Res \[ad\_form\(radiobox\) $W $Command $Par\]
       if \{$Command=="create"\} \{
          ad\_form\(radiobox\) $W set\_choice \{left center right\}
       \}

       return $Res
    \}


Please consult the TEPAM package source file to find additional and more complex
examples of entry widget procedures\.

# <a name='section4'></a>VARIABLES

The __argument\_dialogbox__ is using two variables inside the namespace







|
|
|
|
|
|
<
<
>
>








|
|
|
|
<
>

<
>







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
__argument\_dialogbox__ has to be used for this purpose together with array
indexes starting with *"$W,"*, e\.g\. *argument\_dialogbox\($W,values\)*\.

Examples of entry widget procedures are directly provided by the TEPAM package
source file that specifies the standard entry widget procedures\. The simplest
procedure is the one for the basic *entry* widget:

    proc tepam::ad_form(entry) {W Command {Par ""}} {
       switch $Command {
          "create" {pack [entry \$W.entry] -fill x \
                            -expand yes -pady 4 -side left}
          "set" {\$W.entry insert 0 $Par}
          "get" {return [\$W.entry get]}


       }
    }

It is also possible to relay on an existing entry widget procedure to derive a
new, more specific one\. The *radiobox* widget is used for example, to create a
new entry widget that allows selecting either *left*, *center* or *right*\.
The original *radiobox* widget is called with the *set\_choice* command
immediately after the *create* command, to define the fixed list of selection
options\.

    proc tepam::ad_form(rcl) {W Command {Par ""}} {
       set Res [ad_form(radiobox) $W $Command $Par]
       if {$Command=="create"} {
          ad_form(radiobox) $W set_choice {left center right}

       }
       return $Res

    }

Please consult the TEPAM package source file to find additional and more complex
examples of entry widget procedures\.

# <a name='section4'></a>VARIABLES

The __argument\_dialogbox__ is using two variables inside the namespace

Changes to embedded/md/tcllib/files/modules/tepam/tepam_doc_gen.md.

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
Support for a new document format can be added by defining in the
__tepam::doc\_gen__ namespace a set of procedures that generate the different
document components\.

The following documentation listing contains tokens that refer to the different
document generation procedures:

    *     <01>*
    *<03> <20s>*   NAME*<20e>*
    *     <30s>*       message\_box \- Displays text in a message box*<30e>*
    *     <20s>*   SYNOPSYS*<20e>*
    *     <40s>*       message\_box \[\-mtype <mtype>\] <text>*<40e>*
    *     <20s>*   DESCRIPTION*<20e>*
    *     <21s>     message\_box<21e>*
    *     <54s>       message\_box \[\-mtype <mtype>\] <text><54e>*
    *     <50s>*       This procedure allows displaying a text in an message box\. The following
    *          *       message types are supported:*<50e>*
    *<51> <53s>*       \* Info*<53e>*
    *     <53s>*       \* Warning*<53e>*
    *     <53s>*       \* Error*<53e>*                                           *<52>*
    *     <50s>*       If the text parameter is use multiple times the different texts are
    *          *       concatenated to create the message text\.*<50e>*
    *     <20s>*   ARGUMENTS*<20e>*
    *<60> <62s>*       \[\-mtype <mtype>\]*<62e>*
    *<63> <65s>*          Message type*<65e>*
    *     <66s>*          Default: "Warning"*<66e>*
    *     <66s>*          Multiple: yes*<66e>*
    *     <66s>*          Choices: Info, Warning, Error*<66e>*                  *<64>*
    *     <62s>*       <text>*<62e>*
    *<63> <65s>*          One or multiple text lines to display*<65e>*
    *     <66s>*          Type: string*<66e>*
    *     <66s>*          Multiple: yes*<66e>*                                  *<64><61>*
    *     <20s>*   EXAMPLE*<20e>*
    *<70> <72s>*       message\_box "Please save first the document"*<72e>*
    *     <73s>*       \-> 1*<73e>*                                              *<71><04>*
    *     <02>*

There are 2 types of document generation procedures:

  - Content generation procedures \(e\.g\. <40s>\.\.\.<40e>\)

    These procedures generate some document content based on the text that is
    provided as procedure argument\. The listing above shows two tokens for these







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







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
Support for a new document format can be added by defining in the
__tepam::doc\_gen__ namespace a set of procedures that generate the different
document components\.

The following documentation listing contains tokens that refer to the different
document generation procedures:

> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<01>*  
> &nbsp;*<03> <20s>*   NAME*<20e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<30s>*       message\_box \- Displays text in a message box*<30e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<20s>*   SYNOPSYS*<20e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<40s>*       message\_box \[\-mtype <mtype>\] <text>*<40e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<20s>*   DESCRIPTION*<20e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<21s>     message\_box<21e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<54s>       message\_box \[\-mtype <mtype>\] <text><54e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<50s>*       This procedure allows displaying a text in an message box\. The following  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**       message types are supported:*<50e>*  
> &nbsp;*<51> <53s>*       \* Info*<53e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<53s>*       \* Warning*<53e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<53s>*       \* Error*<53e>*                                           *<52>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<50s>*       If the text parameter is use multiple times the different texts are  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**       concatenated to create the message text\.*<50e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<20s>*   ARGUMENTS*<20e>*  
> &nbsp;*<60> <62s>*       \[\-mtype <mtype>\]*<62e>*  
> &nbsp;*<63> <65s>*          Message type*<65e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<66s>*          Default: "Warning"*<66e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<66s>*          Multiple: yes*<66e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<66s>*          Choices: Info, Warning, Error*<66e>*                  *<64>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<62s>*       <text>*<62e>*  
> &nbsp;*<63> <65s>*          One or multiple text lines to display*<65e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<66s>*          Type: string*<66e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<66s>*          Multiple: yes*<66e>*                                  *<64><61>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<20s>*   EXAMPLE*<20e>*  
> &nbsp;*<70> <72s>*       message\_box "Please save first the document"*<72e>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<73s>*       \-> 1*<73e>*                                              *<71><04>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<02>*

There are 2 types of document generation procedures:

  - Content generation procedures \(e\.g\. <40s>\.\.\.<40e>\)

    These procedures generate some document content based on the text that is
    provided as procedure argument\. The listing above shows two tokens for these
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

      * *IsOptional*

        If true \(=__1__\) the argument is optional which should be indicated
        by the generated string \(for example by putting the argument into
        brackets \{\[\]\} or into question marks '?'\):

    gen\(TXT,ArgumentString\) mtype 1 0 string \->

        *"\[mtype\]"*

      * *IsNamed*

        If true \(=__1__\) an argument is a named argument \(option\)\. The
        generated string should in this case contain the argument/option name,
        followed by the argument itself:

    gen\(TXT,ArgumentString\) mtype 0 1 string \->

        *"\-mtype <mtype>"* Named arguments can also be optional:

    gen\(TXT,ArgumentString\) mtype 1 1 string \->

        *"\[\-mtype <mtype>\]"*

      * *Type*

        Indicates the type of the argument\. If the type is set to __none__
        the argument is a flag, which needs to be indicated by the generated
        string\. Example:

    gen\(TXT,ArgumentString\) close 1 1 none \->

        *"\[\-close\]"*

# <a name='section5'></a>EXAMPLES

## <a name='subsection5'></a>tepam::doc\_gen::generate

The __TEPAM Doc Gen__ package can be explored by generating the
documentation of the command __tepam::doc\_gen::generate__\. The following
example generates the document in text format \(default format\):

    __tepam::doc\_gen::generate__ tepam::doc\_gen::generate

The next example generates the documentation in HTML format:

    __tepam::doc\_gen::generate__ \-format HTML tepam::doc\_gen::generate

The flag ?header\_footer? adds also the file header and footer:

    __tepam::doc\_gen::generate__ \-format HTML \-header\_footer tepam::doc\_gen::generate

The documentation can directly be stored in a file\. The file header and footer
are automatically generated in this way:

    __tepam::doc\_gen::generate__ \-format HTML \-dest\_file doc\_gen\.html tepam::doc\_gen::generate

The generated HTML file refers a CSS stylesheet file \(default:
tepam\_doc\_stylesheet\.css\)\. To display the HTML file correctly this CSS
stylesheet file needs to be copied into the directory of the generated HTML
file\.

The Tcl DOC Tools format can be used as intermediate format to generate other
formats, for example HTML:

    *\# Generate the documentation in Tcl Doc Tool format*
    set dt \[__tepam::doc\_gen::generate__ \-format DT \-header\_footer tepam::doc\_gen::generate\]
    **
    *\# Create a new doc tools object \(HTML format\)*
    package require doctools
    ::doctools::new myDoc \-format html
    **
    *\# Open the HTML file, and write the HTML formatted documentation*
    set fHtml \[open doc\_gen\.dt\.html w\]
    puts $fHtml \[myDoc format $dt\]
    close $fHtml

## <a name='subsection6'></a>tepam::doc\_gen::patch

While __generate__ provides a limited number of possibilities to vary the
document structure, __[patch](\.\./\.\./\.\./\.\./index\.md\#patch)__ offers more
flexibility\. Multiple documentations for different procedures and meta
information can for example be added\.

The following listing shows how the
__[patch](\.\./\.\./\.\./\.\./index\.md\#patch)__ command works\. It defines first
a HTML master document string that contains 2 procedure documentation
placeholders \(*\{\*<ProcedureName>\*\}*\)\. There placeholders are replaced by
__[patch](\.\./\.\./\.\./\.\./index\.md\#patch)__ with the generated documentation
of the referred procedures\. Since nonstandard placeholders are used,
__[patch](\.\./\.\./\.\./\.\./index\.md\#patch)__ is called with an explicit
placeholder pattern definition \(argument *search\_pattern*\)\.

    *\# Define the HTML master document*
    set HtmlMasterDoc \{\\
    <html>
      <head>
        <title>tepam::doc\_gen</title>
        <link rel="stylesheet" href="tepam\_doc\_stylesheet\.css">
        <meta content="documentation" name="keywords"></meta>
      </head>
      <body>
        <h1>tepam::doc\_gen</h1>
          <h2>Generate</h2>
    __\{\*tepam::doc\_gen::generate\*\}__
          <h2>Patch</h2>
    __\{\*tepam::doc\_gen::patch\*\}__
      </body>
    <html>\\
    \}
    **
    *\# Patch the master document: This will replace the placeholders by the
    \# procedure documentation divisions:*

    __tepam::doc\_gen::patch__ \-format HTML \-search\_pattern \{\\\{\\\*\(\.\*?\)\\\*\\\}\} \\
                          \-src\_string $HtmlMasterDoc \-dest\_file tepam\_doc\_gen\.html

# <a name='seealso'></a>SEE ALSO

[tepam\(n\)](tepam\_introduction\.md),
[tepam::procedure\(n\)](tepam\_procedure\.md)

# <a name='keywords'></a>KEYWORDS







|
<
<







|

|

|
<
<







|
<
<









|



|



|




|









|
|
|
|
|
|
|
|
|
|
|

















|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|







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

      * *IsOptional*

        If true \(=__1__\) the argument is optional which should be indicated
        by the generated string \(for example by putting the argument into
        brackets \{\[\]\} or into question marks '?'\):

> gen\(TXT,ArgumentString\) mtype 1 0 string \-> *"\[mtype\]"*



      * *IsNamed*

        If true \(=__1__\) an argument is a named argument \(option\)\. The
        generated string should in this case contain the argument/option name,
        followed by the argument itself:

> gen\(TXT,ArgumentString\) mtype 0 1 string \-> *"\-mtype <mtype>"*

        Named arguments can also be optional:

> gen\(TXT,ArgumentString\) mtype 1 1 string \-> *"\[\-mtype <mtype>\]"*



      * *Type*

        Indicates the type of the argument\. If the type is set to __none__
        the argument is a flag, which needs to be indicated by the generated
        string\. Example:

> gen\(TXT,ArgumentString\) close 1 1 none \-> *"\[\-close\]"*



# <a name='section5'></a>EXAMPLES

## <a name='subsection5'></a>tepam::doc\_gen::generate

The __TEPAM Doc Gen__ package can be explored by generating the
documentation of the command __tepam::doc\_gen::generate__\. The following
example generates the document in text format \(default format\):

> __tepam::doc\_gen::generate__ tepam::doc\_gen::generate

The next example generates the documentation in HTML format:

> __tepam::doc\_gen::generate__ \-format HTML tepam::doc\_gen::generate

The flag ?header\_footer? adds also the file header and footer:

> __tepam::doc\_gen::generate__ \-format HTML \-header\_footer tepam::doc\_gen::generate

The documentation can directly be stored in a file\. The file header and footer
are automatically generated in this way:

> __tepam::doc\_gen::generate__ \-format HTML \-dest\_file doc\_gen\.html tepam::doc\_gen::generate

The generated HTML file refers a CSS stylesheet file \(default:
tepam\_doc\_stylesheet\.css\)\. To display the HTML file correctly this CSS
stylesheet file needs to be copied into the directory of the generated HTML
file\.

The Tcl DOC Tools format can be used as intermediate format to generate other
formats, for example HTML:

> *\# Generate the documentation in Tcl Doc Tool format*  
> set dt \[__tepam::doc\_gen::generate__ \-format DT \-header\_footer tepam::doc\_gen::generate\]  
> **  
> *\# Create a new doc tools object \(HTML format\)*  
> package require doctools  
> ::doctools::new myDoc \-format html  
> **  
> *\# Open the HTML file, and write the HTML formatted documentation*  
> set fHtml \[open doc\_gen\.dt\.html w\]  
> puts $fHtml \[myDoc format $dt\]  
> close $fHtml

## <a name='subsection6'></a>tepam::doc\_gen::patch

While __generate__ provides a limited number of possibilities to vary the
document structure, __[patch](\.\./\.\./\.\./\.\./index\.md\#patch)__ offers more
flexibility\. Multiple documentations for different procedures and meta
information can for example be added\.

The following listing shows how the
__[patch](\.\./\.\./\.\./\.\./index\.md\#patch)__ command works\. It defines first
a HTML master document string that contains 2 procedure documentation
placeholders \(*\{\*<ProcedureName>\*\}*\)\. There placeholders are replaced by
__[patch](\.\./\.\./\.\./\.\./index\.md\#patch)__ with the generated documentation
of the referred procedures\. Since nonstandard placeholders are used,
__[patch](\.\./\.\./\.\./\.\./index\.md\#patch)__ is called with an explicit
placeholder pattern definition \(argument *search\_pattern*\)\.

> *\# Define the HTML master document*  
> set HtmlMasterDoc \{\\  
> <html>  
> &nbsp;&nbsp;<head>  
> &nbsp;&nbsp;&nbsp;&nbsp;<title>tepam::doc\_gen</title>  
> &nbsp;&nbsp;&nbsp;&nbsp;<link rel="stylesheet" href="tepam\_doc\_stylesheet\.css">  
> &nbsp;&nbsp;&nbsp;&nbsp;<meta content="documentation" name="keywords"></meta>  
> &nbsp;&nbsp;</head>  
> &nbsp;&nbsp;<body>  
> &nbsp;&nbsp;&nbsp;&nbsp;<h1>tepam::doc\_gen</h1>  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<h2>Generate</h2>  
> __\{\*tepam::doc\_gen::generate\*\}__  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<h2>Patch</h2>  
> __\{\*tepam::doc\_gen::patch\*\}__  
> &nbsp;&nbsp;</body>  
> <html>\\  
> \}  
> **  
> *\# Patch the master document: This will replace the placeholders by the *  
> *\# procedure documentation divisions:*  
>   
> __tepam::doc\_gen::patch__ \-format HTML \-search\_pattern \{\\\{\\\*\(\.\*?\)\\\*\\\}\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-src\_string $HtmlMasterDoc \-dest\_file tepam\_doc\_gen\.html

# <a name='seealso'></a>SEE ALSO

[tepam\(n\)](tepam\_introduction\.md),
[tepam::procedure\(n\)](tepam\_procedure\.md)

# <a name='keywords'></a>KEYWORDS

Changes to embedded/md/tcllib/files/modules/tepam/tepam_introduction.md.

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
takes as __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ also 3 arguments: The
procedure name, the procedure header and the procedure body\.

The following example declares the subcommand
__[message](\.\./\.\./\.\./\.\./index\.md\#message)__ of the procedure
__display__\. This command has several named and unnamed arguments:

    __[tepam::procedure](tepam\_procedure\.md)__ \{display message\} \{
       \-return            \-
       \-short\_description "Displays a simple message box"
       \-description       "This procedure allows displaying a configurable message box\."
       \-args \{
          \{\-mtype \-default Warning \-choices \{Info Warning Error\} \-description "Message type"\}
          \{\-font \-type font \-default \{Arial 10 italic\} \-description "Message text font"\}
          \{\-level \-type integer \-optional \-range \{1 10\} \-description "Message level"\}
          \{\-fg \-type color \-default black \-description "Message color"\}
          \{\-bg \-type color \-optional \-description "Background color"\}
          \{\-no\_border \-type none \-description "Use a splash window style \(no border\)"\}
          \{\-log\_file \-type file \-optional \-description "Optional message log file"\}
          \{text \-type string \-multiple \-description "Multiple text lines to display"\}
       \}
    \} \{
    *   puts "display message:"
       foreach var \{mtype font level fg bg no\_border log\_file text\} \{
          if \{\[info exists $var\]\} \{
             puts  "  $var=\[set $var\]"
          \}
       \}
    *\}

A call of procedure that has been declared in this way will first invoke the
TEPAM argument manager, before the procedure body is executed\. The argument
manager parses the provided arguments, validates them, completes them eventually
with some default values, and makes them finally available to the procedure body
as local variables\. In case an argument is missing or has a wrong type, the
argument manager generates an error message that explains the reason for the







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







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
takes as __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ also 3 arguments: The
procedure name, the procedure header and the procedure body\.

The following example declares the subcommand
__[message](\.\./\.\./\.\./\.\./index\.md\#message)__ of the procedure
__display__\. This command has several named and unnamed arguments:

> __[tepam::procedure](tepam\_procedure\.md)__ \{display message\} \{  
> &nbsp;&nbsp;&nbsp;\-return            \-  
> &nbsp;&nbsp;&nbsp;\-short\_description "Displays a simple message box"  
> &nbsp;&nbsp;&nbsp;\-description       "This procedure allows displaying a configurable message box\."  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-mtype \-default Warning \-choices \{Info Warning Error\} \-description "Message type"\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-font \-type font \-default \{Arial 10 italic\} \-description "Message text font"\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-level \-type integer \-optional \-range \{1 10\} \-description "Message level"\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-fg \-type color \-default black \-description "Message color"\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-bg \-type color \-optional \-description "Background color"\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-no\_border \-type none \-description "Use a splash window style \(no border\)"\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-log\_file \-type file \-optional \-description "Optional message log file"\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{text \-type string \-multiple \-description "Multiple text lines to display"\}  
> &nbsp;&nbsp;&nbsp;\}  
> \} \{  
> &nbsp;&nbsp;&nbsp;*puts "display message:"*  
> &nbsp;&nbsp;&nbsp;*foreach var \{mtype font level fg bg no\_border log\_file text\} \{*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*if \{\[info exists $var\]\} \{*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*puts  "  $var=\[set $var\]"*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*\}*  
> &nbsp;&nbsp;&nbsp;*\}*  
> \}

A call of procedure that has been declared in this way will first invoke the
TEPAM argument manager, before the procedure body is executed\. The argument
manager parses the provided arguments, validates them, completes them eventually
with some default values, and makes them finally available to the procedure body
as local variables\. In case an argument is missing or has a wrong type, the
argument manager generates an error message that explains the reason for the
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
the named arguments \(Tk style\)\.

# <a name='section4'></a>PROCEDURE HELP

The declared procedure can simply be called with the *\-help* option to get the
information about the usage of the procedure and its arguments:

    __display message__ \-help


* \-> NAME display message \- Displays a simple message box SYNOPSYS display



message \[\-mtype <mtype>\] : Message type, default: "Warning", choices: \{Info

Warning Error\} \[\-font <font>\] : Message text font, type: font, default: Arial 10

italic \[\-level <level>\] : Message level, type: integer, range: 1\.\.10 \[\-fg <fg>\]

: Message color, type: color, default: black \[\-bg <bg>\] : Background color,



type: color \[\-no\_border \] : Use a splash window style \(no border\) \[\-log\_file

<log\_file>\] : Optional message log file, type: file <text> : Multiple text lines


to display, type: string DESCRIPTION This procedure allows displaying a
configurable message box\.*

# <a name='section5'></a>PROCEDURE CALL

The specified procedure can be called in many ways\. The following listing shows
some valid procedure calls:

    __display message__ "The document hasn't yet been saved\!"
    *\-> display message:
         mtype=Warning
         font=Arial 10 italic
         fg=black
         no\_border=0
         text=\{The document hasn't yet been saved\!\}*


    __display message__ \-fg red \-bg black "Please save first the document"
    *\-> display message:
         mtype=Warning
         font=Arial 10 italic
         fg=red
         bg=black
         no\_border=0
         text=\{Please save first the document\}*


    __display message__ \-mtype Error \-no\_border "Why is here no border?"
    *\-> display message:
         mtype=Error
         font=Arial 10 italic
         fg=black
         no\_border=1
         text=\{Why is here no border?\}*


    __display message__ \-font \{Courier 12\} \-level 10 \\
       "Is there enough space?" "Reduce otherwise the font size\!"


*\-> display message: mtype=Warning font=Courier 12 level=10 fg=black



no\_border=0 text=\{Is there enough space?\} \{Reduce otherwise the font size\!\}*

The next lines show how wrong arguments are recognized\. The *text* argument
that is mandatory is missing in the first procedure call:

    __display message__ \-font \{Courier 12\}


* \-> display message: Required argument is missing: text* Only known arguments
are accepted:

    __display message__ \-category warning Hello


* \-> display message: Argument '\-category' not known* Argument types are
automatically checked and an error message is generated in case the argument
value has not the expected type:

    __display message__ \-fg MyColor "Hello"


* \-> display message: Argument 'fg' requires type 'color'\. Provided value:
'MyColor'* Selection choices have to be respected \.\.\.

    __display message__ \-mtype Fatal Hello


* \-> display message: Argument \(mtype\) has to be one of the following elements:
Info, Warning, Error* \.\.\. as well as valid value ranges:

    __display message__ \-level 12 Hello

* \-> display message: Argument \(level\) has to be between 1 and 10*

# <a name='section6'></a>INTERACTIVE PROCEDURE CALLS

The most intuitive way to call the procedure is using an form that allows
specifying all arguments interactively\. This form will automatically be
generated if the declared procedure is called with the *\-interactive* flag\. To
use this feature the Tk library has to be loaded\.

    __display message__ \-interactive

The generated form contains for each argument a data entry widget that is
adapted to the argument type\. Check buttons are used to specify flags, radio
boxes for tiny choice lists, disjoint list boxes for larger choice lists and
files, directories, fonts and colors can be selected with dedicated browsers\.

After acknowledging the specified argument data via an OK button, the entered







|
|
>
|
>
>
>
|
>
|
>
|
>
|
>
>
>
|
>
|
>
>
|
|






|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
>
|
|
|
>
|
>
>
>
|
>



|
>

<
|

|
>

<
|
|

|
>

<
|

|
>

<
|

|
<
|








|







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
the named arguments \(Tk style\)\.

# <a name='section4'></a>PROCEDURE HELP

The declared procedure can simply be called with the *\-help* option to get the
information about the usage of the procedure and its arguments:

> __display message__ \-help  
> &nbsp;&nbsp;*\->*  
> *NAME*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*display message \- Displays a simple message box*  
> *SYNOPSYS*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*display message*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*\[\-mtype <mtype>\] :*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*Message type, default: "Warning", choices: \{Info Warning Error\}*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*\[\-font <font>\] :*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*Message text font, type: font, default: Arial 10 italic*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*\[\-level <level>\] :*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*Message level, type: integer, range: 1\.\.10*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*\[\-fg <fg>\] :*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*Message color, type: color, default: black*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*\[\-bg <bg>\] :*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*Background color, type: color*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*\[\-no\_border \] :*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*Use a splash window style \(no border\)*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*\[\-log\_file <log\_file>\] :*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*Optional message log file, type: file*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<text> :*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*Multiple text lines to display, type: string*  
> *DESCRIPTION*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*This procedure allows displaying a configurable message box\.*

# <a name='section5'></a>PROCEDURE CALL

The specified procedure can be called in many ways\. The following listing shows
some valid procedure calls:

> __display message__ "The document hasn't yet been saved\!"  
> *\-> display message:*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*mtype=Warning*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*font=Arial 10 italic*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*fg=black*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*no\_border=0*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*text=\{The document hasn't yet been saved\!\}*  
>   
>   
> __display message__ \-fg red \-bg black "Please save first the document"  
> *\-> display message:*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*mtype=Warning*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*font=Arial 10 italic*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*fg=red*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*bg=black*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*no\_border=0*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*text=\{Please save first the document\}*  
>   
>   
> __display message__ \-mtype Error \-no\_border "Why is here no border?"  
> *\-> display message:*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*mtype=Error*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*font=Arial 10 italic*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*fg=black*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*no\_border=1*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*text=\{Why is here no border?\}*  
>   
>   
> __display message__ \-font \{Courier 12\} \-level 10 \\  
> &nbsp;&nbsp;&nbsp;"Is there enough space?" "Reduce otherwise the font size\!"  
> *\-> display message:*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*mtype=Warning*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*font=Courier 12*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*level=10*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*fg=black*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*no\_border=0*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*text=\{Is there enough space?\} \{Reduce otherwise the font size\!\}*

The next lines show how wrong arguments are recognized\. The *text* argument
that is mandatory is missing in the first procedure call:

> __display message__ \-font \{Courier 12\}  
> &nbsp;&nbsp;*\-> display message: Required argument is missing: text*


Only known arguments are accepted:

> __display message__ \-category warning Hello  
> &nbsp;&nbsp;*\-> display message: Argument '\-category' not known*


Argument types are automatically checked and an error message is generated in
case the argument value has not the expected type:

> __display message__ \-fg MyColor "Hello"  
> &nbsp;&nbsp;*\-> display message: Argument 'fg' requires type 'color'\.  Provided value: 'MyColor'*


Selection choices have to be respected \.\.\.

> __display message__ \-mtype Fatal Hello  
> &nbsp;&nbsp;*\-> display message: Argument \(mtype\) has to be one of the  following elements: Info, Warning, Error*


\.\.\. as well as valid value ranges:

> __display message__ \-level 12 Hello  

> &nbsp;&nbsp;*\-> display message: Argument \(level\) has to be between 1 and 10*

# <a name='section6'></a>INTERACTIVE PROCEDURE CALLS

The most intuitive way to call the procedure is using an form that allows
specifying all arguments interactively\. This form will automatically be
generated if the declared procedure is called with the *\-interactive* flag\. To
use this feature the Tk library has to be loaded\.

> __display message__ \-interactive

The generated form contains for each argument a data entry widget that is
adapted to the argument type\. Check buttons are used to specify flags, radio
boxes for tiny choice lists, disjoint list boxes for larger choice lists and
files, directories, fonts and colors can be selected with dedicated browsers\.

After acknowledging the specified argument data via an OK button, the entered
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
entry forms\. It creates an input mask that allows specifying a file to copy, a
destination folder as well as a checkbox that allows specifying if an eventual
existing file can be overwritten\. Comfortable browsers can be used to select
files and directories\. And finally, the form offers also the possibility to
accept and decline the selection\. Here is the code snippet that is doing all
this:

    __[tepam::argument\_dialogbox](tepam\_argument\_dialogbox\.md)__ \\
       __\-existingfile__ \{\-label "Source file" \-variable SourceFile\} \\
       __\-existingdirectory__ \{\-label "Destination folder" \-variable DestDir\} \\
       __\-checkbutton__ \{\-label "Overwrite existing file" \-variable Overwrite\}

The __argument\_dialogbox__ returns __ok__ if the entered data are
validated\. It will return __cancel__ if the data entry has been canceled\.
After the validation of the entered data, the __argument\_dialogbox__ defines
all the specified variables with the entered data inside the calling context\.

An __argument\_dialogbox__ requires a pair of arguments for each variable







|
|
|
|







334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
entry forms\. It creates an input mask that allows specifying a file to copy, a
destination folder as well as a checkbox that allows specifying if an eventual
existing file can be overwritten\. Comfortable browsers can be used to select
files and directories\. And finally, the form offers also the possibility to
accept and decline the selection\. Here is the code snippet that is doing all
this:

> __[tepam::argument\_dialogbox](tepam\_argument\_dialogbox\.md)__ \\  
> &nbsp;&nbsp;&nbsp;__\-existingfile__ \{\-label "Source file" \-variable SourceFile\} \\  
> &nbsp;&nbsp;&nbsp;__\-existingdirectory__ \{\-label "Destination folder" \-variable DestDir\} \\  
> &nbsp;&nbsp;&nbsp;__\-checkbutton__ \{\-label "Overwrite existing file" \-variable Overwrite\}

The __argument\_dialogbox__ returns __ok__ if the entered data are
validated\. It will return __cancel__ if the data entry has been canceled\.
After the validation of the entered data, the __argument\_dialogbox__ defines
all the specified variables with the entered data inside the calling context\.

An __argument\_dialogbox__ requires a pair of arguments for each variable
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
expected data types, valid data ranges, etc\.

The next example of a more complex argument dialog box provides a good overview
about the different available entry widget types and parameter attributes\. The
example contains also some formatting instructions like *\-frame* and *\-sep*
which allows organizing the different entry widgets in frames and sections:

    set ChoiceList \{"Choice 1" "Choice 2" "Choice 3" "Choice 4" "Choice 5" "Choice 6"\}

    set Result \[__[tepam::argument\_dialogbox](tepam\_argument\_dialogbox\.md)__ \\
       __\-title__ "System configuration" \\
       __\-context__ test\_1 \\
       __\-frame__ \{\-label "Entries"\} \\
          __\-entry__ \{\-label Entry1 \-variable Entry1\} \\
          __\-entry__ \{\-label Entry2 \-variable Entry2 \-default "my default"\} \\
       __\-frame__ \{\-label "Listbox & combobox"\} \\
          __\-listbox__ \{\-label "Listbox, single selection" \-variable Listbox1 \\
                    \-choices \{1 2 3 4 5 6 7 8\} \-default 1 \-height 3\} \\
          __\-listbox__ \{\-label "Listbox, multiple selection" \-variable Listbox2
                    \-choicevariable ChoiceList \-default \{"Choice 2" "Choice 3"\}
                    \-multiple\_selection 1 \-height 3\} \\
          __\-disjointlistbox__ \{\-label "Disjoined listbox" \-variable DisJntListbox
                            \-choicevariable ChoiceList \\
                            \-default \{"Choice 3" "Choice 5"\} \-height 3\} \\
          __\-combobox__ \{\-label "Combobox" \-variable Combobox \\
                     \-choices \{1 2 3 4 5 6 7 8\} \-default 3\} \\
       __\-frame__ \{\-label "Checkbox, radiobox and checkbutton"\} \\
          __\-checkbox__ \{\-label Checkbox \-variable Checkbox
                     \-choices \{bold italic underline\} \-choicelabels \{Bold Italic Underline\} \\
                     \-default italic\} \\
          __\-radiobox__ \{\-label Radiobox \-variable Radiobox
                     \-choices \{bold italic underline\} \-choicelabels \{Bold Italic Underline\} \\
                     \-default underline\} \\
          __\-checkbutton__ \{\-label CheckButton \-variable Checkbutton \-default 1\} \\
       __\-frame__ \{\-label "Files & directories"\} \\
          __\-existingfile__ \{\-label "Input file" \-variable InputFile\} \\
          __\-file__ \{\-label "Output file" \-variable OutputFile\} \\
          __\-sep__ \{\} \\
          __\-existingdirectory__ \{\-label "Input directory" \-variable InputDirectory\} \\
          __\-directory__ \{\-label "Output irectory" \-variable OutputDirectory\} \\
       __\-frame__ \{\-label "Colors and fonts"\} \\
          __\-color__ \{\-label "Background color" \-variable Color \-default red\} \\
          __\-sep__ \{\} \\
          __\-font__ \{\-label "Font" \-variable Font \-default \{Courier 12 italic\}\}

\] The __argument\_dialogbox__ defines all the specified variables with the
entered data and returns __ok__ if the data have been validated via the Ok
button\. If the data entry is cancelled by activating the Cancel button, the
__argument\_dialogbox__ returns __cancel__\.

    if \{$Result=="cancel"\} \{
       puts "Canceled"
    \} else \{ \# $Result=="ok"
       puts "Arguments: "
       foreach Var \{
          Entry1 Entry2
          Listbox1 Listbox2 DisJntListbox
          Combobox Checkbox Radiobox Checkbutton
          InputFile OutputFile InputDirectory OutputDirectory
          Color Font
       \} \{
          puts "  $Var: '\[set $Var\]'"
       \}
    \}

*\-> Arguments: Entry1: 'Hello, this is a trial' Entry2: 'my default' Listbox1:



'1' Listbox2: '\{Choice 2\} \{Choice 3\}' DisJntListbox: '\{Choice 3\} \{Choice 5\}'


Combobox: '3' Checkbox: 'italic' Radiobox: 'underline' Checkbutton: '1'


InputFile: 'c:\\tepam\\in\.txt' OutputFile: 'c:\\tepam\\out\.txt' InputDirectory:

'c:\\tepam\\input' OutputDirectory: 'c:\\tepam\\output' Color: 'red' Font: 'Courier

12 italic'*

# <a name='seealso'></a>SEE ALSO

[tepam::argument\_dialogbox\(n\)](tepam\_argument\_dialogbox\.md),
[tepam::procedure\(n\)](tepam\_procedure\.md)

# <a name='keywords'></a>KEYWORDS







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|




|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
|
>
>
|
>
>
|
>
|
>
|







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
expected data types, valid data ranges, etc\.

The next example of a more complex argument dialog box provides a good overview
about the different available entry widget types and parameter attributes\. The
example contains also some formatting instructions like *\-frame* and *\-sep*
which allows organizing the different entry widgets in frames and sections:

> set ChoiceList \{"Choice 1" "Choice 2" "Choice 3" "Choice 4" "Choice 5" "Choice 6"\}  
>   
> set Result \[__[tepam::argument\_dialogbox](tepam\_argument\_dialogbox\.md)__ \\  
> &nbsp;&nbsp;&nbsp;__\-title__ "System configuration" \\  
> &nbsp;&nbsp;&nbsp;__\-context__ test\_1 \\  
> &nbsp;&nbsp;&nbsp;__\-frame__ \{\-label "Entries"\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-entry__ \{\-label Entry1 \-variable Entry1\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-entry__ \{\-label Entry2 \-variable Entry2 \-default "my default"\} \\  
> &nbsp;&nbsp;&nbsp;__\-frame__ \{\-label "Listbox & combobox"\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-listbox__ \{\-label "Listbox, single selection" \-variable Listbox1 \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choices \{1 2 3 4 5 6 7 8\} \-default 1 \-height 3\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-listbox__ \{\-label "Listbox, multiple selection" \-variable Listbox2  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choicevariable ChoiceList \-default \{"Choice 2" "Choice 3"\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-multiple\_selection 1 \-height 3\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-disjointlistbox__ \{\-label "Disjoined listbox" \-variable DisJntListbox  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choicevariable ChoiceList \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-default \{"Choice 3" "Choice 5"\} \-height 3\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-combobox__ \{\-label "Combobox" \-variable Combobox \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choices \{1 2 3 4 5 6 7 8\} \-default 3\} \\  
> &nbsp;&nbsp;&nbsp;__\-frame__ \{\-label "Checkbox, radiobox and checkbutton"\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-checkbox__ \{\-label Checkbox \-variable Checkbox  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choices \{bold italic underline\} \-choicelabels \{Bold Italic Underline\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-default italic\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-radiobox__ \{\-label Radiobox \-variable Radiobox  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-choices \{bold italic underline\} \-choicelabels \{Bold Italic Underline\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-default underline\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-checkbutton__ \{\-label CheckButton \-variable Checkbutton \-default 1\} \\  
> &nbsp;&nbsp;&nbsp;__\-frame__ \{\-label "Files & directories"\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-existingfile__ \{\-label "Input file" \-variable InputFile\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-file__ \{\-label "Output file" \-variable OutputFile\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-sep__ \{\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-existingdirectory__ \{\-label "Input directory" \-variable InputDirectory\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-directory__ \{\-label "Output irectory" \-variable OutputDirectory\} \\  
> &nbsp;&nbsp;&nbsp;__\-frame__ \{\-label "Colors and fonts"\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-color__ \{\-label "Background color" \-variable Color \-default red\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-sep__ \{\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-font__ \{\-label "Font" \-variable Font \-default \{Courier 12 italic\}\}\]

The __argument\_dialogbox__ defines all the specified variables with the
entered data and returns __ok__ if the data have been validated via the Ok
button\. If the data entry is cancelled by activating the Cancel button, the
__argument\_dialogbox__ returns __cancel__\.

> if \{$Result=="cancel"\} \{  
> &nbsp;&nbsp;&nbsp;puts "Canceled"  
> \} else \{ \# $Result=="ok"  
> &nbsp;&nbsp;&nbsp;puts "Arguments: "  
> &nbsp;&nbsp;&nbsp;foreach Var \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry1 Entry2  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Listbox1 Listbox2 DisJntListbox  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Combobox Checkbox Radiobox Checkbutton  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputFile OutputFile InputDirectory OutputDirectory  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color Font  
> &nbsp;&nbsp;&nbsp;\} \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts "  $Var: '\[set $Var\]'"  
> &nbsp;&nbsp;&nbsp;\}  
> \}  
> *\-> Arguments:*  
> &nbsp;&nbsp;&nbsp;*Entry1: 'Hello, this is a trial'*  
> &nbsp;&nbsp;&nbsp;*Entry2: 'my default'*  
> &nbsp;&nbsp;&nbsp;*Listbox1: '1'*  
> &nbsp;&nbsp;&nbsp;*Listbox2: '\{Choice 2\} \{Choice 3\}'*  
> &nbsp;&nbsp;&nbsp;*DisJntListbox: '\{Choice 3\} \{Choice 5\}'*  
> &nbsp;&nbsp;&nbsp;*Combobox: '3'*  
> &nbsp;&nbsp;&nbsp;*Checkbox: 'italic'*  
> &nbsp;&nbsp;&nbsp;*Radiobox: 'underline'*  
> &nbsp;&nbsp;&nbsp;*Checkbutton: '1'*  
> &nbsp;&nbsp;&nbsp;*InputFile: 'c:\\tepam\\in\.txt'*  
> &nbsp;&nbsp;&nbsp;*OutputFile: 'c:\\tepam\\out\.txt'*  
> &nbsp;&nbsp;&nbsp;*InputDirectory: 'c:\\tepam\\input'*  
> &nbsp;&nbsp;&nbsp;*OutputDirectory: 'c:\\tepam\\output'*  
> &nbsp;&nbsp;&nbsp;*Color: 'red'*  
> &nbsp;&nbsp;&nbsp;*Font: 'Courier 12 italic'*

# <a name='seealso'></a>SEE ALSO

[tepam::argument\_dialogbox\(n\)](tepam\_argument\_dialogbox\.md),
[tepam::procedure\(n\)](tepam\_procedure\.md)

# <a name='keywords'></a>KEYWORDS

Changes to embedded/md/tcllib/files/modules/tepam/tepam_procedure.md.

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
    commands are incorporated into a single main command and are selectable via
    the first argument\.

    The __string__ command is an example of such a command that implements
    for example subcommands to check a character string length, to compare
    strings, to extract substrings, etc:

        __string length__ *string*
        __string compare__ *string* *string*
        __string range__ *string* *first* *last*
        \.\.\.

    TEPAM provides a framework that allows implementing easily such subcommands
    in form of Tcl procedures\. It allows not only defining a first level of
    subcommands, but also a higher level of subcommands\. The __string__
    command class check could be implemented as independent sub\-sub\-commands of
    the __string__ command:

        __string is alnum__ *string*
        __string is integer__ *string*
        __string is double__ *string*
        \.\.\.

  - *Procedure attribute*

    TEPAM allows attaching to a declared procedure different kind of attributes\.
    Some of these attributes are *just* used for documentation purposes, but
    other attributes specify the way how the procedure has to be called\. Also
    the procedure arguments are defined in form of a procedure attribute\.

  - *Argument*

    TEPAM uses the term *argument* for the parameters of a procedure\.

    The following example calls the subcommand __string compare__ with
    several arguments:

        __string compare__

    *\-nocase \-length 3 "emphasized" "emphasised"* The following paragraphs
    discuss these different argument types\.

  - *Named argument*

    Some parameters, as *\-length 3* of the subcommand __string compare__
    have to be provided as pairs of argument names and argument values\. This
    parameter type is often also called *option*\.








|
|
|
|







|
|
|
|















|

<
|







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
    commands are incorporated into a single main command and are selectable via
    the first argument\.

    The __string__ command is an example of such a command that implements
    for example subcommands to check a character string length, to compare
    strings, to extract substrings, etc:

    > __string length__ *string*  
    > __string compare__ *string* *string*  
    > __string range__ *string* *first* *last*  
    > \.\.\.

    TEPAM provides a framework that allows implementing easily such subcommands
    in form of Tcl procedures\. It allows not only defining a first level of
    subcommands, but also a higher level of subcommands\. The __string__
    command class check could be implemented as independent sub\-sub\-commands of
    the __string__ command:

    > __string is alnum__ *string*  
    > __string is integer__ *string*  
    > __string is double__ *string*  
    > \.\.\.

  - *Procedure attribute*

    TEPAM allows attaching to a declared procedure different kind of attributes\.
    Some of these attributes are *just* used for documentation purposes, but
    other attributes specify the way how the procedure has to be called\. Also
    the procedure arguments are defined in form of a procedure attribute\.

  - *Argument*

    TEPAM uses the term *argument* for the parameters of a procedure\.

    The following example calls the subcommand __string compare__ with
    several arguments:

    > __string compare__ *\-nocase \-length 3 "emphasized" "emphasised"*


    The following paragraphs discuss these different argument types\.

  - *Named argument*

    Some parameters, as *\-length 3* of the subcommand __string compare__
    have to be provided as pairs of argument names and argument values\. This
    parameter type is often also called *option*\.

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

  - *Named arguments first, unnamed arguments later*

    The __string compare__ command of the previous example requires that the
    *named arguments* \(options, flags\) are provided first\. The two mandatory
    \(unnamed\) arguments have to be provided as last argument\.

        __string compare__

    *\-nocase \-length 3 Water $Text* This is the usual Tcl style \(exceptions
    exist\) which is referred in the TEPAM documentation as *named arguments
    first, unnamed arguments later style*\.

  - *Unnamed arguments first, named arguments later*

    In contrast to most Tcl commands, Tk uses generally \(exceptions exist also
    here\) a different calling style where the *unnamed arguments* have to be
    provided first, before the *named arguments* have to be provided:

        __pack__

    *\.ent1 \.ent2 \-fill x \-expand yes \-side left* This style is referred in the
    TEPAM documentation as *unnamed arguments first, named arguments later
    style*\.

# <a name='section3'></a>PROCEDURE DECLARATION

TEPAM allows declaring new Tcl procedures with the command
__tepam::procedure__ that has similar to the standard Tcl command
__proc__ also 3 arguments:

  - <a name='1'></a>__tepam::procedure__ *name* *attributes* *body*

The TEPAM procedure declaration syntax is demonstrated by the following example:

    __tepam::procedure__ \{display message\} \{
       \-short\_description
          "Displays a simple message box"
       \-description
          "This procedure allows displaying a configurable\\
           message box\. The default message type that is\\
           created is a warning, but also errors and info can\\
           be generated\.
           The procedure accepts multiple text lines\."
       \-example
          \{display message \-mtype Warning "Save first your job"\}
       \-args \{
          \{\-mtype \-choices \{Info Warning Error\} \\
                  \-default Warning \-description "Message type"\}
          \{text   \-type string \-multiple \\
                  \-description "Multiple text lines to display"\}
       \}
    \} \{
       puts "Message type: $mtype"
       puts "Message: $text"
    \}

The 3 arguments of __procedure__ are:

  - *name*

    The procedure name can be used in very flexible ways\. Procedure names can
    have namespace qualifiers\. By providing a two element name list as procedure
    name, a subcommand of a procedure will be declared\. It is even possible to
    declare sub\-sub\-commands of a procedure by providing name lists with three
    elements\.

    Here are some valid procedure declarations using different procedure names
    \(the attribute and body arguments are empty for simplicity\):

    *\# Simple procedure name:*
    tepam::procedure __display\_message__ \{\} \{\}
    **
    *\# Procedure declared in the main namespace:*
    tepam::procedure __::display\_message__ \{\} \{\}
    **
    *\# Procedure in the namespace* __::ns__*:*
    tepam::procedure __::ns::display\_message__ \{\} \{\}
    **
    *\# Declaration of the subcommand* __message__ *of the procedure* __display__*:*
    tepam::procedure __\{display message\}__ \{\} \{\}

  - *attributes*

    All procedure attributes are provided in form of an option list that
    contains pairs of option names and option values\. The example above has as
    procedure attribute a short and a normal description, but also the procedure
    arguments are defined in form of a procedure attribute\.







|

|
|
|







|

|
|
<











|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|














|
|
|
|
|
|
|
|
|
|
|







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

  - *Named arguments first, unnamed arguments later*

    The __string compare__ command of the previous example requires that the
    *named arguments* \(options, flags\) are provided first\. The two mandatory
    \(unnamed\) arguments have to be provided as last argument\.

    > __string compare__ *\-nocase \-length 3 Water $Text*

    This is the usual Tcl style \(exceptions exist\) which is referred in the
    TEPAM documentation as *named arguments first, unnamed arguments later
    style*\.

  - *Unnamed arguments first, named arguments later*

    In contrast to most Tcl commands, Tk uses generally \(exceptions exist also
    here\) a different calling style where the *unnamed arguments* have to be
    provided first, before the *named arguments* have to be provided:

    > __pack__ *\.ent1 \.ent2 \-fill x \-expand yes \-side left*

    This style is referred in the TEPAM documentation as *unnamed arguments
    first, named arguments later style*\.


# <a name='section3'></a>PROCEDURE DECLARATION

TEPAM allows declaring new Tcl procedures with the command
__tepam::procedure__ that has similar to the standard Tcl command
__proc__ also 3 arguments:

  - <a name='1'></a>__tepam::procedure__ *name* *attributes* *body*

The TEPAM procedure declaration syntax is demonstrated by the following example:

> __tepam::procedure__ \{display message\} \{  
> &nbsp;&nbsp;&nbsp;\-short\_description  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Displays a simple message box"  
> &nbsp;&nbsp;&nbsp;\-description  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"This procedure allows displaying a configurable\\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message box\. The default message type that is\\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;created is a warning, but also errors and info can\\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;be generated\.  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The procedure accepts multiple text lines\."  
> &nbsp;&nbsp;&nbsp;\-example  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{display message \-mtype Warning "Save first your job"\}  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-mtype \-choices \{Info Warning Error\} \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-default Warning \-description "Message type"\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{text   \-type string \-multiple \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\-description "Multiple text lines to display"\}  
> &nbsp;&nbsp;&nbsp;\}  
> \} \{  
> &nbsp;&nbsp;&nbsp;puts "Message type: $mtype"  
> &nbsp;&nbsp;&nbsp;puts "Message: $text"  
> \}

The 3 arguments of __procedure__ are:

  - *name*

    The procedure name can be used in very flexible ways\. Procedure names can
    have namespace qualifiers\. By providing a two element name list as procedure
    name, a subcommand of a procedure will be declared\. It is even possible to
    declare sub\-sub\-commands of a procedure by providing name lists with three
    elements\.

    Here are some valid procedure declarations using different procedure names
    \(the attribute and body arguments are empty for simplicity\):

> *\# Simple procedure name:*  
> tepam::procedure __display\_message__ \{\} \{\}  
> **  
> *\# Procedure declared in the main namespace:*  
> tepam::procedure __::display\_message__ \{\} \{\}  
> **  
> *\# Procedure in the namespace* __::ns__*:*  
> tepam::procedure __::ns::display\_message__ \{\} \{\}  
> **  
> *\# Declaration of the subcommand* __message__ *of the procedure* __display__*:*  
> tepam::procedure __\{display message\}__ \{\} \{\}

  - *attributes*

    All procedure attributes are provided in form of an option list that
    contains pairs of option names and option values\. The example above has as
    procedure attribute a short and a normal description, but also the procedure
    arguments are defined in form of a procedure attribute\.
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

    This is the normal procedure body\. The declared arguments will be available
    to the procedure body in form of variables\.

    The procedure body will only be executed if the provided set of arguments
    could be validated by the TEPAM argument manager\.

    tepam::procedure \{display\_message\} \{
       \-args \{
          \{\-__mtype__ \-default Warning \-choices \{Warning Error\}\}
          \{__text__ \-type string\}
       \}
    \} \{
       puts "Message type: __$mtype__"
       puts "Message: __$text__"
    \}

The commands __[procedure](\.\./\.\./\.\./\.\./index\.md\#procedure)__ as well as
__argument\_dialogbox__ are exported from the namespace __tepam__\. To use
these commands without the __tepam::__ namespace prefix, it is sufficient to
import them into the main namespace:

    __namespace import tepam::\*__

    __[procedure](\.\./\.\./\.\./\.\./index\.md\#procedure)__ \{display\_message\} \{
       \-args \{
          \.\.\.

## <a name='subsection1'></a>Procedure Attributes

The first group of attributes affect the behavior of the declared procedure:

  - \-named\_arguments\_first __0__&#124;__1__








|
|
|
|
|
|
|
|
|






|
|
|
|
|







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

    This is the normal procedure body\. The declared arguments will be available
    to the procedure body in form of variables\.

    The procedure body will only be executed if the provided set of arguments
    could be validated by the TEPAM argument manager\.

> tepam::procedure \{display\_message\} \{  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-__mtype__ \-default Warning \-choices \{Warning Error\}\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{__text__ \-type string\}  
> &nbsp;&nbsp;&nbsp;\}  
> \} \{  
> &nbsp;&nbsp;&nbsp;puts "Message type: __$mtype__"  
> &nbsp;&nbsp;&nbsp;puts "Message: __$text__"  
> \}

The commands __[procedure](\.\./\.\./\.\./\.\./index\.md\#procedure)__ as well as
__argument\_dialogbox__ are exported from the namespace __tepam__\. To use
these commands without the __tepam::__ namespace prefix, it is sufficient to
import them into the main namespace:

> __namespace import tepam::\*__  
>   
> __[procedure](\.\./\.\./\.\./\.\./index\.md\#procedure)__ \{display\_message\} \{  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\.\.\.

## <a name='subsection1'></a>Procedure Attributes

The first group of attributes affect the behavior of the declared procedure:

  - \-named\_arguments\_first __0__&#124;__1__

363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
  - \-validatecommand *script*

    Custom argument validations can be performed via specific validation
    commands that are defined with the *\-validatecommand* attribute\.

    Validation command declaration example:

    tepam::procedure \{display\_message\} \{
       \-args \{
          \{text \-type string \-description "Message text"\} \}
       __\-validatecommand \{IllegalWordDetector $text\}__
    \} \{
    \}

    The validation command is executed in the context of the declared procedure
    body\. The different argument values are accessed via the argument names\.
    Note there is also an argument attribute *\-validatecommand* that allows
    declaring custom checks for specific arguments\.

    The attribute *\-validatecommand* can be repeated to declare multiple







|
|
|
|
|
|







361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
  - \-validatecommand *script*

    Custom argument validations can be performed via specific validation
    commands that are defined with the *\-validatecommand* attribute\.

    Validation command declaration example:

> tepam::procedure \{display\_message\} \{  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{text \-type string \-description "Message text"\} \}  
> &nbsp;&nbsp;&nbsp;__\-validatecommand \{IllegalWordDetector $text\}__  
> \} \{  
> \}

    The validation command is executed in the context of the declared procedure
    body\. The different argument values are accessed via the argument names\.
    Note there is also an argument attribute *\-validatecommand* that allows
    declaring custom checks for specific arguments\.

    The attribute *\-validatecommand* can be repeated to declare multiple
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
    examples, using the *\-example* attribute\.

## <a name='subsection2'></a>Argument Declaration

The following example shows the structure that is used for the argument
definitions in the context of a procedure declaration:

    tepam::procedure \{display\_message\} \{
       \-args __\{
          \{\-mtype \-default Warning \-choices \{Info Warning Error\} \-description "Message type"\}
          \{\-font \-type font \-default \{Arial 10 italic\} \-description "Message text font"\}
          \{\-level \-type integer \-optional \-range \{1 10\} \-description "Message level"\}
          \{\-fg \-type color \-optional \-description "Message color"\}
          \{\-log\_file \-type file \-optional \-description "Optional message log file"\}
          \{text \-type string \-multiple \-description "Multiple text lines to display"\}
       \}__

    \} \{
    \}

Each of the procedure arguments is declared with a list that has as first
element the argument name, followed by eventual attributes\. The argument
definition syntax can be formalized in the following way:

    tepam::procedure <name> \{
       \-args __\{
          \{<argument\_name\_1> <arg\_attr\_name\_1a> <arg\_attr\_value\_1a>  <arg\_attr\_name\_1b> <arg\_attr\_value\_1b> \.\.\.\}
          \{<argument\_name\_2> <arg\_attr\_name\_2a> <arg\_attr\_value\_2a>  <arg\_attr\_name\_2b> <arg\_attr\_value\_2b> \.\.\.\}
          \.\.\.
       \}__

    \} <body>

The argument names and attributes have to be used in the following way:

  - Argument name \(*<argument\_name\_<n>>*\)

    The provided argument name specifies whether the argument is an *unnamed
    argument* or a *named argument*\. In addition to this, an argument name
    can also be blank to indicate an argument comment, or it can start with \# to
    indicate a section comment\.

      * *"<Name>"*

        This is the simplest form of an argument name: An argument whose name is
        not starting with '\-' is an *unnamed argument*\. The parameter provided
        during a procedure call will be assigned to a variable with the name
        *<Name>*\.

    tepam::procedure \{print\_string\} \{
       \-args \{
          \{__[text](\.\./\.\./\.\./\.\./index\.md\#text)__ \-type string \-description "This is an unnamed argument"\}
       \}
    \} \{
       puts __$text__
    \}

    print\_string __"Hello"__

        * \-> Hello*

      * *"\-<Name>"*

        An argument whose name starts with '\-' is a *named argument* \(also
        called *option*\)\. The parameter provided during a procedure call will
        be assigned to a variable with the name *<Name>* \(not *\-<Name>*\)\.

    tepam::procedure \{print\_string\} \{
       \-args \{
          \{__\-text__ \-type string \-description "This is a named argument"\}
       \}
    \} \{
       puts __$text__
    \}

    print\_string __\-text "Hello"__

        * \-> Hello*

      * *"\-\-"*

        This flag allows clearly specifying the end of the named arguments and
        the beginning of the unnamed arguments, in case the *named arguments
        first, unnamed arguments later style \(Tcl\)* has been selected\.

        If the *unnamed arguments first, named arguments later style \(Tk\)*
        style is selected, this flag is ignored if the unnamed arguments have
        already been parsed\. Otherwise it will be assigned to the corresponding
        unnamed argument\.

      * *"\-"* or *""*

        A blank argument name \(either '\-' or *''*\) starts a comment for the
        following arguments\.

    tepam::procedure \{print\_time\} \{
       \-interactive\_display\_format short
       \-args \{
          \{hours \-type integer \-description "Hour"\}
          \{minutes \-type integer \-description "Minute"\}

          __\{\- The following arguments are optional:\}__
          \{seconds \-type integer \-default 0 \-description "Seconds"\}
          \{milliseconds \-type integer \-default 0 \-description "Milliseconds"\}
       \}
    \} \{
       puts "$\{hour\}h$\{minutes\}:\[expr $seconds\+0\.001\*$milliseconds\]"
    \}

        Argument comments are basically used in the graphical argument
        definition forms that are created if a procedure is called
        interactively\.

      * *"\#\*"*

        An argument definition list that starts with '\#' is considered as a
        section comment\. The argument definition list will be trimmed from the
        '\#' characters and the remaining string will be used as section comment\.

        Section comments can be used to structure visually the argument
        definition code\. Section comments are also used to structure the
        generated help texts and the interactive argument definition forms\.

    tepam::procedure \{complex\_multiply\} \{
       \-description "This function perform a complex multiplication"
       \-args \{
          __\{\#\#\#\# First complex number \#\#\#\#\}__
          \{\-r0 \-type double \-description "First number real part"\}
          \{\-i0 \-type double \-description "First number imaginary part"\}

          __\{\#\#\#\# Second complex number \#\#\#\#\}__
          \{\-r1 \-type double \-description "Second number real part"\}
          \{\-i1 \-type double \-description "Second number imaginary part"\}
       \}
    \} \{
       return \[expr $r0\*$r1 \- $i0\*$i1\]
    \}

  - Argument attributes \(*<arg\_attr\_name\_<mn>> <arg\_attr\_value\_<mn>>*\)

    The following argument attributes are supported:

      * \-description *string*








|
|
|
|
|
|
|
|
|
>
|
|





|
|
|
|
|
|
>
|

















|
|
|
|
|
|
|
|
|
<
|







|
|
|
|
|
|
|
|
|
<
|

















|
|
|
|
|
|
|
|
|
|
|
|
|















|
|
|
|
|
|
|
|
|
|
|
|
|
|







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
    examples, using the *\-example* attribute\.

## <a name='subsection2'></a>Argument Declaration

The following example shows the structure that is used for the argument
definitions in the context of a procedure declaration:

> tepam::procedure \{display\_message\} \{  
> &nbsp;&nbsp;&nbsp;\-args __\{__  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\{\-mtype \-default Warning \-choices \{Info Warning Error\} \-description "Message type"\}__  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\{\-font \-type font \-default \{Arial 10 italic\} \-description "Message text font"\}__  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\{\-level \-type integer \-optional \-range \{1 10\} \-description "Message level"\}__  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\{\-fg \-type color \-optional \-description "Message color"\}__  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\{\-log\_file \-type file \-optional \-description "Optional message log file"\}__  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\{text \-type string \-multiple \-description "Multiple text lines to display"\}__  
> &nbsp;&nbsp;&nbsp;__\}__  
>   
> \} \{  
> \}

Each of the procedure arguments is declared with a list that has as first
element the argument name, followed by eventual attributes\. The argument
definition syntax can be formalized in the following way:

> tepam::procedure <name> \{  
> &nbsp;&nbsp;&nbsp;\-args __\{__  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\{<argument\_name\_1> <arg\_attr\_name\_1a> <arg\_attr\_value\_1a>  <arg\_attr\_name\_1b> <arg\_attr\_value\_1b> \.\.\.\}__  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\{<argument\_name\_2> <arg\_attr\_name\_2a> <arg\_attr\_value\_2a>  <arg\_attr\_name\_2b> <arg\_attr\_value\_2b> \.\.\.\}__  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\.\.\.__  
> &nbsp;&nbsp;&nbsp;__\}__  
>   
> \} <body>

The argument names and attributes have to be used in the following way:

  - Argument name \(*<argument\_name\_<n>>*\)

    The provided argument name specifies whether the argument is an *unnamed
    argument* or a *named argument*\. In addition to this, an argument name
    can also be blank to indicate an argument comment, or it can start with \# to
    indicate a section comment\.

      * *"<Name>"*

        This is the simplest form of an argument name: An argument whose name is
        not starting with '\-' is an *unnamed argument*\. The parameter provided
        during a procedure call will be assigned to a variable with the name
        *<Name>*\.

> tepam::procedure \{print\_string\} \{  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{__[text](\.\./\.\./\.\./\.\./index\.md\#text)__ \-type string \-description "This is an unnamed argument"\}  
> &nbsp;&nbsp;&nbsp;\}  
> \} \{  
> &nbsp;&nbsp;&nbsp;puts __$text__  
> \}  
>   
> print\_string __"Hello"__  

> &nbsp;*\-> Hello*

      * *"\-<Name>"*

        An argument whose name starts with '\-' is a *named argument* \(also
        called *option*\)\. The parameter provided during a procedure call will
        be assigned to a variable with the name *<Name>* \(not *\-<Name>*\)\.

> tepam::procedure \{print\_string\} \{  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{__\-text__ \-type string \-description "This is a named argument"\}  
> &nbsp;&nbsp;&nbsp;\}  
> \} \{  
> &nbsp;&nbsp;&nbsp;puts __$text__  
> \}  
>   
> print\_string __\-text "Hello"__  

> &nbsp;*\-> Hello*

      * *"\-\-"*

        This flag allows clearly specifying the end of the named arguments and
        the beginning of the unnamed arguments, in case the *named arguments
        first, unnamed arguments later style \(Tcl\)* has been selected\.

        If the *unnamed arguments first, named arguments later style \(Tk\)*
        style is selected, this flag is ignored if the unnamed arguments have
        already been parsed\. Otherwise it will be assigned to the corresponding
        unnamed argument\.

      * *"\-"* or *""*

        A blank argument name \(either '\-' or *''*\) starts a comment for the
        following arguments\.

> tepam::procedure \{print\_time\} \{  
> &nbsp;&nbsp;&nbsp;\-interactive\_display\_format short  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{hours \-type integer \-description "Hour"\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{minutes \-type integer \-description "Minute"\}  
>   
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\{\- The following arguments are optional:\}__  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{seconds \-type integer \-default 0 \-description "Seconds"\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{milliseconds \-type integer \-default 0 \-description "Milliseconds"\}  
> &nbsp;&nbsp;&nbsp;\}  
> \} \{  
> &nbsp;&nbsp;&nbsp;puts "$\{hour\}h$\{minutes\}:\[expr $seconds\+0\.001\*$milliseconds\]"  
> \}

        Argument comments are basically used in the graphical argument
        definition forms that are created if a procedure is called
        interactively\.

      * *"\#\*"*

        An argument definition list that starts with '\#' is considered as a
        section comment\. The argument definition list will be trimmed from the
        '\#' characters and the remaining string will be used as section comment\.

        Section comments can be used to structure visually the argument
        definition code\. Section comments are also used to structure the
        generated help texts and the interactive argument definition forms\.

> tepam::procedure \{complex\_multiply\} \{  
> &nbsp;&nbsp;&nbsp;\-description "This function perform a complex multiplication"  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\{\#\#\#\# First complex number \#\#\#\#\}__  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-r0 \-type double \-description "First number real part"\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-i0 \-type double \-description "First number imaginary part"\}  
>   
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\{\#\#\#\# Second complex number \#\#\#\#\}__  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-r1 \-type double \-description "Second number real part"\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-i1 \-type double \-description "Second number imaginary part"\}  
> &nbsp;&nbsp;&nbsp;\}  
> \} \{  
> &nbsp;&nbsp;&nbsp;return \[expr $r0\*$r1 \- $i0\*$i1\]  
> \}

  - Argument attributes \(*<arg\_attr\_name\_<mn>> <arg\_attr\_value\_<mn>>*\)

    The following argument attributes are supported:

      * \-description *string*

651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
        validation commands that are defined with the *\-validatecommand*
        attribute\. The provided validation command can be a complete script in
        which the pattern *%P* is replaced by the argument value that has to
        be validated\.

        Validation command declaration example:

    tepam::procedure \{display\_message\} \{
       \-args \{
          \{text \-type string \-description "Message text" \\
                __\-validatecommand \{IllegalWordDetector %P\}__\}
    \} \{
    \}

        While the purpose of this custom argument validation attribute is the
        validation of a specific argument, there is also a global attribute
        *\-validatecommand* that allows performing validation that involves
        multiple arguments\.

      * \-validatecommand\_error\_text *string*







|
|
|
|
|
|







649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
        validation commands that are defined with the *\-validatecommand*
        attribute\. The provided validation command can be a complete script in
        which the pattern *%P* is replaced by the argument value that has to
        be validated\.

        Validation command declaration example:

> tepam::procedure \{display\_message\} \{  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{text \-type string \-description "Message text" \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-validatecommand \{IllegalWordDetector %P\}__\}  
> \} \{  
> \}

        While the purpose of this custom argument validation attribute is the
        validation of a specific argument, there is also a global attribute
        *\-validatecommand* that allows performing validation that involves
        multiple arguments\.

      * \-validatecommand\_error\_text *string*
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
      * \-auxargs *list*

        In case a procedure is called interactively, additional argument
        attributes can be provided to the interactive argument definition form
        via the *\-auxargs* attribute that is itself a list of attribute
        name/attribute value pairs:

    \-auxargs \{\-<arg\_attr\_name\_1a> <arg\_attr\_value\_1a> \\
              \-<arg\_attr\_name\_1b> <arg\_attr\_value\_1b>
              \.\.\.
    \}


        For example, if a procedure takes as argument a file name it may be
        beneficial to specify the required file type for the interactive
        argument definition form\. This information can be provided via the
        *\-auxargs* attribute to the argument definition form:

    tepam::procedure LoadPicture \{
       \-args \{
          \{FileName \-type existingfile \-description "Picture file" \\
                     __\-auxargs \{\-filetypes \{\{"GIF" \{\*\.gif\}\} \{"JPG" \{\*\.jpg\}\} \}\}__\}
       \}
    \} \{
    \}

      * \-auxargs\_commands *script*

        If the auxiliary argument attributes are not static but have to be
        dynamically adaptable, the *\-auxargs\_commands* allows defining them
        via commands that are executed during a procedure call\. A list of pairs
        of auxiliary attribute names and commands has to be provided to the
        *\-auxargs\_commands* attribute\. The provided commands are executed in
        the context of the calling procedure\.

    \-auxargs\_commands \{\-<arg\_attr\_name\_1a> <arg\_attr\_command\_1a> \\
                       \-<arg\_attr\_name\_1b> <arg\_attr\_command\_1b>
                       \.\.\.
    \}


# <a name='section4'></a>VARIABLES

Several variables defined inside the __::tepam__ namespace impact the mode
of operation of the procedures that have been declared with the TEPAM
__procedure__ command\.

  - __named\_arguments\_first__

    This variable defines the general calling style of the procedures\. It is by
    default set to __1__ which selects the *named arguments first, unnamed
    arguments later* style \(Tcl style\)\.

    By setting this variable to __0__, the *named arguments first, unnamed
    arguments later* style is globally selected \(Tk style\):

    set tepam::named\_arguments\_first 0

    While this variable defines the general calling style, the procedure
    attribute *\-named\_arguments\_first* can adapt this style individually for
    each declared procedure\.

  - __auto\_argument\_name\_completion__

    This variable controls the general automatic argument name matching mode\. By
    default it is set to __1__, meaning that the called procedures are
    trying to match eventually abbreviated argument names with the declared
    argument names\.

    By setting this variable to __0__ the automatic argument name matching
    mode is disabled:

    set tepam::auto\_argument\_name\_completion 0

    While this variable defines the general matching mode, the procedure
    attribute *\-auto\_argument\_name\_completion* can adapt this mode
    individually for each declared procedure\.

  - __interactive\_display\_format__

    A procedure declared via the TEPAM __procedure__ command can always be
    called with the __\-interactive__ switch\. By doing so, a graphical form
    will be generated that allows entering interactively all procedure
    arguments\.

    There are two display modes for these interactive forms\. The *extended*
    mode which is the default mode is more adapted for small procedure argument
    sets\. The __short__ form is more adequate for huge procedure argument
    sets:

    set tepam::interactive\_display\_format "short"

    The choice to use short or extended forms can be globally configured via the
    variable __interactive\_display\_format__\. This global setting can be
    changed individually for a procedure with the procedure attribute
    *\-interactive\_display\_format*\.

  - __help\_line\_length__

    The maximum line length used by the procedure help text generator can be
    specified with this variable\. The default length which is set to 80
    \(characters\) can easily be adapted to the need of an application:

    set tepam::help\_line\_length 120

    Since this variable is applied directly during the help text generation, its
    value can continuously be adapted to the current need\.

  - __command\_log__

    Procedure calls can be logged inside the list variable







|
|
|
<
>






|
|
|
|
|
|
|










|
|
|
<
>
















|















|

















|












|







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
      * \-auxargs *list*

        In case a procedure is called interactively, additional argument
        attributes can be provided to the interactive argument definition form
        via the *\-auxargs* attribute that is itself a list of attribute
        name/attribute value pairs:

            -auxargs {-<arg_attr_name_1a> <arg_attr_value_1a> \
                      -<arg_attr_name_1b> <arg_attr_value_1b>
                      ...

            }

        For example, if a procedure takes as argument a file name it may be
        beneficial to specify the required file type for the interactive
        argument definition form\. This information can be provided via the
        *\-auxargs* attribute to the argument definition form:

> tepam::procedure LoadPicture \{  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{FileName \-type existingfile \-description "Picture file" \\  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\-auxargs \{\-filetypes \{\{"GIF" \{\*\.gif\}\} \{"JPG" \{\*\.jpg\}\} \}\}__\}  
> &nbsp;&nbsp;&nbsp;\}  
> \} \{  
> \}

      * \-auxargs\_commands *script*

        If the auxiliary argument attributes are not static but have to be
        dynamically adaptable, the *\-auxargs\_commands* allows defining them
        via commands that are executed during a procedure call\. A list of pairs
        of auxiliary attribute names and commands has to be provided to the
        *\-auxargs\_commands* attribute\. The provided commands are executed in
        the context of the calling procedure\.

            -auxargs_commands {-<arg_attr_name_1a> <arg_attr_command_1a> \
                               -<arg_attr_name_1b> <arg_attr_command_1b>
                               ...

            }

# <a name='section4'></a>VARIABLES

Several variables defined inside the __::tepam__ namespace impact the mode
of operation of the procedures that have been declared with the TEPAM
__procedure__ command\.

  - __named\_arguments\_first__

    This variable defines the general calling style of the procedures\. It is by
    default set to __1__ which selects the *named arguments first, unnamed
    arguments later* style \(Tcl style\)\.

    By setting this variable to __0__, the *named arguments first, unnamed
    arguments later* style is globally selected \(Tk style\):

        set tepam::named_arguments_first 0

    While this variable defines the general calling style, the procedure
    attribute *\-named\_arguments\_first* can adapt this style individually for
    each declared procedure\.

  - __auto\_argument\_name\_completion__

    This variable controls the general automatic argument name matching mode\. By
    default it is set to __1__, meaning that the called procedures are
    trying to match eventually abbreviated argument names with the declared
    argument names\.

    By setting this variable to __0__ the automatic argument name matching
    mode is disabled:

        set tepam::auto_argument_name_completion 0

    While this variable defines the general matching mode, the procedure
    attribute *\-auto\_argument\_name\_completion* can adapt this mode
    individually for each declared procedure\.

  - __interactive\_display\_format__

    A procedure declared via the TEPAM __procedure__ command can always be
    called with the __\-interactive__ switch\. By doing so, a graphical form
    will be generated that allows entering interactively all procedure
    arguments\.

    There are two display modes for these interactive forms\. The *extended*
    mode which is the default mode is more adapted for small procedure argument
    sets\. The __short__ form is more adequate for huge procedure argument
    sets:

        set tepam::interactive_display_format "short"

    The choice to use short or extended forms can be globally configured via the
    variable __interactive\_display\_format__\. This global setting can be
    changed individually for a procedure with the procedure attribute
    *\-interactive\_display\_format*\.

  - __help\_line\_length__

    The maximum line length used by the procedure help text generator can be
    specified with this variable\. The default length which is set to 80
    \(characters\) can easily be adapted to the need of an application:

        set tepam::help_line_length 120

    Since this variable is applied directly during the help text generation, its
    value can continuously be adapted to the current need\.

  - __command\_log__

    Procedure calls can be logged inside the list variable
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
TEPAM provides a comprehensive set of procedure argument types\. They can easily
be completed with application specific types if necessary\.

## <a name='subsection3'></a>Predefined Argument Types

To remember, a type can be assigned to each specified procedure argument:

    tepam::procedure \{warning\} \{
       \-args \{
          \{\-font __\-type font__ \-default \{Arial 10 italic\}\}
          \{\-severity\_level __\-type integer__ \-optional \-range \{1 10\}\}
          \{\-fg __\-type color__ \-optional \-description "Message color"\}
          \{text __\-type string__ \-multiple \-description "Multiple text lines to display"\}
       \}
    \} \{
       \.\.\.
    \}

There are some *special purpose types* that are building the first category of
predefined argument types:

  - __none__ A *flag*, also called *switch*, is defined as a named
    argument that has the type __none__\. Flags are always optional and the
    default value of the assigned variable is set to __0__\. In contrast to
    the \(normal\) named arguments, no argument value has to be provided to a
    flag\.

    tepam::procedure flag\_test \{
       \-args \{
          __\{\-flag \-type none \-description "This is a flag"\}__
       \}
    \} \{
       puts __$flag__
    \}

    flag\_test
    *\-> 0*

    flag\_test \-flag

    *\-> 1*

    Since no argument value has to be provided to a flag, also no data check is
    performed for this argument type\.

  - __string__ __String__ is a generic argument data type\. Any data
    string can be provided to a string type argument and no data type checks are
    therefore performed\. The string type allows defining single line strings







|
|
|
|
|
|
|
|
|
|










|
|
|
|
|
|
|
|
|
|
|
|
<
|







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
TEPAM provides a comprehensive set of procedure argument types\. They can easily
be completed with application specific types if necessary\.

## <a name='subsection3'></a>Predefined Argument Types

To remember, a type can be assigned to each specified procedure argument:

> tepam::procedure \{warning\} \{  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-font __\-type font__ \-default \{Arial 10 italic\}\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-severity\_level __\-type integer__ \-optional \-range \{1 10\}\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-fg __\-type color__ \-optional \-description "Message color"\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{text __\-type string__ \-multiple \-description "Multiple text lines to display"\}  
> &nbsp;&nbsp;&nbsp;\}  
> \} \{  
> &nbsp;&nbsp;&nbsp;\.\.\.  
> \}

There are some *special purpose types* that are building the first category of
predefined argument types:

  - __none__ A *flag*, also called *switch*, is defined as a named
    argument that has the type __none__\. Flags are always optional and the
    default value of the assigned variable is set to __0__\. In contrast to
    the \(normal\) named arguments, no argument value has to be provided to a
    flag\.

> tepam::procedure flag\_test \{  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__\{\-flag \-type none \-description "This is a flag"\}__  
> &nbsp;&nbsp;&nbsp;\}  
> \} \{  
> &nbsp;&nbsp;&nbsp;puts __$flag__  
> \}  
>   
> flag\_test  
> *\-> 0*  
>   
> flag\_test \-flag  

> *\-> 1*

    Since no argument value has to be provided to a flag, also no data check is
    performed for this argument type\.

  - __string__ __String__ is a generic argument data type\. Any data
    string can be provided to a string type argument and no data type checks are
    therefore performed\. The string type allows defining single line strings
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

Several *numerical types* are defined by TEPAM\. The type validation procedures
are using the __string is <type> \-strict__ commands to check the validity of
the provided arguments, which assures that no empty strings are accepted as
argument value\. The type validation expression for the numerical types and the
argument types to which this expression is applied are:

    string is __<type\_to\_check>__ \-strict

*<argument\_value>*

  - *boolean*

  - *integer*

  - *double*

Empty strings are accepted as argument value for all the alpha numeric argument
types\. The argument types that are falling into this category and validation
expression used for them are:

    string is *<type\_to\_check>*

*<argument\_value>*

  - *alnum*

  - *alpha*

  - *ascii*








|
<
<











|
<
<







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

Several *numerical types* are defined by TEPAM\. The type validation procedures
are using the __string is <type> \-strict__ commands to check the validity of
the provided arguments, which assures that no empty strings are accepted as
argument value\. The type validation expression for the numerical types and the
argument types to which this expression is applied are:

> string is __<type\_to\_check>__ \-strict *<argument\_value>*



  - *boolean*

  - *integer*

  - *double*

Empty strings are accepted as argument value for all the alpha numeric argument
types\. The argument types that are falling into this category and validation
expression used for them are:

> string is *<type\_to\_check>* *<argument\_value>*



  - *alnum*

  - *alpha*

  - *ascii*

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

In addition to the data types checked with the __string is <type>__
commands, TEPAM specifies some other useful data types:

  - *char* Each string that has a length of 1 character meets the
    *character* type\. The type check is made with the following expression:

    expr \[string length *<argument\_value>*\]==1

  - *color* Any character strings that are accepted by Tk as a color are
    considered as valid color argument\. Please note that the Tk package has to
    be loaded to use the type *color*\. TEPAM is using the following command to
    validate the color type:

    expr \!\[catch \{winfo rgb \. *<argument\_value>*\}

    \]

  - *font* Any character strings that are accepted by Tk as a font are
    considered as valid font argument\. Please note that the Tk package has to be
    loaded to use the *font* type\. TEPAM is using the following command to
    validate the color type:

    expr \!\[catch \{font measure <argument\_value> ""\}

    \]

  - *file* Any strings that are not containing one of the following characters
    are considered as valid file names: \* ? " < >\. It is not necessary that the
    file and its containing directory exist\. Zero\-length strings are not
    considered as valid file names\.

    The following expression is used to validate the file names:

    expr \[string length <argument\_value>\]>0 && \!\[regexp \{\[\\"\*?<>:\]\} <argument\_value>

    \]

  - *existingfile* The argument is valid if it matches with an existing file\.
    The following check is performed to validate the arguments of this type:

    file exists <argument\_value>

  - *directory* The directory argument is validated exactly in the same way as
    the file arguments\.

  - *existingdirectory* The argument is valid if it matches with an existing
    directory\. The following check is performed to validate the arguments of
    this type:

    file isdirectory <argument\_value>

## <a name='subsection4'></a>Defining Application Specific Argument Types

To add support for a new application specific argument type it is just necessary
to add into the namespace __tepam__ a validation function
__Validation\(<type>\)__\. This function requires one argument\. It has to
returns __1__ if the provided argument matches with the relevant data type\.
The function has to return otherwise __0__\.

The validation command section of the "tepam\.tcl" package provides sufficient
examples of validation functions, since it implements the ones for the standard
TEPAM types\.

The following additional code snippet shows the validation function for a custom
argument type that requires values that have a character string length of
exactly 2:

    proc tepam::Validate\(two\_char\) \{v\} \{expr \{\[string length $v\]==2\}\}

# <a name='section6'></a>PROCEDURE CALLS

## <a name='subsection5'></a>Help

Each procedure can be called with the *\-help* flag\. The procedure will then
print a generated help text to *stdout* and will then return without
performing any additional actions\.

Taking the first procedure declared in [PROCEDURE CALLS](#section6), the
help request and the printed help text would be:

    __display message \-help__


*\-> NAME display message \- Displays a simple message box SYNOPSIS display



message \[\-mtype <mtype>\] Message type, default: "Warning", choices: \{Info,

Warning, Error\} <text> Multiple text lines to display, type: string DESCRIPTION

This procedure allows displaying a configurable message box\. The default message
type that is created is a warning, but also errors and info can be generated\.

The procedure accepts multiple text lines\. EXAMPLE display message \-mtype



Warning "Save first your job"* The argument manager is checking if the last
provided argument is *\-help* and generates the requested help message if this
is the case\. So, also the following example will print the help message:

__display message \-mtype Info "It is 7:00" \-help__ On the other hand, the

following call will result in an error:

    __display message \-help \-mtype Info "It is 7:00"__

*\-> display message: Argument '\-help' not known*

## <a name='subsection6'></a>Interactive Procedure Call

If Tk has been loaded a procedure can be called with the *\-interactive* flag
to open a graphical form that allows specifying interactively all procedure
arguments\. The following example assures that the Tk library is loaded and shows
the command line to call interactively the procedure declared in [PROCEDURE
CALLS](#section6):

    package require Tk


__display message \-interactive__ Also the *\-interactive* flag has to be
placed at the last argument position as this is also required for the *\-help*
flag\. Arguments defined before the *\-interactive* flag will be ignored\. The
following example is therefore also a valid interactive procedure call:

    __display message__ \-mtype Info "It is 7:00"

__\-interactive__

## <a name='subsection7'></a>Unnamed Arguments

Unnamed arguments are typically provided to the called procedure as simple
parameters\. This procedure calling form requires that the provided arguments are
strictly following the order of the specified arguments\. Several parameters can
be assigned to the last argument if this one has the *\-multiple* attribute\.
So, the following declared procedure \.\.\.

    tepam::procedure \{display\_message\} \{
       \-args \{
          \{mtype \-choices \{Info Warning Error\}\}
          \{text \-type string \-multiple\}

       \}
    \} \{
       puts "$mtype: \[join $text\]"
    \}


\.\.\. can for example be called in the following ways:

    __display\_message Info "It is PM 7:00\."__
    *\-> Info: It is PM 7:00\.*

    __display\_message Info "It is PM 7:00\." "You should go home\."__


*\-> Info: It is PM 7:00\. You should go home\.* The nice thing is that unnamed
arguments can also be called as named arguments, which can be handy, for example
if the exact specified argument order is not known to a user:


    __display\_message \-mtype Info \-text "It is PM 7:00\."__
    *\-> Info: It is PM 7:00\.*

    __display\_message \-text "It is PM 7:00\." \-mtype Info__
    *\-> Info: It is PM 7:00\.*

    __display\_message \-mtype Info \-text "It is PM 7:00\." \-text "You should go home\."__
    *\-> Info: It is PM 7:00\. You should go home\.*

    __display\_message \-text "It is PM 7:00\." \-text "You should go home\." \-mtype Info__

*\-> Info: It is PM 7:00\. You should go home\.*

## <a name='subsection8'></a>Named Arguments

Named arguments have to be provided to a procedure in form of a parameter pairs
composed by the argument names and the argument values\. The order how they are
provided during a procedure call is irrelevant and has not to match with the
argument specification order\.

The following declared procedure \.\.\.

    tepam::procedure \{display\_message\} \{
       \-args \{
          \{\-mtype \-choices \{Info Warning Error\}\}
          \{\-text \-type string \-multiple\}

       \}
    \} \{
       puts "$mtype: \[join $text\]"
    \}


\.\.\. can be called in the following ways:

    __display\_message \-mtype Info \-text "It is PM 7:00\."__
    *\-> Info: It is PM 7:00\.*

    __display\_message \-text "It is PM 7:00\." \-mtype Info__
    *\-> Info: It is PM 7:00\.*

    __display\_message \-mtype Info \-text "It is PM 7:00\." \-text "You should go home\."__
    *\-> Info: It is PM 7:00\. You should go home\.*

    __display\_message \-text "It is PM 7:00\." \-text "You should go home\." \-mtype Info__


*\-> Info: It is PM 7:00\. You should go home\.* Also named arguments that have
not the *\-multiple* attribute can be provided multiple times\. Only the last
provided argument will be retained in such a case:

    __display\_message \-mtype Info \-text "It is PM 7:00\." \-mtype Warning__

*\-> Warning: It is PM 7:00\.*

## <a name='subsection9'></a>Unnamed Arguments First, Named Arguments Later \(Tk Style\)

A procedure that has been defined while the variable
__tepam::named\_arguments\_first__ was set to 1, or with the procedure
attribute *\-named\_arguments\_first* set to 1 has to be called in the Tcl style\.
The following procedure declaration will be used in this section to illustrate
the meaning of this calling style:

    __set tepam::named\_arguments\_first 1__
    tepam::procedure my\_proc \{
       \-args \{
          \{\-n1 \-default ""\}
          \{\-n2 \-default ""\}
          \{u1 \-default ""\}
          \{u2 \-default ""\}
       \}
    \} \{
       puts "n1:'$n1', n2:'$n2', u1:'$u1', u2:'$u2'"
    \}

The unnamed arguments are placed at the end of procedure call, after the named
arguments:

    my\_proc __\-n1 N1 \-n2 N2 U1 U2__


*\-> n1:'N1', n2:'N2', u1:'U1', u2:'U2'* The argument parser considers the
first argument that doesn't start with the '\-' character as well as all
following arguments as unnamed argument:

    my\_proc __U1 U2__


*\-> n1:'', n2:'', u1:'U1', u2:'U2'* Named arguments can be defined multiple
times\. If the named argument has the *\-multiply* attribute, all argument
values will be collected in a list\. Otherwise, only the last provided attribute
value will be retained:

    my\_proc __\-n1 N1 \-n2 N2 \-n1 M1 U1 U2__


*\-> n1:'M1', n2:'N2', u1:'U1', u2:'U2'* The name of the first unnamed argument
has therefore not to start with the '\-' character\. The unnamed argument is
otherwise considered as name of another named argument\. This is especially
important if the first unnamed argument is given by a variable that can contain
any character strings:

    my\_proc __\-n1 N1 \-n2 N2 "\->" "<\-"__
    *\-> my\_proc: Argument '\->' not known*

    set U1 "\->"
    my\_proc __\-n1 N1 \-n2 N2 $U1 U2__
    my\_proc: Argument '\->' not known

The '\-\-' flag allows separating unambiguously the unnamed arguments from the
named arguments\. All data after the '\-\-' flag will be considered as unnamed
argument:

    my\_proc __\-n1 N1 \-n2 N2 \-\- "\->" "<\-"__
    *\-> n1:'N1', n2:'N2', u1:'\->', u2:'<\-'*

    set U1 "\->"
    my\_proc __\-n1 N1 \-n2 N2 \-\- $U1 U2__

*\-> n1:'N1', n2:'N2', u1:'\->', u2:'<\-'*

## <a name='subsection10'></a>Named Arguments First, Unnamed Arguments Later \(Tcl Style\)

The Tk calling style will be chosen if a procedure is defined while the variable
__tepam::named\_arguments\_first__ is set to 0, or if the procedure attribute
*\-named\_arguments\_first* has been set to 0\. The following procedure will be
used in this section to illustrate this calling style:

    __set tepam::named\_arguments\_first 0__
    tepam::procedure my\_proc \{
       \-args \{
          \{\-n1 \-default ""\}
          \{\-n2 \-default ""\}
          \{u1\}
          \{u2 \-default "" \-multiple\}
       \}
    \} \{
       puts "n1:'$n1', n2:'$n2', u1:'$u1', u2:'$u2'"
    \}

The unnamed arguments have to be provided first in this case\. The named
arguments are provided afterwards:

    my\_proc __U1 U2 \-n1 N1 \-n2 N2__


*\-> n1:'N1', n1:'N1', u1:'U1', u2:'U2'* The argument parser will assign to
each defined unnamed argument a value before it switches to read the named
arguments\. This default behavior changes a bit if there are unnamed arguments
that are optional or that can take multiple values\.

An argument value will only be assigned to an unnamed argument that is optional
\(that has either the *\-optional* attribute or that has a default value\), if
the value is not beginning with the '\-' character or if no named arguments are
defined\. The value that starts with '\-' is otherwise considered as the name of a
named argument\.

Argument values are assigned to an argument that has the *\-multiple* attribute
as long as the parameter value doesn't starts with the '\-' character\.

Values that start with the '\-' character can therefore not be assigned to
optional unnamed arguments, which restricts the usage of the Tcl procedure
calling style\. The Tk style may be preferable in some cases, since it allows
separating unambiguously the named arguments from the unnamed ones with the '\-\-'
flag\.

Let's explore in a bit less theoretically the ways how the previously defined
procedure can be called: The first example calls the procedure without any
parameters, which leads to an error since *u1* is a mandatory argument:

    my\_proc


*\-> my\_proc: Required argument is missing: u1* The procedure call is valid if
one parameter is provided for *u1*:

    my\_proc __U1__


*\-> n1:'', n2:'', u1:'U1', u2:''* If more parameters are provided that are not
starting with the '\-' character, they will be attributed to the unnamed
arguments\. *U2* will receive 3 of these parameters, since it accepts multiple
values:

    my\_proc __U1 U2 U3 U4__


*\-> n1:'', n2:'', u1:'U1', u2:'U2 U3 U4'* As soon as one parameter starts with
'\-' and all unnamed arguments have been assigned, the argument manager tries to
interpret the parameter as name of a named argument\. The procedure call will
fail if a value beginning with '\-' is assigned to an unnamed argument:

    my\_proc __U1 U2 U3 U4 \-U5__


*\-> my\_proc: Argument '\-U5' not known* The attribution of a parameter to a
named argument will fail if there are undefined unnamed \(non optional\)
arguments\. The name specification will in this case simply be considered as a
parameter value that is attributed to the *next* unnamed argument\. This was
certainly not the intention in the following example:


    my\_proc __\-n1 N1__


*\-> n1:'', n2:'', u1:'\-n1', u2:'N1'* The situation is completely different if
values have already been assigned to all mandatory unnamed arguments\. A
parameter beginning with the '\-' character will in this case be considered as a
name identifier for a named argument:

    my\_proc __U1 \-n1 N1__


*\-> n1:'N1', n2:'', u1:'U1', u2:''* No unnamed arguments are allowed behind












the named arguments:

    my\_proc __U1 \-n1 N1 U2__

*\-> my\_proc: Argument 'U2' is not an option* The '\-\-' flag has no special
meaning if not all mandatory arguments have got assigned a value\. This flag will
simply be attributed to one of the unnamed arguments:

    my\_proc __\-\- \-n1 N1__

*\-> n1:'N1', n2:'', u1:'\-\-', u2:''* But the '\-\-' flag is simply ignored if the
argument parser has started to handle the named arguments:

    my\_proc __U1 \-\- \-n1 N1__
    *\-> n1:'N1', n2:'', u1:'U1', u2:''*

    my\_proc __U1 \-n1 N1 \-\- \-n2 N2__

*\-> n1:'N1', n2:'N2', u1:'U1', u2:''*

## <a name='subsection11'></a>Raw Argument List

It may be necessary sometimes that the procedure body is able to access the
entire list of arguments provided during a procedure call\. This can happen via
the __args__ variable that contains always the unprocessed argument list:

    tepam::procedure \{display\_message\} \{
       \-args \{
          \{\-mtype \-choices \{Warning Error\} \-default Warning\}
          \{text \-type string \-multiple\}

       \}
    \} \{
       puts "args: __$args__"
    \}
    display\_message \-mtype Warning "It is 7:00"

*\-> args: \-mtype Warning \{It is 7:00\}*

# <a name='seealso'></a>SEE ALSO

[tepam\(n\)](tepam\_introduction\.md),
[tepam::argument\_dialogbox\(n\)](tepam\_argument\_dialogbox\.md)

# <a name='keywords'></a>KEYWORDS







|






|
<
<






|
<
<








<
|
<




|








|

















|












|
|
>
|
>
>
>
|
>
|
>
|
|
>
|
>
>
>
|
|
|

|
>
|

|
|
|









|
>

|
|
|
|

|
<
<









|
|
|
|
>
|
<
|
<
|
>


|
|
|
|
>

<
|
|
>

|
|
|
|
|
|
|
|
|
|
<
|










|
|
|
|
>
|
<
|
<
|
>


|
|
|
|
|
|
|
|
|
|
>

<
|
|

|
<
|









|
|
|
|
|
|
|
|
|
|
|




|
>

<
|
|

|
>

|
|
|
<

|
>

<
|
|
|
|

|
|
|
|
|
|





|
|
|
|
|
<
|








|
|
|
|
|
|
|
|
|
|
|




|
>

<
|
|
|




















|
>

<
|

|
>

|
|
|
<

|
>

|
|
|
|

|
>

<
|
|
|
|
>

|
>

|
<
|
|

|
>

|
>
>
>
>
>
>
>
>
>
>
>
>


<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
<
|







|
|
|
|
|
|
|
|
|
|
<
|







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

In addition to the data types checked with the __string is <type>__
commands, TEPAM specifies some other useful data types:

  - *char* Each string that has a length of 1 character meets the
    *character* type\. The type check is made with the following expression:

> expr \[string length *<argument\_value>*\]==1

  - *color* Any character strings that are accepted by Tk as a color are
    considered as valid color argument\. Please note that the Tk package has to
    be loaded to use the type *color*\. TEPAM is using the following command to
    validate the color type:

> expr \!\[catch \{winfo rgb \. *<argument\_value>*\}\]



  - *font* Any character strings that are accepted by Tk as a font are
    considered as valid font argument\. Please note that the Tk package has to be
    loaded to use the *font* type\. TEPAM is using the following command to
    validate the color type:

        expr ![catch {font measure <argument_value> ""}]



  - *file* Any strings that are not containing one of the following characters
    are considered as valid file names: \* ? " < >\. It is not necessary that the
    file and its containing directory exist\. Zero\-length strings are not
    considered as valid file names\.

    The following expression is used to validate the file names:


        expr [string length <argument_value>]>0 && ![regexp {[\"*?<>:]} <argument_value>]


  - *existingfile* The argument is valid if it matches with an existing file\.
    The following check is performed to validate the arguments of this type:

        file exists <argument_value>

  - *directory* The directory argument is validated exactly in the same way as
    the file arguments\.

  - *existingdirectory* The argument is valid if it matches with an existing
    directory\. The following check is performed to validate the arguments of
    this type:

        file isdirectory <argument_value>

## <a name='subsection4'></a>Defining Application Specific Argument Types

To add support for a new application specific argument type it is just necessary
to add into the namespace __tepam__ a validation function
__Validation\(<type>\)__\. This function requires one argument\. It has to
returns __1__ if the provided argument matches with the relevant data type\.
The function has to return otherwise __0__\.

The validation command section of the "tepam\.tcl" package provides sufficient
examples of validation functions, since it implements the ones for the standard
TEPAM types\.

The following additional code snippet shows the validation function for a custom
argument type that requires values that have a character string length of
exactly 2:

    proc tepam::Validate(two_char) {v} {expr {[string length $v]==2}}

# <a name='section6'></a>PROCEDURE CALLS

## <a name='subsection5'></a>Help

Each procedure can be called with the *\-help* flag\. The procedure will then
print a generated help text to *stdout* and will then return without
performing any additional actions\.

Taking the first procedure declared in [PROCEDURE CALLS](#section6), the
help request and the printed help text would be:

> __display message \-help__  
> *\->*  
> *NAME*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*display message \- Displays a simple message box*  
> *SYNOPSIS*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*display message*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*\[\-mtype <mtype>\]*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*Message type, default: "Warning", choices: \{Info, Warning, Error\}*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<text>*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*Multiple text lines to display, type: string*  
> *DESCRIPTION*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*This procedure allows displaying a configurable message box\. The default*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*message type that is created is a warning, but also errors and info can*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*be generated\.*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*The procedure accepts multiple text lines\.*  
> *EXAMPLE*  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*display message \-mtype Warning "Save first your job"*

The argument manager is checking if the last provided argument is *\-help* and
generates the requested help message if this is the case\. So, also the following
example will print the help message:

> __display message \-mtype Info "It is 7:00" \-help__

On the other hand, the following call will result in an error:

> __display message \-help \-mtype Info "It is 7:00"__  
> *\->*  
> *display message: Argument '\-help' not known*

## <a name='subsection6'></a>Interactive Procedure Call

If Tk has been loaded a procedure can be called with the *\-interactive* flag
to open a graphical form that allows specifying interactively all procedure
arguments\. The following example assures that the Tk library is loaded and shows
the command line to call interactively the procedure declared in [PROCEDURE
CALLS](#section6):

> package require Tk  
> __display message \-interactive__

Also the *\-interactive* flag has to be placed at the last argument position as
this is also required for the *\-help* flag\. Arguments defined before the
*\-interactive* flag will be ignored\. The following example is therefore also a
valid interactive procedure call:

> __display message__ \-mtype Info "It is 7:00" __\-interactive__



## <a name='subsection7'></a>Unnamed Arguments

Unnamed arguments are typically provided to the called procedure as simple
parameters\. This procedure calling form requires that the provided arguments are
strictly following the order of the specified arguments\. Several parameters can
be assigned to the last argument if this one has the *\-multiple* attribute\.
So, the following declared procedure \.\.\.

    tepam::procedure {display_message} {
       -args {
          {mtype -choices {Info Warning Error}}
          {text -type string -multiple}
       }
    } {

       puts "$mtype: [join $text]"

    }

\.\.\. can for example be called in the following ways:

> __display\_message Info "It is PM 7:00\."__  
> *\-> Info: It is PM 7:00\.*  
>   
> __display\_message Info "It is PM 7:00\." "You should go home\."__  
> *\-> Info: It is PM 7:00\. You should go home\.*


The nice thing is that unnamed arguments can also be called as named arguments,
which can be handy, for example if the exact specified argument order is not
known to a user:

> __display\_message \-mtype Info \-text "It is PM 7:00\."__  
> *\-> Info: It is PM 7:00\.*  
>   
> __display\_message \-text "It is PM 7:00\." \-mtype Info__  
> *\-> Info: It is PM 7:00\.*  
>   
> __display\_message \-mtype Info \-text "It is PM 7:00\." \-text "You should go home\."__  
> *\-> Info: It is PM 7:00\. You should go home\.*  
>   
> __display\_message \-text "It is PM 7:00\." \-text "You should go home\." \-mtype Info__  

> *\-> Info: It is PM 7:00\. You should go home\.*

## <a name='subsection8'></a>Named Arguments

Named arguments have to be provided to a procedure in form of a parameter pairs
composed by the argument names and the argument values\. The order how they are
provided during a procedure call is irrelevant and has not to match with the
argument specification order\.

The following declared procedure \.\.\.

    tepam::procedure {display_message} {
       -args {
          {-mtype -choices {Info Warning Error}}
          {-text -type string -multiple}
       }
    } {

       puts "$mtype: [join $text]"

    }

\.\.\. can be called in the following ways:

> __display\_message \-mtype Info \-text "It is PM 7:00\."__  
> *\-> Info: It is PM 7:00\.*  
>   
> __display\_message \-text "It is PM 7:00\." \-mtype Info__  
> *\-> Info: It is PM 7:00\.*  
>   
> __display\_message \-mtype Info \-text "It is PM 7:00\." \-text "You should go home\."__  
> *\-> Info: It is PM 7:00\. You should go home\.*  
>   
> __display\_message \-text "It is PM 7:00\." \-text "You should go home\." \-mtype Info__  
> *\-> Info: It is PM 7:00\. You should go home\.*


Also named arguments that have not the *\-multiple* attribute can be provided
multiple times\. Only the last provided argument will be retained in such a case:

> __display\_message \-mtype Info \-text "It is PM 7:00\." \-mtype Warning__  

> *\-> Warning: It is PM 7:00\.*

## <a name='subsection9'></a>Unnamed Arguments First, Named Arguments Later \(Tk Style\)

A procedure that has been defined while the variable
__tepam::named\_arguments\_first__ was set to 1, or with the procedure
attribute *\-named\_arguments\_first* set to 1 has to be called in the Tcl style\.
The following procedure declaration will be used in this section to illustrate
the meaning of this calling style:

> __set tepam::named\_arguments\_first 1__  
> tepam::procedure my\_proc \{  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-n1 \-default ""\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-n2 \-default ""\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{u1 \-default ""\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{u2 \-default ""\}  
> &nbsp;&nbsp;&nbsp;\}  
> \} \{  
> &nbsp;&nbsp;&nbsp;puts "n1:'$n1', n2:'$n2', u1:'$u1', u2:'$u2'"  
> \}

The unnamed arguments are placed at the end of procedure call, after the named
arguments:

> my\_proc __\-n1 N1 \-n2 N2 U1 U2__  
> *\-> n1:'N1', n2:'N2', u1:'U1', u2:'U2'*


The argument parser considers the first argument that doesn't start with the '\-'
character as well as all following arguments as unnamed argument:

> my\_proc __U1 U2__  
> *\-> n1:'', n2:'', u1:'U1', u2:'U2'*

Named arguments can be defined multiple times\. If the named argument has the
*\-multiply* attribute, all argument values will be collected in a list\.
Otherwise, only the last provided attribute value will be retained:


> my\_proc __\-n1 N1 \-n2 N2 \-n1 M1 U1 U2__  
> *\-> n1:'M1', n2:'N2', u1:'U1', u2:'U2'*


The name of the first unnamed argument has therefore not to start with the '\-'
character\. The unnamed argument is otherwise considered as name of another named
argument\. This is especially important if the first unnamed argument is given by
a variable that can contain any character strings:

> my\_proc __\-n1 N1 \-n2 N2 "\->" "<\-"__  
> *\-> my\_proc: Argument '\->' not known*  
>   
> set U1 "\->"  
> my\_proc __\-n1 N1 \-n2 N2 $U1 U2__  
> my\_proc: Argument '\->' not known

The '\-\-' flag allows separating unambiguously the unnamed arguments from the
named arguments\. All data after the '\-\-' flag will be considered as unnamed
argument:

> my\_proc __\-n1 N1 \-n2 N2 \-\- "\->" "<\-"__  
> *\-> n1:'N1', n2:'N2', u1:'\->', u2:'<\-'*  
>   
> set U1 "\->"  
> my\_proc __\-n1 N1 \-n2 N2 \-\- $U1 U2__  

> *\-> n1:'N1', n2:'N2', u1:'\->', u2:'<\-'*

## <a name='subsection10'></a>Named Arguments First, Unnamed Arguments Later \(Tcl Style\)

The Tk calling style will be chosen if a procedure is defined while the variable
__tepam::named\_arguments\_first__ is set to 0, or if the procedure attribute
*\-named\_arguments\_first* has been set to 0\. The following procedure will be
used in this section to illustrate this calling style:

> __set tepam::named\_arguments\_first 0__  
> tepam::procedure my\_proc \{  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-n1 \-default ""\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-n2 \-default ""\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{u1\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{u2 \-default "" \-multiple\}  
> &nbsp;&nbsp;&nbsp;\}  
> \} \{  
> &nbsp;&nbsp;&nbsp;puts "n1:'$n1', n2:'$n2', u1:'$u1', u2:'$u2'"  
> \}

The unnamed arguments have to be provided first in this case\. The named
arguments are provided afterwards:

> my\_proc __U1 U2 \-n1 N1 \-n2 N2__  
> *\-> n1:'N1', n1:'N1', u1:'U1', u2:'U2'*


The argument parser will assign to each defined unnamed argument a value before
it switches to read the named arguments\. This default behavior changes a bit if
there are unnamed arguments that are optional or that can take multiple values\.

An argument value will only be assigned to an unnamed argument that is optional
\(that has either the *\-optional* attribute or that has a default value\), if
the value is not beginning with the '\-' character or if no named arguments are
defined\. The value that starts with '\-' is otherwise considered as the name of a
named argument\.

Argument values are assigned to an argument that has the *\-multiple* attribute
as long as the parameter value doesn't starts with the '\-' character\.

Values that start with the '\-' character can therefore not be assigned to
optional unnamed arguments, which restricts the usage of the Tcl procedure
calling style\. The Tk style may be preferable in some cases, since it allows
separating unambiguously the named arguments from the unnamed ones with the '\-\-'
flag\.

Let's explore in a bit less theoretically the ways how the previously defined
procedure can be called: The first example calls the procedure without any
parameters, which leads to an error since *u1* is a mandatory argument:

> my\_proc  
> *\-> my\_proc: Required argument is missing: u1*


The procedure call is valid if one parameter is provided for *u1*:

> my\_proc __U1__  
> *\-> n1:'', n2:'', u1:'U1', u2:''*

If more parameters are provided that are not starting with the '\-' character,
they will be attributed to the unnamed arguments\. *U2* will receive 3 of these
parameters, since it accepts multiple values:


> my\_proc __U1 U2 U3 U4__  
> *\-> n1:'', n2:'', u1:'U1', u2:'U2 U3 U4'*

As soon as one parameter starts with '\-' and all unnamed arguments have been
assigned, the argument manager tries to interpret the parameter as name of a
named argument\. The procedure call will fail if a value beginning with '\-' is
assigned to an unnamed argument:

> my\_proc __U1 U2 U3 U4 \-U5__  
> *\-> my\_proc: Argument '\-U5' not known*


The attribution of a parameter to a named argument will fail if there are
undefined unnamed \(non optional\) arguments\. The name specification will in this
case simply be considered as a parameter value that is attributed to the
*next* unnamed argument\. This was certainly not the intention in the following
example:

> my\_proc __\-n1 N1__  
> *\-> n1:'', n2:'', u1:'\-n1', u2:'N1'*

The situation is completely different if values have already been assigned to

all mandatory unnamed arguments\. A parameter beginning with the '\-' character
will in this case be considered as a name identifier for a named argument:

> my\_proc __U1 \-n1 N1__  
> *\-> n1:'N1', n2:'', u1:'U1', u2:''*

No unnamed arguments are allowed behind the named arguments:

> my\_proc __U1 \-n1 N1 U2__  
> *\-> my\_proc: Argument 'U2' is not an option*

The '\-\-' flag has no special meaning if not all mandatory arguments have got
assigned a value\. This flag will simply be attributed to one of the unnamed
arguments:

> my\_proc __\-\- \-n1 N1__  
> *\-> n1:'N1', n2:'', u1:'\-\-', u2:''*

But the '\-\-' flag is simply ignored if the argument parser has started to handle
the named arguments:












> my\_proc __U1 \-\- \-n1 N1__  
> *\-> n1:'N1', n2:'', u1:'U1', u2:''*  
>   
> my\_proc __U1 \-n1 N1 \-\- \-n2 N2__  

> *\-> n1:'N1', n2:'N2', u1:'U1', u2:''*

## <a name='subsection11'></a>Raw Argument List

It may be necessary sometimes that the procedure body is able to access the
entire list of arguments provided during a procedure call\. This can happen via
the __args__ variable that contains always the unprocessed argument list:

> tepam::procedure \{display\_message\} \{  
> &nbsp;&nbsp;&nbsp;\-args \{  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{\-mtype \-choices \{Warning Error\} \-default Warning\}  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\{text \-type string \-multiple\}  
>   
> &nbsp;&nbsp;&nbsp;\}  
> \} \{  
> &nbsp;&nbsp;&nbsp;puts "args: __$args__"  
> \}  
> display\_message \-mtype Warning "It is 7:00"  

> *\-> args: \-mtype Warning \{It is 7:00\}*

# <a name='seealso'></a>SEE ALSO

[tepam\(n\)](tepam\_introduction\.md),
[tepam::argument\_dialogbox\(n\)](tepam\_argument\_dialogbox\.md)

# <a name='keywords'></a>KEYWORDS

Changes to embedded/md/tcllib/files/modules/textutil/expander.md.

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
The Tcl __[subst](\.\./\.\./\.\./\.\./index\.md\#subst)__ command is often used to
support a kind of template processing\. Given a string with embedded variables or
function calls, __[subst](\.\./\.\./\.\./\.\./index\.md\#subst)__ will interpolate
the variable and function values, returning the new string:

    % set greeting "Howdy"
    Howdy
    % proc place \{\} \{return "World"\}
    % subst \{$greeting, \[place\]\!\}
    Howdy, World\!
    %

By defining a suitable set of Tcl commands,
__[subst](\.\./\.\./\.\./\.\./index\.md\#subst)__ can be used to implement a
markup language similar to HTML\.

The __[subst](\.\./\.\./\.\./\.\./index\.md\#subst)__ command is efficient, but it







|
|
|







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
The Tcl __[subst](\.\./\.\./\.\./\.\./index\.md\#subst)__ command is often used to
support a kind of template processing\. Given a string with embedded variables or
function calls, __[subst](\.\./\.\./\.\./\.\./index\.md\#subst)__ will interpolate
the variable and function values, returning the new string:

    % set greeting "Howdy"
    Howdy
    % proc place {} {return "World"}
    % subst {$greeting, [place]!}
    Howdy, World!
    %

By defining a suitable set of Tcl commands,
__[subst](\.\./\.\./\.\./\.\./index\.md\#subst)__ can be used to implement a
markup language similar to HTML\.

The __[subst](\.\./\.\./\.\./\.\./index\.md\#subst)__ command is efficient, but it
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

    The command creates a new expander object with an associated Tcl command
    whose name is *expanderName*\. This command may be used to invoke various
    operations on the graph\. If the *expanderName* is not fully qualified it
    is interpreted as relative to the current namespace\. The command has the
    following general form:

    *expanderName* option ?*arg arg \.\.\.*?

    *Option* and the *arg*s determine the exact behavior of the command\.

The following commands are possible for expander objects:

  - <a name='2'></a>*expanderName* __cappend__ *text*








|







126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

    The command creates a new expander object with an associated Tcl command
    whose name is *expanderName*\. This command may be used to invoke various
    operations on the graph\. If the *expanderName* is not fully qualified it
    is interpreted as relative to the current namespace\. The command has the
    following general form:

    > *expanderName* option ?*arg arg \.\.\.*?

    *Option* and the *arg*s determine the exact behavior of the command\.

The following commands are possible for expander objects:

  - <a name='2'></a>*expanderName* __cappend__ *text*

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
# <a name='section3'></a>TUTORIAL

## <a name='subsection1'></a>Basics

To begin, create an expander object:

    % package require textutil::expander
    1\.2
    % ::textutil::expander myexp
    ::myexp
    %

The created __::myexp__ object can be used to expand text strings containing
embedded Tcl commands\. By default, embedded commands are delimited by square
brackets\. Note that expander doesn't attempt to interpolate variables, since
variables can be referenced by embedded commands:

    % set greeting "Howdy"
    Howdy
    % proc place \{\} \{return "World"\}
    % ::myexp expand \{\[set greeting\], \[place\]\!\}
    Howdy, World\!
    %

## <a name='subsection2'></a>Embedding Macros

An expander macro is simply a Tcl script embedded within a text string\. Expander
evaluates the script in the global context, and replaces it with its result
string\. For example,

        % set greetings \{Howdy Hi "What's up"\}
        Howdy Hi "What's up"
        % ::myexp expand \{There are many ways to say "Hello, World\!":
        \[set result \{\}
        foreach greeting $greetings \{
    	append result "$greeting, World\!\\\\n"
        \}

        set result\]
        And that's just a small sample\!\}
        There are many ways to say "Hello, World\!":
        Howdy, World\!
        Hi, World\!
        What's up, World\!

        And that's just a small sample\!
        %

## <a name='subsection3'></a>Writing Macro Commands

More typically, *macro commands* are used to create a markup language\. A macro
command is just a Tcl command that returns an output string\. For example, expand
can be used to implement a generic document markup language that can be
retargeted to HTML or any other output format:

    % proc bold \{\} \{return "<b>"\}
    % proc /bold \{\} \{return "</b>"\}
    % ::myexp expand \{Some of this text is in \[bold\]boldface\[/bold\]\}
    Some of this text is in <b>boldface</b>
    %

The above definitions of __bold__ and __/bold__ returns HTML, but such
commands can be as complicated as needed; they could, for example, decide what
to return based on the desired output format\.

## <a name='subsection4'></a>Changing the Expansion Brackets

By default, embedded macros are enclosed in square brackets, __\[__ and
__\]__\. If square brackets need to be included in the output, the input can
contain the __lb__ and __rb__ commands\. Alternatively, or if square
brackets are objectionable for some other reason, the macro expansion brackets
can be changed to any pair of non\-empty strings\.

The __setbrackets__ command changes the brackets permanently\. For example,
you can write pseudo\-html by change them to __<__ and __>__:

    % ::myexp setbrackets < >
    % ::myexp expand \{<bold>This is boldface</bold>\}
    <b>This is boldface</b>

Alternatively, you can change the expansion brackets temporarily by passing the
desired brackets to the __expand__ command:

    % ::myexp setbrackets "\\\\\[" "\\\\\]"
    % ::myexp expand \{<bold>This is boldface</bold>\} \{< >\}
    <b>This is boldface</b>
    %

## <a name='subsection5'></a>Customized Macro Expansion

By default, macros are evaluated using the Tcl __uplevel \#0__ command, so
that the embedded code executes in the global context\. The application can
provide a different evaluation command using __evalcmd__; this allows the
application to use a safe interpreter, for example, or even to evaluated
something other than Tcl code\. There is one caveat: to be recognized as valid, a
macro must return 1 when passed to Tcl's "info complete" command\.

For example, the following code "evaluates" each macro by returning the macro
text itself\.

    proc identity \{macro\} \{return $macro\}
    ::myexp evalcmd identity

## <a name='subsection6'></a>Using the Context Stack

Often it's desirable to define a pair of macros which operate in some way on the
plain text between them\. Consider a set of macros for adding footnotes to a web
page: one could have implement something like this:

    Dr\. Pangloss, however, thinks that this is the best of all
    possible worlds\.\[footnote "See Candide, by Voltaire"\]

The __footnote__ macro would, presumably, assign a number to this footnote
and save the text to be formatted later on\. However, this solution is ugly if
the footnote text is long or should contain additional markup\. Consider the
following instead:

    Dr\. Pangloss, however, thinks that this is the best of all
    possible worlds\.\[footnote\]See \[bookTitle "Candide"\], by
    \[authorsName "Voltaire"\], for more information\.\[/footnote\]

Here the footnote text is contained between __footnote__ and
__/footnote__ macros, continues onto a second line, and contains several
macros of its own\. This is both clearer and more flexible; however, with the
features presented so far there's no easy way to do it\. That's the purpose of
the context stack\.

All macro expansion takes place in a particular context\. Here, the
__footnote__ macro pushes a new context onto the context stack\. Then, all
expanded text gets placed in that new context\. __/footnote__ retrieves it by
popping the context\. Here's a skeleton implementation of these two macros:

    proc footnote \{\} \{
        ::myexp cpush footnote
    \}


    proc /footnote \{\} \{
        set footnoteText \[::myexp cpop footnote\]

        \# Save the footnote text, and return an appropriate footnote
        \# number and link\.
    \}


The __cpush__ command pushes a new context onto the stack; the argument is
the context's name\. It can be any string, but would typically be the name of the
macro itself\. Then, __cpop__ verifies that the current context has the
expected name, pops it off of the stack, and returns the accumulated text\.

Expand provides several other tools related to the context stack\. Suppose the
first macro in a context pair takes arguments or computes values which the
second macro in the pair needs\. After calling __cpush__, the first macro can
define one or more context variables; the second macro can retrieve their values
any time before calling __cpop__\. For example, suppose the document must
specify the footnote number explicitly:

    proc footnote \{footnoteNumber\} \{
        ::myexp cpush footnote
        ::myexp csave num $footnoteNumber
        \# Return an appropriate link
    \}


    proc /footnote \{\} \{
        set footnoteNumber \[::myexp cget num\]
        set footnoteText \[::myexp cpop footnote\]

        \# Save the footnote text and its footnoteNumber for future
        \# output\.
    \}


At times, it might be desirable to define macros that are valid only within a
particular context pair; such macros should verify that they are only called
within the correct context using either __cis__ or __cname__\.

# <a name='section4'></a>HISTORY








|











|
|
|








|

|
|
|
|
<
>
|
|
|
|
|
|

|









|
|
|



















|





|
|















|








|
|






|
|
|












|

<
|
>
|
|

|
|
<
>













|


|
<
|
>
|
|
|

|
|
<
>







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
# <a name='section3'></a>TUTORIAL

## <a name='subsection1'></a>Basics

To begin, create an expander object:

    % package require textutil::expander
    1.2
    % ::textutil::expander myexp
    ::myexp
    %

The created __::myexp__ object can be used to expand text strings containing
embedded Tcl commands\. By default, embedded commands are delimited by square
brackets\. Note that expander doesn't attempt to interpolate variables, since
variables can be referenced by embedded commands:

    % set greeting "Howdy"
    Howdy
    % proc place {} {return "World"}
    % ::myexp expand {[set greeting], [place]!}
    Howdy, World!
    %

## <a name='subsection2'></a>Embedding Macros

An expander macro is simply a Tcl script embedded within a text string\. Expander
evaluates the script in the global context, and replaces it with its result
string\. For example,

        % set greetings {Howdy Hi "What's up"}
        Howdy Hi "What's up"
        % ::myexp expand {There are many ways to say "Hello, World!":
        [set result {}
        foreach greeting $greetings {
    	append result "$greeting, World!\\n"

        }
        set result]
        And that's just a small sample!}
        There are many ways to say "Hello, World!":
        Howdy, World!
        Hi, World!
        What's up, World!

        And that's just a small sample!
        %

## <a name='subsection3'></a>Writing Macro Commands

More typically, *macro commands* are used to create a markup language\. A macro
command is just a Tcl command that returns an output string\. For example, expand
can be used to implement a generic document markup language that can be
retargeted to HTML or any other output format:

    % proc bold {} {return "<b>"}
    % proc /bold {} {return "</b>"}
    % ::myexp expand {Some of this text is in [bold]boldface[/bold]}
    Some of this text is in <b>boldface</b>
    %

The above definitions of __bold__ and __/bold__ returns HTML, but such
commands can be as complicated as needed; they could, for example, decide what
to return based on the desired output format\.

## <a name='subsection4'></a>Changing the Expansion Brackets

By default, embedded macros are enclosed in square brackets, __\[__ and
__\]__\. If square brackets need to be included in the output, the input can
contain the __lb__ and __rb__ commands\. Alternatively, or if square
brackets are objectionable for some other reason, the macro expansion brackets
can be changed to any pair of non\-empty strings\.

The __setbrackets__ command changes the brackets permanently\. For example,
you can write pseudo\-html by change them to __<__ and __>__:

    % ::myexp setbrackets < >
    % ::myexp expand {<bold>This is boldface</bold>}
    <b>This is boldface</b>

Alternatively, you can change the expansion brackets temporarily by passing the
desired brackets to the __expand__ command:

    % ::myexp setbrackets "\\[" "\\]"
    % ::myexp expand {<bold>This is boldface</bold>} {< >}
    <b>This is boldface</b>
    %

## <a name='subsection5'></a>Customized Macro Expansion

By default, macros are evaluated using the Tcl __uplevel \#0__ command, so
that the embedded code executes in the global context\. The application can
provide a different evaluation command using __evalcmd__; this allows the
application to use a safe interpreter, for example, or even to evaluated
something other than Tcl code\. There is one caveat: to be recognized as valid, a
macro must return 1 when passed to Tcl's "info complete" command\.

For example, the following code "evaluates" each macro by returning the macro
text itself\.

    proc identity {macro} {return $macro}
    ::myexp evalcmd identity

## <a name='subsection6'></a>Using the Context Stack

Often it's desirable to define a pair of macros which operate in some way on the
plain text between them\. Consider a set of macros for adding footnotes to a web
page: one could have implement something like this:

    Dr. Pangloss, however, thinks that this is the best of all
    possible worlds.[footnote "See Candide, by Voltaire"]

The __footnote__ macro would, presumably, assign a number to this footnote
and save the text to be formatted later on\. However, this solution is ugly if
the footnote text is long or should contain additional markup\. Consider the
following instead:

    Dr. Pangloss, however, thinks that this is the best of all
    possible worlds.[footnote]See [bookTitle "Candide"], by
    [authorsName "Voltaire"], for more information.[/footnote]

Here the footnote text is contained between __footnote__ and
__/footnote__ macros, continues onto a second line, and contains several
macros of its own\. This is both clearer and more flexible; however, with the
features presented so far there's no easy way to do it\. That's the purpose of
the context stack\.

All macro expansion takes place in a particular context\. Here, the
__footnote__ macro pushes a new context onto the context stack\. Then, all
expanded text gets placed in that new context\. __/footnote__ retrieves it by
popping the context\. Here's a skeleton implementation of these two macros:

    proc footnote {} {
        ::myexp cpush footnote

    }

    proc /footnote {} {
        set footnoteText [::myexp cpop footnote]

        # Save the footnote text, and return an appropriate footnote
        # number and link.

    }

The __cpush__ command pushes a new context onto the stack; the argument is
the context's name\. It can be any string, but would typically be the name of the
macro itself\. Then, __cpop__ verifies that the current context has the
expected name, pops it off of the stack, and returns the accumulated text\.

Expand provides several other tools related to the context stack\. Suppose the
first macro in a context pair takes arguments or computes values which the
second macro in the pair needs\. After calling __cpush__, the first macro can
define one or more context variables; the second macro can retrieve their values
any time before calling __cpop__\. For example, suppose the document must
specify the footnote number explicitly:

    proc footnote {footnoteNumber} {
        ::myexp cpush footnote
        ::myexp csave num $footnoteNumber
        # Return an appropriate link

    }

    proc /footnote {} {
        set footnoteNumber [::myexp cget num]
        set footnoteText [::myexp cpop footnote]

        # Save the footnote text and its footnoteNumber for future
        # output.

    }

At times, it might be desirable to define macros that are valid only within a
particular context pair; such macros should verify that they are only called
within the correct context using either __cis__ or __cname__\.

# <a name='section4'></a>HISTORY

Added embedded/md/tcllib/files/modules/textutil/patch.md.

























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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

[//000000001]: # (textutil::patch \- Text and string utilities)
[//000000002]: # (Generated from file 'patch\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (textutil::patch\(n\) 0\.1 tcllib "Text and string utilities")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>

# NAME

textutil::patch \- Application of uni\-diff patches to directory trees

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Synopsis](#synopsis)

  - [Description](#section1)

  - [Bugs, Ideas, Feedback](#section2)

  - [Keywords](#keywords)

  - [Category](#category)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.2  
package require textutil::patch ?0\.1?  

[__::textutil::patch::apply__ *basedirectory* *striplevel* *patch* *reportcmd*](#1)  
[__\{\*\}reportcmd__ __apply__ *filename*](#2)  
[__\{\*\}reportcmd__ __fail__ *filename* *hunk* *expected* *seen*](#3)  
[__\{\*\}reportcmd__ __fail\-already__ *filename* *hunk*](#4)  

# <a name='description'></a>DESCRIPTION

This package provides a single command which applies a patch in [unified
format](https://www\.gnu\.org/software/diffutils/manual/html\_node/Detailed\-Unified\.html)
to a directory tree\.

  - <a name='1'></a>__::textutil::patch::apply__ *basedirectory* *striplevel* *patch* *reportcmd*

    Applies the *patch* \(text of the path, not file\) to the files in the
    *basedirectory* using the specified *striplevel*\. The result of the
    command is the empty string\.

    The *striplevel* argument is equivalent to option __\-p__ of the
    __[patch](\.\./\.\./\.\./\.\./index\.md\#patch)__ command\.

    Errors are thrown when the *patch* does not parse, and nothing is done to
    the files in *basedirectory*\.

    All activities during the application of the patch, including the inability
    to apply a hunk are reported through the command prefix *reportcmd*
    instead\. Files with problems are left unchanged\. Note however that this does
    *not prevent* changes to files with no problems, before and after the
    problematic file\(s\)\.

    The command prefix is called in 3 possible forms:

      * <a name='2'></a>__\{\*\}reportcmd__ __apply__ *filename*

        The caller begins operation on file *fname*, applying all hunks
        collected for said file\.

      * <a name='3'></a>__\{\*\}reportcmd__ __fail__ *filename* *hunk* *expected* *seen*

        Application of hunk number *hunk* of file *filename* has failed\. The
        command expected to find the text *expected*, and saw *seen*
        instead\.

      * <a name='4'></a>__\{\*\}reportcmd__ __fail\-already__ *filename* *hunk*

        Application of hunk number *hunk* of file *filename* has failed\. The
        command believes that this hunk has already been applied to the file\.

# <a name='section2'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *textutil* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

When proposing code changes, please provide *unified diffs*, i\.e the output of
__diff \-u__\.

Note further that *attachments* are strongly preferred over inlined patches\.
Attachments can be made by going to the __Edit__ form of the ticket
immediately after its creation, and then using the left\-most button in the
secondary navigation bar\.

# <a name='keywords'></a>KEYWORDS

[diff \-ruN](\.\./\.\./\.\./\.\./index\.md\#diff\_run), [diff, unified
format](\.\./\.\./\.\./\.\./index\.md\#diff\_unified\_format),
[fossil](\.\./\.\./\.\./\.\./index\.md\#fossil), [git](\.\./\.\./\.\./\.\./index\.md\#git),
[patch](\.\./\.\./\.\./\.\./index\.md\#patch), [unified format
diff](\.\./\.\./\.\./\.\./index\.md\#unified\_format\_diff)

# <a name='category'></a>CATEGORY

Text processing

Changes to embedded/md/tcllib/files/modules/tie/tie.md.

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
    source](\.\./\.\./\.\./\.\./index\.md\#data\_source)* the object talks to\.

And here a small table comparing the *[data
source](\.\./\.\./\.\./\.\./index\.md\#data\_source)* methods to the regular Tcl
commands for accessing an array\.

    Regular Tcl             Data source
    \-\-\-\-\-\-\-\-\-\-\-             \-\-\-\-\-\-\-\-\-\-\-
    array names a           ds names
    array size  a           ds size
    array get   a           ds get
    array set   a dict      ds set   dict
    array unset a pattern   ds unset ?pattern?
    \-\-\-\-\-\-\-\-\-\-\-             \-\-\-\-\-\-\-\-\-\-\-
    set a\($idx\) $val        ds setv   idx val
    unset a\($idx\)           ds unsetv idx
    $a\($idx\)                ds getv   idx
    \-\-\-\-\-\-\-\-\-\-\-             \-\-\-\-\-\-\-\-\-\-\-

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *tie* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|





|
|
|
|
|







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
    source](\.\./\.\./\.\./\.\./index\.md\#data\_source)* the object talks to\.

And here a small table comparing the *[data
source](\.\./\.\./\.\./\.\./index\.md\#data\_source)* methods to the regular Tcl
commands for accessing an array\.

    Regular Tcl             Data source
    -----------             -----------
    array names a           ds names
    array size  a           ds size
    array get   a           ds get
    array set   a dict      ds set   dict
    array unset a pattern   ds unset ?pattern?
    -----------             -----------
    set a($idx) $val        ds setv   idx val
    unset a($idx)           ds unsetv idx
    $a($idx)                ds getv   idx
    -----------             -----------

# <a name='section4'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *tie* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/tiff/tiff.md.

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
    __PhotometricInterpretation__, __ImageDescription__,
    __Orientation__, __XResolution__, __YResolution__,
    __ResolutionUnit__, __DateTime__, __Artist__, and
    __HostComputer__\. The values are the associated properties of the TIFF
    ?image? in *file*\. Values may be empty if the associated tag is not
    present in the file\.

        puts \[::tiff::imageInfo photo\.tif\]

        ImageWidth 686 ImageLength 1024 BitsPerSample \{8 8 8\} Compression 1
        PhotometricInterpretation 2 ImageDescription \{\} Orientation 1
        XResolution 170\.667 YResolution 170\.667 ResolutionUnit 2 DateTime \{2005:12:28 19:44:45\}
        Artist \{\} HostComputer \{\}

    There is nothing special about these tags, this is simply a convience
    procedure which calls __getEntry__ with common entries\. Throws an error
    if *file* is not a TIFF image\.

  - <a name='6'></a>__::tiff::entries__ *file* ?image?

    Returns a list of all entries in the given *file* and ?image? in
    hexadecimal format\. Throws an error if *file* is not a TIFF image\.

  - <a name='7'></a>__::tiff::getEntry__ *file* *entry* ?image?

    Returns the value of *entry* from image ?image? in the TIFF *file*\.
    *entry* may be a list of multiple entries\. If an entry does not exist, an
    empty string is returned

        set data \[::tiff::getEntry photo\.tif \{0131 0132\}\]
        puts "file was written at \[lindex $data 0\] with software \[lindex $data 1\]"

    Throws an error if *file* is not a TIFF image\.

  - <a name='8'></a>__::tiff::addEntry__ *file* *entry* ?image?

    Adds the specified entries to the image named by ?image? \(default 0\), or
    optionally __all__\. *entry* must be a list where each element is a
    list of tag, type, and value\. If a tag already exists, it is overwritten\.

        ::tiff::addEntry photo\.tif \{\{010e 2 "an example photo"\} \{013b 2 "Aaron F"\}\}

    The data types are defined as follows

      * __1__

        BYTE \(8 bit unsigned integer\)








|

|
|
|
|
















|
|









|







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
    __PhotometricInterpretation__, __ImageDescription__,
    __Orientation__, __XResolution__, __YResolution__,
    __ResolutionUnit__, __DateTime__, __Artist__, and
    __HostComputer__\. The values are the associated properties of the TIFF
    ?image? in *file*\. Values may be empty if the associated tag is not
    present in the file\.

        puts [::tiff::imageInfo photo.tif]

        ImageWidth 686 ImageLength 1024 BitsPerSample {8 8 8} Compression 1
        PhotometricInterpretation 2 ImageDescription {} Orientation 1
        XResolution 170.667 YResolution 170.667 ResolutionUnit 2 DateTime {2005:12:28 19:44:45}
        Artist {} HostComputer {}

    There is nothing special about these tags, this is simply a convience
    procedure which calls __getEntry__ with common entries\. Throws an error
    if *file* is not a TIFF image\.

  - <a name='6'></a>__::tiff::entries__ *file* ?image?

    Returns a list of all entries in the given *file* and ?image? in
    hexadecimal format\. Throws an error if *file* is not a TIFF image\.

  - <a name='7'></a>__::tiff::getEntry__ *file* *entry* ?image?

    Returns the value of *entry* from image ?image? in the TIFF *file*\.
    *entry* may be a list of multiple entries\. If an entry does not exist, an
    empty string is returned

        set data [::tiff::getEntry photo.tif {0131 0132}]
        puts "file was written at [lindex $data 0] with software [lindex $data 1]"

    Throws an error if *file* is not a TIFF image\.

  - <a name='8'></a>__::tiff::addEntry__ *file* *entry* ?image?

    Adds the specified entries to the image named by ?image? \(default 0\), or
    optionally __all__\. *entry* must be a list where each element is a
    list of tag, type, and value\. If a tag already exists, it is overwritten\.

        ::tiff::addEntry photo.tif {{010e 2 "an example photo"} {013b 2 "Aaron F"}}

    The data types are defined as follows

      * __1__

        BYTE \(8 bit unsigned integer\)

Changes to embedded/md/tcllib/files/modules/tool/meta.md.

76
77
78
79
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
    available to a user of the class and of derived classes\.

    Note: The command is equivalent to the command __typemethod__ provided
    by the OO package __[snit](\.\./snit/snit\.md)__ for the same purpose\.

    Example

        oo::class create ActiveRecord \{
            classmethod find args \{ puts "\[self\] called with arguments: $args" \}
        \}

        oo::class create Table \{
            superclass ActiveRecord
        \}

        puts \[Table find foo bar\]
        \# ======
        \# which will write
        \# ======
        \# ::Table called with arguments: foo bar

  - <a name='3'></a>__classvariable__ ?*arg*\.\.\.?

    This command is available within instance methods\. It takes a series of
    variable names and makes them available in the method's scope\. The
    originating scope for the variables is the class \(instance\) the object
    instance belongs to\. In other words, the referenced variables are shared
    between all instances of their class\.

    Note: The command is roughly equivalent to the command __typevariable__
    provided by the OO package __[snit](\.\./snit/snit\.md)__ for the same
    purpose\. The difference is that it cannot be used in the class definition
    itself\.

    Example:

        % oo::class create Foo \{
            method bar \{z\} \{
                classvariable x y
                return \[incr x $z\],\[incr y\]
            \}
        \}


        ::Foo
        % Foo create a
        ::a
        % Foo create b
        ::b
        % a bar 2
        2,1
        % a bar 3
        5,2
        % b bar 7
        12,3
        % b bar \-1
        11,4
        % a bar 0
        11,5

  - <a name='4'></a>__link__ *method*\.\.\.

  - <a name='5'></a>__link__ \{*alias* *method*\}\.\.\.

    This command is available within instance methods\. It takes a list of method
    names and/or pairs of alias\- and method\-name and makes the named methods
    available to all instance methods without requiring the __my__ command\.

    The alias name under which the method becomes available defaults to the
    method name, except where explicitly specified through an alias/method pair\.

    Examples:

        link foo
        \# The method foo is now directly accessible as foo instead of my foo\.

        link \{bar foo\}
        \# The method foo is now directly accessible as bar\.

        link a b c
        \# The methods a, b, and c all become directly acessible under their
        \# own names\.

    The main use of this command is expected to be in instance constructors, for
    convenience, or to set up some methods for use in a mini DSL\.

  - <a name='6'></a>__ooutil::singleton__ ?*arg*\.\.\.?

    This command is a meta\-class, i\.e\. a variant of the builtin
    __oo::class__ which ensures that it creates only a single instance of
    the classes defined with it\.

    Syntax and results are like for __oo::class__\.

    Example:

        % oo::class create example \{
           self mixin singleton
           method foo \{\} \{self\}
        \}

        ::example
        % \[example new\] foo
        ::oo::Obj22
        % \[example new\] foo
        ::oo::Obj22

# <a name='section3'></a>AUTHORS

Donal Fellows, Andreas Kupries

# <a name='section4'></a>Bugs, Ideas, Feedback







|
|
<
>
|

<
>
|
|
|
|
|
















|
|

|
<
<
>
>











|


















|

|
|


|
|














|

|
<
>

|

|







76
77
78
79
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
    available to a user of the class and of derived classes\.

    Note: The command is equivalent to the command __typemethod__ provided
    by the OO package __[snit](\.\./snit/snit\.md)__ for the same purpose\.

    Example

        oo::class create ActiveRecord {
            classmethod find args { puts "[self] called with arguments: $args" }

        }
        oo::class create Table {
            superclass ActiveRecord

        }
        puts [Table find foo bar]
        # ======
        # which will write
        # ======
        # ::Table called with arguments: foo bar

  - <a name='3'></a>__classvariable__ ?*arg*\.\.\.?

    This command is available within instance methods\. It takes a series of
    variable names and makes them available in the method's scope\. The
    originating scope for the variables is the class \(instance\) the object
    instance belongs to\. In other words, the referenced variables are shared
    between all instances of their class\.

    Note: The command is roughly equivalent to the command __typevariable__
    provided by the OO package __[snit](\.\./snit/snit\.md)__ for the same
    purpose\. The difference is that it cannot be used in the class definition
    itself\.

    Example:

        % oo::class create Foo {
            method bar {z} {
                classvariable x y
                return [incr x $z],[incr y]


            }
        }
        ::Foo
        % Foo create a
        ::a
        % Foo create b
        ::b
        % a bar 2
        2,1
        % a bar 3
        5,2
        % b bar 7
        12,3
        % b bar -1
        11,4
        % a bar 0
        11,5

  - <a name='4'></a>__link__ *method*\.\.\.

  - <a name='5'></a>__link__ \{*alias* *method*\}\.\.\.

    This command is available within instance methods\. It takes a list of method
    names and/or pairs of alias\- and method\-name and makes the named methods
    available to all instance methods without requiring the __my__ command\.

    The alias name under which the method becomes available defaults to the
    method name, except where explicitly specified through an alias/method pair\.

    Examples:

        link foo
        # The method foo is now directly accessible as foo instead of my foo.

        link {bar foo}
        # The method foo is now directly accessible as bar.

        link a b c
        # The methods a, b, and c all become directly acessible under their
        # own names.

    The main use of this command is expected to be in instance constructors, for
    convenience, or to set up some methods for use in a mini DSL\.

  - <a name='6'></a>__ooutil::singleton__ ?*arg*\.\.\.?

    This command is a meta\-class, i\.e\. a variant of the builtin
    __oo::class__ which ensures that it creates only a single instance of
    the classes defined with it\.

    Syntax and results are like for __oo::class__\.

    Example:

        % oo::class create example {
           self mixin singleton
           method foo {} {self}

        }
        ::example
        % [example new] foo
        ::oo::Obj22
        % [example new] foo
        ::oo::Obj22

# <a name='section3'></a>AUTHORS

Donal Fellows, Andreas Kupries

# <a name='section4'></a>Bugs, Ideas, Feedback

Changes to embedded/md/tcllib/files/modules/tool/tool.md.

77
78
79
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

The TOOL metaclass was build with the __oo::dialect__ package, and thus can
be used as the basis for additional metaclasses\. As a metaclass, TOOL has it's
own "class" class, "object" class, and define namespace\.

    package require tool

    \# tool::class workds just like oo::class
    tool::class create myclass \{
    \}


    \# tool::define works just like oo::define
    tool::define myclass method noop \{\} \{\}

    \# tool::define and tool::class understand additional keywords
    tool::define myclass array\_ensemble mysettings mysettings \{\}

    \# And tool interoperates with oo::define
    oo::define myclass method do\_something \{\} \{ return something \}

    \# TOOL and TclOO objects are interchangeable
    oo::class create myooclass \{
      superclass myclass
    \}


Several manual pages go into more detail about specific keywords and methods\.

  - __tool::array\_ensemble__

  - __[tool::dict\_ensemble](tool\_dict\_ensemble\.md)__








|
|
<
|
>
|
|

|
|

|
|

|
|

<
>







77
78
79
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

The TOOL metaclass was build with the __oo::dialect__ package, and thus can
be used as the basis for additional metaclasses\. As a metaclass, TOOL has it's
own "class" class, "object" class, and define namespace\.

    package require tool

    # tool::class workds just like oo::class
    tool::class create myclass {

    }

    # tool::define works just like oo::define
    tool::define myclass method noop {} {}

    # tool::define and tool::class understand additional keywords
    tool::define myclass array_ensemble mysettings mysettings {}

    # And tool interoperates with oo::define
    oo::define myclass method do_something {} { return something }

    # TOOL and TclOO objects are interchangeable
    oo::class create myooclass {
      superclass myclass

    }

Several manual pages go into more detail about specific keywords and methods\.

  - __tool::array\_ensemble__

  - __[tool::dict\_ensemble](tool\_dict\_ensemble\.md)__

158
159
160
161
162
163
164
165
166
167
168
169
170


171
172
173
174
175
176
177
    __[method](\.\./\.\./\.\./\.\./index\.md\#method)__ command\.

  - <a name='6'></a>tool::define __option__ *name* *dictopts*

    Declares an option\. *dictopts* is a key/value list defining parameters for
    the option\. See __tool::option\_handling__\.

    tool::class create myclass \{
      option color \{
        post\-command: \{puts \[list %self%'s %field% is now %value%\]\}
        default: green
      \}
    \}


    myclass create foo
    foo configure color purple
    > foo's color is now purple

  - <a name='7'></a>tool::define __property__ ?branch? *field* *value*

    Defines a new leaf in the class metadata tree\. With no branch, the leaf will







|
|
|

<
<
>
>







158
159
160
161
162
163
164
165
166
167
168


169
170
171
172
173
174
175
176
177
    __[method](\.\./\.\./\.\./\.\./index\.md\#method)__ command\.

  - <a name='6'></a>tool::define __option__ *name* *dictopts*

    Declares an option\. *dictopts* is a key/value list defining parameters for
    the option\. See __tool::option\_handling__\.

    tool::class create myclass {
      option color {
        post-command: {puts [list %self%'s %field% is now %value%]}
        default: green


      }
    }
    myclass create foo
    foo configure color purple
    > foo's color is now purple

  - <a name='7'></a>tool::define __property__ ?branch? *field* *value*

    Defines a new leaf in the class metadata tree\. With no branch, the leaf will
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
    Executes a block of text within the namespace of the object\. Lines that
    begin with a \# are ignored as comments\. Commands that begin with :: are
    interpreted as calling a global command\. All other Tcl commands that lack a
    "my" prefix are given one, to allow the script to exercise internal methods\.
    This method is intended for configuration scripts, where the object's
    methods are intepreting a domain specific language\.

    tool::class myclass \{
      constructor script \{
        my Eval\_Script $script
      \}

      method node \{nodename info\} \{
        my variable node
        dict set node $nodename $info
      \}

      method get \{args\} \{
        my variable node
        return \[dict get $node $args\]
      \}
    \}


    myclass create movies \{
      \# This block of code is executed by the object
      node \{The Day the Earth Stood Still\} \{
        date: 1952
        characters: \{GORT Klatoo\}
      \}
    \}


    movies get \{The Day the Earth Stood Still\} date:
    > 1952

  - <a name='17'></a>*object* __Option\_Default__ *field*

    Computes the default value for an option\. See __tool::option\_handling__\.

# <a name='section5'></a>AUTHORS







|
|
|
<
>
|


<
>
|

|
<
<
>
>
|
|
|

|
<
<
>
>
|







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
    Executes a block of text within the namespace of the object\. Lines that
    begin with a \# are ignored as comments\. Commands that begin with :: are
    interpreted as calling a global command\. All other Tcl commands that lack a
    "my" prefix are given one, to allow the script to exercise internal methods\.
    This method is intended for configuration scripts, where the object's
    methods are intepreting a domain specific language\.

    tool::class myclass {
      constructor script {
        my Eval_Script $script

      }
      method node {nodename info} {
        my variable node
        dict set node $nodename $info

      }
      method get {args} {
        my variable node
        return [dict get $node $args]


      }
    }
    myclass create movies {
      # This block of code is executed by the object
      node {The Day the Earth Stood Still} {
        date: 1952
        characters: {GORT Klatoo}


      }
    }
    movies get {The Day the Earth Stood Still} date:
    > 1952

  - <a name='17'></a>*object* __Option\_Default__ *field*

    Computes the default value for an option\. See __tool::option\_handling__\.

# <a name='section5'></a>AUTHORS

Changes to embedded/md/tcllib/files/modules/transfer/connect.md.

220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# <a name='section3'></a>Secure connections

One way to secure connections made by objects of this package is to require the
package __[tls](\.\./\.\./\.\./\.\./index\.md\#tls)__ and then configure the
option __\-socketcmd__ to force the use of command __tls::socket__ to
open the socket\.

    \# Load and initialize tls
    package require tls
    tls::init \-cafile /path/to/ca/cert \-keyfile \.\.\.

    \# Create a connector with secure socket setup,
    transfer::connect C \-socketcmd tls::socket \.\.\.
    \.\.\.

# <a name='section4'></a>TLS Security Considerations

This package uses the __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ package to
handle the security for __https__ urls and other socket connections\.

Policy decisions like the set of protocols to support and what ciphers to use







|

|

|
|
|







220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# <a name='section3'></a>Secure connections

One way to secure connections made by objects of this package is to require the
package __[tls](\.\./\.\./\.\./\.\./index\.md\#tls)__ and then configure the
option __\-socketcmd__ to force the use of command __tls::socket__ to
open the socket\.

    # Load and initialize tls
    package require tls
    tls::init -cafile /path/to/ca/cert -keyfile ...

    # Create a connector with secure socket setup,
    transfer::connect C -socketcmd tls::socket ...
    ...

# <a name='section4'></a>TLS Security Considerations

This package uses the __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ package to
handle the security for __https__ urls and other socket connections\.

Policy decisions like the set of protocols to support and what ciphers to use
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init \-tls1 1 ;\# forcibly activate support for the TLS1 protocol

    \.\.\. your own application code \.\.\.

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *transfer* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|

|







249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol

    ... your own application code ...

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *transfer* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/transfer/receiver.md.

266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# <a name='section3'></a>Secure connections

One way to secure connections made by objects of this package is to require the
package __[tls](\.\./\.\./\.\./\.\./index\.md\#tls)__ and then configure the
option __\-socketcmd__ to force the use of command __tls::socket__ to
open the socket\.

    \# Load and initialize tls
    package require tls
    tls::init \-cafile /path/to/ca/cert \-keyfile \.\.\.

    \# Create a connector with secure socket setup,
    transfer::receiver R \-socketcmd tls::socket \.\.\.
    \.\.\.

# <a name='section4'></a>TLS Security Considerations

This package uses the __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ package to
handle the security for __https__ urls and other socket connections\.

Policy decisions like the set of protocols to support and what ciphers to use







|

|

|
|
|







266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# <a name='section3'></a>Secure connections

One way to secure connections made by objects of this package is to require the
package __[tls](\.\./\.\./\.\./\.\./index\.md\#tls)__ and then configure the
option __\-socketcmd__ to force the use of command __tls::socket__ to
open the socket\.

    # Load and initialize tls
    package require tls
    tls::init -cafile /path/to/ca/cert -keyfile ...

    # Create a connector with secure socket setup,
    transfer::receiver R -socketcmd tls::socket ...
    ...

# <a name='section4'></a>TLS Security Considerations

This package uses the __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ package to
handle the security for __https__ urls and other socket connections\.

Policy decisions like the set of protocols to support and what ciphers to use
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init \-tls1 1 ;\# forcibly activate support for the TLS1 protocol

    \.\.\. your own application code \.\.\.

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *transfer* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|

|







295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol

    ... your own application code ...

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *transfer* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/transfer/tqueue.md.

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
them\. Because otherwise everything in the system which depends on getting a
notification about the status of a request will hang in the air\. I am slowly
convincing myself that it is more sensible to trigger the relevant completion
callbacks with an error message about the queue abort, and 0 bytes transfered\.

All transfer requests are of the form

    \{type data options\.\.\.\}

where *type* is in \{__chan__, __string__\}, and *data* specifies the
information to transfer\. For __chan__ the data is the handle of the channel
containing the actual information to transfer, whereas for __string__
*data* contains directly the information to transfer\. The *options* are a
list of them and their values, and are the same as are accepted by the low\-level
copy operations of the package __[transfer::copy](copyops\.md)__\. Note







|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
them\. Because otherwise everything in the system which depends on getting a
notification about the status of a request will hang in the air\. I am slowly
convincing myself that it is more sensible to trigger the relevant completion
callbacks with an error message about the queue abort, and 0 bytes transfered\.

All transfer requests are of the form

    {type data options...}

where *type* is in \{__chan__, __string__\}, and *data* specifies the
information to transfer\. For __chan__ the data is the handle of the channel
containing the actual information to transfer, whereas for __string__
*data* contains directly the information to transfer\. The *options* are a
list of them and their values, and are the same as are accepted by the low\-level
copy operations of the package __[transfer::copy](copyops\.md)__\. Note

Changes to embedded/md/tcllib/files/modules/transfer/transmitter.md.

279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# <a name='section3'></a>Secure connections

One way to secure connections made by objects of this package is to require the
package __[tls](\.\./\.\./\.\./\.\./index\.md\#tls)__ and then configure the
option __\-socketcmd__ to force the use of command __tls::socket__ to
open the socket\.

    \# Load and initialize tls
    package require tls
    tls::init \-cafile /path/to/ca/cert \-keyfile \.\.\.

    \# Create a connector with secure socket setup,
    transfer::transmitter T \-socketcmd tls::socket \.\.\.
    \.\.\.

# <a name='section4'></a>TLS Security Considerations

This package uses the __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ package to
handle the security for __https__ urls and other socket connections\.

Policy decisions like the set of protocols to support and what ciphers to use







|

|

|
|
|







279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# <a name='section3'></a>Secure connections

One way to secure connections made by objects of this package is to require the
package __[tls](\.\./\.\./\.\./\.\./index\.md\#tls)__ and then configure the
option __\-socketcmd__ to force the use of command __tls::socket__ to
open the socket\.

    # Load and initialize tls
    package require tls
    tls::init -cafile /path/to/ca/cert -keyfile ...

    # Create a connector with secure socket setup,
    transfer::transmitter T -socketcmd tls::socket ...
    ...

# <a name='section4'></a>TLS Security Considerations

This package uses the __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ package to
handle the security for __https__ urls and other socket connections\.

Policy decisions like the set of protocols to support and what ciphers to use
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init \-tls1 1 ;\# forcibly activate support for the TLS1 protocol

    \.\.\. your own application code \.\.\.

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *transfer* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|

|







308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol

    ... your own application code ...

# <a name='section5'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *transfer* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/treeql/treeql.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (treeql \- Tree Query Language)
[//000000002]: # (Generated from file 'treeql\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Colin McCormack <coldstore@users\.sourceforge\.net>  
Copyright &copy; 2004 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (treeql\(n\) 1\.3\.1 tcllib "Tree Query Language")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (treeql \- Tree Query Language)
[//000000002]: # (Generated from file 'treeql\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2004 Colin McCormack <coldstore@users\.sourceforge\.net>)
[//000000004]: # (Copyright &copy; 2004 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000005]: # (treeql\(n\) 1\.3\.1 tcllib "Tree Query Language")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
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
         to\.

      1. The arguments used \(i\.e\. operator name and arguments\) are removed from
         the list of method arguments, and then the whole process is repeated
         from step \[1\], until the list of arguments is empty or an error
         occurred\.

            \# q is the query object\.

            q query root children get data

            \# The above query
            \# \- Resets the node set to the root node \- root
            \# \- Adds the children of root to the set \- children
            \# \- Replaces the node set with the       \- get data
            \#   values for the attribute 'data',
            \#   for all nodes in the set which
            \#   have such an attribute\.
            \# \- And returns this information\.

            \# Below we can see the same query, but rewritten
            \# to show the structure as it is seen by the query
            \# interpreter\.

            q query \\\\
        	    root \\\\
        	    children \\\\
        	    get data

    The operators of the TreeQL language available for this are explained in the
    section about [The Tree Query Language](#section3)\. This section also
    explains the term *node set* used above\.

  - <a name='3'></a>*qo* __result__







|



|
|
|
|
|
|
|
|

|
|
|

|
|
|







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
         to\.

      1. The arguments used \(i\.e\. operator name and arguments\) are removed from
         the list of method arguments, and then the whole process is repeated
         from step \[1\], until the list of arguments is empty or an error
         occurred\.

            # q is the query object.

            q query root children get data

            # The above query
            # - Resets the node set to the root node - root
            # - Adds the children of root to the set - children
            # - Replaces the node set with the       - get data
            #   values for the attribute 'data',
            #   for all nodes in the set which
            #   have such an attribute.
            # - And returns this information.

            # Below we can see the same query, but rewritten
            # to show the structure as it is seen by the query
            # interpreter.

            q query \
        	    root \
        	    children \
        	    get data

    The operators of the TreeQL language available for this are explained in the
    section about [The Tree Query Language](#section3)\. This section also
    explains the term *node set* used above\.

  - <a name='3'></a>*qo* __result__

Changes to embedded/md/tcllib/files/modules/try/tcllib_throw.md.

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  - <a name='1'></a>__::throw__ *error\_code* *error\_message*

    throw is merely a reordering of the arguments of the error command\. It
    throws an error with the indicated error code and error message\.

# <a name='section2'></a>EXAMPLES

    __throw__ \{MYERROR CODE\} "My error message"

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *try* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  - <a name='1'></a>__::throw__ *error\_code* *error\_message*

    throw is merely a reordering of the arguments of the error command\. It
    throws an error with the indicated error code and error message\.

# <a name='section2'></a>EXAMPLES

> __throw__ \{MYERROR CODE\} "My error message"

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *try* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/try/tcllib_try.md.

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
        original exception's status dictionary will be added to the new
        exception's status dictionary under the __\-during__ key\.

# <a name='section2'></a>EXAMPLES

Ensure that a file is closed no matter what:

    set f \[open /some/file/name a\]
    __try__ \{
        puts \\$f "some message"
        \# \.\.\.
    \} __finally__ \{
        close \\$f
    \}

Handle different reasons for a file to not be openable for reading:

    __try__ \{
        set f \[open /some/file/name\]
    \} __trap__ \{POSIX EISDIR\} \{\} \{
        puts "failed to open /some/file/name: it's a directory"
    \} __trap__ \{POSIX ENOENT\} \{\} \{
        puts "failed to open /some/file/name: it doesn't exist"
    \}

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *try* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|
|
|
|
|
|
|



|
|
|
|
|
|
|







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
        original exception's status dictionary will be added to the new
        exception's status dictionary under the __\-during__ key\.

# <a name='section2'></a>EXAMPLES

Ensure that a file is closed no matter what:

> set f \[open /some/file/name a\]  
> __try__ \{  
> &nbsp;&nbsp;&nbsp;&nbsp;puts \\$f "some message"  
> &nbsp;&nbsp;&nbsp;&nbsp;\# \.\.\.  
> \} __finally__ \{  
> &nbsp;&nbsp;&nbsp;&nbsp;close \\$f  
> \}

Handle different reasons for a file to not be openable for reading:

> __try__ \{  
> &nbsp;&nbsp;&nbsp;&nbsp;set f \[open /some/file/name\]  
> \} __trap__ \{POSIX EISDIR\} \{\} \{  
> &nbsp;&nbsp;&nbsp;&nbsp;puts "failed to open /some/file/name: it's a directory"  
> \} __trap__ \{POSIX ENOENT\} \{\} \{  
> &nbsp;&nbsp;&nbsp;&nbsp;puts "failed to open /some/file/name: it doesn't exist"  
> \}

# <a name='section3'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *try* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/udpcluster/udpcluster.md.

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
are open, and what protocols are expected on those ports\. Developers are free to
add any additional key/value pairs beyond those\.

Using udpcluster\.

For every service you wish to publish invoke:

    cluster::publish echo@\[cluster::macid\] \{port 10000 protocol echo\}

To query what services are available on the local network:

    set results \[cluster::search PATTERN\]
    \# And inside that result\.\.\.
    echo@LOCALMACID \{
       port 10000
       protocol echo
    \}


To unpublish a service:

    cluster::unpublish echo@\[cluster::macid\]

Results will Historical Notes:

This tool was originally known as nns::cluster, but as development progressed,
it was clear that it wasn't interacting with any of the other facilities in NNS\.

# <a name='section2'></a>Bugs, Ideas, Feedback







|



|
|
|


<
>



|







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73
74
75
76
77
are open, and what protocols are expected on those ports\. Developers are free to
add any additional key/value pairs beyond those\.

Using udpcluster\.

For every service you wish to publish invoke:

    cluster::publish echo@[cluster::macid] {port 10000 protocol echo}

To query what services are available on the local network:

    set results [cluster::search PATTERN]
    # And inside that result...
    echo@LOCALMACID {
       port 10000
       protocol echo

    }

To unpublish a service:

    cluster::unpublish echo@[cluster::macid]

Results will Historical Notes:

This tool was originally known as nns::cluster, but as development progressed,
it was clear that it wasn't interacting with any of the other facilities in NNS\.

# <a name='section2'></a>Bugs, Ideas, Feedback

Changes to embedded/md/tcllib/files/modules/units/units.md.

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

    Converts the *value* string into a floating point number, scaled to the
    specified *targetUnits*\. The *value* string may contain a number and
    units\. If units are specified, then they must be compatible with the
    *targetUnits*\. If units are not specified for the *value*, then it will
    be scaled to the target units\. For example,

        % ::units::convert "2\.3 miles" km
        3\.7014912
        % ::units::convert 300m/s miles/hour
        671\.080887616
        % ::units::convert "1\.0 m kg/s^2" newton
        1\.0
        % ::units::convert 1\.0 millimeter
        1000\.0

  - <a name='2'></a>__::units::reduce__ *unitString*

    Returns a unit string consisting of a scale factor followed by a space
    separated list of sorted and reduced primitive units\. The reduced unit
    string may include a forward\-slash \(separated from the surrounding primitive
    subunits by spaces\) indicating that the remaining subunits are in the
    denominator\. Generates an error if the *unitString* is invalid\.

        % ::units::reduce pascal
        1000\.0 gram / meter second second

  - <a name='3'></a>__::units::new__ *name* *baseUnits*

    Creates a new unit conversion with the specified name\. The new unit *name*
    must be only alphabetic \(upper or lower case\) letters\. The *baseUnits*
    string can consist of any valid units conversion string, including constant
    factors, numerator and denominator parts, units with prefixes, and
    exponents\. The baseUnits may contain any number of subunits, but it must
    reduce to primitive units\. BaseUnits could also be the string *\-primitive*
    to represent a new kind of quantity which cannot be derived from other
    units\. But you probably would not do that unless you have discovered some
    kind of new universal property\.

        % ::units::new furlong "220 yards"
        % ::units::new fortnight "14 days"
        % ::units::convert 100m/s furlongs/fortnight
        601288\.475303

# <a name='section3'></a>UNIT STRING FORMAT

Value and unit string format is quite flexible\. It is possible to define
virtually any combination of units, prefixes, and powers\. Valid unit strings
must conform to these rules\.








|
|

|
|
|
|
|










|
















|







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

    Converts the *value* string into a floating point number, scaled to the
    specified *targetUnits*\. The *value* string may contain a number and
    units\. If units are specified, then they must be compatible with the
    *targetUnits*\. If units are not specified for the *value*, then it will
    be scaled to the target units\. For example,

        % ::units::convert "2.3 miles" km
        3.7014912
        % ::units::convert 300m/s miles/hour
        671.080887616
        % ::units::convert "1.0 m kg/s^2" newton
        1.0
        % ::units::convert 1.0 millimeter
        1000.0

  - <a name='2'></a>__::units::reduce__ *unitString*

    Returns a unit string consisting of a scale factor followed by a space
    separated list of sorted and reduced primitive units\. The reduced unit
    string may include a forward\-slash \(separated from the surrounding primitive
    subunits by spaces\) indicating that the remaining subunits are in the
    denominator\. Generates an error if the *unitString* is invalid\.

        % ::units::reduce pascal
        1000.0 gram / meter second second

  - <a name='3'></a>__::units::new__ *name* *baseUnits*

    Creates a new unit conversion with the specified name\. The new unit *name*
    must be only alphabetic \(upper or lower case\) letters\. The *baseUnits*
    string can consist of any valid units conversion string, including constant
    factors, numerator and denominator parts, units with prefixes, and
    exponents\. The baseUnits may contain any number of subunits, but it must
    reduce to primitive units\. BaseUnits could also be the string *\-primitive*
    to represent a new kind of quantity which cannot be derived from other
    units\. But you probably would not do that unless you have discovered some
    kind of new universal property\.

        % ::units::new furlong "220 yards"
        % ::units::new fortnight "14 days"
        % ::units::convert 100m/s furlongs/fortnight
        601288.475303

# <a name='section3'></a>UNIT STRING FORMAT

Value and unit string format is quite flexible\. It is possible to define
virtually any combination of units, prefixes, and powers\. Valid unit strings
must conform to these rules\.

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
    string denoted by a circumflex \("^"\), followed by a integer, after the unit
    name \(or plural suffix, if there is one\)\. Negative exponents are not
    allowed\. \(Remember that the hyphen is a unit separator\.\)

## <a name='subsection1'></a>Example Valid Unit Strings

    Unit String              Reduced Unit String
    \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
    meter                    1\.0 meter
    kilometer                1000\.0 meter
    km                       1000\.0 meter
    km/s                     1000\.0 meter / second
    /microsecond             1000000\.0 / second
    /us                      1000000\.0 / second
    kg\-m/s^2                 1000\.0 gram meter / second second
    30second                 30\.0 second
    30 second                30\.0 second
    30 seconds               30\.0 second
    200\*meter/20\.5\*second    9\.75609756098 meter / second

# <a name='section4'></a>SI UNITS

The standard SI units are predefined according to *NIST Special Publication
330*\. Standard units for both SI Base Units \(Table 1\) and SI Derived Units with
Special Names \(Tables 3a and 3b\) are included here for reference\. Each standard
unit name and abbreviation are included in this package\.

## <a name='subsection2'></a>SI Base Units

    Quantity                Unit Name    Abbr\.
    \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
    Length                  meter        m
    Mass                    kilogram     kg
    Time                    second       s
    Current                 ampere       A
    Temperature             kelvin       K
    Amount                  mole         mol
    Luminous Intensity      candela      cd

## <a name='subsection3'></a>SI Derived Units with Special Names

    Quantity                Unit Name    Abbr\.   Units     Base Units
    \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
    plane angle             radian      rad     m/m       m/m
    solid angle             steradian   sr      m^2/m^2   m^2/m^2
    frequency               hertz       Hz                /s
    force                   newton      N                 m\-kg/s^2
    pressure                pascal      Pa      N/m^2     kg/m\-s^2
    energy, work            joule       J       N\-m       m^2\-kg/s^2
    power, radiant flux     watt        W       J/s       m^2\-kg/s^3
    electric charge         coulomb     C                 s\-A
    electric potential      volt        V       W/A       m^2\-kg/s^3\-A
    capacitance             farad       F       C/V       s^4\-A^2/m^2\-kg
    electric resistance     ohm                 V/A       m^2\-kg/s^3\-A^2
    electric conductance    siemens     S       A/V       s^3\-A^2/m^2\-kg
    magnetic flux           weber       Wb      V\-s       m^2\-kg/s^2\-A
    magnetic flux density   tesla       T       Wb/m^2    kg/s^2\-A
    inductance              henry       H       Wb/A      m^2\-kg/s^2\-A^2
    luminous flux           lumen       lm                cd\-sr
    illuminance             lux         lx      lm/m^2    cd\-sr/m^2
    activity \(of a
    radionuclide\)           becquerel   Bq                /s
    absorbed dose           gray        Gy      J/kg      m^2/s^2
    dose equivalent         sievert     Sv      J/kg      m^2/s^2

Note that the SI unit kilograms is actually implemented as grams because 1e\-6
kilogram = 1 milligram, not 1 microkilogram\. The abbreviation for Electric
Resistance \(ohms\), which is the omega character, is not supported\.

Also note that there is no support for Celsius or Farenheit temperature\. The
units conversion routines can only scale values with multiplication and
division, so it is not possible to convert from thermodynamic temperature
\(kelvins\) to absolute degrees Celsius or Farenheit\. Conversion of thermodynamic
quantities, such as thermal expansion \(per unit temperature\), however, are easy
to add to the units library\.

SI Units can have a multiple or sub\-multiple prefix\. The prefix or its
abbreviation should appear before the unit, without spaces\. Compound prefixes
are not allowed, and a prefix should never be used alone\. These prefixes are
defined in Table 5 of *Special Publication 330*\.

## <a name='subsection4'></a>SI Prefixes

    Prefix Name     Abbr\.   Factor
    \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
    yotta           Y       1e24
    zetta           Z       1e21
    exa             E       1e18
    peta            P       1e15
    tera            T       1e12
    giga            G       1e9
    mega            M       1e6
    kilo            k       1e3
    hecto           h       1e2
    deka            da      1e1
    deca                    1e1

    deci            d       1e\-1
    centi           c       1e\-2
    milli           m       1e\-3
    micro           u       1e\-6
    nano            n       1e\-9
    pico            p       1e\-12
    femto           f       1e\-15
    atto            a       1e\-18
    zepto           z       1e\-21
    yocto           y       1e\-24

Note that we define the same prefix with both the USA \("deka"\) and non\-USA
\("deca"\) spellings\. Also note that we take the liberty of allowing "micro" to be
typed as a "u" instead of the Greek character mu\.

Many non\-SI units are commonly used in applications\. Appendix B\.8 of *NIST
Special Publication 811* lists many non\-SI conversion factors\. It is not
possible to include all possible unit definitions in this package\. In some
cases, many different conversion factors exist for a given unit, depending on
the context\. \(The appendix lists over 40 conversions for British thermal units\!\)
Application specific conversions can always be added using the __new__
command, but some well known and often used conversions are included in this
package\.

## <a name='subsection5'></a>Non\-SI Units

    Unit Name            Abbr\.    Base Units
    \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
    angstrom                      1\.0E\-10 m
    astronomicalUnit     AU       1\.495979E11 m
    atmosphere                    1\.01325E5 Pa
    bar                           1\.0E5 Pa
    calorie                       4\.1868 J
    curie                         3\.7E10 Bq
    day                           8\.64E4 s
    degree                        1\.745329E\-2 rad
    erg                           1\.0E\-7 J
    faraday                       9\.648531 C
    fermi                         1\.0E\-15 m
    foot                 ft       3\.048E\-1 m
    gauss                         1\.0E\-4 T
    gilbert                       7\.957747E\-1 A
    grain                gr       6\.479891E\-5 kg
    hectare              ha       1\.0E4 m^2
    hour                 h        3\.6E3 s
    inch                 in       2\.54E\-2 m
    lightYear                     9\.46073E15 m
    liter                L        1\.0E\-3 m^3
    maxwell              Mx       1\.0E\-8 Wb
    mho                           1\.0 S
    micron                        1\.0E\-6 m
    mil                           2\.54E\-5 m
    mile                 mi       1\.609344E3 m
    minute               min      6\.0E1 s
    parsec               pc       3\.085E16 m
    pica                          4\.233333E\-3 m
    pound                lb       4\.535924E\-1 kg
    revolution                    6\.283185 rad
    revolutionPerMinute  rpm      1\.047198E\-1 rad/s
    yard                 yd       9\.144E\-1 m
    year                          3\.1536E7 s

## <a name='subsection6'></a>Quantities and Derived Units with Special Names

This units conversion package is limited specifically to unit reduction,
comparison, and scaling\. This package does not consider any of the quantity
names for either base or derived units\. A similar implementation or an extension
in a typed or object\-oriented language might introduce user defined types for







|
|
|
|
|
|
|
|
|
|
|
|



|
|
|
|



|
|










|
|



|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

















|



|
|












|
|
|
|
|
|
|
|
|
|
















|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







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
    string denoted by a circumflex \("^"\), followed by a integer, after the unit
    name \(or plural suffix, if there is one\)\. Negative exponents are not
    allowed\. \(Remember that the hyphen is a unit separator\.\)

## <a name='subsection1'></a>Example Valid Unit Strings

    Unit String              Reduced Unit String
    ------------------------------------------------------------
    meter                    1.0 meter
    kilometer                1000.0 meter
    km                       1000.0 meter
    km/s                     1000.0 meter / second
    /microsecond             1000000.0 / second
    /us                      1000000.0 / second
    kg-m/s^2                 1000.0 gram meter / second second
    30second                 30.0 second
    30 second                30.0 second
    30 seconds               30.0 second
    200*meter/20.5*second    9.75609756098 meter / second

# <a name='section4'></a>SI UNITS

The standard SI units are predefined according to *NIST Special* *Publication
330* \. Standard units for both SI Base Units \(Table 1\) and SI Derived Units
with Special Names \(Tables 3a and 3b\) are included here for reference\. Each
standard unit name and abbreviation are included in this package\.

## <a name='subsection2'></a>SI Base Units

    Quantity                Unit Name    Abbr.
    ---------------------------------------------
    Length                  meter        m
    Mass                    kilogram     kg
    Time                    second       s
    Current                 ampere       A
    Temperature             kelvin       K
    Amount                  mole         mol
    Luminous Intensity      candela      cd

## <a name='subsection3'></a>SI Derived Units with Special Names

    Quantity                Unit Name    Abbr.   Units     Base Units
    --------------------------------------------------------------------
    plane angle             radian      rad     m/m       m/m
    solid angle             steradian   sr      m^2/m^2   m^2/m^2
    frequency               hertz       Hz                /s
    force                   newton      N                 m-kg/s^2
    pressure                pascal      Pa      N/m^2     kg/m-s^2
    energy, work            joule       J       N-m       m^2-kg/s^2
    power, radiant flux     watt        W       J/s       m^2-kg/s^3
    electric charge         coulomb     C                 s-A
    electric potential      volt        V       W/A       m^2-kg/s^3-A
    capacitance             farad       F       C/V       s^4-A^2/m^2-kg
    electric resistance     ohm                 V/A       m^2-kg/s^3-A^2
    electric conductance    siemens     S       A/V       s^3-A^2/m^2-kg
    magnetic flux           weber       Wb      V-s       m^2-kg/s^2-A
    magnetic flux density   tesla       T       Wb/m^2    kg/s^2-A
    inductance              henry       H       Wb/A      m^2-kg/s^2-A^2
    luminous flux           lumen       lm                cd-sr
    illuminance             lux         lx      lm/m^2    cd-sr/m^2
    activity (of a
    radionuclide)           becquerel   Bq                /s
    absorbed dose           gray        Gy      J/kg      m^2/s^2
    dose equivalent         sievert     Sv      J/kg      m^2/s^2

Note that the SI unit kilograms is actually implemented as grams because 1e\-6
kilogram = 1 milligram, not 1 microkilogram\. The abbreviation for Electric
Resistance \(ohms\), which is the omega character, is not supported\.

Also note that there is no support for Celsius or Farenheit temperature\. The
units conversion routines can only scale values with multiplication and
division, so it is not possible to convert from thermodynamic temperature
\(kelvins\) to absolute degrees Celsius or Farenheit\. Conversion of thermodynamic
quantities, such as thermal expansion \(per unit temperature\), however, are easy
to add to the units library\.

SI Units can have a multiple or sub\-multiple prefix\. The prefix or its
abbreviation should appear before the unit, without spaces\. Compound prefixes
are not allowed, and a prefix should never be used alone\. These prefixes are
defined in Table 5 of *Special Publication* *330* \.

## <a name='subsection4'></a>SI Prefixes

    Prefix Name     Abbr.   Factor
    ---------------------------------------
    yotta           Y       1e24
    zetta           Z       1e21
    exa             E       1e18
    peta            P       1e15
    tera            T       1e12
    giga            G       1e9
    mega            M       1e6
    kilo            k       1e3
    hecto           h       1e2
    deka            da      1e1
    deca                    1e1

    deci            d       1e-1
    centi           c       1e-2
    milli           m       1e-3
    micro           u       1e-6
    nano            n       1e-9
    pico            p       1e-12
    femto           f       1e-15
    atto            a       1e-18
    zepto           z       1e-21
    yocto           y       1e-24

Note that we define the same prefix with both the USA \("deka"\) and non\-USA
\("deca"\) spellings\. Also note that we take the liberty of allowing "micro" to be
typed as a "u" instead of the Greek character mu\.

Many non\-SI units are commonly used in applications\. Appendix B\.8 of *NIST
Special Publication 811* lists many non\-SI conversion factors\. It is not
possible to include all possible unit definitions in this package\. In some
cases, many different conversion factors exist for a given unit, depending on
the context\. \(The appendix lists over 40 conversions for British thermal units\!\)
Application specific conversions can always be added using the __new__
command, but some well known and often used conversions are included in this
package\.

## <a name='subsection5'></a>Non\-SI Units

    Unit Name            Abbr.    Base Units
    --------------------------------------------------
    angstrom                      1.0E-10 m
    astronomicalUnit     AU       1.495979E11 m
    atmosphere                    1.01325E5 Pa
    bar                           1.0E5 Pa
    calorie                       4.1868 J
    curie                         3.7E10 Bq
    day                           8.64E4 s
    degree                        1.745329E-2 rad
    erg                           1.0E-7 J
    faraday                       9.648531 C
    fermi                         1.0E-15 m
    foot                 ft       3.048E-1 m
    gauss                         1.0E-4 T
    gilbert                       7.957747E-1 A
    grain                gr       6.479891E-5 kg
    hectare              ha       1.0E4 m^2
    hour                 h        3.6E3 s
    inch                 in       2.54E-2 m
    lightYear                     9.46073E15 m
    liter                L        1.0E-3 m^3
    maxwell              Mx       1.0E-8 Wb
    mho                           1.0 S
    micron                        1.0E-6 m
    mil                           2.54E-5 m
    mile                 mi       1.609344E3 m
    minute               min      6.0E1 s
    parsec               pc       3.085E16 m
    pica                          4.233333E-3 m
    pound                lb       4.535924E-1 kg
    revolution                    6.283185 rad
    revolutionPerMinute  rpm      1.047198E-1 rad/s
    yard                 yd       9.144E-1 m
    year                          3.1536E7 s

## <a name='subsection6'></a>Quantities and Derived Units with Special Names

This units conversion package is limited specifically to unit reduction,
comparison, and scaling\. This package does not consider any of the quantity
names for either base or derived units\. A similar implementation or an extension
in a typed or object\-oriented language might introduce user defined types for
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
types \(e\.g\., *typedef float Length*\), and target units \(expected by the C
application code\) are specified in an associative array\. Default units are also
defined for each quantity type, and are applied to any unit\-less quantity
strings\.

A units system enhanced with quantity type checking might benefit from inclusion
of other derived types which are expressed in terms of special units, as
illustrated in Table 2 of *NIST Publication 330*\. The quantity *area*, for
example, could be defined as units properly reducing to *meter^2*, although
the utility of defining a unit named *square meter* is arguable\.

# <a name='section5'></a>REFERENCES

The unit names, abbreviations, and conversion values are derived from those
published by the United States Department of Commerce Technology Administration,
National Institute of Standards and Technology \(NIST\) in *NIST Special
Publication 330: The International System of Units \(SI\)* and *NIST Special
Publication 811: Guide for the Use of the International System of Units \(SI\)*\.
Both of these publications are available \(as of December 2000\) from
[http://physics\.nist\.gov/cuu/Reference/contents\.html](http://physics\.nist\.gov/cuu/Reference/contents\.html)

The ideas behind implementation of this package is based in part on code written
in 1993 by Adrian Mariano which performed dimensional analysis of unit strings
using fixed size tables of C structs\. After going missing in the late 1990's,
Adrian's code has reappeared in the GNU Units program at
[http://www\.gnu\.org/software/units/](http://www\.gnu\.org/software/units/)







|
|
|






|
|
|







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
types \(e\.g\., *typedef float Length*\), and target units \(expected by the C
application code\) are specified in an associative array\. Default units are also
defined for each quantity type, and are applied to any unit\-less quantity
strings\.

A units system enhanced with quantity type checking might benefit from inclusion
of other derived types which are expressed in terms of special units, as
illustrated in Table 2 of *NIST Publication* *330* \. The quantity *area*,
for example, could be defined as units properly reducing to *meter^2*,
although the utility of defining a unit named *square meter* is arguable\.

# <a name='section5'></a>REFERENCES

The unit names, abbreviations, and conversion values are derived from those
published by the United States Department of Commerce Technology Administration,
National Institute of Standards and Technology \(NIST\) in *NIST Special
Publication 330: The International System of* *Units \(SI\)* and *NIST Special
Publication 811: Guide for* *the Use of the International System of Units
\(SI\)* \. Both of these publications are available \(as of December 2000\) from
[http://physics\.nist\.gov/cuu/Reference/contents\.html](http://physics\.nist\.gov/cuu/Reference/contents\.html)

The ideas behind implementation of this package is based in part on code written
in 1993 by Adrian Mariano which performed dimensional analysis of unit strings
using fixed size tables of C structs\. After going missing in the late 1990's,
Adrian's code has reappeared in the GNU Units program at
[http://www\.gnu\.org/software/units/](http://www\.gnu\.org/software/units/)

Changes to embedded/md/tcllib/files/modules/uri/uri.md.

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

The Tcl command __file normalize__ will convert the backslashes to forward
slashes\. To generate a valid __path__ for the scheme
*[file](\.\./\.\./\.\./\.\./index\.md\#file)*, the normalized filename must be
prepended with "__/__", and then any characters that do not match the
__regexp__ bracket expression

    \[a\-zA\-Z0\-9$\_\.\+\!\*'\(,\)?:@&=\-\]

must be percent\-encoded\.

The result in this example is "__/C:/Other%20Files/startup\.txt__" which is a
valid value for __path__\.

    % uri::join path /C:/Other%20Files/startup\.txt scheme file

    file:///C:/Other%20Files/startup\.txt

    % uri::split file:///C:/Other%20Files/startup\.txt

    path /C:/Other%20Files/startup\.txt scheme file

On UNIX® systems filenames begin with "__/__" which is also used as the
directory separator\. The only action needed to convert a filename to a valid
__path__ is percent\-encoding\.

# <a name='section7'></a>CREDITS








|






|

|

|

|







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

The Tcl command __file normalize__ will convert the backslashes to forward
slashes\. To generate a valid __path__ for the scheme
*[file](\.\./\.\./\.\./\.\./index\.md\#file)*, the normalized filename must be
prepended with "__/__", and then any characters that do not match the
__regexp__ bracket expression

    [a-zA-Z0-9$_.+!*'(,)?:@&=-]

must be percent\-encoded\.

The result in this example is "__/C:/Other%20Files/startup\.txt__" which is a
valid value for __path__\.

    % uri::join path /C:/Other%20Files/startup.txt scheme file

    file:///C:/Other%20Files/startup.txt

    % uri::split file:///C:/Other%20Files/startup.txt

    path /C:/Other%20Files/startup.txt scheme file

On UNIX® systems filenames begin with "__/__" which is also used as the
directory separator\. The only action needed to convert a filename to a valid
__path__ is percent\-encoding\.

# <a name='section7'></a>CREDITS

Changes to embedded/md/tcllib/files/modules/uuid/uuid.md.

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  - <a name='2'></a>__::uuid::uuid equal__ *id1* *id2*

    Compares two uuids and returns true if both arguments are the same uuid\.

# <a name='section3'></a>EXAMPLES

    % uuid::uuid generate
    b12dc22c\-5c36\-41d2\-57da\-e29d0ef5839c

# <a name='section4'></a>REFERENCES

  1. Paul J\. Leach, "UUIDs and GUIDs", February 1998\.
     \([http://www\.opengroup\.org/dce/info/draft\-leach\-uuids\-guids\-01\.txt](http://www\.opengroup\.org/dce/info/draft\-leach\-uuids\-guids\-01\.txt)\)

# <a name='section5'></a>Bugs, Ideas, Feedback







|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  - <a name='2'></a>__::uuid::uuid equal__ *id1* *id2*

    Compares two uuids and returns true if both arguments are the same uuid\.

# <a name='section3'></a>EXAMPLES

    % uuid::uuid generate
    b12dc22c-5c36-41d2-57da-e29d0ef5839c

# <a name='section4'></a>REFERENCES

  1. Paul J\. Leach, "UUIDs and GUIDs", February 1998\.
     \([http://www\.opengroup\.org/dce/info/draft\-leach\-uuids\-guids\-01\.txt](http://www\.opengroup\.org/dce/info/draft\-leach\-uuids\-guids\-01\.txt)\)

# <a name='section5'></a>Bugs, Ideas, Feedback

Changes to embedded/md/tcllib/files/modules/valtype/cc_amex.md.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::creditcard::amex validate \.\.\.\. ;\# Does nothing
    valtype::creditcard::amex validate \.\.\.\. ;\# Throws an error \(bad American Expresss creditcard number\)\.

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API








|
|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::creditcard::amex validate .... ;# Does nothing
    valtype::creditcard::amex validate .... ;# Throws an error (bad American Expresss creditcard number).

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API

Changes to embedded/md/tcllib/files/modules/valtype/cc_discover.md.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::creditcard::discover validate \.\.\.\. ;\# Does nothing
    valtype::creditcard::discover validate \.\.\.\. ;\# Throws an error \(bad Discover creditcard number\)\.

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API








|
|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::creditcard::discover validate .... ;# Does nothing
    valtype::creditcard::discover validate .... ;# Throws an error (bad Discover creditcard number).

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API

Changes to embedded/md/tcllib/files/modules/valtype/cc_mastercard.md.

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::creditcard::mastercard validate \.\.\.\. ;\# Does nothing
    valtype::creditcard::mastercard validate \.\.\.\. ;\# Throws an error \(bad Mastercard creditcard number\)\.

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API








|
|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::creditcard::mastercard validate .... ;# Does nothing
    valtype::creditcard::mastercard validate .... ;# Throws an error (bad Mastercard creditcard number).

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API

Changes to embedded/md/tcllib/files/modules/valtype/cc_visa.md.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::creditcard::visa validate \.\.\.\. ;\# Does nothing
    valtype::creditcard::visa validate \.\.\.\. ;\# Throws an error \(bad VISA creditcard number\)\.

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API








|
|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::creditcard::visa validate .... ;# Does nothing
    valtype::creditcard::visa validate .... ;# Throws an error (bad VISA creditcard number).

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API

Changes to embedded/md/tcllib/files/modules/valtype/ean13.md.

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::gs1::ean13 validate \.\.\.\. ;\# Does nothing
    valtype::gs1::ean13 validate \.\.\.\. ;\# Throws an error \(bad EAN13\)\.

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API








|
|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::gs1::ean13 validate .... ;# Does nothing
    valtype::gs1::ean13 validate .... ;# Throws an error (bad EAN13).

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API

Changes to embedded/md/tcllib/files/modules/valtype/iban.md.

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::iban validate \.\.\.\. ;\# Does nothing
    valtype::iban validate \.\.\.\. ;\# Throws an error \(bad International Bank Account Number\)\.

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API








|
|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::iban validate .... ;# Does nothing
    valtype::iban validate .... ;# Throws an error (bad International Bank Account Number).

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API

Changes to embedded/md/tcllib/files/modules/valtype/imei.md.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::imei validate \.\.\.\. ;\# Does nothing
    valtype::imei validate \.\.\.\. ;\# Throws an error \(bad International Mobile Equipment Identity \(IMEI\) number\)\.

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API








|
|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::imei validate .... ;# Does nothing
    valtype::imei validate .... ;# Throws an error (bad International Mobile Equipment Identity (IMEI) number).

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API

Changes to embedded/md/tcllib/files/modules/valtype/isbn.md.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::isbn validate \.\.\.\. ;\# Does nothing
    valtype::isbn validate \.\.\.\. ;\# Throws an error \(bad ISBN\)\.

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API








|
|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::isbn validate .... ;# Does nothing
    valtype::isbn validate .... ;# Throws an error (bad ISBN).

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API

Changes to embedded/md/tcllib/files/modules/valtype/luhn.md.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::luhn validate \.\.\.\. ;\# Does nothing
    valtype::luhn validate \.\.\.\. ;\# Throws an error \(bad luhn checkdigit\)\.

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API








|
|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::luhn validate .... ;# Does nothing
    valtype::luhn validate .... ;# Throws an error (bad luhn checkdigit).

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API

Changes to embedded/md/tcllib/files/modules/valtype/luhn5.md.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::luhn5 validate \.\.\.\. ;\# Does nothing
    valtype::luhn5 validate \.\.\.\. ;\# Throws an error \(bad luhn5 checkdigit\)\.

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API








|
|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::luhn5 validate .... ;# Does nothing
    valtype::luhn5 validate .... ;# Throws an error (bad luhn5 checkdigit).

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API

Changes to embedded/md/tcllib/files/modules/valtype/usnpi.md.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::usnpi validate \.\.\.\. ;\# Does nothing
    valtype::usnpi validate \.\.\.\. ;\# Throws an error \(bad US National Provider Identifier \(US\-NPI\) number\)\.

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API








|
|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::usnpi validate .... ;# Does nothing
    valtype::usnpi validate .... ;# Throws an error (bad US National Provider Identifier (US-NPI) number).

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API

Changes to embedded/md/tcllib/files/modules/valtype/verhoeff.md.

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::verhoeff validate \.\.\.\. ;\# Does nothing
    valtype::verhoeff validate \.\.\.\. ;\# Throws an error \(bad verhoeff checkdigit\)\.

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API








|
|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Tcl value is an integer\.

Every validation type has a __validate__ method which is used to do the
validation\. This method must take a single argument, the value to be validated;
further, it must do nothing if the value is valid, but throw an error if the
value is invalid:

    valtype::verhoeff validate .... ;# Does nothing
    valtype::verhoeff validate .... ;# Throws an error (bad verhoeff checkdigit).

The __validate__ method will always return the validated value on success,
and throw the __\-errorcode__ INVALID on error, possibly with additional
elements which provide more details about the problem\.

# <a name='section2'></a>API

Changes to embedded/md/tcllib/files/modules/virtchannel_base/cat.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (tcl::chan::cat \- Reflected/virtual channel support)
[//000000002]: # (Generated from file 'cat\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2011 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (tcl::chan::cat\(n\) 1 tcllib "Reflected/virtual channel support")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>




|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (tcl::chan::cat \- Reflected/virtual channel support)
[//000000002]: # (Generated from file 'cat\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2011 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (tcl::chan::cat\(n\) 1\.0\.3 tcllib "Reflected/virtual channel support")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require TclOO  
package require tcl::chan::core ?1?  
package require tcl::chan::cat ?1?  

[__::tcl::chan::cat__ *chan*\.\.\.](#1)  

# <a name='description'></a>DESCRIPTION

The __tcl::chan::cat__ package provides a command creating concatenation
channels\. These are non\-seekable channels owning a list of subordinate channels







|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require TclOO  
package require tcl::chan::core ?1?  
package require tcl::chan::cat ?1\.0\.3?  

[__::tcl::chan::cat__ *chan*\.\.\.](#1)  

# <a name='description'></a>DESCRIPTION

The __tcl::chan::cat__ package provides a command creating concatenation
channels\. These are non\-seekable channels owning a list of subordinate channels

Changes to embedded/md/tcllib/files/modules/virtchannel_base/halfpipe.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (tcl::chan::halfpipe \- Reflected/virtual channel support)
[//000000002]: # (Generated from file 'halfpipe\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (tcl::chan::halfpipe\(n\) 1 tcllib "Reflected/virtual channel support")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (tcl::chan::halfpipe \- Reflected/virtual channel support)
[//000000002]: # (Generated from file 'halfpipe\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009, 2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>)
[//000000004]: # (tcl::chan::halfpipe\(n\) 1\.0\.1 tcllib "Reflected/virtual channel support")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require TclOO  
package require tcl::chan::events ?1?  
package require tcl::chan::halfpipe ?1?  
package require tcl::chan::halfpipe ?1?  

[__::tcl::chan::halfpipe__ ?__\-option__ *value*\.\.\.?](#1)  
[*objectCmd* __put__ *bytes*](#2)  

# <a name='description'></a>DESCRIPTION

The __tcl::chan::halfpipe__ package provides a command creating one half of







|
<







36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.5  
package require TclOO  
package require tcl::chan::events ?1?  
package require tcl::chan::halfpipe ?1\.0\.1?  


[__::tcl::chan::halfpipe__ ?__\-option__ *value*\.\.\.?](#1)  
[*objectCmd* __put__ *bytes*](#2)  

# <a name='description'></a>DESCRIPTION

The __tcl::chan::halfpipe__ package provides a command creating one half of
122
123
124
125
126
127
128
129

# <a name='category'></a>CATEGORY

Channels

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>







|
121
122
123
124
125
126
127
128

# <a name='category'></a>CATEGORY

Channels

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2009, 2019 Andreas Kupries <andreas\_kupries@users\.sourceforge\.net>

Changes to embedded/md/tcllib/files/modules/websocket/websocket.md.

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
textual message which should be echoed back by the echo service\. A real example
would probably use the __connect__ callback to know when connection to the
remote server has been establish and would only send data at that time\.

    package require websocket
    ::websocket::loglevel debug

    proc handler \{ sock type msg \} \{
        switch \-glob \-nocase \-\- $type \{
    	co\* \{
    	    puts "Connected on $sock"
    	\}

    	te\* \{
    	    puts "RECEIVED: $msg"
    	\}

    	cl\* \-
    	dis\* \{
    	\}
        \}


    \}


    proc test \{ sock \} \{
        puts "\[::websocket::conninfo $sock type\] from \[::websocket::conninfo $sock sockname\] to \[::websocket::conninfo $sock peername\]"

        ::websocket::send $sock text "Testing, testing\.\.\."
    \}


    set sock \[::websocket::open ws://echo\.websocket\.org/ handler\]
    after 400 test $sock
    vwait forever

# <a name='section5'></a>TLS Security Considerations

This package uses the __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ package to
handle the security for __https__ urls and other socket connections\.







|
|
|

<
>
|

<
>
|
|
<
<
|
>
|
|
>
|
|

|
<
|
>
|







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
textual message which should be echoed back by the echo service\. A real example
would probably use the __connect__ callback to know when connection to the
remote server has been establish and would only send data at that time\.

    package require websocket
    ::websocket::loglevel debug

    proc handler { sock type msg } {
        switch -glob -nocase -- $type {
    	co* {
    	    puts "Connected on $sock"

    	}
    	te* {
    	    puts "RECEIVED: $msg"

    	}
    	cl* -
    	dis* {


    	}
        }

    }

    proc test { sock } {
        puts "[::websocket::conninfo $sock type] from [::websocket::conninfo $sock sockname] to [::websocket::conninfo $sock peername]"

        ::websocket::send $sock text "Testing, testing..."

    }

    set sock [::websocket::open ws://echo.websocket.org/ handler]
    after 400 test $sock
    vwait forever

# <a name='section5'></a>TLS Security Considerations

This package uses the __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ package to
handle the security for __https__ urls and other socket connections\.
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init \-tls1 1 ;\# forcibly activate support for the TLS1 protocol

    \.\.\. your own application code \.\.\.

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *websocket* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.







|

|







469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
To handle this change the applications using
__[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ must be patched, and not this
package, nor __[TLS](\.\./\.\./\.\./\.\./index\.md\#tls)__ itself\. Such a patch
may be as simple as generally activating __tls1__ support, as shown in the
example below\.

    package require tls
    tls::init -tls1 1 ;# forcibly activate support for the TLS1 protocol

    ... your own application code ...

# <a name='section6'></a>Bugs, Ideas, Feedback

This document, and the package it describes, will undoubtedly contain bugs and
other problems\. Please report such in the category *websocket* of the [Tcllib
Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas
for enhancements you may have for either package and/or documentation\.

Changes to embedded/md/tcllib/files/modules/yaml/huddle.md.

1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (huddle \- HUDDLE)
[//000000002]: # (Generated from file 'huddle\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2008\-2011 KATO Kanryu <kanryu6@users\.sourceforge\.net>  
Copyright &copy; 2015 Miguel Martínez López <aplicacionamedida@gmail\.com>)
[//000000004]: # (huddle\(n\) 0\.3 tcllib "HUDDLE")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13

[//000000001]: # (huddle \- HUDDLE)
[//000000002]: # (Generated from file 'huddle\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2008\-2011 KATO Kanryu <kanryu6@users\.sourceforge\.net>)
[//000000004]: # (Copyright &copy; 2015 Miguel Martínez López <aplicacionamedida@gmail\.com>)
[//000000005]: # (huddle\(n\) 0\.3 tcllib "HUDDLE")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
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
When converting huddle\-notation to other serialization formats like JSON or YAML
this type information is used to select the proper notation\. And when going from
JSON/YAML/\.\.\. to huddle their notation can be used to select the proper huddle
type\.

In that manner huddle can serve as a common intermediary format\.

    huddle\-format: >
      \{HUDDLE \{huddle\-node\}\}
    huddle\-node: >
      \{tag content\}
    each content of tag means:
      s: \(content is a\) string
      L: list, each sub node is a huddle\-node
      D: dict, each sub node is a huddle\-node
    confirmed:
      \- JSON
      \- YAML\(generally, but cannot discribe YAML\-tags\)
    limitation:
      \- cannot discribe aliases from a node to other node\.

The __huddle__ package returns data as a Tcl
__[dict](\.\./\.\./\.\./\.\./index\.md\#dict)__\. Either the
__[dict](\.\./\.\./\.\./\.\./index\.md\#dict)__ package or Tcl 8\.5 is required for
use\.

# <a name='section2'></a>COMMANDS







|
|
|
|

|
|
|

|
|

|







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
When converting huddle\-notation to other serialization formats like JSON or YAML
this type information is used to select the proper notation\. And when going from
JSON/YAML/\.\.\. to huddle their notation can be used to select the proper huddle
type\.

In that manner huddle can serve as a common intermediary format\.

    huddle-format: >
      {HUDDLE {huddle-node}}
    huddle-node: >
      {tag content}
    each content of tag means:
      s: (content is a) string
      L: list, each sub node is a huddle-node
      D: dict, each sub node is a huddle-node
    confirmed:
      - JSON
      - YAML(generally, but cannot discribe YAML-tags)
    limitation:
      - cannot discribe aliases from a node to other node.

The __huddle__ package returns data as a Tcl
__[dict](\.\./\.\./\.\./\.\./index\.md\#dict)__\. Either the
__[dict](\.\./\.\./\.\./\.\./index\.md\#dict)__ package or Tcl 8\.5 is required for
use\.

# <a name='section2'></a>COMMANDS
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
    Almost the same as __dict remove__\. Remove a sub\-object from the huddle
    object\. *key* can be used to huddle\-list's index\.

  - <a name='13'></a>__huddle combine__ *object1* *object2* ?*object3 \.\.\.*?

    Merging huddle objects given\.

    % set aa \[huddle create a b c d\]
    HUDDLE \{D \{a \{s b\} c \{s d\}\}\}
    % set bb \[huddle create a k l m\]
    HUDDLE \{D \{a \{s k\} l \{s m\}\}\}
    % huddle combine $aa $bb
    HUDDLE \{D \{a \{s k\} c \{s d\} l \{s m\}\}\}

  - <a name='14'></a>__huddle equal__ *object1* *object2*

    Comparing two huddle objects recursively\. When to equal, returns 1,
    otherwise 0\.

    % set aa \[huddle create a b c d\]
    HUDDLE \{D \{a \{s b\} c \{s d\}\}\}
    % set bb \[huddle create c d a b\]
    HUDDLE \{D \{c \{s d\} a \{s b\}\}\}
    % huddle equal $aa $bb
    1

  - <a name='15'></a>__huddle append__ *objectVar* *key* *value* ?*key value \.\.\.*?

  - <a name='16'></a>__huddle append__ *objectVar* *value* ?*value \.\.\.*?

    Appending child elements\. When for dicts, giving key/value\. When for lists,
    giving values\.

    % set aa \[huddle create a b c d\]
    HUDDLE \{D \{a \{s b\} c \{s d\}\}\}
    % huddle append aa a k l m
    HUDDLE \{D \{a \{s k\} c \{s d\} l \{s m\}\}\}
    % set bb \[huddle list i j k l\]
    HUDDLE \{L \{\{s i\} \{s j\} \{s k\} \{s l\}\}\}
    % huddle append bb g h i
    HUDDLE \{L \{\{s i\} \{s j\} \{s k\} \{s l\} \{s g\} \{s h\} \{s i\}\}\}

  - <a name='17'></a>__huddle keys__ *object*

    The same as __dict keys__\.

  - <a name='18'></a>__huddle llength__ *object*








|
|
|
|

|






|
|
|
|










|
|

|
|
|

|







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
    Almost the same as __dict remove__\. Remove a sub\-object from the huddle
    object\. *key* can be used to huddle\-list's index\.

  - <a name='13'></a>__huddle combine__ *object1* *object2* ?*object3 \.\.\.*?

    Merging huddle objects given\.

    % set aa [huddle create a b c d]
    HUDDLE {D {a {s b} c {s d}}}
    % set bb [huddle create a k l m]
    HUDDLE {D {a {s k} l {s m}}}
    % huddle combine $aa $bb
    HUDDLE {D {a {s k} c {s d} l {s m}}}

  - <a name='14'></a>__huddle equal__ *object1* *object2*

    Comparing two huddle objects recursively\. When to equal, returns 1,
    otherwise 0\.

    % set aa [huddle create a b c d]
    HUDDLE {D {a {s b} c {s d}}}
    % set bb [huddle create c d a b]
    HUDDLE {D {c {s d} a {s b}}}
    % huddle equal $aa $bb
    1

  - <a name='15'></a>__huddle append__ *objectVar* *key* *value* ?*key value \.\.\.*?

  - <a name='16'></a>__huddle append__ *objectVar* *value* ?*value \.\.\.*?

    Appending child elements\. When for dicts, giving key/value\. When for lists,
    giving values\.

    % set aa [huddle create a b c d]
    HUDDLE {D {a {s b} c {s d}}}
    % huddle append aa a k l m
    HUDDLE {D {a {s k} c {s d} l {s m}}}
    % set bb [huddle list i j k l]
    HUDDLE {L {{s i} {s j} {s k} {s l}}}
    % huddle append bb g h i
    HUDDLE {L {{s i} {s j} {s k} {s l} {s g} {s h} {s i}}}

  - <a name='17'></a>__huddle keys__ *object*

    The same as __dict keys__\.

  - <a name='18'></a>__huddle llength__ *object*

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

        the node is a boolean\.

      * ____null____

        the node is a null\.

    % huddle type \{HUDDLE \{s str\}\}
    string
    % huddle type \{HUDDLE \{L \{\{s a\} \{s b\} \{s c\}\}\}\}
    list
    % huddle type \{HUDDLE \{D \{aa \{s b\} cc \{s d\}\}\}\} cc
    string

  - <a name='20'></a>__huddle strip__ *object*

    Stripped all tags\. Converted to normal Tcl's list/dict\.

  - <a name='21'></a>__huddle jsondump__ *object* ?*offset*? ?*newline*? ?*begin\_offset*?

    dump a json\-stream from the huddle\-object\.

      * ____offset__ ""__

        begin offset as spaces " "\.

    \# normal output has some indents\. some strings are escaped\.
    % huddle jsondump \{HUDDLE \{L \{\{L \{\{s i\} \{s baa\} \{s \\\\k\} \{L \{\{s 1\.0\} \{s true\} \{s /g\} \{s h\}\}\} \{L \{\{s g\}\}\}\}\} \{s t\}\}\}\}
    \[
      \[


        "i",
        "baa",
        "\\\\k",
        \[

          1\.0,
          true,
          "\\/g",
          "h"
        \],
        \["g"\]
      \],
      "t"
    \]

    \# stripped output
    % huddle jsondump \{HUDDLE \{D \{dd \{D \{bb \{D \{a \{s baa\} c \{s \{d
    a\}\}\}\} cc \{D \{g \{s h\}\}\}\}\} ee \{D \{i \{s j\} k \{s 1\} j \{s \{ m\\a\}\}\}\}\}\}\} "" ""
    \{"dd": \{"bb": \{"a": "baa","c": "d\\na"\},"cc": \{"g": "h"\}\},"ee": \{"i": "j","k": 1,"j": " m\\\\a"\}\}

  - <a name='22'></a>__huddle compile__ *spec* *data*

    construct a huddle object from plain old tcl values\. *spec* is defined as
    follows:

      * __string__







|

|

|














|
|
<
<
>
>


|
<
>
|

|

|
|
|

<
>
|
|
|
|







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

        the node is a boolean\.

      * ____null____

        the node is a null\.

    % huddle type {HUDDLE {s str}}
    string
    % huddle type {HUDDLE {L {{s a} {s b} {s c}}}}
    list
    % huddle type {HUDDLE {D {aa {s b} cc {s d}}}} cc
    string

  - <a name='20'></a>__huddle strip__ *object*

    Stripped all tags\. Converted to normal Tcl's list/dict\.

  - <a name='21'></a>__huddle jsondump__ *object* ?*offset*? ?*newline*? ?*begin\_offset*?

    dump a json\-stream from the huddle\-object\.

      * ____offset__ ""__

        begin offset as spaces " "\.

    # normal output has some indents. some strings are escaped.
    % huddle jsondump {HUDDLE {L {{L {{s i} {s baa} {s \\k} {L {{s 1.0} {s true} {s /g} {s h}}} {L {{s g}}}}} {s t}}}}


    [
      [
        "i",
        "baa",
        "\\k",

        [
          1.0,
          true,
          "\/g",
          "h"
        ],
        ["g"]
      ],
      "t"

    ]
    # stripped output
    % huddle jsondump {HUDDLE {D {dd {D {bb {D {a {s baa} c {s {d
    a}}}} cc {D {g {s h}}}}} ee {D {i {s j} k {s 1} j {s { m\a}}}}}}} "" ""
    {"dd": {"bb": {"a": "baa","c": "d\na"},"cc": {"g": "h"}},"ee": {"i": "j","k": 1,"j": " m\\a"}}

  - <a name='22'></a>__huddle compile__ *spec* *data*

    construct a huddle object from plain old tcl values\. *spec* is defined as
    follows:

      * __string__
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

        data is a tcl dict where the value of key xx is a tcl list

      * dict \* list

        data is a tcl dict of lists *data* is plain old tcl values

    % huddle compile \{dict \* list\} \{a \{1 2 3\} b \{4 5\}\}
    HUDDLE \{D \{a \{L \{\{s 1\} \{s 2\} \{s 3\}\}\} b \{L \{\{s 4\} \{s 5\}\}\}\}\}
    % huddle compile \{dict \* \{list \{dict d list\}\}\} \{a \{\{c 1\} \{d \{2 2 2\} e 3\}\} b \{\{f 4 g 5\}\}\}
    HUDDLE \{D \{a \{L \{\{D \{c \{s 1\}\}\} \{D \{d \{L \{\{s 2\} \{s 2\} \{s 2\}\}\} e \{s 3\}\}\}\}\} b \{L \{\{D \{f \{s 4\} g \{s 5\}\}\}\}\}\}\}

  - <a name='23'></a>__huddle isHuddle__ *object*

    if *object* is a huddle, returns 1\. the other, returns 0\.

  - <a name='24'></a>__huddle checkHuddle__ *object*

    if *object* is not a huddle, rises an error\.

  - <a name='25'></a>__huddle to\_node__ *object* ?*tag*?

    for type\-callbacks\.

    if *object* is a huddle, returns root\-node\. the other, returns __\[list s
    $object\]__\.

    % huddle to\_node str
    s str
    % huddle to\_node str \!\!str
    \!\!str str
    % huddle to\_node \{HUDDLE \{s str\}\}
    s str
    % huddle to\_node \{HUDDLE \{l \{a b c\}\}\}
    l \{a b c\}

  - <a name='26'></a>__huddle wrap__ *tag* *src*

    for type\-callbacks\.

    Create a huddle object from *src* with specified *tag*\.

    % huddle wrap "" str
    HUDDLE str
    % huddle wrap s str
    HUDDLE \{s str\}

  - <a name='27'></a>__huddle call__ *tag* *command* *args*

    for type\-callbacks\.

    devolving *command* to default *tag*\-callback








|
|
|
|
















|

|
|
|

|
|










|







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

        data is a tcl dict where the value of key xx is a tcl list

      * dict \* list

        data is a tcl dict of lists *data* is plain old tcl values

    % huddle compile {dict * list} {a {1 2 3} b {4 5}}
    HUDDLE {D {a {L {{s 1} {s 2} {s 3}}} b {L {{s 4} {s 5}}}}}
    % huddle compile {dict * {list {dict d list}}} {a {{c 1} {d {2 2 2} e 3}} b {{f 4 g 5}}}
    HUDDLE {D {a {L {{D {c {s 1}}} {D {d {L {{s 2} {s 2} {s 2}}} e {s 3}}}}} b {L {{D {f {s 4} g {s 5}}}}}}}

  - <a name='23'></a>__huddle isHuddle__ *object*

    if *object* is a huddle, returns 1\. the other, returns 0\.

  - <a name='24'></a>__huddle checkHuddle__ *object*

    if *object* is not a huddle, rises an error\.

  - <a name='25'></a>__huddle to\_node__ *object* ?*tag*?

    for type\-callbacks\.

    if *object* is a huddle, returns root\-node\. the other, returns __\[list s
    $object\]__\.

    % huddle to_node str
    s str
    % huddle to_node str !!str
    !!str str
    % huddle to_node {HUDDLE {s str}}
    s str
    % huddle to_node {HUDDLE {l {a b c}}}
    l {a b c}

  - <a name='26'></a>__huddle wrap__ *tag* *src*

    for type\-callbacks\.

    Create a huddle object from *src* with specified *tag*\.

    % huddle wrap "" str
    HUDDLE str
    % huddle wrap s str
    HUDDLE {s str}

  - <a name='27'></a>__huddle call__ *tag* *command* *args*

    for type\-callbacks\.

    devolving *command* to default *tag*\-callback

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
  - <a name='34'></a>__[remove](\.\./\.\./\.\./\.\./index\.md\#remove)__ *src* *key* *value*

    removes a sub\-node from the tagged\-content, and returns self\.

__strip__ must be defined at all types\. __get\_sub__ must be defined at
container types\. __set/remove__ shuould be defined, if you call them\.

    \# callback sample for my\-dict
    proc my\_dict\_setting \{command args\} \{
        switch \-\- $command \{
            setting \{ ; \# type definition
                return \{
                    type dict
                    method \{create keys\}
                    tag \{d child D parent\}
                    constructor create
                    str s
                \}

                \# type:   the type\-name
                \# method: add methods to huddle's subcommand\.
                \#          "get\_sub/strip/set/remove/equal/append" called by huddle module\.
                \#          "strip" must be defined at all types\.
                \#          "get\_sub" must be defined at container types\.
                \#          "set/remove/equal/append" shuould be defined, if you call them\.
                \# tag:    tag definition\("child/parent" word is maybe obsoleted\)
            \}

            get\_sub \{ ; \# get a sub\-node specified by "key" from the tagged\-content
                foreach \{src key\} $args break
                return \[dict get $src $key\]
            \}

            strip \{ ; \# strip from the tagged\-content
                foreach \{src nop\} $args break
                foreach \{key val\} $src \{
                    lappend result $key \[huddle strip $val\]
                \}

                return $result
            \}

            set \{ ; \# set a sub\-node from the tagged\-content
                foreach \{src key value\} $args break
                dict set src $key $value
                return $src
            \}

            remove \{ ; \# remove a sub\-node from the tagged\-content
                foreach \{src key value\} $args break
                return \[dict remove $src $key\]
            \}

            equal \{ ; \# check equal for each node
                foreach \{src1 src2\} $args break
                if \{\[llength $src1\] \!= \[llength $src2\]\} \{return 0\}
                foreach \{key1 val1\} $src1 \{
                    if \{\!\[dict exists $src2 $key1\]\} \{return 0\}
                    if \{\!\[huddle \_equal\_subs $val1 \[dict get $src2 $key1\]\]\} \{return 0\}
                \}

                return 1
            \}

            append \{ ; \# append nodes
                foreach \{str src list\} $args break
                if \{\[llength $list\] % 2\} \{error \{wrong \# args: should be "huddle append objvar ?key value \.\.\.?"\}\}
                set resultL $src
                foreach \{key value\} $list \{
                    if \{$str ne ""\} \{
                        lappend resultL $key \[huddle to\_node $value $str\]
                    \} else \{
                        lappend resultL $key $value
                    \}
                \}


                return \[eval dict create $resultL\]
            \}

            create \{ ; \# $args: all arguments after "huddle create"
                if \{\[llength $args\] % 2\} \{error \{wrong \# args: should be "huddle create ?key value \.\.\.?"\}\}
                set resultL \{\}
                foreach \{key value\} $args \{
                    lappend resultL $key \[huddle to\_node $value\]
                \}

                return \[huddle wrap D $resultL\]
            \}

            keys \{
                foreach \{src nop\} $args break
                return \[dict keys \[lindex \[lindex $src 1\] 1\]\]
            \}

            default \{
                error "$command is not callback for dict"
            \}
        \}
    \}




    \# inheritance sample from default dict\-callback
    proc ::yaml::\_huddle\_mapping \{command args\} \{
        switch \-\- $command \{
            setting \{ ; \# type definition
                return \{
                    type dict
                    method \{mapping\}
                    tag \{\!\!map parent\}
                    constructor mapping
                    str \!\!str
                \}
            \}


            mapping \{ ; \# $args: all arguments after "huddle mapping"
                if \{\[llength $args\] % 2\} \{error \{wrong \# args: should be "huddle mapping ?key value \.\.\.?"\}\}
                set resultL \{\}
                foreach \{key value\} $args \{
                    lappend resultL $key \[huddle to\_node $value \!\!str\]
                \}

                return \[huddle wrap \!\!map $resultL\]
            \}

            default \{ ; \# devolving to default dict\-callback
                return \[huddle call D $command $args\]
            \}
        \}
    \}




# <a name='section4'></a>How to add type

You can add huddle\-node types e\.g\. ::struct::tree\. To do so, first, define a
callback\-procedure for additional tagged\-type\. The proc get argments as
*command* and ?*args*?\. It has some switch\-sections\.

And, addType subcommand will called\.

    huddle addType my\_dict\_setting

# <a name='section5'></a>WORKING SAMPLE

    \# create as a dict
    % set bb \[huddle create a b c d\]
    HUDDLE \{D \{a \{s b\} c \{s d\}\}\}

    \# create as a list
    % set cc \[huddle list e f g h\]
    HUDDLE \{L \{\{s e\} \{s f\} \{s g\} \{s h\}\}\}
    % set bbcc \[huddle create bb $bb cc $cc\]
    HUDDLE \{D \{bb \{D \{a \{s b\} c \{s d\}\}\} cc \{L \{\{s e\} \{s f\} \{s g\} \{s h\}\}\}\}\}
    % set folding \[huddle list $bbcc p \[huddle list q r\] s\]
    HUDDLE \{L \{\{D \{bb \{D \{a \{s b\} c \{s d\}\}\} cc \{L \{\{s e\} \{s f\} \{s g\} \{s h\}\}\}\}\} \{s p\} \{L \{\{s q\} \{s r\}\}\} \{s s\}\}\}

    \# normal Tcl's notation
    % huddle strip $folding
    \{bb \{a b c d\} cc \{e f g h\}\} p \{q r\} s

    \# get a sub node
    % huddle get $folding 0 bb
    HUDDLE \{D \{a \{s b\} c \{s d\}\}\}
    % huddle gets $folding 0 bb
    a b c d

    \# overwrite a node
    % huddle set folding 0 bb c kkk
    HUDDLE \{L \{\{D \{bb \{D \{a \{s b\} c \{s kkk\}\}\} cc \{L \{\{s e\} \{s f\} \{s g\} \{s h\}\}\}\}\} \{s p\} \{L \{\{s q\} \{s r\}\}\} \{s s\}\}\}

    \# remove a node
    % huddle remove $folding 2 1
    HUDDLE \{L \{\{D \{bb \{D \{a \{s b\} c \{s kkk\}\}\} cc \{L \{\{s e\} \{s f\} \{s g\} \{s h\}\}\}\}\} \{s p\} \{L \{\{s q\}\}\} \{s s\}\}\}
    % huddle strip $folding
    \{bb \{a b c kkk\} cc \{e f g h\}\} p \{q r\} s

    \# dump as a JSON stream
    % huddle jsondump $folding
    \[
      \{


        "bb": \{
          "a": "b",
          "c": "kkk"
        \},
        "cc": \[
          "e",
          "f",
          "g",
          "h"
        \]

      \},
      "p",
      \[

        "q",
        "r"
      \],
      "s"
    \]


# <a name='section6'></a>LIMITATIONS

now printing\.

# <a name='section7'></a>Bugs, Ideas, Feedback








|
|
|
|
|

|
|


<
>
|
|
|
|
|
|
|
<
>
|
|
|
<
>
|
|
|
|
<
>

<
>
|
|


<
>
|
|
|
<
>
|
|
|
|
|
|
<
>

<
>
|
|
|

|
|
|
|

<
<
>
>
|
<
>
|
|
|
|
|
<
>
|
<
>
|
|
|
<
>
|

<
<
<
|
>
>
>
|
|
|
|
|

|
|

|
<
<
>
>
|
|
|
|
|
<
>
|
<
>
|
|
<
<
<
>
>
>









|



|
|
|

|
|
|
|
|
|
|

|

|

|

|



|

|

|

|

|

|

<
<
>
>
|


|
|




<
>
|

<
>


|

<
>







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
  - <a name='34'></a>__[remove](\.\./\.\./\.\./\.\./index\.md\#remove)__ *src* *key* *value*

    removes a sub\-node from the tagged\-content, and returns self\.

__strip__ must be defined at all types\. __get\_sub__ must be defined at
container types\. __set/remove__ shuould be defined, if you call them\.

    # callback sample for my-dict
    proc my_dict_setting {command args} {
        switch -- $command {
            setting { ; # type definition
                return {
                    type dict
                    method {create keys}
                    tag {d child D parent}
                    constructor create
                    str s

                }
                # type:   the type-name
                # method: add methods to huddle's subcommand.
                #          "get_sub/strip/set/remove/equal/append" called by huddle module.
                #          "strip" must be defined at all types.
                #          "get_sub" must be defined at container types.
                #          "set/remove/equal/append" shuould be defined, if you call them.
                # tag:    tag definition("child/parent" word is maybe obsoleted)

            }
            get_sub { ; # get a sub-node specified by "key" from the tagged-content
                foreach {src key} $args break
                return [dict get $src $key]

            }
            strip { ; # strip from the tagged-content
                foreach {src nop} $args break
                foreach {key val} $src {
                    lappend result $key [huddle strip $val]

                }
                return $result

            }
            set { ; # set a sub-node from the tagged-content
                foreach {src key value} $args break
                dict set src $key $value
                return $src

            }
            remove { ; # remove a sub-node from the tagged-content
                foreach {src key value} $args break
                return [dict remove $src $key]

            }
            equal { ; # check equal for each node
                foreach {src1 src2} $args break
                if {[llength $src1] != [llength $src2]} {return 0}
                foreach {key1 val1} $src1 {
                    if {![dict exists $src2 $key1]} {return 0}
                    if {![huddle _equal_subs $val1 [dict get $src2 $key1]]} {return 0}

                }
                return 1

            }
            append { ; # append nodes
                foreach {str src list} $args break
                if {[llength $list] % 2} {error {wrong # args: should be "huddle append objvar ?key value ...?"}}
                set resultL $src
                foreach {key value} $list {
                    if {$str ne ""} {
                        lappend resultL $key [huddle to_node $value $str]
                    } else {
                        lappend resultL $key $value


                    }
                }
                return [eval dict create $resultL]

            }
            create { ; # $args: all arguments after "huddle create"
                if {[llength $args] % 2} {error {wrong # args: should be "huddle create ?key value ...?"}}
                set resultL {}
                foreach {key value} $args {
                    lappend resultL $key [huddle to_node $value]

                }
                return [huddle wrap D $resultL]

            }
            keys {
                foreach {src nop} $args break
                return [dict keys [lindex [lindex $src 1] 1]]

            }
            default {
                error "$command is not callback for dict"



            }
        }
    }

    # inheritance sample from default dict-callback
    proc ::yaml::_huddle_mapping {command args} {
        switch -- $command {
            setting { ; # type definition
                return {
                    type dict
                    method {mapping}
                    tag {!!map parent}
                    constructor mapping
                    str !!str


                }
            }
            mapping { ; # $args: all arguments after "huddle mapping"
                if {[llength $args] % 2} {error {wrong # args: should be "huddle mapping ?key value ...?"}}
                set resultL {}
                foreach {key value} $args {
                    lappend resultL $key [huddle to_node $value !!str]

                }
                return [huddle wrap !!map $resultL]

            }
            default { ; # devolving to default dict-callback
                return [huddle call D $command $args]



            }
        }
    }

# <a name='section4'></a>How to add type

You can add huddle\-node types e\.g\. ::struct::tree\. To do so, first, define a
callback\-procedure for additional tagged\-type\. The proc get argments as
*command* and ?*args*?\. It has some switch\-sections\.

And, addType subcommand will called\.

    huddle addType my_dict_setting

# <a name='section5'></a>WORKING SAMPLE

    # create as a dict
    % set bb [huddle create a b c d]
    HUDDLE {D {a {s b} c {s d}}}

    # create as a list
    % set cc [huddle list e f g h]
    HUDDLE {L {{s e} {s f} {s g} {s h}}}
    % set bbcc [huddle create bb $bb cc $cc]
    HUDDLE {D {bb {D {a {s b} c {s d}}} cc {L {{s e} {s f} {s g} {s h}}}}}
    % set folding [huddle list $bbcc p [huddle list q r] s]
    HUDDLE {L {{D {bb {D {a {s b} c {s d}}} cc {L {{s e} {s f} {s g} {s h}}}}} {s p} {L {{s q} {s r}}} {s s}}}

    # normal Tcl's notation
    % huddle strip $folding
    {bb {a b c d} cc {e f g h}} p {q r} s

    # get a sub node
    % huddle get $folding 0 bb
    HUDDLE {D {a {s b} c {s d}}}
    % huddle gets $folding 0 bb
    a b c d

    # overwrite a node
    % huddle set folding 0 bb c kkk
    HUDDLE {L {{D {bb {D {a {s b} c {s kkk}}} cc {L {{s e} {s f} {s g} {s h}}}}} {s p} {L {{s q} {s r}}} {s s}}}

    # remove a node
    % huddle remove $folding 2 1
    HUDDLE {L {{D {bb {D {a {s b} c {s kkk}}} cc {L {{s e} {s f} {s g} {s h}}}}} {s p} {L {{s q}}} {s s}}}
    % huddle strip $folding
    {bb {a b c kkk} cc {e f g h}} p {q r} s

    # dump as a JSON stream
    % huddle jsondump $folding


    [
      {
        "bb": {
          "a": "b",
          "c": "kkk"
        },
        "cc": [
          "e",
          "f",
          "g",
          "h"

        ]
      },
      "p",

      [
        "q",
        "r"
      ],
      "s"

    ]

# <a name='section6'></a>LIMITATIONS

now printing\.

# <a name='section7'></a>Bugs, Ideas, Feedback

Changes to embedded/md/tcllib/files/modules/yaml/yaml.md.

78
79
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
        *txt* is just a YAML\-stream\.

      * ____\-types__ *list*__

        The *list* is a type list for the yaml\-scalar types\.\(e\.g\. \!\!str
        \!\!timestamp \!\!integer \!\!true \.\.\.\)

            \-types \{timestamp integer null true false\}

        In this case, if a string matched "timestamp", converted to the TCL
        internal timestamp\.\(e\.g\. "2001\-12\-15T02:59:43\.1Z" => 1008385183\)

      * ____\-m:true__ *param*__

        The *param* is two elements of list for the value of true, and
        considered strings\.

            \-m:true \{1 \{true on \+ yes y\}\}

        In this case, the string "yes" found in YAML Stream, automatically
        converted 1\.

      * ____\-m:false__ *param*__

        The *param* is two elements of list for the value of false, and
        considered strings\.

            \-m:false \{0 \{false off \- no n\}\}

      * ____\-m:null__ *param*__

        The *param* is two elements of list for the value of null, and
        considered strings\.

            \-m:null \{"" \{null nil "" ~\}\}

      * ____\-validate____

        Experiment,old: Output stream contains YAML's\-tag, each node\.

            % puts \[::yaml::load \-validate \{\[aaa, bbb\]\}\]
            =>
            \!\!seq \{\{\!\!str aaa\} \{\!\!str bbb\}\}

  - <a name='3'></a>__::yaml::setOption__ ?*options*?

    Change implicit options for the library\. Now, the params are the same as
    __::yaml::yaml2dict__\. Arguments of__::yaml::yaml2dict__ is more
    priority than this setting\.








|









|









|






|





|

|







78
79
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
        *txt* is just a YAML\-stream\.

      * ____\-types__ *list*__

        The *list* is a type list for the yaml\-scalar types\.\(e\.g\. \!\!str
        \!\!timestamp \!\!integer \!\!true \.\.\.\)

            -types {timestamp integer null true false}

        In this case, if a string matched "timestamp", converted to the TCL
        internal timestamp\.\(e\.g\. "2001\-12\-15T02:59:43\.1Z" => 1008385183\)

      * ____\-m:true__ *param*__

        The *param* is two elements of list for the value of true, and
        considered strings\.

            -m:true {1 {true on + yes y}}

        In this case, the string "yes" found in YAML Stream, automatically
        converted 1\.

      * ____\-m:false__ *param*__

        The *param* is two elements of list for the value of false, and
        considered strings\.

            -m:false {0 {false off - no n}}

      * ____\-m:null__ *param*__

        The *param* is two elements of list for the value of null, and
        considered strings\.

            -m:null {"" {null nil "" ~}}

      * ____\-validate____

        Experiment,old: Output stream contains YAML's\-tag, each node\.

            % puts [::yaml::load -validate {[aaa, bbb]}]
            =>
            !!seq {{!!str aaa} {!!str bbb}}

  - <a name='3'></a>__::yaml::setOption__ ?*options*?

    Change implicit options for the library\. Now, the params are the same as
    __::yaml::yaml2dict__\. Arguments of__::yaml::yaml2dict__ is more
    priority than this setting\.

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
        word wrap for YAML stream\. currently default is 40\.

# <a name='section3'></a>EXAMPLES

An example of a yaml stream converted to Tcl\. A yaml stream is returned as a
single item with multiple elements\.

    \{

    \-\-\- \!<tag:clarkevans\.com,2002:invoice>
    invoice: 34843
    date   : 2001\-01\-23
    bill\-to: &id001
        given  : Chris
        family : Dumars
        address:
            lines: &#124;
                458 Walkman Dr\.
                Suite \#292
            city    : Royal Oak
            state   : MI
            postal  : 48046
    ship\-to: \*id001
    product:
        \- sku         : BL394D
          quantity    : 4
          description : Basketball
          price       : 450\.00
        \- sku         : BL4438H
          quantity    : 1
          description : Super Hoop
          price       : 2392\.00
    tax  : 251\.42
    total: 4443\.52
    comments:
        Late afternoon is best\.
        Backup contact is Nancy
        Billsmer @ 338\-4338\.
    \}

    =>
    invoice 34843 date 2001\-01\-23 bill\-to \{given Chris family Dumars address \{lines \{458 Walkman Dr\.
    Suite \#292
    \} city \{Royal Oak\} state MI postal 48046\}\} ship\-to \{given Chris family Dumars address \{lines \{458 Walkman Dr\.
    Suite \#292
    \} city \{Royal Oak\} state MI postal 48046\}\} product \{\{sku BL394D quantity 4 description Basketball price 450\.00\} \{sku BL4438H quantity 1 description \{Super Hoop\} price 2392\.00\}\} tax 251\.42 total 4443\.52 comments \{Late afternoon is best\. Backup contact is Nancy Billsmer @ 338\-4338\.\}

An example of a yaml object converted to Tcl\. A yaml object is returned as a
multi\-element list \(a dict\)\.

    \{

    \-\-\-
    \- \[name        , hr, avg  \]
    \- \[Mark McGwire, 65, 0\.278\]
    \- \[Sammy Sosa  , 63, 0\.288\]
    \-

      Mark McGwire: \{hr: 65, avg: 0\.278\}
      Sammy Sosa: \{ hr: 63, avg: 0\.288\}
    \}

    =>
    \{name hr avg\} \{\{Mark McGwire\} 65 0\.278\} \{\{Sammy Sosa\} 63 0\.288\} \{\{Mark McGwire\} \{hr 65 avg 0\.278\} \{Sammy Sosa\} \{hr 63 avg 0\.288\}\}

# <a name='section4'></a>LIMITATIONS

tag parser not implemented\. currentry, tags are merely ignored\.

Only Anchor => Aliases ordering\. back alias\-referring is not supported\.








<
>
|

|
|



|
|
|



|

|


|
|


|
|
|

|

|
<
>

|
|
|
|
|




<
>
|
|
|
|
<
>
|
|
<
>

|







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
        word wrap for YAML stream\. currently default is 40\.

# <a name='section3'></a>EXAMPLES

An example of a yaml stream converted to Tcl\. A yaml stream is returned as a
single item with multiple elements\.


    {
    --- !<tag:clarkevans.com,2002:invoice>
    invoice: 34843
    date   : 2001-01-23
    bill-to: &id001
        given  : Chris
        family : Dumars
        address:
            lines: |
                458 Walkman Dr.
                Suite #292
            city    : Royal Oak
            state   : MI
            postal  : 48046
    ship-to: *id001
    product:
        - sku         : BL394D
          quantity    : 4
          description : Basketball
          price       : 450.00
        - sku         : BL4438H
          quantity    : 1
          description : Super Hoop
          price       : 2392.00
    tax  : 251.42
    total: 4443.52
    comments:
        Late afternoon is best.
        Backup contact is Nancy
        Billsmer @ 338-4338.

    }
    =>
    invoice 34843 date 2001-01-23 bill-to {given Chris family Dumars address {lines {458 Walkman Dr.
    Suite #292
    } city {Royal Oak} state MI postal 48046}} ship-to {given Chris family Dumars address {lines {458 Walkman Dr.
    Suite #292
    } city {Royal Oak} state MI postal 48046}} product {{sku BL394D quantity 4 description Basketball price 450.00} {sku BL4438H quantity 1 description {Super Hoop} price 2392.00}} tax 251.42 total 4443.52 comments {Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.}

An example of a yaml object converted to Tcl\. A yaml object is returned as a
multi\-element list \(a dict\)\.


    {
    ---
    - [name        , hr, avg  ]
    - [Mark McGwire, 65, 0.278]
    - [Sammy Sosa  , 63, 0.288]

    -
      Mark McGwire: {hr: 65, avg: 0.278}
      Sammy Sosa: { hr: 63, avg: 0.288}

    }
    =>
    {name hr avg} {{Mark McGwire} 65 0.278} {{Sammy Sosa} 63 0.288} {{Mark McGwire} {hr 65 avg 0.278} {Sammy Sosa} {hr 63 avg 0.288}}

# <a name='section4'></a>LIMITATIONS

tag parser not implemented\. currentry, tags are merely ignored\.

Only Anchor => Aliases ordering\. back alias\-referring is not supported\.

Changes to embedded/md/tcllib/files/modules/zip/mkzip.md.

1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (zipfile::mkzip \- Zip archive creation)
[//000000002]: # (Generated from file 'mkzip\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Pat Thoyts)
[//000000004]: # (zipfile::mkzip\(n\) 1\.2 tcllib "Zip archive creation")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>




|







1
2
3
4
5
6
7
8
9
10
11
12

[//000000001]: # (zipfile::mkzip \- Zip archive creation)
[//000000002]: # (Generated from file 'mkzip\.man' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2009 Pat Thoyts)
[//000000004]: # (zipfile::mkzip\(n\) 1\.2\.1 tcllib "Zip archive creation")

<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> &#124; <a
href="../../../toc.md">Table Of Contents</a> &#124; <a
href="../../../../index.md">Keyword Index</a> &#124; <a
href="../../../../toc0.md">Categories</a> &#124; <a
href="../../../../toc1.md">Modules</a> &#124; <a
href="../../../../toc2.md">Applications</a> ] <hr>
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.6  
package require zipfile::mkzip ?1\.2?  

[__::zipfile::mkzip::mkzip__ *zipfile* ?__\-zipkit__? ?__\-runtime__ *prefix*? ?__\-comment__ *string*? ?__\-directory__ *rootpath*? ?__\-exclude__ *exclude*? ?__\-\-__? ?*path*\.\.\.?](#1)  

# <a name='description'></a>DESCRIPTION

This package utilizes the zlib functions in Tcl 8\.6 to build zip archives\.








|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  - [Category](#category)

  - [Copyright](#copyright)

# <a name='synopsis'></a>SYNOPSIS

package require Tcl 8\.6  
package require zipfile::mkzip ?1\.2\.1?  

[__::zipfile::mkzip::mkzip__ *zipfile* ?__\-zipkit__? ?__\-runtime__ *prefix*? ?__\-comment__ *string*? ?__\-directory__ *rootpath*? ?__\-exclude__ *exclude*? ?__\-\-__? ?*path*\.\.\.?](#1)  

# <a name='description'></a>DESCRIPTION

This package utilizes the zlib functions in Tcl 8\.6 to build zip archives\.

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
    particularly on Windows the __info\-zip__ and the Windows built\-in zip
    view have rather poor support for this part of the ZIP file specification\.
    The __7\-Zip__ program does correctly display utf8 filenames however and
    the __vfs::zip__ package will use these of course\.

    If you use

        __::mkzip::mkzip__ mystuff\.tm \-zipkit \-directory mystuff\.vfs

    it will pack your "mystuff\.vfs/" virtual filesystem tree into a zip archive
    with a suitable header such that on unix you may mark it executable and it
    should run with tclkit\. Or you can run it with __tclsh__ or __wish__
    8\.6 if you like\.

    To change the executable header, specify the __\-runtime__ "preface"
    where preface is a file containing code you want prefixed\. For instance, on
    Windows you can create a self\-extracting zip archive using

        mkzip mystuff\.exe \-directory mystuff\.vfs \-runtime unzipsfx\.exe

    The "unzipsfx\.exe" is the Info\-Zip self\-extracting stub\.

    Accepted options:

      * __\-runtime__ path








|










|







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
    particularly on Windows the __info\-zip__ and the Windows built\-in zip
    view have rather poor support for this part of the ZIP file specification\.
    The __7\-Zip__ program does correctly display utf8 filenames however and
    the __vfs::zip__ package will use these of course\.

    If you use

    > __::mkzip::mkzip__ mystuff\.tm \-zipkit \-directory mystuff\.vfs

    it will pack your "mystuff\.vfs/" virtual filesystem tree into a zip archive
    with a suitable header such that on unix you may mark it executable and it
    should run with tclkit\. Or you can run it with __tclsh__ or __wish__
    8\.6 if you like\.

    To change the executable header, specify the __\-runtime__ "preface"
    where preface is a file containing code you want prefixed\. For instance, on
    Windows you can create a self\-extracting zip archive using

        mkzip mystuff.exe -directory mystuff.vfs -runtime unzipsfx.exe

    The "unzipsfx\.exe" is the Info\-Zip self\-extracting stub\.

    Accepted options:

      * __\-runtime__ path

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

      * __\-exclude__ list

        This option specifies a list of glob patterns\. All paths matching at
        least one of the patterns are not placed into the generated archive\.
        This option defaults to

            CVS/\* \*/CVS/\* \*~ "\.\#\*" "\*/\.\#\*"

      * __\-\-__

        This option signals the end of the options, forcing processing of all
        further words as arguments, even if they begin with a dash character\.

    Accepted arguments:







|







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

      * __\-exclude__ list

        This option specifies a list of glob patterns\. All paths matching at
        least one of the patterns are not placed into the generated archive\.
        This option defaults to

            CVS/* */CVS/* *~ ".#*" "*/.#*"

      * __\-\-__

        This option signals the end of the options, forcing processing of all
        further words as arguments, even if they begin with a dash character\.

    Accepted arguments:

Changes to embedded/md/tcllib/toc.md.

39
40
41
42
43
44
45


46
47
48
49
50
51
52

  - [blowfish](tcllib/files/modules/blowfish/blowfish\.md) Implementation of the Blowfish block cipher

  - [cache::async](tcllib/files/modules/cache/async\.md) Asynchronous in\-memory cache

  - [cksum](tcllib/files/modules/crc/cksum\.md) Calculate a cksum\(1\) compatible checksum



  - [clock\_iso8601](tcllib/files/modules/clock/iso8601\.md) Parsing ISO 8601 dates/times

  - [clock\_rfc2822](tcllib/files/modules/clock/rfc2822\.md) Parsing ISO 8601 dates/times

  - [cmdline](tcllib/files/modules/cmdline/cmdline\.md) Procedures to process command lines and options\.

  - [comm](tcllib/files/modules/comm/comm\.md) A remote communication facility for Tcl \(8\.3 and later\)







>
>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

  - [blowfish](tcllib/files/modules/blowfish/blowfish\.md) Implementation of the Blowfish block cipher

  - [cache::async](tcllib/files/modules/cache/async\.md) Asynchronous in\-memory cache

  - [cksum](tcllib/files/modules/crc/cksum\.md) Calculate a cksum\(1\) compatible checksum

  - [clay](tcllib/files/modules/clay/clay\.md) A minimalist framework for large scale OO Projects

  - [clock\_iso8601](tcllib/files/modules/clock/iso8601\.md) Parsing ISO 8601 dates/times

  - [clock\_rfc2822](tcllib/files/modules/clock/rfc2822\.md) Parsing ISO 8601 dates/times

  - [cmdline](tcllib/files/modules/cmdline/cmdline\.md) Procedures to process command lines and options\.

  - [comm](tcllib/files/modules/comm/comm\.md) A remote communication facility for Tcl \(8\.3 and later\)
232
233
234
235
236
237
238


239
240
241
242
243
244
245
  - [fileutil::magic::filetype](tcllib/files/modules/fumagic/filetypes\.md) Procedures implementing file\-type recognition

  - [fileutil::magic::rt](tcllib/files/modules/fumagic/rtcore\.md) Runtime core for file type recognition engines written in pure Tcl

  - [fileutil::multi](tcllib/files/modules/fileutil/multi\.md) Multi\-file operation, scatter/gather, standard object

  - [fileutil::multi::op](tcllib/files/modules/fileutil/multiop\.md) Multi\-file operation, scatter/gather



  - [fileutil\_traverse](tcllib/files/modules/fileutil/traverse\.md) Iterative directory traversal

  - [ftp](tcllib/files/modules/ftp/ftp\.md) Client\-side tcl implementation of the ftp protocol

  - [ftp::geturl](tcllib/files/modules/ftp/ftp\_geturl\.md) Uri handler for ftp urls








>
>







234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
  - [fileutil::magic::filetype](tcllib/files/modules/fumagic/filetypes\.md) Procedures implementing file\-type recognition

  - [fileutil::magic::rt](tcllib/files/modules/fumagic/rtcore\.md) Runtime core for file type recognition engines written in pure Tcl

  - [fileutil::multi](tcllib/files/modules/fileutil/multi\.md) Multi\-file operation, scatter/gather, standard object

  - [fileutil::multi::op](tcllib/files/modules/fileutil/multiop\.md) Multi\-file operation, scatter/gather

  - [fileutil::paths](tcllib/files/modules/fileutil/paths\.md) Manage search path pools

  - [fileutil\_traverse](tcllib/files/modules/fileutil/traverse\.md) Iterative directory traversal

  - [ftp](tcllib/files/modules/ftp/ftp\.md) Client\-side tcl implementation of the ftp protocol

  - [ftp::geturl](tcllib/files/modules/ftp/ftp\_geturl\.md) Uri handler for ftp urls

280
281
282
283
284
285
286


287
288
289
290
291
292
293
  - [grammar::peg::interp](tcllib/files/modules/grammar\_peg/peg\_interp\.md) Interpreter for parsing expression grammars

  - [hook](tcllib/files/modules/hook/hook\.md) Hooks

  - [html](tcllib/files/modules/html/html\.md) Procedures to generate HTML structures

  - [htmlparse](tcllib/files/modules/htmlparse/htmlparse\.md) Procedures to parse HTML strings



  - [huddle](tcllib/files/modules/yaml/huddle\.md) Create and manipulate huddle object

  - [ident](tcllib/files/modules/ident/ident\.md) Ident protocol client

  - [imap4](tcllib/files/modules/imap4/imap4\.md) imap client\-side tcl implementation of imap protocol








>
>







284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
  - [grammar::peg::interp](tcllib/files/modules/grammar\_peg/peg\_interp\.md) Interpreter for parsing expression grammars

  - [hook](tcllib/files/modules/hook/hook\.md) Hooks

  - [html](tcllib/files/modules/html/html\.md) Procedures to generate HTML structures

  - [htmlparse](tcllib/files/modules/htmlparse/htmlparse\.md) Procedures to parse HTML strings

  - [httpd](tcllib/files/modules/httpd/httpd\.md) A TclOO and coroutine based web server

  - [huddle](tcllib/files/modules/yaml/huddle\.md) Create and manipulate huddle object

  - [ident](tcllib/files/modules/ident/ident\.md) Ident protocol client

  - [imap4](tcllib/files/modules/imap4/imap4\.md) imap client\-side tcl implementation of imap protocol

368
369
370
371
372
373
374


375
376
377
378
379
380
381
  - [math::numtheory](tcllib/files/modules/math/numtheory\.md) Number Theory

  - [math::optimize](tcllib/files/modules/math/optimize\.md) Optimisation routines

  - [math::PCA](tcllib/files/modules/math/pca\.md) Package for Principal Component Analysis

  - [math::polynomials](tcllib/files/modules/math/polynomials\.md) Polynomial functions



  - [math::rationalfunctions](tcllib/files/modules/math/rational\_funcs\.md) Polynomial functions

  - [math::roman](tcllib/files/modules/math/roman\.md) Tools for creating and manipulating roman numerals

  - [math::special](tcllib/files/modules/math/special\.md) Special mathematical functions








>
>







374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
  - [math::numtheory](tcllib/files/modules/math/numtheory\.md) Number Theory

  - [math::optimize](tcllib/files/modules/math/optimize\.md) Optimisation routines

  - [math::PCA](tcllib/files/modules/math/pca\.md) Package for Principal Component Analysis

  - [math::polynomials](tcllib/files/modules/math/polynomials\.md) Polynomial functions

  - [math::quasirandom](tcllib/files/modules/math/quasirandom\.md) Quasi\-random points for integration and Monte Carlo type methods

  - [math::rationalfunctions](tcllib/files/modules/math/rational\_funcs\.md) Polynomial functions

  - [math::roman](tcllib/files/modules/math/roman\.md) Tools for creating and manipulating roman numerals

  - [math::special](tcllib/files/modules/math/special\.md) Special mathematical functions

616
617
618
619
620
621
622


623
624
625
626
627
628
629
  - [struct::graph](tcllib/files/modules/struct/graph\.md) Create and manipulate directed graph objects

  - [struct::graph::op](tcllib/files/modules/struct/graphops\.md) Operation for \(un\)directed graph objects

  - [struct::graph\_v1](tcllib/files/modules/struct/graph1\.md) Create and manipulate directed graph objects

  - [struct::list](tcllib/files/modules/struct/struct\_list\.md) Procedures for manipulating lists



  - [struct::matrix](tcllib/files/modules/struct/matrix\.md) Create and manipulate matrix objects

  - [struct::matrix\_v1](tcllib/files/modules/struct/matrix1\.md) Create and manipulate matrix objects

  - [struct::pool](tcllib/files/modules/struct/pool\.md) Create and manipulate pool objects \(of discrete items\)








>
>







624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
  - [struct::graph](tcllib/files/modules/struct/graph\.md) Create and manipulate directed graph objects

  - [struct::graph::op](tcllib/files/modules/struct/graphops\.md) Operation for \(un\)directed graph objects

  - [struct::graph\_v1](tcllib/files/modules/struct/graph1\.md) Create and manipulate directed graph objects

  - [struct::list](tcllib/files/modules/struct/struct\_list\.md) Procedures for manipulating lists

  - [struct::map](tcllib/files/modules/struct/struct\_map\.md) Manage key/value maps

  - [struct::matrix](tcllib/files/modules/struct/matrix\.md) Create and manipulate matrix objects

  - [struct::matrix\_v1](tcllib/files/modules/struct/matrix1\.md) Create and manipulate matrix objects

  - [struct::pool](tcllib/files/modules/struct/pool\.md) Create and manipulate pool objects \(of discrete items\)

705
706
707
708
709
710
711


712
713
714
715
716
717




718
719






720
721
722
723
724
725
726

  - [tcl::transform::rot](tcllib/files/modules/virtchannel\_transform/rot\.md) rot\-encryption

  - [tcl::transform::spacer](tcllib/files/modules/virtchannel\_transform/spacer\.md) Space insertation and removal

  - [tcl::transform::zlib](tcllib/files/modules/virtchannel\_transform/tcllib\_zlib\.md) zlib \(de\)compression



  - [tclDES](tcllib/files/modules/des/tcldes\.md) Implementation of the DES and triple\-DES ciphers

  - [tclDESjr](tcllib/files/modules/des/tcldesjr\.md) Implementation of the DES and triple\-DES ciphers

  - [tcldocstrip](tcllib/files/apps/tcldocstrip\.md) Tcl\-based Docstrip Processor





  - [tcllib\_ip](tcllib/files/modules/dns/tcllib\_ip\.md) IPv4 and IPv6 address manipulation







  - [tclrep/machineparameters](tcllib/files/modules/math/machineparameters\.md) Compute double precision machine parameters\.

  - [tepam](tcllib/files/modules/tepam/tepam\_introduction\.md) An introduction into TEPAM, Tcl's Enhanced Procedure and Argument Manager

  - [tepam::argument\_dialogbox](tcllib/files/modules/tepam/tepam\_argument\_dialogbox\.md) TEPAM argument\_dialogbox, reference manual

  - [tepam::doc\_gen](tcllib/files/modules/tepam/tepam\_doc\_gen\.md) TEPAM DOC Generation, reference manual







>
>






>
>
>
>


>
>
>
>
>
>







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

  - [tcl::transform::rot](tcllib/files/modules/virtchannel\_transform/rot\.md) rot\-encryption

  - [tcl::transform::spacer](tcllib/files/modules/virtchannel\_transform/spacer\.md) Space insertation and removal

  - [tcl::transform::zlib](tcllib/files/modules/virtchannel\_transform/tcllib\_zlib\.md) zlib \(de\)compression

  - [tcl\_community\_communication](tcllib/files/devdoc/tcl\_community\_communication\.md) Tcl Community \- Kind Communication

  - [tclDES](tcllib/files/modules/des/tcldes\.md) Implementation of the DES and triple\-DES ciphers

  - [tclDESjr](tcllib/files/modules/des/tcldesjr\.md) Implementation of the DES and triple\-DES ciphers

  - [tcldocstrip](tcllib/files/apps/tcldocstrip\.md) Tcl\-based Docstrip Processor

  - [tcllib\_devguide](tcllib/files/devdoc/tcllib\_devguide\.md) Tcllib \- The Developer's Guide

  - [tcllib\_install\_guide](tcllib/files/devdoc/tcllib\_installer\.md) Tcllib \- The Installer's Guide

  - [tcllib\_ip](tcllib/files/modules/dns/tcllib\_ip\.md) IPv4 and IPv6 address manipulation

  - [tcllib\_license](tcllib/files/devdoc/tcllib\_license\.md) Tcllib \- License

  - [tcllib\_releasemgr](tcllib/files/devdoc/tcllib\_releasemgr\.md) Tcllib \- The Release Manager's Guide

  - [tcllib\_sources](tcllib/files/devdoc/tcllib\_sources\.md) Tcllib \- How To Get The Sources

  - [tclrep/machineparameters](tcllib/files/modules/math/machineparameters\.md) Compute double precision machine parameters\.

  - [tepam](tcllib/files/modules/tepam/tepam\_introduction\.md) An introduction into TEPAM, Tcl's Enhanced Procedure and Argument Manager

  - [tepam::argument\_dialogbox](tcllib/files/modules/tepam/tepam\_argument\_dialogbox\.md) TEPAM argument\_dialogbox, reference manual

  - [tepam::doc\_gen](tcllib/files/modules/tepam/tepam\_doc\_gen\.md) TEPAM DOC Generation, reference manual
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

  - [textutil](tcllib/files/modules/textutil/textutil\.md) Procedures to manipulate texts and strings\.

  - [textutil::adjust](tcllib/files/modules/textutil/adjust\.md) Procedures to adjust, indent, and undent paragraphs

  - [textutil::expander](tcllib/files/modules/textutil/expander\.md) Procedures to process templates and expand text\.



  - [textutil::repeat](tcllib/files/modules/textutil/repeat\.md) Procedures to repeat strings\.

  - [textutil::split](tcllib/files/modules/textutil/textutil\_split\.md) Procedures to split texts

  - [textutil::string](tcllib/files/modules/textutil/textutil\_string\.md) Procedures to manipulate texts and strings\.

  - [textutil::tabify](tcllib/files/modules/textutil/tabify\.md) Procedures to \(un\)tabify strings

  - [textutil::trim](tcllib/files/modules/textutil/trim\.md) Procedures to trim strings

  - [throw](tcllib/files/modules/try/tcllib\_throw\.md) throw \- Throw an error exception with a message

  - [tie](tcllib/files/modules/tie/tie\_std\.md) Array persistence, standard data sources

  - [tie](tcllib/files/modules/tie/tie\.md) Array persistence

  - [tiff](tcllib/files/modules/tiff/tiff\.md) TIFF reading, writing, and querying and manipulation of meta data

  - [tool](tcllib/files/modules/httpd/httpd\.md) A TclOO and coroutine based web server

  - [tool](tcllib/files/modules/tool/tool\.md) TclOO Library \(TOOL\) Framework

  - [tool::dict\_ensemble](tcllib/files/modules/tool/tool\_dict\_ensemble\.md) Dictionary Tools

  - [transfer::connect](tcllib/files/modules/transfer/connect\.md) Connection setup

  - [transfer::copy](tcllib/files/modules/transfer/copyops\.md) Data transfer foundation







>
>


















<
<







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

  - [textutil](tcllib/files/modules/textutil/textutil\.md) Procedures to manipulate texts and strings\.

  - [textutil::adjust](tcllib/files/modules/textutil/adjust\.md) Procedures to adjust, indent, and undent paragraphs

  - [textutil::expander](tcllib/files/modules/textutil/expander\.md) Procedures to process templates and expand text\.

  - [textutil::patch](tcllib/files/modules/textutil/patch\.md) Application of uni\-diff patches to directory trees

  - [textutil::repeat](tcllib/files/modules/textutil/repeat\.md) Procedures to repeat strings\.

  - [textutil::split](tcllib/files/modules/textutil/textutil\_split\.md) Procedures to split texts

  - [textutil::string](tcllib/files/modules/textutil/textutil\_string\.md) Procedures to manipulate texts and strings\.

  - [textutil::tabify](tcllib/files/modules/textutil/tabify\.md) Procedures to \(un\)tabify strings

  - [textutil::trim](tcllib/files/modules/textutil/trim\.md) Procedures to trim strings

  - [throw](tcllib/files/modules/try/tcllib\_throw\.md) throw \- Throw an error exception with a message

  - [tie](tcllib/files/modules/tie/tie\_std\.md) Array persistence, standard data sources

  - [tie](tcllib/files/modules/tie/tie\.md) Array persistence

  - [tiff](tcllib/files/modules/tiff/tiff\.md) TIFF reading, writing, and querying and manipulation of meta data



  - [tool](tcllib/files/modules/tool/tool\.md) TclOO Library \(TOOL\) Framework

  - [tool::dict\_ensemble](tcllib/files/modules/tool/tool\_dict\_ensemble\.md) Dictionary Tools

  - [transfer::connect](tcllib/files/modules/transfer/connect\.md) Connection setup

  - [transfer::copy](tcllib/files/modules/transfer/copyops\.md) Data transfer foundation

Changes to embedded/md/toc.md.

399
400
401
402
403
404
405


406
407
408
409
410
411
412

          + [math::optimize](tcllib/files/modules/math/optimize\.md) Optimisation routines

          + [math::PCA](tcllib/files/modules/math/pca\.md) Package for Principal Component Analysis

          + [math::polynomials](tcllib/files/modules/math/polynomials\.md) Polynomial functions



          + [math::rationalfunctions](tcllib/files/modules/math/rational\_funcs\.md) Polynomial functions

          + [math::roman](tcllib/files/modules/math/roman\.md) Tools for creating and manipulating roman numerals

          + [math::special](tcllib/files/modules/math/special\.md) Special mathematical functions

          + [math::statistics](tcllib/files/modules/math/statistics\.md) Basic statistical functions and procedures







>
>







399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414

          + [math::optimize](tcllib/files/modules/math/optimize\.md) Optimisation routines

          + [math::PCA](tcllib/files/modules/math/pca\.md) Package for Principal Component Analysis

          + [math::polynomials](tcllib/files/modules/math/polynomials\.md) Polynomial functions

          + [math::quasirandom](tcllib/files/modules/math/quasirandom\.md) Quasi\-random points for integration and Monte Carlo type methods

          + [math::rationalfunctions](tcllib/files/modules/math/rational\_funcs\.md) Polynomial functions

          + [math::roman](tcllib/files/modules/math/roman\.md) Tools for creating and manipulating roman numerals

          + [math::special](tcllib/files/modules/math/special\.md) Special mathematical functions

          + [math::statistics](tcllib/files/modules/math/statistics\.md) Basic statistical functions and procedures
431
432
433
434
435
436
437


438


439
440
441
442
443
444
445

          + [ftp](tcllib/files/modules/ftp/ftp\.md) Client\-side tcl implementation of the ftp protocol

          + [ftp::geturl](tcllib/files/modules/ftp/ftp\_geturl\.md) Uri handler for ftp urls

          + [ftpd](tcllib/files/modules/ftpd/ftpd\.md) Tcl FTP server implementation



          + [ident](tcllib/files/modules/ident/ident\.md) Ident protocol client



          + [irc](tcllib/files/modules/irc/irc\.md) Create IRC connection and interface\.

          + [ldap](tcllib/files/modules/ldap/ldap\.md) LDAP client

          + [ldapx](tcllib/files/modules/ldap/ldapx\.md) LDAP extended object interface








>
>

>
>







433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451

          + [ftp](tcllib/files/modules/ftp/ftp\.md) Client\-side tcl implementation of the ftp protocol

          + [ftp::geturl](tcllib/files/modules/ftp/ftp\_geturl\.md) Uri handler for ftp urls

          + [ftpd](tcllib/files/modules/ftpd/ftpd\.md) Tcl FTP server implementation

          + [httpd](tcllib/files/modules/httpd/httpd\.md) A TclOO and coroutine based web server

          + [ident](tcllib/files/modules/ident/ident\.md) Ident protocol client

          + [imap4](tcllib/files/modules/imap4/imap4\.md) imap client\-side tcl implementation of imap protocol

          + [irc](tcllib/files/modules/irc/irc\.md) Create IRC connection and interface\.

          + [ldap](tcllib/files/modules/ldap/ldap\.md) LDAP client

          + [ldapx](tcllib/files/modules/ldap/ldapx\.md) LDAP extended object interface

491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506

          + [smtp](tcllib/files/modules/mime/smtp\.md) Client\-side tcl implementation of the smtp protocol

          + [smtpd](tcllib/files/modules/smtpd/smtpd\.md) Tcl SMTP server implementation

          + [tcllib\_ip](tcllib/files/modules/dns/tcllib\_ip\.md) IPv4 and IPv6 address manipulation

          + [tool](tcllib/files/modules/httpd/httpd\.md) A TclOO and coroutine based web server

          + [udpcluster](tcllib/files/modules/udpcluster/udpcluster\.md) UDP Peer\-to\-Peer cluster

          + [uri](tcllib/files/modules/uri/uri\.md) URI utilities

          + [uri\_urn](tcllib/files/modules/uri/urn\-scheme\.md) URI utilities, URN scheme

          + [websocket](tcllib/files/modules/websocket/websocket\.md) Tcl implementation of the websocket protocol







<
<







497
498
499
500
501
502
503


504
505
506
507
508
509
510

          + [smtp](tcllib/files/modules/mime/smtp\.md) Client\-side tcl implementation of the smtp protocol

          + [smtpd](tcllib/files/modules/smtpd/smtpd\.md) Tcl SMTP server implementation

          + [tcllib\_ip](tcllib/files/modules/dns/tcllib\_ip\.md) IPv4 and IPv6 address manipulation



          + [udpcluster](tcllib/files/modules/udpcluster/udpcluster\.md) UDP Peer\-to\-Peer cluster

          + [uri](tcllib/files/modules/uri/uri\.md) URI utilities

          + [uri\_urn](tcllib/files/modules/uri/urn\-scheme\.md) URI utilities, URN scheme

          + [websocket](tcllib/files/modules/websocket/websocket\.md) Tcl implementation of the websocket protocol
614
615
616
617
618
619
620


621
622
623
624
625
626
627
      * [Procedures, arguments, parameters, options]()

          + [tepam](tcllib/files/modules/tepam/tepam\_introduction\.md) An introduction into TEPAM, Tcl's Enhanced Procedure and Argument Manager

          + [tepam::procedure](tcllib/files/modules/tepam/tepam\_procedure\.md) TEPAM procedure, reference manual

      * [Programming tools]()



          + [cmdline](tcllib/files/modules/cmdline/cmdline\.md) Procedures to process command lines and options\.

          + [comm](tcllib/files/modules/comm/comm\.md) A remote communication facility for Tcl \(8\.3 and later\)

          + [comm\_wire](tcllib/files/modules/comm/comm\_wire\.md) The comm wire protocol








>
>







618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
      * [Procedures, arguments, parameters, options]()

          + [tepam](tcllib/files/modules/tepam/tepam\_introduction\.md) An introduction into TEPAM, Tcl's Enhanced Procedure and Argument Manager

          + [tepam::procedure](tcllib/files/modules/tepam/tepam\_procedure\.md) TEPAM procedure, reference manual

      * [Programming tools]()

          + [clay](tcllib/files/modules/clay/clay\.md) A minimalist framework for large scale OO Projects

          + [cmdline](tcllib/files/modules/cmdline/cmdline\.md) Procedures to process command lines and options\.

          + [comm](tcllib/files/modules/comm/comm\.md) A remote communication facility for Tcl \(8\.3 and later\)

          + [comm\_wire](tcllib/files/modules/comm/comm\_wire\.md) The comm wire protocol

791
792
793
794
795
796
797


798
799
800
801
802
803
804

          + [string::token::shell](tcllib/files/modules/string/token\_shell\.md) Parsing of shell command line

          + [textutil](tcllib/files/modules/textutil/textutil\.md) Procedures to manipulate texts and strings\.

          + [textutil::adjust](tcllib/files/modules/textutil/adjust\.md) Procedures to adjust, indent, and undent paragraphs



          + [textutil::repeat](tcllib/files/modules/textutil/repeat\.md) Procedures to repeat strings\.

          + [textutil::split](tcllib/files/modules/textutil/textutil\_split\.md) Procedures to split texts

          + [textutil::string](tcllib/files/modules/textutil/textutil\_string\.md) Procedures to manipulate texts and strings\.

          + [textutil::tabify](tcllib/files/modules/textutil/tabify\.md) Procedures to \(un\)tabify strings







>
>







797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812

          + [string::token::shell](tcllib/files/modules/string/token\_shell\.md) Parsing of shell command line

          + [textutil](tcllib/files/modules/textutil/textutil\.md) Procedures to manipulate texts and strings\.

          + [textutil::adjust](tcllib/files/modules/textutil/adjust\.md) Procedures to adjust, indent, and undent paragraphs

          + [textutil::patch](tcllib/files/modules/textutil/patch\.md) Application of uni\-diff patches to directory trees

          + [textutil::repeat](tcllib/files/modules/textutil/repeat\.md) Procedures to repeat strings\.

          + [textutil::split](tcllib/files/modules/textutil/textutil\_split\.md) Procedures to split texts

          + [textutil::string](tcllib/files/modules/textutil/textutil\_string\.md) Procedures to manipulate texts and strings\.

          + [textutil::tabify](tcllib/files/modules/textutil/tabify\.md) Procedures to \(un\)tabify strings
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
          + [transfer::receiver](tcllib/files/modules/transfer/receiver\.md) Data source

          + [transfer::transmitter](tcllib/files/modules/transfer/transmitter\.md) Data source

      * [Unfiled]()

          + [cache::async](tcllib/files/modules/cache/async\.md) Asynchronous in\-memory cache



          + [generator](tcllib/files/modules/generator/generator\.md) Procedures for creating and using generators\.

          + [huddle](tcllib/files/modules/yaml/huddle\.md) Create and manipulate huddle object

          + [imap4](tcllib/files/modules/imap4/imap4\.md) imap client\-side tcl implementation of imap protocol

          + [map::geocode::nominatim](tcllib/files/modules/map/map\_geocode\_nominatim\.md) Resolving geographical names with a Nominatim service

          + [map::slippy](tcllib/files/modules/map/map\_slippy\.md) Common code for slippy based map packages

          + [map::slippy::cache](tcllib/files/modules/map/map\_slippy\_cache\.md) Management of a tile cache in the local filesystem

          + [map::slippy::fetcher](tcllib/files/modules/map/map\_slippy\_fetcher\.md) Accessing a server providing tiles for slippy\-based maps

          + [mapproj](tcllib/files/modules/mapproj/mapproj\.md) Map projection routines

          + [math::calculus::symdiff](tcllib/files/modules/math/symdiff\.md) Symbolic differentiation for Tcl

          + [namespacex](tcllib/files/modules/namespacex/namespacex\.md) Namespace utility commands

          + [rest](tcllib/files/modules/rest/rest\.md) define REST web APIs and call them inline or asychronously

          + [stringprep](tcllib/files/modules/stringprep/stringprep\.md) Implementation of stringprep

          + [stringprep::data](tcllib/files/modules/stringprep/stringprep\_data\.md) stringprep data tables, generated, internal



          + [tclrep/machineparameters](tcllib/files/modules/math/machineparameters\.md) Compute double precision machine parameters\.

          + [uevent::onidle](tcllib/files/modules/uev/uevent\_onidle\.md) Request merging and deferal to idle time

          + [unicode](tcllib/files/modules/stringprep/unicode\.md) Implementation of Unicode normalization








>
>





<
<



















>
>







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
          + [transfer::receiver](tcllib/files/modules/transfer/receiver\.md) Data source

          + [transfer::transmitter](tcllib/files/modules/transfer/transmitter\.md) Data source

      * [Unfiled]()

          + [cache::async](tcllib/files/modules/cache/async\.md) Asynchronous in\-memory cache

          + [fileutil::paths](tcllib/files/modules/fileutil/paths\.md) Manage search path pools

          + [generator](tcllib/files/modules/generator/generator\.md) Procedures for creating and using generators\.

          + [huddle](tcllib/files/modules/yaml/huddle\.md) Create and manipulate huddle object



          + [map::geocode::nominatim](tcllib/files/modules/map/map\_geocode\_nominatim\.md) Resolving geographical names with a Nominatim service

          + [map::slippy](tcllib/files/modules/map/map\_slippy\.md) Common code for slippy based map packages

          + [map::slippy::cache](tcllib/files/modules/map/map\_slippy\_cache\.md) Management of a tile cache in the local filesystem

          + [map::slippy::fetcher](tcllib/files/modules/map/map\_slippy\_fetcher\.md) Accessing a server providing tiles for slippy\-based maps

          + [mapproj](tcllib/files/modules/mapproj/mapproj\.md) Map projection routines

          + [math::calculus::symdiff](tcllib/files/modules/math/symdiff\.md) Symbolic differentiation for Tcl

          + [namespacex](tcllib/files/modules/namespacex/namespacex\.md) Namespace utility commands

          + [rest](tcllib/files/modules/rest/rest\.md) define REST web APIs and call them inline or asychronously

          + [stringprep](tcllib/files/modules/stringprep/stringprep\.md) Implementation of stringprep

          + [stringprep::data](tcllib/files/modules/stringprep/stringprep\_data\.md) stringprep data tables, generated, internal

          + [struct::map](tcllib/files/modules/struct/struct\_map\.md) Manage key/value maps

          + [tclrep/machineparameters](tcllib/files/modules/math/machineparameters\.md) Compute double precision machine parameters\.

          + [uevent::onidle](tcllib/files/modules/uev/uevent\_onidle\.md) Request merging and deferal to idle time

          + [unicode](tcllib/files/modules/stringprep/unicode\.md) Implementation of Unicode normalization

999
1000
1001
1002
1003
1004
1005




1006
1007
1008
1009
1010
1011
1012

              - [blowfish](tcllib/files/modules/blowfish/blowfish\.md) Implementation of the Blowfish block cipher

          + [cache]()

              - [cache::async](tcllib/files/modules/cache/async\.md) Asynchronous in\-memory cache





          + [clock]()

              - [clock\_iso8601](tcllib/files/modules/clock/iso8601\.md) Parsing ISO 8601 dates/times

              - [clock\_rfc2822](tcllib/files/modules/clock/rfc2822\.md) Parsing ISO 8601 dates/times

          + [cmdline]()







>
>
>
>







1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026

              - [blowfish](tcllib/files/modules/blowfish/blowfish\.md) Implementation of the Blowfish block cipher

          + [cache]()

              - [cache::async](tcllib/files/modules/cache/async\.md) Asynchronous in\-memory cache

          + [clay]()

              - [clay](tcllib/files/modules/clay/clay\.md) A minimalist framework for large scale OO Projects

          + [clock]()

              - [clock\_iso8601](tcllib/files/modules/clock/iso8601\.md) Parsing ISO 8601 dates/times

              - [clock\_rfc2822](tcllib/files/modules/clock/rfc2822\.md) Parsing ISO 8601 dates/times

          + [cmdline]()
1232
1233
1234
1235
1236
1237
1238


1239
1240
1241
1242
1243
1244
1245
          + [fileutil]()

              - [fileutil](tcllib/files/modules/fileutil/fileutil\.md) Procedures implementing some file utilities

              - [fileutil::multi](tcllib/files/modules/fileutil/multi\.md) Multi\-file operation, scatter/gather, standard object

              - [fileutil::multi::op](tcllib/files/modules/fileutil/multiop\.md) Multi\-file operation, scatter/gather



              - [fileutil\_traverse](tcllib/files/modules/fileutil/traverse\.md) Iterative directory traversal

          + [ftp]()

              - [ftp](tcllib/files/modules/ftp/ftp\.md) Client\-side tcl implementation of the ftp protocol








>
>







1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
          + [fileutil]()

              - [fileutil](tcllib/files/modules/fileutil/fileutil\.md) Procedures implementing some file utilities

              - [fileutil::multi](tcllib/files/modules/fileutil/multi\.md) Multi\-file operation, scatter/gather, standard object

              - [fileutil::multi::op](tcllib/files/modules/fileutil/multiop\.md) Multi\-file operation, scatter/gather

              - [fileutil::paths](tcllib/files/modules/fileutil/paths\.md) Manage search path pools

              - [fileutil\_traverse](tcllib/files/modules/fileutil/traverse\.md) Iterative directory traversal

          + [ftp]()

              - [ftp](tcllib/files/modules/ftp/ftp\.md) Client\-side tcl implementation of the ftp protocol

1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333

          + [http]()

              - [autoproxy](tcllib/files/modules/http/autoproxy\.md) Automatic HTTP proxy usage and authentication

          + [httpd]()

              - [tool](tcllib/files/modules/httpd/httpd\.md) A TclOO and coroutine based web server

          + [ident]()

              - [ident](tcllib/files/modules/ident/ident\.md) Ident protocol client

          + [imap4]()








|







1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349

          + [http]()

              - [autoproxy](tcllib/files/modules/http/autoproxy\.md) Automatic HTTP proxy usage and authentication

          + [httpd]()

              - [httpd](tcllib/files/modules/httpd/httpd\.md) A TclOO and coroutine based web server

          + [ident]()

              - [ident](tcllib/files/modules/ident/ident\.md) Ident protocol client

          + [imap4]()

1444
1445
1446
1447
1448
1449
1450


1451
1452
1453
1454
1455
1456
1457
              - [math::numtheory](tcllib/files/modules/math/numtheory\.md) Number Theory

              - [math::optimize](tcllib/files/modules/math/optimize\.md) Optimisation routines

              - [math::PCA](tcllib/files/modules/math/pca\.md) Package for Principal Component Analysis

              - [math::polynomials](tcllib/files/modules/math/polynomials\.md) Polynomial functions



              - [math::rationalfunctions](tcllib/files/modules/math/rational\_funcs\.md) Polynomial functions

              - [math::roman](tcllib/files/modules/math/roman\.md) Tools for creating and manipulating roman numerals

              - [math::special](tcllib/files/modules/math/special\.md) Special mathematical functions








>
>







1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
              - [math::numtheory](tcllib/files/modules/math/numtheory\.md) Number Theory

              - [math::optimize](tcllib/files/modules/math/optimize\.md) Optimisation routines

              - [math::PCA](tcllib/files/modules/math/pca\.md) Package for Principal Component Analysis

              - [math::polynomials](tcllib/files/modules/math/polynomials\.md) Polynomial functions

              - [math::quasirandom](tcllib/files/modules/math/quasirandom\.md) Quasi\-random points for integration and Monte Carlo type methods

              - [math::rationalfunctions](tcllib/files/modules/math/rational\_funcs\.md) Polynomial functions

              - [math::roman](tcllib/files/modules/math/roman\.md) Tools for creating and manipulating roman numerals

              - [math::special](tcllib/files/modules/math/special\.md) Special mathematical functions

1764
1765
1766
1767
1768
1769
1770


1771
1772
1773
1774
1775
1776
1777
              - [struct::graph](tcllib/files/modules/struct/graph\.md) Create and manipulate directed graph objects

              - [struct::graph::op](tcllib/files/modules/struct/graphops\.md) Operation for \(un\)directed graph objects

              - [struct::graph\_v1](tcllib/files/modules/struct/graph1\.md) Create and manipulate directed graph objects

              - [struct::list](tcllib/files/modules/struct/struct\_list\.md) Procedures for manipulating lists



              - [struct::matrix](tcllib/files/modules/struct/matrix\.md) Create and manipulate matrix objects

              - [struct::matrix\_v1](tcllib/files/modules/struct/matrix1\.md) Create and manipulate matrix objects

              - [struct::pool](tcllib/files/modules/struct/pool\.md) Create and manipulate pool objects \(of discrete items\)








>
>







1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
              - [struct::graph](tcllib/files/modules/struct/graph\.md) Create and manipulate directed graph objects

              - [struct::graph::op](tcllib/files/modules/struct/graphops\.md) Operation for \(un\)directed graph objects

              - [struct::graph\_v1](tcllib/files/modules/struct/graph1\.md) Create and manipulate directed graph objects

              - [struct::list](tcllib/files/modules/struct/struct\_list\.md) Procedures for manipulating lists

              - [struct::map](tcllib/files/modules/struct/struct\_map\.md) Manage key/value maps

              - [struct::matrix](tcllib/files/modules/struct/matrix\.md) Create and manipulate matrix objects

              - [struct::matrix\_v1](tcllib/files/modules/struct/matrix1\.md) Create and manipulate matrix objects

              - [struct::pool](tcllib/files/modules/struct/pool\.md) Create and manipulate pool objects \(of discrete items\)

1834
1835
1836
1837
1838
1839
1840


1841
1842
1843
1844
1845
1846
1847
          + [textutil]()

              - [textutil](tcllib/files/modules/textutil/textutil\.md) Procedures to manipulate texts and strings\.

              - [textutil::adjust](tcllib/files/modules/textutil/adjust\.md) Procedures to adjust, indent, and undent paragraphs

              - [textutil::expander](tcllib/files/modules/textutil/expander\.md) Procedures to process templates and expand text\.



              - [textutil::repeat](tcllib/files/modules/textutil/repeat\.md) Procedures to repeat strings\.

              - [textutil::split](tcllib/files/modules/textutil/textutil\_split\.md) Procedures to split texts

              - [textutil::string](tcllib/files/modules/textutil/textutil\_string\.md) Procedures to manipulate texts and strings\.








>
>







1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
          + [textutil]()

              - [textutil](tcllib/files/modules/textutil/textutil\.md) Procedures to manipulate texts and strings\.

              - [textutil::adjust](tcllib/files/modules/textutil/adjust\.md) Procedures to adjust, indent, and undent paragraphs

              - [textutil::expander](tcllib/files/modules/textutil/expander\.md) Procedures to process templates and expand text\.

              - [textutil::patch](tcllib/files/modules/textutil/patch\.md) Application of uni\-diff patches to directory trees

              - [textutil::repeat](tcllib/files/modules/textutil/repeat\.md) Procedures to repeat strings\.

              - [textutil::split](tcllib/files/modules/textutil/textutil\_split\.md) Procedures to split texts

              - [textutil::string](tcllib/files/modules/textutil/textutil\_string\.md) Procedures to manipulate texts and strings\.

Changes to embedded/md/toc0.md.

399
400
401
402
403
404
405


406
407
408
409
410
411
412

          + [math::optimize](tcllib/files/modules/math/optimize\.md) Optimisation routines

          + [math::PCA](tcllib/files/modules/math/pca\.md) Package for Principal Component Analysis

          + [math::polynomials](tcllib/files/modules/math/polynomials\.md) Polynomial functions



          + [math::rationalfunctions](tcllib/files/modules/math/rational\_funcs\.md) Polynomial functions

          + [math::roman](tcllib/files/modules/math/roman\.md) Tools for creating and manipulating roman numerals

          + [math::special](tcllib/files/modules/math/special\.md) Special mathematical functions

          + [math::statistics](tcllib/files/modules/math/statistics\.md) Basic statistical functions and procedures







>
>







399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414

          + [math::optimize](tcllib/files/modules/math/optimize\.md) Optimisation routines

          + [math::PCA](tcllib/files/modules/math/pca\.md) Package for Principal Component Analysis

          + [math::polynomials](tcllib/files/modules/math/polynomials\.md) Polynomial functions

          + [math::quasirandom](tcllib/files/modules/math/quasirandom\.md) Quasi\-random points for integration and Monte Carlo type methods

          + [math::rationalfunctions](tcllib/files/modules/math/rational\_funcs\.md) Polynomial functions

          + [math::roman](tcllib/files/modules/math/roman\.md) Tools for creating and manipulating roman numerals

          + [math::special](tcllib/files/modules/math/special\.md) Special mathematical functions

          + [math::statistics](tcllib/files/modules/math/statistics\.md) Basic statistical functions and procedures
431
432
433
434
435
436
437


438


439
440
441
442
443
444
445

          + [ftp](tcllib/files/modules/ftp/ftp\.md) Client\-side tcl implementation of the ftp protocol

          + [ftp::geturl](tcllib/files/modules/ftp/ftp\_geturl\.md) Uri handler for ftp urls

          + [ftpd](tcllib/files/modules/ftpd/ftpd\.md) Tcl FTP server implementation



          + [ident](tcllib/files/modules/ident/ident\.md) Ident protocol client



          + [irc](tcllib/files/modules/irc/irc\.md) Create IRC connection and interface\.

          + [ldap](tcllib/files/modules/ldap/ldap\.md) LDAP client

          + [ldapx](tcllib/files/modules/ldap/ldapx\.md) LDAP extended object interface








>
>

>
>







433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451

          + [ftp](tcllib/files/modules/ftp/ftp\.md) Client\-side tcl implementation of the ftp protocol

          + [ftp::geturl](tcllib/files/modules/ftp/ftp\_geturl\.md) Uri handler for ftp urls

          + [ftpd](tcllib/files/modules/ftpd/ftpd\.md) Tcl FTP server implementation

          + [httpd](tcllib/files/modules/httpd/httpd\.md) A TclOO and coroutine based web server

          + [ident](tcllib/files/modules/ident/ident\.md) Ident protocol client

          + [imap4](tcllib/files/modules/imap4/imap4\.md) imap client\-side tcl implementation of imap protocol

          + [irc](tcllib/files/modules/irc/irc\.md) Create IRC connection and interface\.

          + [ldap](tcllib/files/modules/ldap/ldap\.md) LDAP client

          + [ldapx](tcllib/files/modules/ldap/ldapx\.md) LDAP extended object interface

491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506

          + [smtp](tcllib/files/modules/mime/smtp\.md) Client\-side tcl implementation of the smtp protocol

          + [smtpd](tcllib/files/modules/smtpd/smtpd\.md) Tcl SMTP server implementation

          + [tcllib\_ip](tcllib/files/modules/dns/tcllib\_ip\.md) IPv4 and IPv6 address manipulation

          + [tool](tcllib/files/modules/httpd/httpd\.md) A TclOO and coroutine based web server

          + [udpcluster](tcllib/files/modules/udpcluster/udpcluster\.md) UDP Peer\-to\-Peer cluster

          + [uri](tcllib/files/modules/uri/uri\.md) URI utilities

          + [uri\_urn](tcllib/files/modules/uri/urn\-scheme\.md) URI utilities, URN scheme

          + [websocket](tcllib/files/modules/websocket/websocket\.md) Tcl implementation of the websocket protocol







<
<







497
498
499
500
501
502
503


504
505
506
507
508
509
510

          + [smtp](tcllib/files/modules/mime/smtp\.md) Client\-side tcl implementation of the smtp protocol

          + [smtpd](tcllib/files/modules/smtpd/smtpd\.md) Tcl SMTP server implementation

          + [tcllib\_ip](tcllib/files/modules/dns/tcllib\_ip\.md) IPv4 and IPv6 address manipulation



          + [udpcluster](tcllib/files/modules/udpcluster/udpcluster\.md) UDP Peer\-to\-Peer cluster

          + [uri](tcllib/files/modules/uri/uri\.md) URI utilities

          + [uri\_urn](tcllib/files/modules/uri/urn\-scheme\.md) URI utilities, URN scheme

          + [websocket](tcllib/files/modules/websocket/websocket\.md) Tcl implementation of the websocket protocol
614
615
616
617
618
619
620


621
622
623
624
625
626
627
      * [Procedures, arguments, parameters, options]()

          + [tepam](tcllib/files/modules/tepam/tepam\_introduction\.md) An introduction into TEPAM, Tcl's Enhanced Procedure and Argument Manager

          + [tepam::procedure](tcllib/files/modules/tepam/tepam\_procedure\.md) TEPAM procedure, reference manual

      * [Programming tools]()



          + [cmdline](tcllib/files/modules/cmdline/cmdline\.md) Procedures to process command lines and options\.

          + [comm](tcllib/files/modules/comm/comm\.md) A remote communication facility for Tcl \(8\.3 and later\)

          + [comm\_wire](tcllib/files/modules/comm/comm\_wire\.md) The comm wire protocol








>
>







618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
      * [Procedures, arguments, parameters, options]()

          + [tepam](tcllib/files/modules/tepam/tepam\_introduction\.md) An introduction into TEPAM, Tcl's Enhanced Procedure and Argument Manager

          + [tepam::procedure](tcllib/files/modules/tepam/tepam\_procedure\.md) TEPAM procedure, reference manual

      * [Programming tools]()

          + [clay](tcllib/files/modules/clay/clay\.md) A minimalist framework for large scale OO Projects

          + [cmdline](tcllib/files/modules/cmdline/cmdline\.md) Procedures to process command lines and options\.

          + [comm](tcllib/files/modules/comm/comm\.md) A remote communication facility for Tcl \(8\.3 and later\)

          + [comm\_wire](tcllib/files/modules/comm/comm\_wire\.md) The comm wire protocol

791
792
793
794
795
796
797


798
799
800
801
802
803
804

          + [string::token::shell](tcllib/files/modules/string/token\_shell\.md) Parsing of shell command line

          + [textutil](tcllib/files/modules/textutil/textutil\.md) Procedures to manipulate texts and strings\.

          + [textutil::adjust](tcllib/files/modules/textutil/adjust\.md) Procedures to adjust, indent, and undent paragraphs



          + [textutil::repeat](tcllib/files/modules/textutil/repeat\.md) Procedures to repeat strings\.

          + [textutil::split](tcllib/files/modules/textutil/textutil\_split\.md) Procedures to split texts

          + [textutil::string](tcllib/files/modules/textutil/textutil\_string\.md) Procedures to manipulate texts and strings\.

          + [textutil::tabify](tcllib/files/modules/textutil/tabify\.md) Procedures to \(un\)tabify strings







>
>







797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812

          + [string::token::shell](tcllib/files/modules/string/token\_shell\.md) Parsing of shell command line

          + [textutil](tcllib/files/modules/textutil/textutil\.md) Procedures to manipulate texts and strings\.

          + [textutil::adjust](tcllib/files/modules/textutil/adjust\.md) Procedures to adjust, indent, and undent paragraphs

          + [textutil::patch](tcllib/files/modules/textutil/patch\.md) Application of uni\-diff patches to directory trees

          + [textutil::repeat](tcllib/files/modules/textutil/repeat\.md) Procedures to repeat strings\.

          + [textutil::split](tcllib/files/modules/textutil/textutil\_split\.md) Procedures to split texts

          + [textutil::string](tcllib/files/modules/textutil/textutil\_string\.md) Procedures to manipulate texts and strings\.

          + [textutil::tabify](tcllib/files/modules/textutil/tabify\.md) Procedures to \(un\)tabify strings
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
          + [transfer::receiver](tcllib/files/modules/transfer/receiver\.md) Data source

          + [transfer::transmitter](tcllib/files/modules/transfer/transmitter\.md) Data source

      * [Unfiled]()

          + [cache::async](tcllib/files/modules/cache/async\.md) Asynchronous in\-memory cache



          + [generator](tcllib/files/modules/generator/generator\.md) Procedures for creating and using generators\.

          + [huddle](tcllib/files/modules/yaml/huddle\.md) Create and manipulate huddle object

          + [imap4](tcllib/files/modules/imap4/imap4\.md) imap client\-side tcl implementation of imap protocol

          + [map::geocode::nominatim](tcllib/files/modules/map/map\_geocode\_nominatim\.md) Resolving geographical names with a Nominatim service

          + [map::slippy](tcllib/files/modules/map/map\_slippy\.md) Common code for slippy based map packages

          + [map::slippy::cache](tcllib/files/modules/map/map\_slippy\_cache\.md) Management of a tile cache in the local filesystem

          + [map::slippy::fetcher](tcllib/files/modules/map/map\_slippy\_fetcher\.md) Accessing a server providing tiles for slippy\-based maps

          + [mapproj](tcllib/files/modules/mapproj/mapproj\.md) Map projection routines

          + [math::calculus::symdiff](tcllib/files/modules/math/symdiff\.md) Symbolic differentiation for Tcl

          + [namespacex](tcllib/files/modules/namespacex/namespacex\.md) Namespace utility commands

          + [rest](tcllib/files/modules/rest/rest\.md) define REST web APIs and call them inline or asychronously

          + [stringprep](tcllib/files/modules/stringprep/stringprep\.md) Implementation of stringprep

          + [stringprep::data](tcllib/files/modules/stringprep/stringprep\_data\.md) stringprep data tables, generated, internal



          + [tclrep/machineparameters](tcllib/files/modules/math/machineparameters\.md) Compute double precision machine parameters\.

          + [uevent::onidle](tcllib/files/modules/uev/uevent\_onidle\.md) Request merging and deferal to idle time

          + [unicode](tcllib/files/modules/stringprep/unicode\.md) Implementation of Unicode normalization








>
>





<
<



















>
>







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
          + [transfer::receiver](tcllib/files/modules/transfer/receiver\.md) Data source

          + [transfer::transmitter](tcllib/files/modules/transfer/transmitter\.md) Data source

      * [Unfiled]()

          + [cache::async](tcllib/files/modules/cache/async\.md) Asynchronous in\-memory cache

          + [fileutil::paths](tcllib/files/modules/fileutil/paths\.md) Manage search path pools

          + [generator](tcllib/files/modules/generator/generator\.md) Procedures for creating and using generators\.

          + [huddle](tcllib/files/modules/yaml/huddle\.md) Create and manipulate huddle object



          + [map::geocode::nominatim](tcllib/files/modules/map/map\_geocode\_nominatim\.md) Resolving geographical names with a Nominatim service

          + [map::slippy](tcllib/files/modules/map/map\_slippy\.md) Common code for slippy based map packages

          + [map::slippy::cache](tcllib/files/modules/map/map\_slippy\_cache\.md) Management of a tile cache in the local filesystem

          + [map::slippy::fetcher](tcllib/files/modules/map/map\_slippy\_fetcher\.md) Accessing a server providing tiles for slippy\-based maps

          + [mapproj](tcllib/files/modules/mapproj/mapproj\.md) Map projection routines

          + [math::calculus::symdiff](tcllib/files/modules/math/symdiff\.md) Symbolic differentiation for Tcl

          + [namespacex](tcllib/files/modules/namespacex/namespacex\.md) Namespace utility commands

          + [rest](tcllib/files/modules/rest/rest\.md) define REST web APIs and call them inline or asychronously

          + [stringprep](tcllib/files/modules/stringprep/stringprep\.md) Implementation of stringprep

          + [stringprep::data](tcllib/files/modules/stringprep/stringprep\_data\.md) stringprep data tables, generated, internal

          + [struct::map](tcllib/files/modules/struct/struct\_map\.md) Manage key/value maps

          + [tclrep/machineparameters](tcllib/files/modules/math/machineparameters\.md) Compute double precision machine parameters\.

          + [uevent::onidle](tcllib/files/modules/uev/uevent\_onidle\.md) Request merging and deferal to idle time

          + [unicode](tcllib/files/modules/stringprep/unicode\.md) Implementation of Unicode normalization

Changes to embedded/md/toc1.md.

65
66
67
68
69
70
71




72
73
74
75
76
77
78

          + [blowfish](tcllib/files/modules/blowfish/blowfish\.md) Implementation of the Blowfish block cipher

      * [cache]()

          + [cache::async](tcllib/files/modules/cache/async\.md) Asynchronous in\-memory cache





      * [clock]()

          + [clock\_iso8601](tcllib/files/modules/clock/iso8601\.md) Parsing ISO 8601 dates/times

          + [clock\_rfc2822](tcllib/files/modules/clock/rfc2822\.md) Parsing ISO 8601 dates/times

      * [cmdline]()







>
>
>
>







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

          + [blowfish](tcllib/files/modules/blowfish/blowfish\.md) Implementation of the Blowfish block cipher

      * [cache]()

          + [cache::async](tcllib/files/modules/cache/async\.md) Asynchronous in\-memory cache

      * [clay]()

          + [clay](tcllib/files/modules/clay/clay\.md) A minimalist framework for large scale OO Projects

      * [clock]()

          + [clock\_iso8601](tcllib/files/modules/clock/iso8601\.md) Parsing ISO 8601 dates/times

          + [clock\_rfc2822](tcllib/files/modules/clock/rfc2822\.md) Parsing ISO 8601 dates/times

      * [cmdline]()
298
299
300
301
302
303
304


305
306
307
308
309
310
311
      * [fileutil]()

          + [fileutil](tcllib/files/modules/fileutil/fileutil\.md) Procedures implementing some file utilities

          + [fileutil::multi](tcllib/files/modules/fileutil/multi\.md) Multi\-file operation, scatter/gather, standard object

          + [fileutil::multi::op](tcllib/files/modules/fileutil/multiop\.md) Multi\-file operation, scatter/gather



          + [fileutil\_traverse](tcllib/files/modules/fileutil/traverse\.md) Iterative directory traversal

      * [ftp]()

          + [ftp](tcllib/files/modules/ftp/ftp\.md) Client\-side tcl implementation of the ftp protocol








>
>







302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
      * [fileutil]()

          + [fileutil](tcllib/files/modules/fileutil/fileutil\.md) Procedures implementing some file utilities

          + [fileutil::multi](tcllib/files/modules/fileutil/multi\.md) Multi\-file operation, scatter/gather, standard object

          + [fileutil::multi::op](tcllib/files/modules/fileutil/multiop\.md) Multi\-file operation, scatter/gather

          + [fileutil::paths](tcllib/files/modules/fileutil/paths\.md) Manage search path pools

          + [fileutil\_traverse](tcllib/files/modules/fileutil/traverse\.md) Iterative directory traversal

      * [ftp]()

          + [ftp](tcllib/files/modules/ftp/ftp\.md) Client\-side tcl implementation of the ftp protocol

385
386
387
388
389
390
391
392
393
394
395
396
397
398
399

      * [http]()

          + [autoproxy](tcllib/files/modules/http/autoproxy\.md) Automatic HTTP proxy usage and authentication

      * [httpd]()

          + [tool](tcllib/files/modules/httpd/httpd\.md) A TclOO and coroutine based web server

      * [ident]()

          + [ident](tcllib/files/modules/ident/ident\.md) Ident protocol client

      * [imap4]()








|







391
392
393
394
395
396
397
398
399
400
401
402
403
404
405

      * [http]()

          + [autoproxy](tcllib/files/modules/http/autoproxy\.md) Automatic HTTP proxy usage and authentication

      * [httpd]()

          + [httpd](tcllib/files/modules/httpd/httpd\.md) A TclOO and coroutine based web server

      * [ident]()

          + [ident](tcllib/files/modules/ident/ident\.md) Ident protocol client

      * [imap4]()

510
511
512
513
514
515
516


517
518
519
520
521
522
523
          + [math::numtheory](tcllib/files/modules/math/numtheory\.md) Number Theory

          + [math::optimize](tcllib/files/modules/math/optimize\.md) Optimisation routines

          + [math::PCA](tcllib/files/modules/math/pca\.md) Package for Principal Component Analysis

          + [math::polynomials](tcllib/files/modules/math/polynomials\.md) Polynomial functions



          + [math::rationalfunctions](tcllib/files/modules/math/rational\_funcs\.md) Polynomial functions

          + [math::roman](tcllib/files/modules/math/roman\.md) Tools for creating and manipulating roman numerals

          + [math::special](tcllib/files/modules/math/special\.md) Special mathematical functions








>
>







516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
          + [math::numtheory](tcllib/files/modules/math/numtheory\.md) Number Theory

          + [math::optimize](tcllib/files/modules/math/optimize\.md) Optimisation routines

          + [math::PCA](tcllib/files/modules/math/pca\.md) Package for Principal Component Analysis

          + [math::polynomials](tcllib/files/modules/math/polynomials\.md) Polynomial functions

          + [math::quasirandom](tcllib/files/modules/math/quasirandom\.md) Quasi\-random points for integration and Monte Carlo type methods

          + [math::rationalfunctions](tcllib/files/modules/math/rational\_funcs\.md) Polynomial functions

          + [math::roman](tcllib/files/modules/math/roman\.md) Tools for creating and manipulating roman numerals

          + [math::special](tcllib/files/modules/math/special\.md) Special mathematical functions

830
831
832
833
834
835
836


837
838
839
840
841
842
843
          + [struct::graph](tcllib/files/modules/struct/graph\.md) Create and manipulate directed graph objects

          + [struct::graph::op](tcllib/files/modules/struct/graphops\.md) Operation for \(un\)directed graph objects

          + [struct::graph\_v1](tcllib/files/modules/struct/graph1\.md) Create and manipulate directed graph objects

          + [struct::list](tcllib/files/modules/struct/struct\_list\.md) Procedures for manipulating lists



          + [struct::matrix](tcllib/files/modules/struct/matrix\.md) Create and manipulate matrix objects

          + [struct::matrix\_v1](tcllib/files/modules/struct/matrix1\.md) Create and manipulate matrix objects

          + [struct::pool](tcllib/files/modules/struct/pool\.md) Create and manipulate pool objects \(of discrete items\)








>
>







838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
          + [struct::graph](tcllib/files/modules/struct/graph\.md) Create and manipulate directed graph objects

          + [struct::graph::op](tcllib/files/modules/struct/graphops\.md) Operation for \(un\)directed graph objects

          + [struct::graph\_v1](tcllib/files/modules/struct/graph1\.md) Create and manipulate directed graph objects

          + [struct::list](tcllib/files/modules/struct/struct\_list\.md) Procedures for manipulating lists

          + [struct::map](tcllib/files/modules/struct/struct\_map\.md) Manage key/value maps

          + [struct::matrix](tcllib/files/modules/struct/matrix\.md) Create and manipulate matrix objects

          + [struct::matrix\_v1](tcllib/files/modules/struct/matrix1\.md) Create and manipulate matrix objects

          + [struct::pool](tcllib/files/modules/struct/pool\.md) Create and manipulate pool objects \(of discrete items\)

900
901
902
903
904
905
906


907
908
909
910
911
912
913
      * [textutil]()

          + [textutil](tcllib/files/modules/textutil/textutil\.md) Procedures to manipulate texts and strings\.

          + [textutil::adjust](tcllib/files/modules/textutil/adjust\.md) Procedures to adjust, indent, and undent paragraphs

          + [textutil::expander](tcllib/files/modules/textutil/expander\.md) Procedures to process templates and expand text\.



          + [textutil::repeat](tcllib/files/modules/textutil/repeat\.md) Procedures to repeat strings\.

          + [textutil::split](tcllib/files/modules/textutil/textutil\_split\.md) Procedures to split texts

          + [textutil::string](tcllib/files/modules/textutil/textutil\_string\.md) Procedures to manipulate texts and strings\.








>
>







910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
      * [textutil]()

          + [textutil](tcllib/files/modules/textutil/textutil\.md) Procedures to manipulate texts and strings\.

          + [textutil::adjust](tcllib/files/modules/textutil/adjust\.md) Procedures to adjust, indent, and undent paragraphs

          + [textutil::expander](tcllib/files/modules/textutil/expander\.md) Procedures to process templates and expand text\.

          + [textutil::patch](tcllib/files/modules/textutil/patch\.md) Application of uni\-diff patches to directory trees

          + [textutil::repeat](tcllib/files/modules/textutil/repeat\.md) Procedures to repeat strings\.

          + [textutil::split](tcllib/files/modules/textutil/textutil\_split\.md) Procedures to split texts

          + [textutil::string](tcllib/files/modules/textutil/textutil\_string\.md) Procedures to manipulate texts and strings\.

Changes to examples/httpd/htdocs/index.md.

1
2
3
4
5
6

7
8
9
10
11
12
13
Your test server works!

* [Tcllib embedded docs](/tcllib/index.html)
* [Tcllib's fossil repo (hosted via SCGI)](/fossil)
* [Standard Markdown Example Page](example.md)
* [Static HTML Page](html_static_page.html)


A locally served image:
![Locally Served Image](/tcllib/image/arch_core_container.png "Core Container")

Internal documentation for httpd:

* [Operating Principals](operations.md)






>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
Your test server works!

* [Tcllib embedded docs](/tcllib/index.html)
* [Tcllib's fossil repo (hosted via SCGI)](/fossil)
* [Standard Markdown Example Page](example.md)
* [Static HTML Page](html_static_page.html)
* [Template HTML Page](header.tml)

A locally served image:
![Locally Served Image](/tcllib/image/arch_core_container.png "Core Container")

Internal documentation for httpd:

* [Operating Principals](operations.md)

Changes to examples/httpd/httpd.tcl.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
  }
  if {[llength $args]==0} {
    return $::fossil_exe
  }
  return [exec ${::fossil_exe} {*}$args]
}

tool::define httpd::content.fossil_root {

  method content {} {
    my puts "<HTML><HEAD><TITLE>Local Fossil Repositories</TITLE></HEAD><BODY>"
    global recipe
    my puts "<UL>"
    set dbfiles [::fossil-list]
    foreach file [lsort -dictionary $dbfiles]  {
      dict set result [file rootname [file tail $file]] $file
    }
    foreach {module dbfile} [lsort -dictionary -stride 2 $result] {
      my puts "<li><a HREF=/fossil/$module>$module</a>"
    }
    my puts {</UL></BODY></HTML>}
  }
}


tool::define httpd::content.fossil_node_proxy {

  superclass httpd::content.proxy

  method FileName {} {
    set uri    [my http_info get REQUEST_URI]
    set prefix [my http_info get prefix]
    set module [lindex [split $uri /] 2]
    if {![info exists ::fossil_process($module)]} {
      set dbfiles [::fossil-list]
      foreach file [lsort -dictionary $dbfiles]  {
        dict set result [file rootname [file tail $file]] $file
      }
      if {![dict exists $result $module]} {
        return {}
      }
      set dbfile [dict get $result $module]
      if {![file exists $dbfile]} {
        return {}
      }
      set ::fossil_process($module) $dbfile
    }
    return [list $module $::fossil_process($module)]
  }

  method proxy_path {} {
    set uri [string trimleft [my http_info get REQUEST_URI] /]
    set prefix [my http_info get prefix]
    set module [lindex [split $uri /] 1]
    set path /[string range $uri [string length $prefix/$module] end]
    return $path
  }

  method proxy_channel {} {
    ###
    # This method returns a channel to the
    # proxied socket/stdout/etc
    ###
    lassign [my FileName] module dbfile
    set EXE [my Cgi_Executable fossil]
    set baseurl http://[my http_info get HTTP_HOST][my http_info get prefix]/$module
    if { $::tcl_platform(platform) eq "windows"} {
      return [open "|fossil.exe http $dbfile -baseurl $baseurl" r+]
    } else {
      return [open "|fossil http $dbfile -baseurl $baseurl 2>@1" r+]
    }
  }
}

tool::define httpd::content.fossil_node_scgi {

  superclass httpd::content.scgi
  method scgi_info {} {
    set uri    [my http_info get REQUEST_URI]
    set prefix [my http_info get prefix]
    set module [lindex [split $uri /] 2]
    file mkdir ~/tmp
    if {![info exists ::fossil_process($module)]} {
      package require processman
      package require nettool
      set port [::nettool::allocate_port 40000]
      set handle fossil:$port







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|




|
|



















|
|












|








|



|
|







23
24
25
26
27
28
29


















30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  }
  if {[llength $args]==0} {
    return $::fossil_exe
  }
  return [exec ${::fossil_exe} {*}$args]
}



















clay::define httpd::content.fossil_node_proxy {

  superclass httpd::content.proxy

  method FileName {} {
    set uri    [my request get REQUEST_URI]
    set prefix [my clay get prefix]
    set module [lindex [split $uri /] 2]
    if {![info exists ::fossil_process($module)]} {
      set dbfiles [::fossil-list]
      foreach file [lsort -dictionary $dbfiles]  {
        dict set result [file rootname [file tail $file]] $file
      }
      if {![dict exists $result $module]} {
        return {}
      }
      set dbfile [dict get $result $module]
      if {![file exists $dbfile]} {
        return {}
      }
      set ::fossil_process($module) $dbfile
    }
    return [list $module $::fossil_process($module)]
  }

  method proxy_path {} {
    set uri [string trimleft [my request get REQUEST_URI] /]
    set prefix [my clay get prefix]
    set module [lindex [split $uri /] 1]
    set path /[string range $uri [string length $prefix/$module] end]
    return $path
  }

  method proxy_channel {} {
    ###
    # This method returns a channel to the
    # proxied socket/stdout/etc
    ###
    lassign [my FileName] module dbfile
    set EXE [my Cgi_Executable fossil]
    set baseurl http://[my request get HTTP_HOST][my clay get prefix]/$module
    if { $::tcl_platform(platform) eq "windows"} {
      return [open "|fossil.exe http $dbfile -baseurl $baseurl" r+]
    } else {
      return [open "|fossil http $dbfile -baseurl $baseurl 2>@1" r+]
    }
  }
}

clay::define httpd::content.fossil_node_scgi {

  superclass httpd::content.scgi
  method scgi_info {} {
    set uri    [my request get REQUEST_URI]
    set prefix [my clay get prefix]
    set module [lindex [split $uri /] 2]
    file mkdir ~/tmp
    if {![info exists ::fossil_process($module)]} {
      package require processman
      package require nettool
      set port [::nettool::allocate_port 40000]
      set handle fossil:$port
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
      my varname paused
      after 500
    }
    return [list localhost $port $SCRIPT_NAME]
  }
}

tool::class create ::docserver::server {
  superclass ::httpd::server

  method log args {
    #puts [list {*}$args]
  }

}

tool::define ::docserver::dynamic {

  method content {} {
    my puts "<HTML><HEAD><TITLE>IRM Dispatch Server</TITLE></HEAD><BODY>"
    my puts "<TABLE width=100%>"
    foreach {f v} [my request dump] {
        my puts "<tr><th>$f</th><td>$v</td></tr>"
    }
    my puts "<tr><td colspan=10><hr></td></tr>"
    foreach {f v} [my http_info dump] {
        my puts "<tr><th>$f</th><td>$v</td></tr>"
    }
    my puts "<tr><th>File Size</th><td>[my http_info get CONTENT_LENGTH]</td></tr>"
    my puts </TABLE>
    my puts </BODY></HTML>
  }

}

tool::define ::docserver::upload {
  superclass ::docserver::dynamic

  method content {} {
    my puts "<HTML><HEAD><TITLE>IRM Dispatch Server</TITLE></HEAD><BODY>"
    my puts "<TABLE width=100%>"
    set FORMDAT [my FormData]
    foreach {f v} [my FormData] {
        my puts "<tr><th>$f</th><td>$v</td></tr>"
    }
    my puts "<tr><td colspan=10><hr></td></tr>"
    foreach {f v} [my http_info dump] {
        my puts "<tr><th>$f</th><td>$v</td></tr>"
    }
    my puts "<tr><td colspan=10><hr></td></tr>"
    foreach part [dict getnull $FORMDAT MIME_PARTS] {
      my puts "<tr><td colspan=10><hr></td></tr>"
      foreach f [::mime::getheader $part -names] {
        my puts "<tr><th>$f</th><td>[mime::getheader $part $f]</td></tr>"
      }
      my puts "<tr><td colspan=10>[::mime::getbody $part -decode]</td></tr>"
    }
    my puts "<tr><th>File Size</th><td>[my http_info get CONTENT_LENGTH]</td></tr>"
    my puts </TABLE>
    my puts </BODY></HTML>
  }
}

set opts [::tool::args_to_options {*}$argv]
set serveropts {}
set optinfo [::docserver::server meta getnull option]
foreach {f v} $opts {
  if {[dict exists $optinfo $f]} {
    dict set serveropts $f $v
  }
}
puts $serveropts
set fossilopts {}
set optinfo [::httpd::content.fossil_root meta getnull option]
foreach {f v} $opts {
  if {[dict exists $optinfo $f]} {
    dict set fossilopts $f $v
  }
}
if {[dict exists $opts fossil]} {
  set ::fossil_exe [dict get $opts fossil]
}

::docserver::server create appmain doc_root $DEMOROOT {*}$argv
appmain plugin basic_url ::httpd::plugin.dict_dispatch
appmain uri add /tcllib* [list mixin httpd::content.file path [file join $tcllibroot embedded www]]
appmain uri add /fossil [list mixin httpd::content.fossil_root {*}$fossilopts]












appmain uri add /fossil/* [list mixin httpd::content.fossil_node_proxy {*}$fossilopts]
appmain uri add /upload [list mixin ::docserver::upload]
appmain uri add /dynamic [list mixin ::docserver::dynamic]






















appmain uri add /listen [list mixin ::docserver::listen]













appmain uri add /send   [list mixin ::docserver::send]
puts [list LISTENING on [appmain port_listening]]
tool::main







|


|
|

<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|

<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
|



<
<
<
<
|
<
<
<
<
|




|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|

|
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
      my varname paused
      after 500
    }
    return [list localhost $port $SCRIPT_NAME]
  }
}

::clay::define ::docserver::server {
  superclass ::httpd::server

  method debug args {
    #puts [list DEBUG {*}$args]
  }





  method log args {













    #puts [list LOG {*}$args]
  }










}



















set serveropts [::httpd::server clay get server/]

foreach {f v}  [::clay::args_to_options {*}$::argv] {
  if {[dict exists $serveropts $f]} {
    dict set serveropts $f $v
  }
}




if {[dict exists $serveropts fossil]} {




  set ::fossil_exe [dict get $serveropts fossil]
}

::docserver::server create appmain doc_root $DEMOROOT {*}$argv
appmain plugin basic_url ::httpd::plugin.dict_dispatch
appmain uri add * /tcllib* [list mixin {reply httpd::content.file} path [file join $tcllibroot embedded www]]
appmain uri direct * /fossil {} {
  my puts "<HTML><HEAD><TITLE>Local Fossil Repositories</TITLE></HEAD><BODY>"
  global recipe
  my puts "<UL>"
  set dbfiles [::fossil-list]
  foreach file [lsort -dictionary $dbfiles]  {
    dict set result [file rootname [file tail $file]] $file
  }
  foreach {module dbfile} [lsort -dictionary -stride 2 $result] {
    my puts "<li><a HREF=/fossil/$module>$module</a>"
  }
  my puts {</UL></BODY></HTML>}
}
appmain uri add * /fossil/* [list mixin {reply httpd::content.fossil_node_proxy}]
appmain uri direct * /upload {} {

  my puts "<HTML><HEAD><TITLE>IRM Dispatch Server</TITLE></HEAD><BODY>"
  my puts "<TABLE width=100%>"
  set FORMDAT [my FormData]
  foreach {f v} [my FormData] {
      my puts "<tr><th>$f</th><td>$v</td></tr>"
  }
  my puts "<tr><td colspan=10><hr></td></tr>"
  foreach {f v} [my clay dump] {
      my puts "<tr><th>$f</th><td>$v</td></tr>"
  }
  my puts "<tr><td colspan=10><hr></td></tr>"
  foreach part [dict getnull $FORMDAT MIME_PARTS] {
    my puts "<tr><td colspan=10><hr></td></tr>"
    foreach f [::mime::getheader $part -names] {
      my puts "<tr><th>$f</th><td>[mime::getheader $part $f]</td></tr>"
    }
    my puts "<tr><td colspan=10>[::mime::getbody $part -decode]</td></tr>"
  }
  my puts "<tr><th>File Size</th><td>[my request get CONTENT_LENGTH]</td></tr>"
  my puts </TABLE>
  my puts </BODY></HTML>
}
appmain uri direct * /dynamic {} {
  my puts "<HTML><HEAD><TITLE>IRM Dispatch Server</TITLE></HEAD><BODY>"
  my puts "<TABLE width=100%>"
  foreach {f v} [my request dump] {
    my puts "<tr><th>$f</th><td>$v</td></tr>"
  }
  my puts "<tr><td colspan=10><hr></td></tr>"
  foreach {f v} [my clay dump] {
    my puts "<tr><th>$f</th><td>$v</td></tr>"
  }
  my puts "<tr><th>File Size</th><td>[my request get CONTENT_LENGTH]</td></tr>"
  my puts </TABLE>
  my puts </BODY></HTML>
}

puts [list LISTENING on [appmain port_listening]]
cron::main

Added idoc/man/files/devdoc/tcl_community_communication.n.





































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
'\"
'\" Generated from file 'tcl_community_communication\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "tcl_community_communication" n 1 tcllib ""
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
.\"	and indent is equivalent to second arg of .IP (shouldn't ever be
.\"	needed;  use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\"	Give maximum sizes of arguments for setting tab stops.  Type and
.\"	name are examples of largest possible arguments that will be passed
.\"	to .AP later.  If args are omitted, default tab stops are used.
.\"
.\" .BS
.\"	Start box enclosure.  From here until next .BE, everything will be
.\"	enclosed in one large box.
.\"
.\" .BE
.\"	End of box enclosure.
.\"
.\" .CS
.\"	Begin code excerpt.
.\"
.\" .CE
.\"	End code excerpt.
.\"
.\" .VS ?version? ?br?
.\"	Begin vertical sidebar, for use in marking newly-changed parts
.\"	of man pages.  The first argument is ignored and used for recording
.\"	the version when the .VS was added, so that the sidebars can be
.\"	found and removed when they reach a certain age.  If another argument
.\"	is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\"	End of vertical sidebar.
.\"
.\" .DS
.\"	Begin an indented unfilled display.
.\"
.\" .DE
.\"	End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\"	Start of list of standard options for a Tk widget. The manpage
.\"	argument defines where to look up the standard options; if
.\"	omitted, defaults to "options". The options follow on successive
.\"	lines, in three columns separated by tabs.
.\"
.\" .SE
.\"	End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\"	Start of description of a specific option.  cmdName gives the
.\"	option's name as specified in the class command, dbName gives
.\"	the option's name in the option database, and dbClass gives
.\"	the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\"	Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\"	Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\"	Print an open parenthesis, arg1 in quotes, then arg2 normally
.\"	(for trailing punctuation) and then a closing parenthesis.
.\"
.\"	# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\"	# Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
.   ie !"\\$2"" .TP \\n()Cu
.   el          .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1	\\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\"	# define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\"	# BS - start boxed text
.\"	# ^y = starting y location
.\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\"	Draw four-sided box normally, but don't draw top of
.\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# VS - start vertical sidebar
.\"	# ^Y = starting y location
.\"	# ^v = 1 (for troff;  for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\"	# VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\"	# Special macro to handle page bottom:  finish off current
.\"	# box/sidebar if in box/sidebar mode, then invoked standard
.\"	# page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\"	Draw three-sided box if this is the box's first page,
.\"	draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\"	# DS - begin display
.de DS
.RS
.nf
.sp
..
.\"	# DE - end display
.de DE
.fi
.RE
.sp
..
.\"	# SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\"	# SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\"	# OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name:	\\fB\\$1\\fR
Database Name:	\\fB\\$2\\fR
Database Class:	\\fB\\$3\\fR
.fi
.IP
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
.\"	# UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\"	# QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\"	# PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\"	# QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
tcl_community_communication \- Tcl Community - Kind Communication
.SH DESCRIPTION
The Tcl Community encourages contributions from anyone who wishes to
advance the development of:
.IP \(bu
The Tcl Language
.IP \(bu
Tcl derived languages
.IP \(bu
Tcl related libraries
.IP \(bu
Tcl extensions
.IP \(bu
External Projects that Integrate Tcl
.PP
.PP
We welcome those contributions from anyone\&. We are blind to
gender, race, religion, cultural background, cybernetic nature, and
any other demographic characteristics, as well as personal political
views\&.
.PP
A community lives and dies by communications\&. And occasionally
our communications are peppered with patterns that are harsh,
unfriendly, unwelcoming and/or otherwise unkind\&. As a volunteer
community, we need all of the help we can get\&. Therefore, we ask all
contributors to make a conscious effort, in Tcl Community discussions,
to communicate in ways that are welcoming\&. Ways that are
friendly\&. Ways that are, in a word: kind\&.
.PP
These guidelines suggest specific ways to accomplish that goal\&.
.PP
Please note: for the balance of this document any reference to
"People", "Persons", "anybody" or "somebody" can refer to any sentient
being, not merely corporeal members of the species Homo Sapien\&.
.TP
We are a Sanctuary not a Clubhouse
The Tcl Community is a collective of amateurs and professionals who
code, test, and use tools\&. Our community is open to all\&. There is no
velvet rope\&. There is no bouncer at the door\&. There are no secret
handshakes\&. Any sentient being who enters our midst is welcome\&. If
someone is ever asked to leave, it is only because they are being
disruptive to the functioning of the community\&.
.TP
We Merit Ideas, Not People
A good idea can come from anyone, regardless of how little time they
have been with us\&. A bad idea can come from anyone, regardless of how
much time or how little time they have been with us\&. We judge a
concept by how it stands up to scrutiny of logic, implementation, and
regression testing\&. We don’t judge ideas based on who had the idea
first, who agrees with the idea, or who disagrees with it\&.
.TP
Treat Everyone with Respect
Everyone is deserving of respect and courtesy at all times\&.
.TP
Refer to people by the names they use\&.
If grammar requires you to state a gender for a person, honor their
preferences about their gender identity\&. If you are unsure as to the
gender of an individual, ask\&. If someone had to guess about your
gender and got it wrong, please correct them and do not take it
personally\&.
.TP
Do not take a harsh tone towards other participants\&.
Do not make personal attacks against anyone (participant or not\&.)
.sp
Criticize statements and actions, never people\&.
.TP
Don’t Take Things Personally
When in doubt, assume the best in people\&. A criticism of your
statements is not a personal attack on you\&.
.TP
Persons, not People
Stereotypes are an unhelpful tool on many accounts\&. They are generally
oversimplified\&. They are usually flat out wrong\&. And even if "right"
they are of absolutely no utility in determining the capabilities,
motivations, or fitness of an individual\&.
.sp
Don’t use them in Tcl Community communications\&.
.TP
Mistakes Happen
The human condition is a series of trials and errors\&. Progress is when
we get one more trial than error\&. Being wrong or making a mistake is
the default state of humanity\&. Accept the errors of your fellow
sentient beings, and be aware that you are also fallible\&.
.TP
Keep it Real
Please respond to what people actually say\&. We are all amazing
individuals, but none among us are mind readers\&. If you find yourself
responding to what you imagine someone is thinking, odds are you are
going to be wrong\&.
.sp
If you must criticize someone, stick to things they have
actually done\&. Never criticize for something you speculate they have
done\&. Or imagine they have done\&. Or something someone who shares some
attribute with them has done in the past\&.
.sp
Keep discussions about any non-Tcl subjects to what can be
stated factually and without emotion or judgement\&.
.TP
When Trouble Arises, Don’t Escalate
If you feel you are being personally attacked or offended, take the
high road\&. Punching back in a public forum will only makes things
worse\&. Address the matter in a private correspondence\&. Be
polite\&. Express your feelings, but note that you are expressing your
feelings\&. When writing, look for a way to calm matters down\&. And when
in doubt, sleep on your letter before pressing send\&. And when not in
doubt, sleep on it for another day after that\&.
.sp
If you are a spectator to a fight in progress, politely request
the two parties take the matter to a more private forum\&.
.TP
Always get the Last Word: I’m Sorry
If an personal argument does arise, be the first to apologize\&. An
apology does not concede a logical point\&. It merely acknowledges that
at some point the discussion left either logic, community decency, or
both\&. Return to the topic when cooler heads can prevail\&.
.TP
Nobody is Keeping Score
There is no prize for being right\&. There is no cost for being wrong\&. A
hard sell is not going to advance your idea along any more than a
logical argument\&. You aren’t running for office\&. This isn’t debate
club\&. If you find yourself continuing a discussion beyond where a
topic can be logically discussed, stop\&.
.TP
No Evangelizing
The Tcl Community is not the place to promote your chosen operating
system, political outlook, religion, marketing scheme, or economic
model\&. Period\&.
.sp
(And if you do bring it up, be prepared to have your chosen
topic discussed logically\&. And odds are, not favorably\&.)
.TP
Respect the Community
If the Community has come to a decision on a course of action, please
stop arguing\&.
.sp
If someone complains about how you are expressing your ideas,
listen\&.
.sp
If your words are hurting people, stop\&. There is no amount of
being "right" that makes up for someone leaving our midst because they
felt insulted, threatened, or ignored\&.
.PP
By following these guidelines, we will build our community, encourage
more contribution to our projects, and our discussions will be
friendlier and reach conclusions more easily\&.
.PP
Thank You\&.
.SH SIGNATORIES
.IP \(bu
Sean "the Hypnotoad" Woods
.IP \(bu
Andreas Kupries
.PP
.SH AUTHORS
.TP
Primary
Sean "the Hypnotoad" Woods
.TP
Light editing
Andreas Kupries
.PP

Added idoc/man/files/devdoc/tcllib_devguide.n.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
'\"
'\" Generated from file 'tcllib_devguide\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "tcllib_devguide" n 1 tcllib ""
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
.\"	and indent is equivalent to second arg of .IP (shouldn't ever be
.\"	needed;  use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\"	Give maximum sizes of arguments for setting tab stops.  Type and
.\"	name are examples of largest possible arguments that will be passed
.\"	to .AP later.  If args are omitted, default tab stops are used.
.\"
.\" .BS
.\"	Start box enclosure.  From here until next .BE, everything will be
.\"	enclosed in one large box.
.\"
.\" .BE
.\"	End of box enclosure.
.\"
.\" .CS
.\"	Begin code excerpt.
.\"
.\" .CE
.\"	End code excerpt.
.\"
.\" .VS ?version? ?br?
.\"	Begin vertical sidebar, for use in marking newly-changed parts
.\"	of man pages.  The first argument is ignored and used for recording
.\"	the version when the .VS was added, so that the sidebars can be
.\"	found and removed when they reach a certain age.  If another argument
.\"	is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\"	End of vertical sidebar.
.\"
.\" .DS
.\"	Begin an indented unfilled display.
.\"
.\" .DE
.\"	End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\"	Start of list of standard options for a Tk widget. The manpage
.\"	argument defines where to look up the standard options; if
.\"	omitted, defaults to "options". The options follow on successive
.\"	lines, in three columns separated by tabs.
.\"
.\" .SE
.\"	End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\"	Start of description of a specific option.  cmdName gives the
.\"	option's name as specified in the class command, dbName gives
.\"	the option's name in the option database, and dbClass gives
.\"	the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\"	Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\"	Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\"	Print an open parenthesis, arg1 in quotes, then arg2 normally
.\"	(for trailing punctuation) and then a closing parenthesis.
.\"
.\"	# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\"	# Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
.   ie !"\\$2"" .TP \\n()Cu
.   el          .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1	\\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\"	# define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\"	# BS - start boxed text
.\"	# ^y = starting y location
.\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\"	Draw four-sided box normally, but don't draw top of
.\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# VS - start vertical sidebar
.\"	# ^Y = starting y location
.\"	# ^v = 1 (for troff;  for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\"	# VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\"	# Special macro to handle page bottom:  finish off current
.\"	# box/sidebar if in box/sidebar mode, then invoked standard
.\"	# page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\"	Draw three-sided box if this is the box's first page,
.\"	draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\"	# DS - begin display
.de DS
.RS
.nf
.sp
..
.\"	# DE - end display
.de DE
.fi
.RE
.sp
..
.\"	# SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\"	# SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\"	# OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name:	\\fB\\$1\\fR
Database Name:	\\fB\\$2\\fR
Database Class:	\\fB\\$3\\fR
.fi
.IP
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
.\"	# UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\"	# QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\"	# PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\"	# QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
tcllib_devguide \- Tcllib - The Developer's Guide
.SH SYNOPSIS
\fBModule\fR \fIname\fR \fIcode-action\fR \fIdoc-action\fR \fIexample-action\fR
.sp
\fBApplication\fR \fIname\fR
.sp
\fBExclude\fR \fIname\fR
.sp
.BE
.SH DESCRIPTION
Welcome to Tcllib, the Tcl Standard Library\&. Note that Tcllib is not a
package itself\&. It is a collection of (semi-independent) \fITcl\fR
packages that provide utility functions useful to a large collection
of Tcl programmers\&.
.PP
This document is a guide for developers working on Tcllib,
i\&.e\&. maintainers fixing bugs, extending the collection's
functionality, etc\&.
.PP
Please read
.IP [1]
\fITcllib - How To Get The Sources\fR and
.IP [2]
\fITcllib - The Installer's Guide\fR
.PP
first, if that was not done already\&.
.PP
Here we assume that the sources are already available in a
directory of your choice, and that you not only know how to build and
install them, but also have all the necessary requisites to actually
do so\&. The guide to the sources in particular also explains which
source code management system is used, where to find it, how to set it
up, etc\&.
.SH COMMITMENTS
.SS CONTRIBUTOR
As a contributor to Tcllib you are committing yourself to:
.IP [1]
keep the guidelines written down in
\fITcl Community - Kind Communication\fR in your mind\&.
The main point to take away from there is
\fIto be kind to each other\fR\&.
.IP [2]
Your contributions getting distributed under a BSD/MIT license\&.
For the details see \fITcllib - License\fR
.PP
Contributions are made by entering tickets into our tracker, providing
patches, bundles or branches of code for inclusion, or posting to the
Tcllib related mailing lists\&.
.SS MAINTAINER
When contributing one or more packages for full inclusion into Tcllib
you are committing yourself to
.IP [1]
Keep the guidelines written down in
\fITcl Community - Kind Communication\fR
(as any contributor) in your mind\&. The main point to take away
from there is \fIto be kind to each other\fR\&.
.IP [2]
Your packages getting distributed under a BSD/MIT license\&.  For
the details see \fITcllib - License\fR
.IP [3]
Maintenance of the new packages for a period of two years under
the following rules, and responsibilities:
.RS
.IP [1]
A maintainer may step down after the mandatory period as
they see fit\&.
.IP [2]
A maintainer may step down before the end of the
mandatory period, under the condition that a replacement
maintainer is immediately available and has agreed to
serve the remainder of the period, plus their own
mandatory period (see below)\&.
.IP [3]
When stepping down without a replacement maintainer
taking over the relevant packages have to be flagged as
\fBunmaintained\fR\&.
.IP [4]
When a replacement mantainer is brought in for a package
it is (kept) marked as \fBmaintained\fR (again)\&.
.sp
A replacement maintainer is bound by the same rules as
the original maintainer, except that the mandatory
period of maintenance is shortened to one year\&.
.IP [5]
For any \fBunmaintained\fR package a contributor
interested in becoming its maintainer can become so by
flagging them as \fBmaintained\fR with their name and
contact information, committing themselves to the rules
of a replacement maintainer (see previous point)\&.
.IP [6]
For any already \fBmaintained\fR package a contributor
interested in becoming a co-maintainer can become so
with the agreement of the existing maintainer(s),
committing themselves to the rules of a replacement
maintainer (see two points previous)\&.
.RE
.sp
The responsibilities as a maintainer include:
.RS
.IP [1]
Watching Tcllib's ticket tracker for bugs, bug fixes,
and feature requests related to the new packages\&.
.IP [2]
Reviewing the aforementioned tickets, rejecting or
applying them
.IP [3]
Coordination and discussion with ticket submitter during
the development and/or application of bug fixes\&.
.RE
.IP [4]
Follow the \fBBranching and Workflow\fR of this guide\&.
.PP
.SH "BRANCHING AND WORKFLOW"
.SS "PACKAGE DEPENDENCIES"
Regarding packages and dependencies between them Tcllib occupies a
middle position between two extremes:
.IP [1]
On one side a strongly interdependent set of packages, usually
by a single author, for a single project\&. Looking at my
(Andreas Kupries) own work examples of such are
\fIMarpa\fR [https://core\&.tcl\&.tk/akupries/marpa/index],
\fICRIMP\fR [https://core\&.tcl\&.tk/akupries/crimp/index],
\fIKinetcl\fR [https://core\&.tcl\&.tk/akupries/kinetcl/index], etc\&.
.sp
For every change the author of the project handles all the
modifications cascading from any incompatibilities it
introduced to the system\&.
.IP [2]
On the other side, the world of semi-independent projects by
many different authors where authors know what packages their
own creations depend on, yet usually do not know who else
depends on them\&.
.sp
The best thing an author making an (incompatible) change to
their project can do is to for one announce such changes in
some way, and for two use versioning to distinguish the code
before and after the change\&.
.sp
The world is then responsible for adapting, be it by updating
their own projects to the new version, or by sticking to the
old\&.
.PP
As mentioned already, Tcllib lives in the middle of that\&.
.PP
While we as maintainers cannot be aware of all users of
Tcllib's packages, and thus have to rely on the mechanisms
touched on in point 2 above for that, the dependencies between
the packages contained in Tcllib are a different matter\&.
.PP
As we are collectively responsible for the usability of Tcllib
in toto to the outside world, it behooves us to be individually
mindful even of Tcllib packages we are not directly
maintaining, when they depend on packages under our
maintainership\&.
This may be as simple as coordinating with the maintainers of
the affected packages\&.
It may also require us to choose how to adapt affected packages
which do not have maintainers, i\&.e\&. modify them to use our
changed package properly, or modify them to properly depend on
the unchanged version of our package\&.
.PP
Note that the above is not only a chore but an opportunity as
well\&.
Additional insight can be had by forcing ourselves to look at
our package and the planned change(s) from an outside
perspective, to consider the ramifications of our actions on
others in general, and on dependent packages in particular\&.
.SS TRUNK
The management and use of branches is an important part of working
with a \fIDistributed Version Control System\fR (\fIDVCS\fR) like
\fIfossil\fR [https://www\&.fossil-scm\&.org/]\&.
.PP
For Tcllib the main branch of the collection is
\fItrunk\fR\&. In \fIgit\fR this branch would be called
\fImaster\fR, and this is exactly the case in the
\fIgithub mirror\fR [https://github\&.com/tcltk/tcllib/] of
Tcllib\&.
.PP
To properly support debugging \fIeach commit\fR on this
branch \fIhas to pass the entire testsuite\fR of the
collection\&. Using bisection to determine when an issue appeared
is an example of an action made easier by this constraint\&.
.PP
This is part of our collective responsibility for the usability
of Tcllib in toto to the outside world\&.
As \fIfossil\fR has no mechanism to enforce this condition
this is handled on the honor system for developers and maintainers\&.
.PP
To make the task easier Tcllib comes with a tool
("\fIsak\&.tcl\fR") providing a number of commands in
support\&. These commands are explained in the following sections
of this guide\&.
.PP
While it is possible and allowed to commit directly to trunk
remember the above constraint regarding the testsuite, and the
coming notes about other possible issues with a commit\&.
.SS BRANCHES
Given the constraints placed on the \fItrunk\fR branch of the
repository it is (strongly) recommended to perform any development
going beyond trivial changes on a non-trunk branch\&.
.PP
Outside of the trunk developers are allowed to commit
intermediate broken states of their work\&.
Only at the end of a development cycle, when the relevant
branch is considered ready for merging, will it be necessary to
perform full the set of validations ensuring that the merge to
come will create a good commit on trunk\&.
.PP
Note that while a review from a second developer is not a
required condition for merging a branch it is recommended to
seek out such an independent opinion as a means of
cross-checking the work\&.
.PP
It also recommended to give any new branch a name which aids in
determining additional details about it\&. Examples of good
things to stick into a branch name would be
.IP \(bu
Developer (nick)name
.IP \(bu
Ticket hash/reference
.IP \(bu
One or two keywords applicable to the work
.IP \(bu
\&.\&.\&.
.PP
.PP
Further, while most development branches are likely quite
short-lived, no prohibitions exist against making longer-lived
branches\&.
Creators should however be mindful that the longer such a
branch exists without merges the more divergent they will tend
to be, with an associated increase in the effort which will
have to be spent on either merging from and merging to trunk\&.
.SS "WORKING WITH BRANCHES"
In the hope of engendering good work practices now a few example
operations which will come up with branches, and their associated
fossil command (sequences)\&.
.TP
\fIAwareness\fR
When developing we have to keep ourselves aware of the context of our
work\&. On what branch are we ? What files have we changed ? What new
files are not yet known to the repository ? What has happened remotely
since we used our checkout ?
The answers to these questions become especially important when using
a long-lived checkout and coming back to it after some time away\&.
.sp
Commands to answer questions like the above are:
.RS
.TP
\fBfossil pull\fR
Get all changes done on the remote since the last pull or sync
from it\&. This has to be done first, before any of the commands
below\&.
.sp
Even if the commit in our checkout refers to the branch we want
right now control operations committed to the remote may have
changed that from underneath us\&.
.TP
\fBfossil info | grep tags\fR
.TP
\fBfossil branch list | grep '\\*'\fR
Two different ways of determining the branch our checkout is
on\&.
.TP
\fBfossil timeline\fR
What have we (and others) done recently ?
.sp
\fIAttention\fR, this information is very likely outdated, the
more the longer we did not use this checkout\&.
Run \fBfossil pull\fR first to get latest information from
the remote repository of the project\&.
.TP
\fBfossil timeline current\fR
Place the commit our checkout is based on at the top of the
timeline\&.
.TP
\fBfossil changes\fR
Lists the files we have changed compared to the commit the
checkout is based on\&.
.TP
\fBfossil extra\fR
Lists the files we have in the checkout the repository does not
know about\&. This may be leftover chaff from our work, or
something we have forgotten to \fBfossil add\fR to the
repository yet\&.
.RE
.TP
\fIClean checkouts\fR
Be aware of where you are (see first definition)\&.
.sp
For pretty much all the operation recipes below a clean
checkout is at least desired, often required\&.
To check that a checkout is clean invoke
.CS


    fossil changes
    fossil extra

.CE
.IP
How to clean up when uncommitted changes of all sorts are found is
context-specific and outside of the scope of this guide\&.
.TP
\fIStarting a new branch\fR
Be aware of where you are (see first definition)\&.
.sp
Ensure that you have clean checkout (see second definition)\&.
It is \fIrequired\fR\&.
.sp
In most situations you want to be on branch \fItrunk\fR, and
you want to be on the latest commit for it\&. To get there use
.CS


    fossil pull
    fossil update trunk

.CE
.IP
If some other branch is desired as the starting point for the coming
work replace \fItrunk\fR in the commands above with the name of that
branch\&.
.sp
With the base line established we now have two ways of creating
the new branch, with differing (dis)advantages\&.
The simpler way is to
.CS


    fossil branch new NAME_OF_NEW_BRANCH

.CE
.IP
and start developing\&. The advantage here is that you cannot forget to
create the branch\&. The disadvantages are that we have a branch commit
unchanged from where we branched from, and that we have to use
high-handed techniques like hiding or shunning to get rid of the
commit should we decide to abandon the work before the first actual
commit on the branch\&.
.sp
The other way of creating the branch is to start developing,
and then on the first commit use the option \fB--branch\fR to tell
\fBfossil\fR that we are starting a branch now\&. I\&.e\&. run
.CS


    fossil commit --branch NAME_OF_NEW_BRANCH \&.\&.\&.

.CE
.IP
where \fI\&.\&.\&.\fR are any other options used to supply the commit
message, files to commit, etc\&.
.sp
The (dis)advantages are now reversed\&.
.sp
We have no superflous commit, only what is actually
developed\&. The work is hidden until we commit to make our first
commit\&.
.sp
We may forget to use \fB--branch NAME_OF_NEW_BRANCH\fR and
then have to correct that oversight via the fossil web
interface (I am currently unaware of ways of doing such from
the command line, although some magic incantantion of
\fBfossil tag create\fR may work)\&.
.sp
It helps to keep awareness, like checking before any commit
that we are on the desired branch\&.
.TP
\fIMerging a branch into trunk\fR
Be aware of where you are (see first definition)\&.
.sp
Ensure that you have clean checkout (see second definition)\&.
In the full-blown sequence (zig-zag) it is \fIrequired\fR, due
to the merging from trunk\&. In the shorter sequence it is only
desired\&. That said, keeping the checkout clean before
any major operations is a good habit to have, in my opinion\&.
.sp
The full-blown sequencing with checks all the way is to
.RS
.IP [1]
Validate the checkout, i\&.e\&. last commit on your branch\&. Run the
full test suite and other validations, fix all the issues which
have cropped up\&.
.IP [2]
Merge the latest state of the \fItrunk\fR (see next definition)\&.
.IP [3]
Validate the checkout again\&. The incoming trunk changes may
have broken something now\&. Do any required fixes\&.
.IP [4]
Now merge to the trunk using
.CS


    fossil update trunk
    fossil merge --integrate YOUR_BRANCH

.CE
.IP [5]
At this point the checkout should be in the same state as at
the end of point (3) above, because we resolved any issues with
the trunk already\&. Thus a simple
.CS


    fossil commit \&.\&.\&.

.CE
.IP
should be sufficient now to commit the merge back and close the
branch (due to the \fB--integrate\fR we used on the merge)\&.
.sp
The more paranoid may validate the checkout a third time before
commiting\&.
.RE
.sp
I call this a \fIzig-zag merge\fR because of how the arrows
look in the timeline, from trunk to feature branch for the
first merge, and then back for the final merge\&.
.sp
A less paranoid can do what I call a \fIsimple merge\fR,
which moves step (2) after step (4) and skips step (3)
entirely\&. The resulting shorter sequence is
.RS
.IP [1]
Validate
.IP [2]
Merge to trunk
.IP [3]
Validate again
.IP [4]
Commit to trunk
.RE
.IP
The last step after either zig-zag or plain merge is to
.CS


    fossil sync

.CE
.IP
This saves our work to the remote side, and further gives us any other
work done while we were doing our merge\&. It especially allows us to
check if we raced somebody else, resulting in a split trunk\&.
.sp
When that happens we should coordinate with the other developer
on who fixes the split, to ensure that we do not race each
other again\&.
.TP
\fIMerging from trunk\fR
Be aware of where you are (see first definition)\&.
.sp
Ensure that you have clean checkout (see second definition)\&.
It is \fIrequired\fR\&.
.sp
In most situations you want to import the latest commit of
branch \fItrunk\fR (or other origin)\&. To get it use
.CS


    fossil pull

.CE
.sp
With that done we can now import this commit into our current
branch with
.CS


    fossil merge trunk

.CE
.sp
Even if \fBfossil\fR does not report any conflicts it is a
good idea to check that the operation has not broken the new
and/or changed functionality we are working on\&.
.sp
With the establishment of a good merge we then save the state
with
.CS


    fossil commit \&.\&.\&.

.CE
.IP
before continuing development\&.
.PP
.SS "VERSION NUMBERS"
In Tcllib all changes to a package have to come with an increment of
its version number\&. What part is incremented (patchlevel, minor, major
version) depends on the kind of change made\&. With multiple changes in
a commit the highest "wins"\&.
.PP
When working in a development branch the version change can be
deferred until it is time to merge, and then has to cover all
the changes in the branch\&.
.PP
Below a list of the kinds of changes and their associated
version increments:
.TP
\fID - documentation\fR
No increment
.TP
\fIT - testsuite\fR
No increment
.TP
\fIB - bugfix\fR
Patchlevel
.TP
\fII - implementation tweak\fR
Patchlevel
.TP
\fIP - performance tweak\fR
Patchlevel
.TP
\fIE - backward-compatible extension\fR
Minor
.TP
\fIAPI - incompatible change\fR
Major
.PP
.PP
Note that a commit containing a version increment has to
mention the new version number in its commit message, as well
as the kind of change which caused it\&.
.PP
Note further that the version number of a package currently
exists in three places\&. An increment has to update all of them:
.IP [1]
The package implementation\&.
.IP [2]
The package index ("\fIpkgIndex\&.tcl\fR")
.IP [3]
The package documentation\&.
.PP
.PP
The "\fIsak\&.tcl\fR" command \fBvalidate version\fR helps
finding discrepancies between the first two\&.
All the other \fBvalidate\fR methods are also of interest to
any developer\&. Invoke it with
.CS

 sak\&.tcl help validate
.CE
to see their documentation\&.
.SH "STRUCTURAL OVERVIEW"
.SS "MAIN DIRECTORIES"
The main directories in the Tcllib toplevel directory and of interest
to a developer are:
.TP
"\fImodules\fR"
Each child directory represents one or more packages\&.
In the case of the latter the packages are usually related in some
way\&. Examples are "\fIbase64\fR", "\fImath\fR", and "\fIstruct\fR", with
loose (base64) to strong (math) relations between the packages in the
directory\&.
.TP
"\fIapps\fR"
This directory contains all the installable applications, with their
documentation\&. Note that this directory is currently \fInot\fR split
into sub-directories\&.
.TP
"\fIexamples\fR"
Each child directory "\fIfoo\fR" contains one or more example
application for the packages in "\fImodules/foo\fR"\&. These examples are
generally not polished enough to be considered for installation\&.
.PP
.SS "MORE DIRECTORIES"
.TP
"\fIconfig\fR"
This directory contains files supporting the Unix build system,
i\&.e\&. "\fIconfigure\fR" and "\fIMakefile\&.in\fR"\&.
.TP
"\fIdevdoc\fR"
This directories contains the doctools sources for the global
documentation, like this document and its sibling guides\&.
.TP
"\fIembedded\fR"
This directory contains the entire documentation formatted for
\fIHTML\fR and styled to properly mix into the web site generated by
fossil for the repository\&.
.sp
This is the documentation accessible from the Tcllib home
directory, represented in the repository as "\fIembedded/index\&.md\fR"\&.
.TP
"\fIidoc\fR"
This directory contains the entire documentation formatted for
\fInroff\fR and \fIHTML\fR, the latter without any styling\&.
This is the documentation which will be installed\&.
.TP
"\fIsupport\fR"
This directory contains the sources of internal packages and utilities
used in the implementation of the "\fIinstaller\&.tcl\fR" and
"\fIsak\&.tcl\fR" scripts/tools\&.
.PP
.SS "TOP FILES"
.TP
"\fIaclocal\&.m4\fR"
.TP
"\fIconfigure\fR"
.TP
"\fIconfigure\&.in\fR"
.TP
"\fIMakefile\&.in\fR"
These four files comprise the Unix build system layered on top of the
"\fIinstaller\&.tcl\fR" script\&.
.TP
"\fIinstaller\&.tcl\fR"
The Tcl-based installation script/tool\&.
.TP
"\fIproject\&.shed\fR"
Configuration file for \fISean Wood\fR's \fBPracTcl\fR
buildsystem\&.
.TP
"\fIsak\&.tcl\fR"
This is the main tool for developers and release managers, the
\fISwiss Army Knife\fR of management operations on the collection\&.
.TP
"\fIChangeLog\fR"
The log of changes to the global support, when the sources were held
in \fICVS\fR\&. Not relevant any longer with the switch to the
\fIfossil\fR SCM\&.
.TP
"\fIlicense\&.terms\fR"
The license in plain ASCII\&. See also \fITcllib - License\fR for the
nicely formatted form\&. The text is identical\&.
.TP
"\fIREADME\&.md\fR"
.TP
"\fI\&.github/CONTRIBUTING\&.md\fR"
.TP
"\fI\&.github/ISSUE_TEMPLATE\&.md\fR"
.TP
"\fI\&.github/PULL_REQUEST_TEMPLATE\&.md\fR"
These markdown-formatted documents are used and shown by the github
mirror of these sources, pointing people back to the official location
and issue trackers\&.
.TP
"\fIDESCRIPTION\&.txt\fR"
.TP
"\fISTATUS\fR"
.TP
"\fItcllib\&.spec\fR"
.TP
"\fItcllib\&.tap\fR"
.TP
"\fItcllib\&.yml\fR"
????
.PP
.SS "FILE TYPES"
The most common file types, by file extension, are:
.TP
"\fI\&.tcl\fR"
Tcl code for a package, application, or example\&.
.TP
"\fI\&.man\fR"
Doctools-formatted documentation, usually for a package\&.
.TP
"\fI\&.test\fR"
Test suite for a package, or part of\&.
Based on \fBtcltest\fR\&.
.TP
"\fI\&.bench\fR"
Performance benchmarks for a package, or part of\&.
Based on "\fImodules/bench\fR"\&.
.TP
"\fI\&.pcx\fR"
Syntax rules for \fITclDevKit\fR's \fBtclchecker\fR\&. Using these
rules allows the checker to validate the use of commands of a Tcllib
package \fBfoo\fR without having to scan the "\fI\&.tcl\fR" files
implementing it\&.
.PP
.SH "TESTSUITE TOOLING"
Testsuites in Tcllib are based on Tcl's standard test package
\fBtcltest\fR, plus utilities found in the directory
"\fImodules/devtools\fR"
.PP
Tcllib developers invoke the suites through the
\fBtest run\fR method of the "\fIsak\&.tcl\fR" tool, with other methods
of \fBtest\fR providing management operations, for example setting a
list of standard Tcl shells to use\&.
.SS "INVOKE THE TESTSUITES OF A SPECIFIC MODULE"
Invoke either
.CS

  \&./sak\&.tcl test run foo
.CE
or
.CS

  \&./sak\&.tcl test run modules/foo
.CE
to invoke the testsuites found in a specific module "\fIfoo\fR"\&.
.SS "INVOKE THE TESTSUITES OF ALL MODULES"
Invoke the tool without a module name, i\&.e\&.
.CS

  \&./sak\&.tcl test run
.CE
to invoke the testsuites of all modules\&.
.SS "DETAILED TEST LOGS"
In all the previous examples the test runner will write a combination
of progress display and testsuite log to the standard output, showing
for each module only the tests that passed or failed and how many of
each in a summary at the end\&.
.PP
To get a detailed log, it is necessary to invoke the test
runner with additional options\&.
.PP
For one:
.CS


   \&./sak\&.tcl test run --log LOG foo

.CE
While this shows the same short log on the terminal as before, it also
writes a detailed log to the file "\fILOG\&.log\fR", and excerpts to
other files ("\fILOG\&.summary\fR", "\fILOG\&.failures\fR", etc\&.)\&.
.PP
For two:
.CS


  \&./sak\&.tcl test run -v foo

.CE
This writes the detailed log to the standard output, instead of the
short log\&.
.PP
Regardless of form, the detailed log contains a list of all test
cases executed, which failed, and how they failed (expected versus
actual results)\&.
.SS "SHELL SELECTION"
By default the test runner will use all the Tcl shells specified via
\fBtest add\fR to invoke the specified testsuites, if any\&. If no
such are specified it will fall back to the Tcl shell used to run the
tool itself\&.
.PP
Use option \fB--shell\fR to explicitly specify the Tcl shell
to use, like
.CS


  \&./sak\&.tcl test run --shell /path/to/tclsh \&.\&.\&.

.CE
.SS HELP
Invoke the tool as
.CS

  \&./sak\&.tcl help test
.CE
to see the detailed help for all methods of \fBtest\fR, and the
associated options\&.
.SH "DOCUMENTATION TOOLING"
The standard format used for documentation of packages and other
things in Tcllib is \fIdoctools\fR\&.
Its supporting packages are a part of Tcllib, see the directories
"\fImodules/doctools\fR" and "\fImodules/dtplite\fR"\&. The latter is
an application package, with the actual application
"\fIapps/dtplite\fR" a light wrapper around it\&.
.PP
Tcllib developers gain access to these through the \fBdoc\fR
method of the "\fIsak\&.tcl\fR" tool, another (internal) wrapper around
the "\fImodules/dtplite\fR" application package\&.
.SS "GENERATE DOCUMENTATION FOR A SPECIFIC MODULE"
Invoke either
.CS

  \&./sak\&.tcl doc html foo
.CE
or
.CS

  \&./sak\&.tcl doc html modules/foo
.CE
to generate HTML for the documentation found in the module "\fIfoo\fR"\&.
Instead of \fBhtml\fR any other supported format can be used here,
of course\&.
.PP
The generated formatted documentation will be placed into a
directory "\fIdoc\fR" in the current working directory\&.
.SS "GENERATE DOCUMENTATION FOR ALL MODULES"
Invoke the tool without a module name, i\&.e\&.
.CS

  \&./sak\&.tcl doc html
.CE
to generate HTML for the documentation found in all modules\&.
Instead of \fBhtml\fR any other supported format can be used here,
of course\&.
.PP
The generated formatted documentation will be placed into a
directory "\fIdoc\fR" in the current working directory\&.
.SS "AVAILABLE OUTPUT FORMATS, HELP"
Invoke the tool as
.CS

  \&./sak\&.tcl help doc
.CE
to see the entire set of supported output formats which can be
generated\&.
.SS "VALIDATION WITHOUT OUTPUT"
Note the special format \fBvalidate\fR\&.
.PP
Using this value as the name of the format to generate forces
the tool to simply check that the documentation is syntactically
correct, without generating actual output\&.
.PP
Invoke it as either
.CS

  \&./sak\&.tcl doc validate (modules/)foo
.CE
or
.CS

  \&./sak\&.tcl doc validate
.CE
to either check the packages of a specific module or check all of
them\&.
.SH "NOTES ON WRITING A TESTSUITE"
While previous sections talked about running the testsuites for a
module and the packages therein, this has no meaning if the module in
question has no testsuites at all\&.
.PP
This section gives a very basic overview on possible
methodologies for writing tests and testsuites\&.
.PP
First there are "drudgery" tests\&. Written to check absolutely
basic assumptions which should never fail\&.
.PP
For example for a command FOO taking two arguments, three tests
calling it with zero, one, and three arguments\&. The basic checks that
the command fails if it has not enough arguments, or too many\&.
.PP
After that come the tests checking things based on our
knowledge of the command, about its properties and assumptions\&. Some
examples based on the graph operations added during Google's Summer of
Code 2009 are:
.IP \(bu
The BellmanFord command in struct::graph::ops takes a
\fIstartnode\fR as argument, and this node should be a node of
the graph\&. This equals one test case checking the behavior when the
specified node is not a node of the graph\&.
.sp
This often gives rise to code in the implementation which
explicitly checks the assumption and throws an understandable error,
instead of letting the algorithm fail later in some weird
non-deterministic way\&.
.sp
It is not always possible to do such checks\&. The graph argument
for example is just a command in itself, and while we expect
it to exhibit a certain interface, i\&.e\&. a set of sub-commands
aka methods, we cannot check that it has them, except by
actually trying to use them\&. That is done by the algorithm
anyway, so an explicit check is just overhead we can get by
without\&.
.IP \(bu
IIRC one of the distinguishing characteristic of either
BellmanFord and/or Johnson is that they are able to handle
negative weights\&. Whereas Dijkstra requires positive weights\&.
.sp
This induces (at least) three testcases \&.\&.\&. Graph with all
positive weights, all negative, and a mix of positive and
negative weights\&.
Thinking further does the algorithm handle the weight
\fB0\fR as well ? Another test case, or several, if we mix
zero with positive and negative weights\&.
.IP \(bu
The two algorithms we are currently thinking about are about
distances between nodes, and distance can be 'Inf'inity,
i\&.e\&. nodes may not be connected\&. This means that good test
cases are
.RS
.IP [1]
Strongly connected graph
.IP [2]
Connected graph
.IP [3]
Disconnected graph\&.
.RE
.sp
At the extremes of strongly connected and disconnected
we have the fully connected graphs and graphs without edges,
only nodes, i\&.e\&. completely disconnected\&.
.IP \(bu
IIRC both of the algorithms take weighted arcs, and fill in a
default if arcs are left unweighted in the input graph\&.
.sp
This also induces three test cases:
.RS
.IP [1]
Graph will all arcs with explicit weights\&.
.IP [2]
Graph without weights at all\&.
.IP [3]
Graph with mixture of weighted and unweighted graphs\&.
.RE
.PP
.PP
What was described above via examples is called
\fIblack-box\fR testing\&. Test cases are designed and written based on
the developer's knowledge of the properties of the algorithm and its
inputs, without referencing a particular implementation\&.
.PP
Going further, a complement to \fIblack-box\fR testing is
\fIwhite-box\fR\&. For this we know the implementation of the
algorithm, we look at it and design our tests cases so that they force
the code through all possible paths in the implementation\&. Wherever a
decision is made we have a test case forcing a specific direction of
the decision, for all possible combinations and directions\&. It is easy
to get a combinatorial explosion in the number of needed test-cases\&.
.PP
In practice I often hope that the black-box tests I have made
are enough to cover all the paths, obviating the need for white-box
tests\&.
.PP
The above should be enough to make it clear that writing tests
for an algorithm takes at least as much time as coding the algorithm,
and often more time\&. Much more time\&.
See for example also \fIhttp://sqlite\&.org/testing\&.html\fR, a writeup
on how the Sqlite database engine is tested\&. Another article of
interest might be \fIhttps://www\&.researchgate\&.net/publication/298896236\fR\&.
While geared to a particular numerical algorithm it still shows that
even a simple-looking algorithm can lead to an incredible number of
test cases\&.
.PP
An interesting connection is to documentation\&. In one
direction, the properties checked with black-box testing are exactly
the properties which should be documented in the algorithm's man
page\&. And conversely, the documentation of the properties of an
algorithm makes a good reference to base the black-box tests on\&.
.PP
In practice test cases and documentation often get written
together, cross-influencing each other\&. And the actual writing of test
cases is a mix of black and white box, possibly influencing the
implementation while writing the tests\&. Like writing a test for a
condition like \fIstartnode not in input graph\fR serving as
reminder to put a check for this condition into the code\&.
.SH "INSTALLATION TOOLING"
A last thing to consider when adding a new package to the collection
is installation\&.
.PP
How to \fIuse\fR the "\fIinstaller\&.tcl\fR" script is documented
in \fITcllib - The Installer's Guide\fR\&.
.PP
Here we document how to extend said installer so that it may
install new package(s) and/or application(s)\&.
.PP
In most cases only a single file has to be modified, the
"\fIsupport/installation/modules\&.tcl\fR" holding one command per module
and application to install\&.
.PP
The relevant commands are:
.TP
\fBModule\fR \fIname\fR \fIcode-action\fR \fIdoc-action\fR \fIexample-action\fR
Install the packages of module \fIname\fR, found in
"\fImodules/\fIname\fR\fR"\&.
.sp
The \fIcode-action\fR is responsible for installing the
packages and their index\&. The system currently provides
.RS
.TP
\fB_tcl\fR
Copy all "\fI\&.tcl\fR" files found in
"\fImodules/\fIname\fR\fR" into the installation\&.
.TP
\fB_tcr\fR
As \fB_tcl\fR, copy the "\fI\&.tcl\fR" files found in
the subdirectories of "\fImodules/\fIname\fR\fR" as well\&.
.TP
\fB_tci\fR
As \fB_tcl\fR, and copy the "\fItclIndex\&.tcl\fR" file
as well\&.
.TP
\fB_msg\fR
As \fB_tcl\fR, and copy the subdirectory "\fImsgs\fR"
as well\&.
.TP
\fB_doc\fR
As \fB_tcl\fR, and copy the subdirectory
"\fImpformats\fR" as well\&.
.TP
\fB_tex\fR
As \fB_tcl\fR, and copy "\fI\&.tex\fR" files as well\&.
.RE
.sp
The \fIdoc-action\fR is responsible for installing the package
documentation\&. The system currently provides
.RS
.TP
\fB_null\fR
No documentation available, do nothing\&.
.TP
\fB_man\fR
Process the "\fI\&.man\fR" files found in
"\fImodules/\fIname\fR\fR" and install the results (nroff and/or HTML)
in the proper location, as given to the installer\&.
.sp
This is actually a fallback, normally the installer uses the
pre-made formatted documentation found under "\fIidoc\fR"\&.
.RE
.sp
The \fIexample-action\fR is responsible for installing the
examples\&. The system currently provides
.RS
.TP
\fB_null\fR
No examples available, do nothing\&.
.TP
\fB_exa\fR
Copy the the directory "\fIexamples/\fIname\fR\fR"
recursively to the install location for examples\&.
.RE
.TP
\fBApplication\fR \fIname\fR
Install the application with \fIname\fR, found in "\fIapps\fR"\&.
.TP
\fBExclude\fR \fIname\fR
This command signals to the installer which of the listed modules to
\fInot\fR install\&. I\&.e\&. they name the deprecated modules of Tcllib\&.
.PP
.PP
If, and only if the above actions are not suitable for the new
module then a second file has to be modified,
"\fIsupport/installation/actions\&.tcl\fR"\&.
.PP
This file contains the implementations of the available
actions, and is the place where any custom action needed to handle the
special circumstances of module has to be added\&.

Added idoc/man/files/devdoc/tcllib_installer.n.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
'\"
'\" Generated from file 'tcllib_installer\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "tcllib_install_guide" n 1 tcllib ""
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
.\"	and indent is equivalent to second arg of .IP (shouldn't ever be
.\"	needed;  use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\"	Give maximum sizes of arguments for setting tab stops.  Type and
.\"	name are examples of largest possible arguments that will be passed
.\"	to .AP later.  If args are omitted, default tab stops are used.
.\"
.\" .BS
.\"	Start box enclosure.  From here until next .BE, everything will be
.\"	enclosed in one large box.
.\"
.\" .BE
.\"	End of box enclosure.
.\"
.\" .CS
.\"	Begin code excerpt.
.\"
.\" .CE
.\"	End code excerpt.
.\"
.\" .VS ?version? ?br?
.\"	Begin vertical sidebar, for use in marking newly-changed parts
.\"	of man pages.  The first argument is ignored and used for recording
.\"	the version when the .VS was added, so that the sidebars can be
.\"	found and removed when they reach a certain age.  If another argument
.\"	is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\"	End of vertical sidebar.
.\"
.\" .DS
.\"	Begin an indented unfilled display.
.\"
.\" .DE
.\"	End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\"	Start of list of standard options for a Tk widget. The manpage
.\"	argument defines where to look up the standard options; if
.\"	omitted, defaults to "options". The options follow on successive
.\"	lines, in three columns separated by tabs.
.\"
.\" .SE
.\"	End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\"	Start of description of a specific option.  cmdName gives the
.\"	option's name as specified in the class command, dbName gives
.\"	the option's name in the option database, and dbClass gives
.\"	the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\"	Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\"	Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\"	Print an open parenthesis, arg1 in quotes, then arg2 normally
.\"	(for trailing punctuation) and then a closing parenthesis.
.\"
.\"	# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\"	# Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
.   ie !"\\$2"" .TP \\n()Cu
.   el          .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1	\\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\"	# define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\"	# BS - start boxed text
.\"	# ^y = starting y location
.\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\"	Draw four-sided box normally, but don't draw top of
.\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# VS - start vertical sidebar
.\"	# ^Y = starting y location
.\"	# ^v = 1 (for troff;  for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\"	# VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\"	# Special macro to handle page bottom:  finish off current
.\"	# box/sidebar if in box/sidebar mode, then invoked standard
.\"	# page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\"	Draw three-sided box if this is the box's first page,
.\"	draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\"	# DS - begin display
.de DS
.RS
.nf
.sp
..
.\"	# DE - end display
.de DE
.fi
.RE
.sp
..
.\"	# SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\"	# SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\"	# OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name:	\\fB\\$1\\fR
Database Name:	\\fB\\$2\\fR
Database Class:	\\fB\\$3\\fR
.fi
.IP
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
.\"	# UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\"	# QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\"	# PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\"	# QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
tcllib_install_guide \- Tcllib - The Installer's Guide
.SH DESCRIPTION
Welcome to Tcllib, the Tcl Standard Library\&. Note that Tcllib is not a
package itself\&. It is a collection of (semi-independent) \fITcl\fR
packages that provide utility functions useful to a large collection
of Tcl programmers\&.
.PP
The audience of this document is anyone wishing to build and install
the packages found in Tcllib, for either themselves, or others\&.
.PP
For developers intending to work on the packages themselves we
additionally provide
.IP [1]
\fITcllib - The Developer's Guide\fR\&.
.PP
.PP
Please read \fITcllib - How To Get The Sources\fR first, if that
was not done already\&. Here we assume that the sources are already
available in a directory of your choice\&.
.PP
.SH REQUISITES
Before Tcllib can be build and used a number of requisites must be installed\&.
These are:
.IP [1]
The scripting language Tcl\&.
For details see \fBTcl\fR\&.
.IP [2]
Optionally, the \fBcritcl\fR package (C embedding) for \fBTcl\fR\&.
For details see \fBCriTcl\fR\&.
.PP
This list assumes that the machine where Tcllib is to be installed is
essentially clean\&. Of course, if parts of the dependencies listed
below are already installed the associated steps can be skipped\&. It is
still recommended to read their sections though, to validate that the
dependencies they talk about are indeed installed\&.
.SS TCL
As we are installing a number of Tcl packages and applications it
should be pretty much obvious that a working installation of Tcl
itself is needed, and I will not belabor the point\&.
.PP
Out of the many possibilities use whatever you are comfortable
with, as long as it provides at the very least Tcl 8\&.2, or higher\&.
This may be a Tcl installation provided by your operating system
distribution, from a distribution-independent vendor, or built by
yourself\&.
.PP
\fINote\fR that the packages in Tcllib have begun to require
8\&.4, 8\&.5, and even 8\&.6\&. Older versions of Tcl will not be able to use
such packages\&. Trying to use them will result in
\fIpackage not found\fR errors, as their package index files will
not register them in versions of the core unable to use them\&.
.PP
Myself, I used (and still use)
\fIActiveState's\fR [http://www\&.activestate\&.com]
ActiveTcl 8\&.5 distribution during development, as I am most familiar
with it\&.
.PP
\fI(Disclosure: I, Andreas Kupries, worked for ActiveState until 2016, maintaining ActiveTcl and TclDevKit for them)\&.\fR\&.
I am currently working for SUSE Software Canada ULC, although not in
Tcl-related areas\&.
.PP
This distribution can be found at
\fIhttp://www\&.activestate\&.com/activetcl\fR\&. Retrieve the archive of
ActiveTcl 8\&.5 (or higher) for your platform and install it as directed
by ActiveState\&.
.PP
For those wishing to build and install Tcl on their own, the
relevant sources can be found at
.TP
Tcl
\fIhttp://core\&.tcl-lang\&.org/tcl/\fR
.PP
together with the necessary instructions on how to build it\&.
.PP
If there are problems with building, installing, or using Tcl,
please file a ticket against \fITcl\fR, or the vendor of your
distribution, and \fInot\fR \fITcllib\fR\&.
.SS CRITCL
The \fBcritcl\fR tool is an \fIoptional\fR dependency\&.
.PP
It is only required when trying to build the C-based
\fIaccelerators\fR for a number of packages, as explained in
\fBCritcl & Accelerators\fR
.PP
Tcllib's build system looks for it in the ,
using the name \fBcritcl\fR\&. This is for Unix\&.
On Windows on the other hand the search is more complex\&. First we look
for a proper application \fBcritcl\&.exe\fR\&. When that is not found
we look for a combination of interpreter (\fBtclkitsh\&.exe\fR,
\fBtclsh\&.exe\fR) and starkit (\fBcritcl\&.kit\fR, \fBcritcl\fR)
instead\&. \fINote\fR that the choice of starkit can be overriden via
the environment variable \&.
.PP
Tcllib requires Critcl version 2 or higher\&.
.PP
The github repository providing releases of version 2 and
higher, and the associated sources, can be found at
\fIhttp://andreas-kupries\&.github\&.com/critcl\fR\&.
.PP
Any branch of the repository can be used (if not using the
prebuild starkit or starpack), although the use of the stable branch
\fImaster\fR is recommended\&.
.PP
At the above url is also an explanation on how to build and
install Critcl, including a list of its dependencies\&.
.PP
Its instructions will not be repeated here\&. If there are
problems with these directions please file a ticket against the
\fICritcl\fR project, and not Tcllib\&.
.SH "BUILD & INSTALLATION INSTRUCTIONS"
As Tcllib is mainly a bundle of packages written in pure Tcl building
it is the same as installing it\&. The exceptions to this have their own
subsection, \fBCritcl & Accelerators\fR, later on\&.
.PP
Before that however comes the standard case, differentiated by
the platforms with material differences in the instruction, i\&.e\&.
\fIUnix\fR-like, versus \fIWindows\fR\&.
.PP
Regarding the latter it should also be noted that it is
possible set up an \fIUnix\fR-like environment using projects
like \fIMSYS\fR, \fICygwin\fR, and others\&. In that case the
user has the choice of which instructions to follow\&.
.PP
Regardless of environment or platform, a suitable \fITcl\fR
has to be installed, and its \fBtclsh\fR should be placed on
the  (\fIUnix\fR) or associated with
"\fI\&.tcl\fR" files (\fIWindows\fR)\&.
.SS "INSTALLING ON UNIX"
For \fIUnix\fR-like environments Tcllib comes with the standard set
of files to make
.CS


  \&./configure
  make install

.CE
a suitable way of installing it\&.
This is a standard non-interactive install automatically figuring out
where to place everything, i\&.e\&. packages, applications, and the
manpages\&.
.PP
To get a graphical installer invoke
.CS


  \&./installer\&.tcl

.CE
instead\&.
.SS "INSTALLING ON WINDOWS"
In a Windows environment we have the \fBinstaller\&.tcl\fR script to
perform installation\&.
.PP
If the desired \fBtclsh\fR is associated "\fI\&.tcl\fR" files
then double-clicking / opening the \fBinstaller\&.tcl\fR is
enough to invoke it in graphical mode\&.
This assumes that \fITk\fR is installed and available as well\&.
.PP
Without \fITk\fR the only way to invoke the installer are to
open a DOS window, i\&.e\&. \fBcmd\&.exe\fR, and then to invoke
.CS


  \&./installer\&.tcl

.CE
inside it\&.
.SS "CRITCL & ACCELERATORS"
While the majority of Tcllib consists of packages written in pure Tcl
a number of packages also have \fIaccelerators\fR associated with them\&.
These are \fBcritcl\fR-based C packages whose use will boost the
performance of the packages using them\&.
These accelerators are optional, and they are not installed by
default\&.
.PP
To build the accelerators the normally optional dependency on
\fBcritcl\fR becomes required\&.
.PP
To build and install Tcllib with the accelerators in a
Unix-like environment invoke:
.CS


  \&./configure
  make critcl # This builds the shared library holding
              # the accelerators
  make install

.CE
.PP
The underlying tool is "\fIsak\&.tcl\fR" in the toplevel directory
of Tcllib and the command \fBmake critcl\fR is just a wrapper around
.CS


  \&./sak\&.tcl critcl

.CE
.PP
Therefore in a Windows environment instead invoke
.CS


  \&./sak\&.tcl critcl
  \&./installer\&.tcl

.CE
from within a DOS window, i\&.e\&. \fBcmd\&.exe\fR\&.
.SS TOOLING
The core of Tcllib's build system is the script "\fIinstaller\&.tcl\fR"
found in the toplevel directory of a checkout or release\&.
.PP
The
.CS


         configure ; make install

.CE
setup available to
developers on Unix-like systems is just a wrapper around it\&.
To go beyond the standard embodied in the wrapper it is
necessary to directly invoke this script\&.
.PP
On Windows system using it directly is the only way to invoke
it\&.
.PP
For basic help invoke it as
.CS


         \&./installer\&.tcl -help

.CE
This will print a short list of all the available options to
the standard output channel\&.
.PP
The commands associated with the various \fIinstall\fR targets
in the \fIMakefile\&.in\fR for Unix can be used as additional
examples on how to use this tool as well\&.
.PP
The installer can operate in GUI and CLI modes\&.
By default it chooses the mode automatically, based on if the
Tcl package \fBTk\fR can be used or not\&.
The option \fB-no-gui\fR can be used to force CLI mode\&.
.PP
Note that it is possible to specify options on the command line
even if the installer ultimatively selects GUI mode\&. In that
case the hardwired defaults and the options determine the data
presented to the user for editing\&.
.PP
The installer will select a number of defaults for the
locations of packages, examples, and documentation, and also
the format of the documentation\&. The user can overide these
defaults in the GUI, or by specifying additional options\&.
The defaults depend on the platform detected (Unix/Windows) and
on the \fBtclsh\fR executable used to run the installer\&.
.PP
\fIOptions\fR
.TP
\fB-help\fR
Show the list of options explained here on the standard output channel
and exit\&.
.TP
\fB+excluded\fR
Include deprecated packages in the installation\&.
.TP
\fB-no-gui\fR
Force command line operation of the installer
.TP
\fB-no-wait\fR
In CLI mode the installer will by default ask the user to confirm that
the chosen configuration (destination paths, things to install) is
correct before performing any action\&. Using this option causes the
installer to skip this query and immediately jump to installation\&.
.TP
\fB-app-path\fR \fIpath\fR
.TP
\fB-example-path\fR \fIpath\fR
.TP
\fB-html-path\fR \fIpath\fR
.TP
\fB-nroff-path\fR \fIpath\fR
.TP
\fB-pkg-path\fR \fIpath\fR
Declare the destination paths for the applications, examples, html
documentation, nroff manpages, and packages\&. The defaults are derived
from the location of the \fBtclsh\fR used to run the installer\&.
.TP
\fB-dry-run\fR
.TP
\fB-simulate\fR
Run the installer without modifying the destination directories\&.
.TP
\fB-apps\fR
.TP
\fB-no-apps\fR
.TP
\fB-examples\fR
.TP
\fB-no-examples\fR
.TP
\fB-pkgs\fR
.TP
\fB-no-pkgs\fR
.TP
\fB-html\fR
.TP
\fB-no-html\fR
.TP
\fB-nroff\fR
.TP
\fB-no-nroff\fR
(De)activate the installation of applications, examples, packages,
html documentation, and nroff manpages\&.
.sp
Applications, examples, and packages are installed by default\&.
.sp
On Windows the html documentation is installed by default\&.
.sp
On Unix the nroff manpages are installed by default\&.
.PP

Added idoc/man/files/devdoc/tcllib_license.n.



































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
'\"
'\" Generated from file 'tcllib_license\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "tcllib_license" n 1 tcllib ""
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
.\"	and indent is equivalent to second arg of .IP (shouldn't ever be
.\"	needed;  use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\"	Give maximum sizes of arguments for setting tab stops.  Type and
.\"	name are examples of largest possible arguments that will be passed
.\"	to .AP later.  If args are omitted, default tab stops are used.
.\"
.\" .BS
.\"	Start box enclosure.  From here until next .BE, everything will be
.\"	enclosed in one large box.
.\"
.\" .BE
.\"	End of box enclosure.
.\"
.\" .CS
.\"	Begin code excerpt.
.\"
.\" .CE
.\"	End code excerpt.
.\"
.\" .VS ?version? ?br?
.\"	Begin vertical sidebar, for use in marking newly-changed parts
.\"	of man pages.  The first argument is ignored and used for recording
.\"	the version when the .VS was added, so that the sidebars can be
.\"	found and removed when they reach a certain age.  If another argument
.\"	is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\"	End of vertical sidebar.
.\"
.\" .DS
.\"	Begin an indented unfilled display.
.\"
.\" .DE
.\"	End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\"	Start of list of standard options for a Tk widget. The manpage
.\"	argument defines where to look up the standard options; if
.\"	omitted, defaults to "options". The options follow on successive
.\"	lines, in three columns separated by tabs.
.\"
.\" .SE
.\"	End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\"	Start of description of a specific option.  cmdName gives the
.\"	option's name as specified in the class command, dbName gives
.\"	the option's name in the option database, and dbClass gives
.\"	the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\"	Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\"	Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\"	Print an open parenthesis, arg1 in quotes, then arg2 normally
.\"	(for trailing punctuation) and then a closing parenthesis.
.\"
.\"	# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\"	# Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
.   ie !"\\$2"" .TP \\n()Cu
.   el          .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1	\\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\"	# define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\"	# BS - start boxed text
.\"	# ^y = starting y location
.\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\"	Draw four-sided box normally, but don't draw top of
.\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# VS - start vertical sidebar
.\"	# ^Y = starting y location
.\"	# ^v = 1 (for troff;  for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\"	# VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\"	# Special macro to handle page bottom:  finish off current
.\"	# box/sidebar if in box/sidebar mode, then invoked standard
.\"	# page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\"	Draw three-sided box if this is the box's first page,
.\"	draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\"	# DS - begin display
.de DS
.RS
.nf
.sp
..
.\"	# DE - end display
.de DE
.fi
.RE
.sp
..
.\"	# SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\"	# SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\"	# OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name:	\\fB\\$1\\fR
Database Name:	\\fB\\$2\\fR
Database Class:	\\fB\\$3\\fR
.fi
.IP
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
.\"	# UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\"	# QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\"	# PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\"	# QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
tcllib_license \- Tcllib - License
.SH DESCRIPTION
Welcome to Tcllib, the Tcl Standard Library\&. Note that Tcllib is not a
package itself\&. It is a collection of (semi-independent) \fITcl\fR
packages that provide utility functions useful to a large collection
of Tcl programmers\&.
.PP
The collection is under the BSD license\&.
.SH LICENSE
.PP
This software is copyrighted by Ajuba Solutions and other parties\&.
The following terms apply to all files associated with the software
unless explicitly disclaimed in individual files\&.
.PP
The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose,
provided that existing copyright notices are retained in all copies
and that this notice is included verbatim in any distributions\&. No
written agreement, license, or royalty fee is required for any of the
authorized uses\&.  Modifications to this software may be copyrighted by
their authors and need not follow the licensing terms described here,
provided that the new terms are clearly indicated on the first page of
each file where they apply\&.
.PP
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE\&.
.PP
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT\&.  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS\&.
.PP
GOVERNMENT USE: If you are acquiring this software on behalf of the
U\&.S\&. government, the Government shall have only "Restricted Rights" in
the software and related documentation as defined in the Federal
Acquisition Regulations (FARs) in Clause 52\&.227\&.19 (c) (2)\&.  If you
are acquiring the software on behalf of the Department of Defense, the
software shall be classified as "Commercial Computer Software" and the
Government shall have only "Restricted Rights" as defined in Clause
252\&.227-7013 (c) (1) of DFARs\&.  Notwithstanding the foregoing, the
authors grant the U\&.S\&. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license\&.

Added idoc/man/files/devdoc/tcllib_releasemgr.n.















































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
'\"
'\" Generated from file 'tcllib_releasemgr\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "tcllib_releasemgr" n 1 tcllib ""
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
.\"	and indent is equivalent to second arg of .IP (shouldn't ever be
.\"	needed;  use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\"	Give maximum sizes of arguments for setting tab stops.  Type and
.\"	name are examples of largest possible arguments that will be passed
.\"	to .AP later.  If args are omitted, default tab stops are used.
.\"
.\" .BS
.\"	Start box enclosure.  From here until next .BE, everything will be
.\"	enclosed in one large box.
.\"
.\" .BE
.\"	End of box enclosure.
.\"
.\" .CS
.\"	Begin code excerpt.
.\"
.\" .CE
.\"	End code excerpt.
.\"
.\" .VS ?version? ?br?
.\"	Begin vertical sidebar, for use in marking newly-changed parts
.\"	of man pages.  The first argument is ignored and used for recording
.\"	the version when the .VS was added, so that the sidebars can be
.\"	found and removed when they reach a certain age.  If another argument
.\"	is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\"	End of vertical sidebar.
.\"
.\" .DS
.\"	Begin an indented unfilled display.
.\"
.\" .DE
.\"	End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\"	Start of list of standard options for a Tk widget. The manpage
.\"	argument defines where to look up the standard options; if
.\"	omitted, defaults to "options". The options follow on successive
.\"	lines, in three columns separated by tabs.
.\"
.\" .SE
.\"	End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\"	Start of description of a specific option.  cmdName gives the
.\"	option's name as specified in the class command, dbName gives
.\"	the option's name in the option database, and dbClass gives
.\"	the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\"	Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\"	Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\"	Print an open parenthesis, arg1 in quotes, then arg2 normally
.\"	(for trailing punctuation) and then a closing parenthesis.
.\"
.\"	# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\"	# Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
.   ie !"\\$2"" .TP \\n()Cu
.   el          .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1	\\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\"	# define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\"	# BS - start boxed text
.\"	# ^y = starting y location
.\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\"	Draw four-sided box normally, but don't draw top of
.\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# VS - start vertical sidebar
.\"	# ^Y = starting y location
.\"	# ^v = 1 (for troff;  for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\"	# VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\"	# Special macro to handle page bottom:  finish off current
.\"	# box/sidebar if in box/sidebar mode, then invoked standard
.\"	# page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\"	Draw three-sided box if this is the box's first page,
.\"	draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\"	# DS - begin display
.de DS
.RS
.nf
.sp
..
.\"	# DE - end display
.de DE
.fi
.RE
.sp
..
.\"	# SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\"	# SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\"	# OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name:	\\fB\\$1\\fR
Database Name:	\\fB\\$2\\fR
Database Class:	\\fB\\$3\\fR
.fi
.IP
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
.\"	# UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\"	# QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\"	# PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\"	# QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
tcllib_releasemgr \- Tcllib - The Release Manager's Guide
.SH DESCRIPTION
Welcome to Tcllib, the Tcl Standard Library\&. Note that Tcllib is not a
package itself\&. It is a collection of (semi-independent) \fITcl\fR
packages that provide utility functions useful to a large collection
of Tcl programmers\&.
.PP
The audience of this document is the release manager for Tcllib, their
deputies, and anybody else interested in the task of creating
an official release of Tcllib for distribution\&.
.PP
Please read \fITcllib - How To Get The Sources\fR first, if that
was not done already\&. Here we assume that the sources are already
available in a directory of your choice\&.
.PP
.SH TOOLS
The "\fIsak\&.tcl\fR" script in the toplevel directory of a Tcllib
checkout is the one tool used by the release manager to perform its
\fBTasks\fR\&.
.PP
The main commands to be used are
.CS


    sak\&.tcl validate
    sak\&.tcl test run
    sak\&.tcl review
    sak\&.tcl readme
    sak\&.tcl localdoc
    sak\&.tcl release

.CE
More detail will be provided in the explanations of the various
\fBTasks\fR\&.
.SH TASKS
.SS "START A RELEASE CANDIDATE"
todo: open a candidate for release
.SS "READY THE CANDIDATE"
todo: test, validate and check that the candidate is worthy of release
fix testsuites, possibly fix packages, documentation
regenerate docs
coordinate with package maintainers wrt fixes
big thing: going over the packages, classify changes since last
release to generate a nice readme\&.
.SS "MAKE IT OFFICIAL"
todo: finalize release, make candidate official
.SS "DISTRIBUTE THE RELEASE"
With the release made it has to be published and the world notified of
its existence\&.
.IP [1]
Create a proper fossil event for the release, via
\fIhttp://core\&.tcl-lang\&.org/tcllib/eventedit\fR\&.
.sp
An \fIexisting event\fR [http://core\&.tcl-lang\&.org/tcllib/event/dac0ddcd2e990234143196b4dc438fe01e7b9817] should be used as template\&.
.IP [2]
Update a number of web locations:
.RS
.IP [1]
\fIHome page\fR [http://core\&.tcl-lang\&.org/tcllib/doc/trunk/embedded/index\&.md]
.IP [2]
\fIDownloads\fR [http://core\&.tcl-lang\&.org/tcllib/wiki?name=Downloads]
.IP [3]
\fIPast Releases\fR [http://core\&.tcl-lang\&.org/tcllib/wiki?name=Past+Releases]
.IP [4]
\fIhttp://www\&.tcl-lang\&.org/home/release\&.txt\fR
.IP [5]
\fIhttp://www\&.tcl-lang\&.org/software/tcllib/*\&.tml\fR
.IP [6]
\fIhttp://wiki\&.tcl-lang\&.org/page/Tcllib\fR
.RE
.IP
The first location maps to the file "\fIembedded/index\&.md\fR" in the
repository itself, as such it can edited as part of the release
process\&. This is where reference to the new fossil event is added, as
the new current release\&.
.sp
The next two locations are in the fossil tcllib wiki and
require admin or wiki write permissions for
\fIhttp://core\&.tcl-lang\&.org/tcllib\fR\&.
.sp
The last two locations require ssh access to
\fIhttp://www\&.tcl-lang\&.org\fR and permission to edit
files in the web area\&.
.IP [3]
***TODO*** mailing lists and other places to send notes to\&.
.PP

Added idoc/man/files/devdoc/tcllib_sources.n.

























































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
'\"
'\" Generated from file 'tcllib_sources\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "tcllib_sources" n 1 tcllib ""
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
.\"	and indent is equivalent to second arg of .IP (shouldn't ever be
.\"	needed;  use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\"	Give maximum sizes of arguments for setting tab stops.  Type and
.\"	name are examples of largest possible arguments that will be passed
.\"	to .AP later.  If args are omitted, default tab stops are used.
.\"
.\" .BS
.\"	Start box enclosure.  From here until next .BE, everything will be
.\"	enclosed in one large box.
.\"
.\" .BE
.\"	End of box enclosure.
.\"
.\" .CS
.\"	Begin code excerpt.
.\"
.\" .CE
.\"	End code excerpt.
.\"
.\" .VS ?version? ?br?
.\"	Begin vertical sidebar, for use in marking newly-changed parts
.\"	of man pages.  The first argument is ignored and used for recording
.\"	the version when the .VS was added, so that the sidebars can be
.\"	found and removed when they reach a certain age.  If another argument
.\"	is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\"	End of vertical sidebar.
.\"
.\" .DS
.\"	Begin an indented unfilled display.
.\"
.\" .DE
.\"	End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\"	Start of list of standard options for a Tk widget. The manpage
.\"	argument defines where to look up the standard options; if
.\"	omitted, defaults to "options". The options follow on successive
.\"	lines, in three columns separated by tabs.
.\"
.\" .SE
.\"	End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\"	Start of description of a specific option.  cmdName gives the
.\"	option's name as specified in the class command, dbName gives
.\"	the option's name in the option database, and dbClass gives
.\"	the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\"	Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\"	Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\"	Print an open parenthesis, arg1 in quotes, then arg2 normally
.\"	(for trailing punctuation) and then a closing parenthesis.
.\"
.\"	# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\"	# Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
.   ie !"\\$2"" .TP \\n()Cu
.   el          .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1	\\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\"	# define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\"	# BS - start boxed text
.\"	# ^y = starting y location
.\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\"	Draw four-sided box normally, but don't draw top of
.\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# VS - start vertical sidebar
.\"	# ^Y = starting y location
.\"	# ^v = 1 (for troff;  for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\"	# VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\"	# Special macro to handle page bottom:  finish off current
.\"	# box/sidebar if in box/sidebar mode, then invoked standard
.\"	# page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\"	Draw three-sided box if this is the box's first page,
.\"	draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\"	# DS - begin display
.de DS
.RS
.nf
.sp
..
.\"	# DE - end display
.de DE
.fi
.RE
.sp
..
.\"	# SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\"	# SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\"	# OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name:	\\fB\\$1\\fR
Database Name:	\\fB\\$2\\fR
Database Class:	\\fB\\$3\\fR
.fi
.IP
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
.\"	# UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\"	# QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\"	# PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\"	# QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
tcllib_sources \- Tcllib - How To Get The Sources
.SH DESCRIPTION
Welcome to Tcllib, the Tcl Standard Library\&. Note that Tcllib is not a
package itself\&. It is a collection of (semi-independent) \fITcl\fR
packages that provide utility functions useful to a large collection
of Tcl programmers\&.
.PP
The audience of this document is anyone wishing to either have just a
look at Tcllib's source code, or build the packages, or to extend and
modify them\&.
.PP
For builders and developers we additionally provide
.IP [1]
\fITcllib - The Installer's Guide\fR\&.
.IP [2]
\fITcllib - The Developer's Guide\fR\&.
.PP
respectively\&.
.SH "SOURCE LOCATION"
The official repository for Tcllib can be found at
\fIhttp://core\&.tcl-lang\&.org/tcllib\fR
.SH RETRIEVAL
Assuming that you simply wish to look at the sources, or build a
specific revision, the easiest way of retrieving it is to:
.IP [1]
Log into this site, as "anonymous", using the semi-random password in the captcha\&.
.IP [2]
Go to the "Timeline"\&.
.IP [3]
Choose the revision you wish to have\&.
.IP [4]
Follow its link to its detailed information page\&.
.IP [5]
On that page, choose either the "ZIP" or "Tarball" link to get
a copy of this revision in the format of your choice\&.
.PP
.SH "SOURCE CODE MANAGEMENT"
For the curious (or a developer-to-be), the sources are managed by the
\fIFossil SCM\fR [http://www\&.fossil-scm\&.org]\&.
Binaries for popular platforms can be found directly at its
\fIdownload page\fR [http://www\&.fossil-scm\&.org/download\&.html]\&.
.PP
With that tool available the full history can be retrieved via:
.CS


    fossil clone  http://core\&.tcl-lang\&.org/tcllib  tcllib\&.fossil

.CE
followed by
.CS


    mkdir tcllib
    cd tcllib
    fossil open \&.\&./tcllib\&.fossil

.CE
to get a checkout of the head of the trunk\&.

Added idoc/man/files/modules/clay/clay.n.































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
'\"
'\" Generated from file 'clay\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2018 Sean Woods <yoda@etoyoc\&.com>
'\"
.TH "clay" n 0\&.8\&.6 tcllib "Clay Framework"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
.\"	and indent is equivalent to second arg of .IP (shouldn't ever be
.\"	needed;  use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\"	Give maximum sizes of arguments for setting tab stops.  Type and
.\"	name are examples of largest possible arguments that will be passed
.\"	to .AP later.  If args are omitted, default tab stops are used.
.\"
.\" .BS
.\"	Start box enclosure.  From here until next .BE, everything will be
.\"	enclosed in one large box.
.\"
.\" .BE
.\"	End of box enclosure.
.\"
.\" .CS
.\"	Begin code excerpt.
.\"
.\" .CE
.\"	End code excerpt.
.\"
.\" .VS ?version? ?br?
.\"	Begin vertical sidebar, for use in marking newly-changed parts
.\"	of man pages.  The first argument is ignored and used for recording
.\"	the version when the .VS was added, so that the sidebars can be
.\"	found and removed when they reach a certain age.  If another argument
.\"	is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\"	End of vertical sidebar.
.\"
.\" .DS
.\"	Begin an indented unfilled display.
.\"
.\" .DE
.\"	End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\"	Start of list of standard options for a Tk widget. The manpage
.\"	argument defines where to look up the standard options; if
.\"	omitted, defaults to "options". The options follow on successive
.\"	lines, in three columns separated by tabs.
.\"
.\" .SE
.\"	End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\"	Start of description of a specific option.  cmdName gives the
.\"	option's name as specified in the class command, dbName gives
.\"	the option's name in the option database, and dbClass gives
.\"	the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\"	Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\"	Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\"	Print an open parenthesis, arg1 in quotes, then arg2 normally
.\"	(for trailing punctuation) and then a closing parenthesis.
.\"
.\"	# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\"	# Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
.   ie !"\\$2"" .TP \\n()Cu
.   el          .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1	\\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\"	# define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\"	# BS - start boxed text
.\"	# ^y = starting y location
.\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\"	Draw four-sided box normally, but don't draw top of
.\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# VS - start vertical sidebar
.\"	# ^Y = starting y location
.\"	# ^v = 1 (for troff;  for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\"	# VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\"	# Special macro to handle page bottom:  finish off current
.\"	# box/sidebar if in box/sidebar mode, then invoked standard
.\"	# page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\"	Draw three-sided box if this is the box's first page,
.\"	draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\"	# DS - begin display
.de DS
.RS
.nf
.sp
..
.\"	# DE - end display
.de DE
.fi
.RE
.sp
..
.\"	# SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\"	# SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\"	# OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name:	\\fB\\$1\\fR
Database Name:	\\fB\\$2\\fR
Database Class:	\\fB\\$3\\fR
.fi
.IP
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
.\"	# UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\"	# QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\"	# PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\"	# QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
clay \- A minimalist framework for large scale OO Projects
.SH SYNOPSIS
package require \fBTcl  8\&.6\fR
.sp
package require \fBuuid \fR
.sp
package require \fBoo::dialect \fR
.sp
proc \fBclay::PROC\fR \fIname\fR \fIarglist\fR \fIbody\fR ?\fIninja\fR \fB\fR?
.sp
proc \fBclay::_ancestors\fR \fIresultvar\fR \fIclass\fR
.sp
proc \fBclay::ancestors\fR ?\fIargs\fR?
.sp
proc \fBclay::args_to_dict\fR ?\fIargs\fR?
.sp
proc \fBclay::args_to_options\fR ?\fIargs\fR?
.sp
proc \fBclay::dynamic_arguments\fR \fIensemble\fR \fImethod\fR \fIarglist\fR ?\fIargs\fR?
.sp
proc \fBclay::dynamic_wrongargs_message\fR \fIarglist\fR
.sp
proc \fBclay::is_dict\fR \fId\fR
.sp
proc \fBclay::is_null\fR \fIvalue\fR
.sp
proc \fBclay::leaf\fR ?\fIargs\fR?
.sp
proc \fBclay::K\fR \fIa\fR \fIb\fR
.sp
proc \fBclay::noop\fR ?\fIargs\fR?
.sp
proc \fBclay::cleanup\fR
.sp
proc \fBclay::object_create\fR \fIobjname\fR ?\fIclass\fR \fB\fR?
.sp
proc \fBclay::object_rename\fR \fIobject\fR \fInewname\fR
.sp
proc \fBclay::object_destroy\fR ?\fIargs\fR?
.sp
proc \fBclay::path\fR ?\fIargs\fR?
.sp
proc \fBclay::putb\fR ?\fImap\fR? \fItext\fR
.sp
proc \fBclay::script_path\fR
.sp
proc \fBclay::NSNormalize\fR \fIqualname\fR
.sp
proc \fBclay::uuid_generate\fR ?\fIargs\fR?
.sp
proc \fBclay::uuid::generate_tcl_machinfo\fR
.sp
proc \fBclay::uuid::tostring\fR \fIuuid\fR
.sp
proc \fBclay::uuid::fromstring\fR \fIuuid\fR
.sp
proc \fBclay::uuid::equal\fR \fIleft\fR \fIright\fR
.sp
proc \fBclay::uuid\fR \fIcmd\fR ?\fIargs\fR?
.sp
proc \fBclay::tree::sanitize\fR \fIdict\fR
.sp
proc \fBclay::tree::_sanitizeb\fR \fIpath\fR \fIvarname\fR \fIdict\fR
.sp
proc \fBclay::tree::storage\fR \fIrawpath\fR
.sp
proc \fBclay::tree::dictset\fR \fIvarname\fR ?\fIargs\fR?
.sp
proc \fBclay::tree::dictmerge\fR \fIvarname\fR ?\fIargs\fR?
.sp
proc \fBclay::tree::merge\fR ?\fIargs\fR?
.sp
proc \fBdictargs::proc\fR \fIname\fR \fIargspec\fR \fIbody\fR
.sp
proc \fBdictargs::method\fR \fIname\fR \fIargspec\fR \fIbody\fR
.sp
proc \fBclay::dialect::Push\fR \fIclass\fR
.sp
proc \fBclay::dialect::Peek\fR
.sp
proc \fBclay::dialect::Pop\fR
.sp
proc \fBclay::dialect::create\fR \fIname\fR ?\fIparent\fR \fB\fR?
.sp
proc \fBclay::dialect::NSNormalize\fR \fInamespace\fR \fIqualname\fR
.sp
proc \fBclay::dialect::DefineThunk\fR \fItarget\fR ?\fIargs\fR?
.sp
proc \fBclay::dialect::Canonical\fR \fInamespace\fR \fINSpace\fR \fIclass\fR
.sp
proc \fBclay::dialect::Define\fR \fInamespace\fR \fIclass\fR ?\fIargs\fR?
.sp
proc \fBclay::dialect::Aliases\fR \fInamespace\fR ?\fIargs\fR?
.sp
proc \fBclay::dialect::SuperClass\fR \fInamespace\fR ?\fIargs\fR?
.sp
proc \fBclay::dynamic_methods\fR \fIclass\fR
.sp
proc \fBclay::dynamic_methods_class\fR \fIthisclass\fR
.sp
proc \fBclay::define::Array\fR \fIname\fR ?\fIvalues\fR \fB\fR?
.sp
proc \fBclay::define::Delegate\fR \fIname\fR \fIinfo\fR
.sp
proc \fBclay::define::constructor\fR \fIarglist\fR \fIrawbody\fR
.sp
proc \fBclay::define::Class_Method\fR \fIname\fR \fIarglist\fR \fIbody\fR
.sp
proc \fBclay::define::class_method\fR \fIname\fR \fIarglist\fR \fIbody\fR
.sp
proc \fBclay::define::clay\fR ?\fIargs\fR?
.sp
proc \fBclay::define::destructor\fR \fIrawbody\fR
.sp
proc \fBclay::define::Dict\fR \fIname\fR ?\fIvalues\fR \fB\fR?
.sp
proc \fBclay::define::Option\fR \fIname\fR ?\fIargs\fR?
.sp
proc \fBclay::define::Method\fR \fIname\fR \fIargstyle\fR \fIargspec\fR \fIbody\fR
.sp
proc \fBclay::define::Option_Class\fR \fIname\fR ?\fIargs\fR?
.sp
proc \fBclay::define::Variable\fR \fIname\fR ?\fIdefault\fR \fB\fR?
.sp
proc \fBclay::ensemble_methodbody\fR \fIensemble\fR \fIeinfo\fR
.sp
proc \fBclay::define::Ensemble\fR \fIrawmethod\fR ?\fIargs\fR?
.sp
proc \fBclay::event::cancel\fR \fIself\fR ?\fItask\fR \fB*\fR?
.sp
proc \fBclay::event::generate\fR \fIself\fR \fIevent\fR ?\fIargs\fR?
.sp
proc \fBclay::event::nextid\fR
.sp
proc \fBclay::event::Notification_list\fR \fIself\fR \fIevent\fR ?\fIstackvar\fR \fB\fR?
.sp
proc \fBclay::event::notify\fR \fIrcpt\fR \fIsender\fR \fIevent\fR \fIeventinfo\fR
.sp
proc \fBclay::event::process\fR \fIself\fR \fIhandle\fR \fIscript\fR
.sp
proc \fBclay::event::schedule\fR \fIself\fR \fIhandle\fR \fIinterval\fR \fIscript\fR
.sp
proc \fBclay::event::subscribe\fR \fIself\fR \fIwho\fR \fIevent\fR
.sp
proc \fBclay::event::unsubscribe\fR \fIself\fR ?\fIargs\fR?
.sp
proc \fBclay::singleton\fR \fIname\fR \fIscript\fR
.sp
method \fBclay ancestors\fR
.sp
method \fBclay dump\fR
.sp
method \fBclay find\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
.sp
method \fBclay get\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
.sp
method \fBclay GET\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
.sp
method \fBclay merge\fR \fIdict\fR ?\fBdict\&.\&.\&.\fR?
.sp
method \fBclay replace\fR \fIdictionary\fR
.sp
method \fBclay search\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
.sp
method \fBclay set\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR? \fIvalue\fR
.sp
method \fBclay ancestors\fR
.sp
method \fBclay cache\fR \fIpath\fR \fIvalue\fR
.sp
method \fBclay cget\fR \fIfield\fR
.sp
method \fBclay delegate\fR ?\fIstub\fR? ?\fIobject\fR?
.sp
method \fBclay dump\fR
.sp
method \fBclay ensemble_map\fR
.sp
method \fBclay eval\fR \fIscript\fR
.sp
method \fBclay evolve\fR
.sp
method \fBclay exists\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
.sp
method \fBclay flush\fR
.sp
method \fBclay forward\fR \fImethod\fR \fIobject\fR
.sp
method \fBclay get\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
.sp
method \fBclay leaf\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
.sp
method \fBclay merge\fR \fIdict\fR ?\fBdict\&.\&.\&.\fR?
.sp
method \fBclay mixin\fR \fIclass\fR ?\fBclass\&.\&.\&.\fR?
.sp
method \fBclay mixinmap\fR ?\fIstub\fR? ?\fIclasses\fR?
.sp
method \fBclay provenance\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
.sp
method \fBclay replace\fR \fIdictionary\fR
.sp
method \fBclay search\fR \fIpath\fR \fIvaluevar\fR \fIisleafvar\fR
.sp
method \fBclay source\fR \fIfilename\fR
.sp
method \fBclay set\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR? \fIvalue\fR
.sp
method \fBInitializePublic\fR
.sp
.BE
.SH DESCRIPTION
Clay introduces a method ensemble to both \fBoo::class\fR and \fBoo::object\fR called
clay\&. This ensemble handles all of the high level interactions within the framework\&.
Clay stores structured data\&. Clan manages method delegation\&. Clay has facilities to
manage the complex interactions that come about with mixins\&.
.PP
The central concept is that inside of every object and class
(which are actually objects too) is a dict called clay\&. What is stored in that dict is
left to the imagination\&. But because this dict is exposed via a public method, we can
share structured data between object, classes, and mixins\&.
.PP
.SS "STRUCTURED DATA"
Clay uses a standardized set of method interactions and introspection that TclOO already provides to perform on-the-fly searches\&. On-the-fly searches mean that the data is never stale, and we avoid many of the sorts of collisions that would arise when objects start mixing in other classes during operation\&.
.PP
The \fBclay\fR methods for both classes and objects have a get and a set method\&. For objects, get will search through the local clay dict\&. If the requested leaf is not found, or the query is for a branch, the system will then begin to poll the clay methods of all of the class that implements the object, all of that classes’ ancestors, as well as all of the classes that have been mixed into this object, and all of their ancestors\&.
.PP
Intended branches on a tree end with a directory slash (/)\&. Intended leaves are left unadorned\&. This is a guide for the tool that builds the search
results to know what parts of a dict are intended to be branches and which are intended to be leaves\&.
For simple cases, branch marking can be ignored:
.CS


::oo::class create ::foo { }
::foo clay set property/ color blue
::foo clay set property/ shape round

set A [::foo new]
$A clay get property/
{color blue shape round}

$A clay set property/ shape square
$A clay get property/
{color blue shape square}

.CE
.PP
But when you start storing blocks of text, guessing what field is a dict and what isn’t gets messy:
.CS


::foo clay set description {A generic thing of designated color and shape}

$A clay get description
{A generic thing of designated color and shape}

Without a convention for discerning branches for leaves what should have been a value can be accidentally parsed as a dictionary, and merged with all of the other values that were never intended to be merge\&. Here is an example of it all going wrong:
::oo::class create ::foo { }
# Add description as a leaf
::foo clay set description  {A generic thing of designated color and shape}
# Add description as a branch
::foo clay set description/  {A generic thing of designated color and shape}

::oo::class create ::bar {
  superclass foo
}
# Add description as a leaf
::bar clay set description  {A drinking establishment of designated color and shape and size}
# Add description as a branch
::bar clay set description/  {A drinking establishment of designated color and shape and size}

set B [::bar new]
# As a leaf we get the value verbatim from he nearest ancestor
$B clay get description
  {A drinking establishment of designated color and shape and size}
# As a branch we get a recursive merge
$B clay get description/
{A drinking establishment of designated color and size thing of}

.CE
.SS "CLAY DIALECT"
Clay is built using the oo::dialect module from Tcllib\&. oo::dialect allows you to either add keywords directly to clay, or to create your own
metaclass and keyword set using Clay as a foundation\&. For details on the keywords and what they do, consult the functions in the ::clay::define namespace\&.
.SS "METHOD DELEGATION"
Method Delegation
It is sometimes useful to have an external object that can be invoked as if it were a method of the object\&. Clay provides a delegate ensemble method to perform that delegation, as well as introspect which methods are delegated in that manner\&. All delegated methods are marked with html-like tag markings (< >) around them\&.
.CS


::clay::define counter {
  Variable counter 0
  method incr {{howmuch 1}} {
    my variable counter
    incr counter $howmuch
  }
  method value {} {
    my variable counter
    return $counter
  }
  method reset {} {
    my variable counter
    set counter 0
  }
}
::clay::define example {
  variable buffer
  constructor {} {
    # Build a counter object
    set obj [namespace current]::counter
    ::counter create $obj
    # Delegate the counter
    my delegate <counter> $obj
  }
  method line {text} {
    my <counter> incr
    append buffer $text
  }
}

set A [example new]
$A line {Who’s line is it anyway?}
$A <counter> value
1

.CE
.SH COMMANDS
.TP
proc \fBclay::PROC\fR \fIname\fR \fIarglist\fR \fIbody\fR ?\fIninja\fR \fB\fR?
Because many features in this package may be added as
commands to future tcl cores, or be provided in binary
form by packages, I need a declaritive way of saying
\fICreate this command if there isn't one already\fR\&.
The \fIninja\fR argument is a script to execute if the
command is created by this mechanism\&.
.TP
proc \fBclay::_ancestors\fR \fIresultvar\fR \fIclass\fR
.TP
proc \fBclay::ancestors\fR ?\fIargs\fR?
.TP
proc \fBclay::args_to_dict\fR ?\fIargs\fR?
.TP
proc \fBclay::args_to_options\fR ?\fIargs\fR?
.TP
proc \fBclay::dynamic_arguments\fR \fIensemble\fR \fImethod\fR \fIarglist\fR ?\fIargs\fR?
.TP
proc \fBclay::dynamic_wrongargs_message\fR \fIarglist\fR
.TP
proc \fBclay::is_dict\fR \fId\fR
.TP
proc \fBclay::is_null\fR \fIvalue\fR
.TP
proc \fBclay::leaf\fR ?\fIargs\fR?
.TP
proc \fBclay::K\fR \fIa\fR \fIb\fR
.TP
proc \fBclay::noop\fR ?\fIargs\fR?
Perform a noop\&. Useful in prototyping for commenting out blocks
of code without actually having to comment them out\&. It also makes
a handy default for method delegation if a delegate has not been
assigned yet\&.
.TP
proc \fBclay::cleanup\fR
Process the queue of objects to be destroyed
.TP
proc \fBclay::object_create\fR \fIobjname\fR ?\fIclass\fR \fB\fR?
.TP
proc \fBclay::object_rename\fR \fIobject\fR \fInewname\fR
.TP
proc \fBclay::object_destroy\fR ?\fIargs\fR?
Mark an objects for destruction on the next cleanup
.TP
proc \fBclay::path\fR ?\fIargs\fR?
.TP
proc \fBclay::putb\fR ?\fImap\fR? \fItext\fR
Append a line of text to a variable\&. Optionally apply a string mapping\&.
.TP
proc \fBclay::script_path\fR
.TP
proc \fBclay::NSNormalize\fR \fIqualname\fR
.TP
proc \fBclay::uuid_generate\fR ?\fIargs\fR?
.TP
proc \fBclay::uuid::generate_tcl_machinfo\fR
.TP
proc \fBclay::uuid::tostring\fR \fIuuid\fR
.TP
proc \fBclay::uuid::fromstring\fR \fIuuid\fR
Convert a string representation of a uuid into its binary format\&.
.TP
proc \fBclay::uuid::equal\fR \fIleft\fR \fIright\fR
Compare two uuids for equality\&.
.TP
proc \fBclay::uuid\fR \fIcmd\fR ?\fIargs\fR?
uuid generate -> string rep of a new uuid
uuid equal uuid1 uuid2
.TP
proc \fBclay::tree::sanitize\fR \fIdict\fR
Output a dictionary removing any \&. entries added by \fBclay::tree::merge\fR
.TP
proc \fBclay::tree::_sanitizeb\fR \fIpath\fR \fIvarname\fR \fIdict\fR
Helper function for ::clay::tree::sanitize
Formats the string representation for a dictionary element within
a human readable stream of lines, and determines if it needs to call itself
with further indentation to express a sub-branch
.TP
proc \fBclay::tree::storage\fR \fIrawpath\fR
Return the path as a storage path for clay::tree
with all branch terminators removed\&.
This command will also break arguments up if they
contain /\&.
.sp
Example:
.CS

 > clay::tree::storage {foo bar baz bang}
 foo bar baz bang
 > clay::tree::storage {foo bar baz bang/}
 foo bar baz bang
 > clay::tree::storage {foo bar baz bang:}
 foo bar baz bang:
 > clay::tree::storage {foo/bar/baz bang:}
 foo bar baz bang:
 > clay::tree::storage {foo/bar/baz/bang}
 foo bar baz bang



.CE
.TP
proc \fBclay::tree::dictset\fR \fIvarname\fR ?\fIargs\fR?
Set an element with a recursive dictionary,
marking all branches on the way down to the
final element\&.
If the value does not exists in the nested dictionary
it is added as a leaf\&. If the value already exists as a branch
the value given is merged if the value is a valid dict\&. If the
incoming value is not a valid dict, the value overrides the value
stored, and the value is treated as a leaf from then on\&.
.sp
Example:
.CS

 > set r {}
 > ::clay::tree::dictset r option color default Green
 \&. {} option {\&. {} color {\&. {} default Green}}
 > ::clay::tree::dictset r option {Something not dictlike}
 \&. {} option {Something not dictlike}
 # Note that if the value is not a dict, and you try to force it to be
 # an error with be thrown on the merge
 > ::clay::tree::dictset r option color default Blue
 missing value to go with key



.CE
.TP
proc \fBclay::tree::dictmerge\fR \fIvarname\fR ?\fIargs\fR?
A recursive form of dict merge, intended for modifying variables in place\&.
.sp
Example:
.CS

 > set mydict {sub/ {sub/ {description {a block of text}}}}
 > ::clay::tree::dictmerge mydict {sub/ {sub/ {field {another block of text}}}}]
 > clay::tree::print $mydict
 sub/ {
   sub/ {
     description {a block of text}
     field {another block of text}
   }
 }



.CE
.TP
proc \fBclay::tree::merge\fR ?\fIargs\fR?
A recursive form of dict merge
.sp
A routine to recursively dig through dicts and merge
adapted from http://stevehavelka\&.com/tcl-dict-operation-nested-merge/
.sp
Example:
.CS

 > set mydict {sub/ {sub/ {description {a block of text}}}}
 > set odict [clay::tree::merge $mydict {sub/ {sub/ {field {another block of text}}}}]
 > clay::tree::print $odict
 sub/ {
   sub/ {
     description {a block of text}
     field {another block of text}
   }
 }



.CE
.TP
proc \fBdictargs::proc\fR \fIname\fR \fIargspec\fR \fIbody\fR
Named Procedures as new command
.TP
proc \fBdictargs::method\fR \fIname\fR \fIargspec\fR \fIbody\fR
.TP
proc \fBclay::dialect::Push\fR \fIclass\fR
.TP
proc \fBclay::dialect::Peek\fR
.TP
proc \fBclay::dialect::Pop\fR
.TP
proc \fBclay::dialect::create\fR \fIname\fR ?\fIparent\fR \fB\fR?
This proc will generate a namespace, a "mother of all classes", and a
rudimentary set of policies for this dialect\&.
.TP
proc \fBclay::dialect::NSNormalize\fR \fInamespace\fR \fIqualname\fR
Support commands; not intended to be called directly\&.
.TP
proc \fBclay::dialect::DefineThunk\fR \fItarget\fR ?\fIargs\fR?
.TP
proc \fBclay::dialect::Canonical\fR \fInamespace\fR \fINSpace\fR \fIclass\fR
.TP
proc \fBclay::dialect::Define\fR \fInamespace\fR \fIclass\fR ?\fIargs\fR?
Implementation of the languages' define command
.TP
proc \fBclay::dialect::Aliases\fR \fInamespace\fR ?\fIargs\fR?
.TP
proc \fBclay::dialect::SuperClass\fR \fInamespace\fR ?\fIargs\fR?
.TP
proc \fBclay::dynamic_methods\fR \fIclass\fR
.TP
proc \fBclay::dynamic_methods_class\fR \fIthisclass\fR
.TP
proc \fBclay::define::Array\fR \fIname\fR ?\fIvalues\fR \fB\fR?
New OO Keywords for clay
.TP
proc \fBclay::define::Delegate\fR \fIname\fR \fIinfo\fR
An annotation that objects of this class interact with delegated
methods\&. The annotation is intended to be a dictionary, and the
only reserved key is \fIdescription\fR, a human readable description\&.
.TP
proc \fBclay::define::constructor\fR \fIarglist\fR \fIrawbody\fR
.TP
proc \fBclay::define::Class_Method\fR \fIname\fR \fIarglist\fR \fIbody\fR
Specify the a method for the class object itself, instead of for objects of the class
.TP
proc \fBclay::define::class_method\fR \fIname\fR \fIarglist\fR \fIbody\fR
And alias to the new Class_Method keyword
.TP
proc \fBclay::define::clay\fR ?\fIargs\fR?
.TP
proc \fBclay::define::destructor\fR \fIrawbody\fR
.TP
proc \fBclay::define::Dict\fR \fIname\fR ?\fIvalues\fR \fB\fR?
.TP
proc \fBclay::define::Option\fR \fIname\fR ?\fIargs\fR?
Define an option for the class
.TP
proc \fBclay::define::Method\fR \fIname\fR \fIargstyle\fR \fIargspec\fR \fIbody\fR
.TP
proc \fBclay::define::Option_Class\fR \fIname\fR ?\fIargs\fR?
Define a class of options
All field / value pairs will be be inherited by an option that
specify \fIname\fR as it class field\&.
.TP
proc \fBclay::define::Variable\fR \fIname\fR ?\fIdefault\fR \fB\fR?
This keyword can also be expressed:
.CS

property variable NAME {default DEFAULT}
.CE
.sp
Variables registered in the variable property are also initialized
(if missing) when the object changes class via the \fImorph\fR method\&.
.TP
proc \fBclay::ensemble_methodbody\fR \fIensemble\fR \fIeinfo\fR
Produce the body of an ensemble's public dispatch method
ensemble is the name of the the ensemble\&.
einfo is a dictionary of methods for the ensemble, and each value is a script
to execute on dispatch
.sp
Example:
.CS

 ::clay::ensemble_methodbody foo {
   bar {tailcall my Foo_bar {*}$args}
   baz {tailcall my Foo_baz {*}$args}
   clock {return [clock seconds]}
   default {puts "You gave me $method"}
 }



.CE
.TP
proc \fBclay::define::Ensemble\fR \fIrawmethod\fR ?\fIargs\fR?
.TP
proc \fBclay::event::cancel\fR \fIself\fR ?\fItask\fR \fB*\fR?
Cancel a scheduled event
.TP
proc \fBclay::event::generate\fR \fIself\fR \fIevent\fR ?\fIargs\fR?
Generate an event
Adds a subscription mechanism for objects
to see who has recieved this event and prevent
spamming or infinite recursion
.TP
proc \fBclay::event::nextid\fR
.TP
proc \fBclay::event::Notification_list\fR \fIself\fR \fIevent\fR ?\fIstackvar\fR \fB\fR?
Called recursively to produce a list of
who recieves notifications
.TP
proc \fBclay::event::notify\fR \fIrcpt\fR \fIsender\fR \fIevent\fR \fIeventinfo\fR
Final delivery to intended recipient object
.TP
proc \fBclay::event::process\fR \fIself\fR \fIhandle\fR \fIscript\fR
Evaluate an event script in the global namespace
.TP
proc \fBclay::event::schedule\fR \fIself\fR \fIhandle\fR \fIinterval\fR \fIscript\fR
Schedule an event to occur later
.TP
proc \fBclay::event::subscribe\fR \fIself\fR \fIwho\fR \fIevent\fR
Subscribe an object to an event pattern
.TP
proc \fBclay::event::unsubscribe\fR \fIself\fR ?\fIargs\fR?
Unsubscribe an object from an event pattern
.TP
proc \fBclay::singleton\fR \fIname\fR \fIscript\fR
An object which is intended to be it's own class\&.
.PP
.SH CLASSES
.SS "CLASS  CLAY::CLASS"
.PP
\fBMethods\fR
.TP
method \fBclay ancestors\fR
Return this class and all ancestors in search order\&.
.TP
method \fBclay dump\fR
Return a complete dump of this object's clay data, but only this object's clay data\&.
.TP
method \fBclay find\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
Pull a chunk of data from the clay system\&. If the last element of \fIpath\fR is a branch,
returns a recursive merge of all data from this object and it's constituent classes of the data in that branch\&.
If the last element is a leaf, search this object for a matching leaf, or search all  constituent classes for a matching
leaf and return the first value found\&.
If no value is found, returns an empty string\&.
If a branch is returned the topmost \&. entry is omitted\&.
.TP
method \fBclay get\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
Pull a chunk of data from the class's clay system\&.
If no value is found, returns an empty string\&.
If a branch is returned the topmost \&. entry is omitted\&.
.TP
method \fBclay GET\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
Pull a chunk of data from the class's clay system\&.
If no value is found, returns an empty string\&.
.TP
method \fBclay merge\fR \fIdict\fR ?\fBdict\&.\&.\&.\fR?
Recursively merge the dictionaries given into the object's local clay storage\&.
.TP
method \fBclay replace\fR \fIdictionary\fR
Replace the contents of the internal clay storage with the dictionary given\&.
.TP
method \fBclay search\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
Return the first matching value for the path in either this class's clay data or one of its ancestors
.TP
method \fBclay set\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR? \fIvalue\fR
Merge the conents of \fBvalue\fR with the object's clay storage at \fBpath\fR\&.
.PP
.PP
.SS "CLASS  CLAY::OBJECT"
clay::object
This class is inherited by all classes that have options\&.
.PP
\fBMethods\fR
.TP
method \fBclay ancestors\fR
Return the class this object belongs to, all classes mixed into this object, and all ancestors of those classes in search order\&.
.TP
method \fBclay cache\fR \fIpath\fR \fIvalue\fR
Store VALUE in such a way that request in SEARCH for PATH will always return it until the cache is flushed
.TP
method \fBclay cget\fR \fIfield\fR
Pull a value from either the object's clay structure or one of its constituent classes that matches the field name\&.
The order of search us:
.sp
1\&. The as a value in local dict variable config
.sp
2\&. The as a value in local dict variable clay
.sp
3\&. As a leaf in any ancestor as a root of the clay tree
.sp
4\&. As a leaf in any ancestor as \fBconst\fR \fIfield\fR
.sp
5\&. As a leaf in any ancestor as \fBoption\fR \fIfield\fR \fBdefault\fR
.TP
method \fBclay delegate\fR ?\fIstub\fR? ?\fIobject\fR?
Introspect or control method delegation\&. With no arguments, the method will return a
key/value list of stubs and objects\&. With just the \fIstub\fR argument, the method will
return the object (if any) attached to the stub\&. With a \fIstub\fR and an \fIobject\fR
this command will forward all calls to the method \fIstub\fR to the \fIobject\fR\&.
.TP
method \fBclay dump\fR
Return a complete dump of this object's clay data, as well as the data from all constituent classes recursively blended in\&.
.TP
method \fBclay ensemble_map\fR
Return a dictionary describing the method ensembles to be assembled for this object
.TP
method \fBclay eval\fR \fIscript\fR
Evaluated a script in the namespace of this object
.TP
method \fBclay evolve\fR
Trigger the \fBInitializePublic\fR private method
.TP
method \fBclay exists\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
Returns 1 if \fIpath\fR exists in either the object's clay data\&. Values greater than one indicate the element exists in one of the object's constituent classes\&. A value of zero indicates the path could not be found\&.
.TP
method \fBclay flush\fR
Wipe any caches built by the clay implementation
.TP
method \fBclay forward\fR \fImethod\fR \fIobject\fR
A convenience wrapper for
.CS

oo::objdefine [self] forward {*}$args
.CE
.TP
method \fBclay get\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
Pull a chunk of data from the clay system\&. If the last element of \fIpath\fR is a branch (ends in a slash /),
returns a recursive merge of all data from this object and it's constituent classes of the data in that branch\&.
If the last element is a leaf, search this object for a matching leaf, or search all  constituent classes for a matching
leaf and return the first value found\&.
If no value is found, returns an empty string\&.
.TP
method \fBclay leaf\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
A modified get which is tailored to pull only leaf elements
.TP
method \fBclay merge\fR \fIdict\fR ?\fBdict\&.\&.\&.\fR?
Recursively merge the dictionaries given into the object's local clay storage\&.
.TP
method \fBclay mixin\fR \fIclass\fR ?\fBclass\&.\&.\&.\fR?
Perform [oo::objdefine [self] mixin] on this object, with a few additional rules:
Prior to the call, for any class was previously mixed in, but not in the new result, execute the script registered to mixin/ unmap-script (if given\&.)
For all new classes, that were not present prior to this call, after the native TclOO mixin is invoked, execute the script registered to mixin/ map-script (if given\&.)
Fall all classes that are now present and “mixed in”, execute the script registered to mixin/ react-script (if given\&.)
.TP
method \fBclay mixinmap\fR ?\fIstub\fR? ?\fIclasses\fR?
With no arguments returns the map of stubs and classes mixed into the current object\&. When only stub is given,
returns the classes mixed in on that stub\&. When stub and classlist given, replace the classes currently on that stub with the given
classes and invoke clay mixin on the new matrix of mixed in classes\&.
.TP
method \fBclay provenance\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR?
Return either \fBself\fR if that path exists in the current object, or return the first class (if any) along the clay search path which contains that element\&.
.TP
method \fBclay replace\fR \fIdictionary\fR
Replace the contents of the internal clay storage with the dictionary given\&.
.TP
method \fBclay search\fR \fIpath\fR \fIvaluevar\fR \fIisleafvar\fR
Return true, and set valuevar to the value and isleafar to true for false if PATH was found in the cache\&.
.TP
method \fBclay source\fR \fIfilename\fR
Source the given filename within the object's namespace
.TP
method \fBclay set\fR \fIpath\fR ?\fBpath\&.\&.\&.\fR? \fIvalue\fR
Merge the conents of \fBvalue\fR with the object's clay storage at \fBpath\fR\&.
.TP
method \fBInitializePublic\fR
Instantiate variables\&. Called on object creation and during clay mixin\&.
.PP
.PP
.SH AUTHORS
Sean Woods \fImailto:<yoda@etoyoc\&.com>\fR
.PP
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fIoo\fR of the
\fITcllib Trackers\fR [http://core\&.tcl\&.tk/tcllib/reportlist]\&.
Please also report any ideas for enhancements you may have for either
package and/or documentation\&.
.PP
When proposing code changes, please provide \fIunified diffs\fR,
i\&.e the output of \fBdiff -u\fR\&.
.PP
Note further that \fIattachments\fR are strongly preferred over
inlined patches\&. Attachments can be made by going to the \fBEdit\fR
form of the ticket immediately after its creation, and then using the
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
TclOO, oo
.SH CATEGORY
Programming tools
.SH COPYRIGHT
.nf
Copyright (c) 2018 Sean Woods <yoda@etoyoc\&.com>

.fi

Changes to idoc/man/files/modules/debug/debug_heartbeat.n.

1
2
3
4
5
6
7
8
9
10
11
12
13
'\"
'\" Generated from file 'debug_heartbeat\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 200?, Colin McCormack, Wub Server Utilities
'\" Copyright (c) 2012, Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "debug::heartbeat" n 1 tcllib "debug narrative"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,





|







1
2
3
4
5
6
7
8
9
10
11
12
13
'\"
'\" Generated from file 'debug_heartbeat\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 200?, Colin McCormack, Wub Server Utilities
'\" Copyright (c) 2012, Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "debug::heartbeat" n 1\&.0\&.1 tcllib "debug narrative"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
..
.BS
.SH NAME
debug::heartbeat \- debug narrative - heartbeat
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBdebug::heartbeat  ?1?\fR
.sp
package require \fBdebug  ?1?\fR
.sp
\fBdebug\fR \fBheartbeat\fR ?\fIdelta\fR?
.sp
.BE
.SH DESCRIPTION







|







273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
..
.BS
.SH NAME
debug::heartbeat \- debug narrative - heartbeat
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBdebug::heartbeat  ?1\&.0\&.1?\fR
.sp
package require \fBdebug  ?1?\fR
.sp
\fBdebug\fR \fBheartbeat\fR ?\fIdelta\fR?
.sp
.BE
.SH DESCRIPTION

Changes to idoc/man/files/modules/dicttool/dicttool.n.

272
273
274
275
276
277
278


279
280
281
282
283
284
285
..
.BS
.SH NAME
dicttool \- Dictionary Tools
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp


\fBladd\fR \fIvarname\fR \fIargs\fR
.sp
\fBldelete\fR \fIvarname\fR \fIargs\fR
.sp
\fBdict getnull\fR \fIargs\fR
.sp
\fBdict print\fR \fIdict\fR







>
>







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
..
.BS
.SH NAME
dicttool \- Dictionary Tools
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBdicttool  ?1\&.0?\fR
.sp
\fBladd\fR \fIvarname\fR \fIargs\fR
.sp
\fBldelete\fR \fIvarname\fR \fIargs\fR
.sp
\fBdict getnull\fR \fIargs\fR
.sp
\fBdict print\fR \fIdict\fR
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
just in case any of these slip into the core\&.
.TP
\fBladd\fR \fIvarname\fR \fIargs\fR
This command will add a new instance of each element in \fIargs\fR to \fIvarname\fR, but only if that element
is not already present\&.
.TP
\fBldelete\fR \fIvarname\fR \fIargs\fR
This command will add a delete all instances of each element in \fIargs\fR from \fIvarname\fR\&.
.TP
\fBdict getnull\fR \fIargs\fR
Operates like \fBdict get\fR, however if the key \fIargs\fR does not exist, it returns an empty
list instead of throwing an error\&.
.TP
\fBdict print\fR \fIdict\fR
This command will produce a string representation of \fIdict\fR, with each nested branch on







|







299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
just in case any of these slip into the core\&.
.TP
\fBladd\fR \fIvarname\fR \fIargs\fR
This command will add a new instance of each element in \fIargs\fR to \fIvarname\fR, but only if that element
is not already present\&.
.TP
\fBldelete\fR \fIvarname\fR \fIargs\fR
This command will delete all instances of each element in \fIargs\fR from \fIvarname\fR\&.
.TP
\fBdict getnull\fR \fIargs\fR
Operates like \fBdict get\fR, however if the key \fIargs\fR does not exist, it returns an empty
list instead of throwing an error\&.
.TP
\fBdict print\fR \fIdict\fR
This command will produce a string representation of \fIdict\fR, with each nested branch on

Changes to idoc/man/files/modules/dns/tcllib_dns.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'tcllib_dns\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2002, Pat Thoyts
'\"
.TH "dns" n 1\&.4\&.0 tcllib "Domain Name Service"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'tcllib_dns\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2002, Pat Thoyts
'\"
.TH "dns" n 1\&.4\&.1 tcllib "Domain Name Service"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
dns \- Tcl Domain Name Service Client
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBdns  ?1\&.4\&.0?\fR
.sp
\fB::dns::resolve\fR \fIquery\fR ?\fIoptions\fR?
.sp
\fB::dns::configure\fR ?\fIoptions\fR?
.sp
\fB::dns::name\fR \fItoken\fR
.sp







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
dns \- Tcl Domain Name Service Client
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBdns  ?1\&.4\&.1?\fR
.sp
\fB::dns::resolve\fR \fIquery\fR ?\fIoptions\fR?
.sp
\fB::dns::configure\fR ?\fIoptions\fR?
.sp
\fB::dns::name\fR \fItoken\fR
.sp

Changes to idoc/man/files/modules/doctools/docidx_lang_intro.n.

297
298
299
300
301
302
303
304
305
306
307
308
309
310
311

    \&.\&.\&. [key {markup language}] \&.\&.\&.

.CE
.CS


  \&.\&.\&. [manpage thefile \\\\
          {file description}] \&.\&.\&.

.CE
.SS "BASIC STRUCTURE"
The most simple document which can be written in docidx is
.CS








|







297
298
299
300
301
302
303
304
305
306
307
308
309
310
311

    \&.\&.\&. [key {markup language}] \&.\&.\&.

.CE
.CS


  \&.\&.\&. [manpage thefile \\
          {file description}] \&.\&.\&.

.CE
.SS "BASIC STRUCTURE"
The most simple document which can be written in docidx is
.CS

Changes to idoc/man/files/modules/doctools/doctoc_lang_intro.n.

297
298
299
300
301
302
303
304
305
306
307
308
309
310
311

    \&.\&.\&. [division_start {Appendix 1}] \&.\&.\&.

.CE
.CS


  \&.\&.\&. [item thefile \\\\
          label {file description}] \&.\&.\&.

.CE
.SS "BASIC STRUCTURE"
The most simple document which can be written in doctoc is
.CS








|







297
298
299
300
301
302
303
304
305
306
307
308
309
310
311

    \&.\&.\&. [division_start {Appendix 1}] \&.\&.\&.

.CE
.CS


  \&.\&.\&. [item thefile \\
          label {file description}] \&.\&.\&.

.CE
.SS "BASIC STRUCTURE"
The most simple document which can be written in doctoc is
.CS

Changes to idoc/man/files/modules/doctools/doctools.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'doctools\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2003-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools" n 1\&.5\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'doctools\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2003-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools" n 1\&.5\&.6 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
doctools \- doctools - Processing documents
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBdoctools  ?1\&.5\&.1?\fR
.sp
\fB::doctools::new\fR \fIobjectName\fR ?\fIoption value\fR\&.\&.\&.?
.sp
\fB::doctools::help\fR
.sp
\fB::doctools::search\fR \fIpath\fR
.sp







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
doctools \- doctools - Processing documents
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBdoctools  ?1\&.5\&.6?\fR
.sp
\fB::doctools::new\fR \fIobjectName\fR ?\fIoption value\fR\&.\&.\&.?
.sp
\fB::doctools::help\fR
.sp
\fB::doctools::search\fR \fIpath\fR
.sp

Changes to idoc/man/files/modules/doctools/doctools_lang_intro.n.

296
297
298
299
300
301
302
303
304
305
306
307
308
309
310

  \&.\&.\&. [list_begin enumerated] \&.\&.\&.

.CE
.CS


  \&.\&.\&. [call [cmd foo] \\\\
          [arg bar]] \&.\&.\&.

.CE
.CS


  \&.\&.\&. [term {complex concept}] \&.\&.\&.







|







296
297
298
299
300
301
302
303
304
305
306
307
308
309
310

  \&.\&.\&. [list_begin enumerated] \&.\&.\&.

.CE
.CS


  \&.\&.\&. [call [cmd foo] \\
          [arg bar]] \&.\&.\&.

.CE
.CS


  \&.\&.\&. [term {complex concept}] \&.\&.\&.
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
[keywords {doctools language}]
[keywords {doctools markup}]
[keywords {doctools syntax}]
[keywords markup]
[keywords {semantic markup}]
    [description]
    [vset CATEGORY doctools]
[include \&.\&./doctools2base/include/feedback\&.inc]
[manpage_end]

.CE
This also shows us that all doctools documents are split into two
parts, the \fIheader\fR and the \fIbody\fR\&. Everything coming before
[\fBdescription\fR] belongs to the header, and everything coming
after belongs to the body, with the whole document bracketed by the







|







330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
[keywords {doctools language}]
[keywords {doctools markup}]
[keywords {doctools syntax}]
[keywords markup]
[keywords {semantic markup}]
    [description]
    [vset CATEGORY doctools]
[include \&.\&./common-text/feedback\&.inc]
[manpage_end]

.CE
This also shows us that all doctools documents are split into two
parts, the \fIheader\fR and the \fIbody\fR\&. Everything coming before
[\fBdescription\fR] belongs to the header, and everything coming
after belongs to the body, with the whole document bracketed by the
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
.CS


    [manpage_begin NAME SECTION VERSION]
    [copyright {YEAR AUTHOR}][titledesc TITLE][moddesc MODULE_TITLE]
    [require PACKAGE VERSION][require PACKAGE][description]
    [vset CATEGORY doctools]
[include \&.\&./doctools2base/include/feedback\&.inc]
[manpage_end]

.CE
has the same meaning as the example before\&.
.PP
On the other hand, if \fIwhitespace\fR is present it consists not
only of any sequence of characters containing the space character,







|







389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
.CS


    [manpage_begin NAME SECTION VERSION]
    [copyright {YEAR AUTHOR}][titledesc TITLE][moddesc MODULE_TITLE]
    [require PACKAGE VERSION][require PACKAGE][description]
    [vset CATEGORY doctools]
[include \&.\&./common-text/feedback\&.inc]
[manpage_end]

.CE
has the same meaning as the example before\&.
.PP
On the other hand, if \fIwhitespace\fR is present it consists not
only of any sequence of characters containing the space character,

Changes to idoc/man/files/modules/doctools2idx/export_docidx.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::export::docidx" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,


|

|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::export::docidx" n 0\&.2\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
doctools::idx::export::docidx \- docidx export plugin
.SH SYNOPSIS
package require \fBTcl  8\&.4\fR
.sp
package require \fBdoctools::idx::export::docidx  ?0\&.1?\fR
.sp
\fBexport\fR \fIserial\fR \fIconfiguration\fR
.sp
.BE
.SH DESCRIPTION
This package implements the doctools keyword index export plugin for
the generation of docidx markup\&.







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
doctools::idx::export::docidx \- docidx export plugin
.SH SYNOPSIS
package require \fBTcl  8\&.4\fR
.sp
package require \fBdoctools::idx::export::docidx  ?0\&.2\&.1?\fR
.sp
\fBexport\fR \fIserial\fR \fIconfiguration\fR
.sp
.BE
.SH DESCRIPTION
This package implements the doctools keyword index export plugin for
the generation of docidx markup\&.
464
465
466
467
468
469
470
471
472
473
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
docidx, doctools, export, index, serialization
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


464
465
466
467
468
469
470
471
472
473
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
docidx, doctools, export, index, serialization
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2idx/idx_export.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'idx_export\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2018 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::export" n 0\&.2 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,


|

|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'idx_export\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::export" n 0\&.2\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
.de MT
.QW ""
..
.BS
.SH NAME
doctools::idx::export \- Exporting keyword indices
.SH SYNOPSIS
package require \fBdoctools::idx::export  ?0\&.2?\fR
.sp
package require \fBTcl  8\&.4\fR
.sp
package require \fBdoctools::config \fR
.sp
package require \fBdoctools::idx::structure \fR
.sp
package require \fBsnit \fR
.sp
package require \fBpluginmgr \fR
.sp







|



|







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
.de MT
.QW ""
..
.BS
.SH NAME
doctools::idx::export \- Exporting keyword indices
.SH SYNOPSIS
package require \fBdoctools::idx::export  ?0\&.2\&.1?\fR
.sp
package require \fBTcl  8\&.4\fR
.sp
package require \fBstruct::map \fR
.sp
package require \fBdoctools::idx::structure \fR
.sp
package require \fBsnit \fR
.sp
package require \fBpluginmgr \fR
.sp
670
671
672
673
674
675
676
677
678
679
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
HTML, conversion, docidx, documentation, export, formatting, generation, index, json, keyword index, manpage, markup, nroff, plugin, reference, tcler's wiki, text, url, wiki
.SH CATEGORY
Documentation tools
.SH COPYRIGHT
.nf
Copyright (c) 2009-2018 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


670
671
672
673
674
675
676
677
678
679
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
HTML, conversion, docidx, documentation, export, formatting, generation, index, json, keyword index, manpage, markup, nroff, plugin, reference, tcler's wiki, text, url, wiki
.SH CATEGORY
Documentation tools
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2idx/idx_export_html.n.

1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::export::html" n 0\&.2 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.


|







1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::export::html" n 0\&.2 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
549
550
551
552
553
554
555
556
557
558
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
HTML, doctools, export, index, serialization
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


549
550
551
552
553
554
555
556
557
558
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
HTML, doctools, export, index, serialization
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2idx/idx_export_json.n.

1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::export::json" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.


|







1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::export::json" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
481
482
483
484
485
486
487
488
489
490
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
JSON, doctools, export, index, serialization
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


481
482
483
484
485
486
487
488
489
490
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
JSON, doctools, export, index, serialization
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2idx/idx_export_nroff.n.

1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::export::nroff" n 0\&.3 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.


|







1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::export::nroff" n 0\&.3 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
432
433
434
435
436
437
438
439
440
441
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
doctools, export, index, nroff, serialization
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


432
433
434
435
436
437
438
439
440
441
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
doctools, export, index, nroff, serialization
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2idx/idx_export_text.n.

1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::export::text" n 0\&.2 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.


|







1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::export::text" n 0\&.2 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
416
417
418
419
420
421
422
423
424
425
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
doctools, export, index, plain text, serialization
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


416
417
418
419
420
421
422
423
424
425
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
doctools, export, index, plain text, serialization
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2idx/idx_export_wiki.n.

1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::export::wiki" n 0\&.2 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.


|







1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::export::wiki" n 0\&.2 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
429
430
431
432
433
434
435
436
437
438
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
doctools, export, index, serialization, wiki
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


429
430
431
432
433
434
435
436
437
438
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
doctools, export, index, serialization, wiki
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2idx/idx_import.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'idx_import\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2018 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::import" n 0\&.2 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,


|

|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'idx_import\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::import" n 0\&.2\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
.de MT
.QW ""
..
.BS
.SH NAME
doctools::idx::import \- Importing keyword indices
.SH SYNOPSIS
package require \fBdoctools::idx::import  ?0\&.2?\fR
.sp
package require \fBTcl  8\&.4\fR
.sp
package require \fBdoctools::config \fR
.sp
package require \fBdoctools::idx::structure \fR
.sp
package require \fBsnit \fR
.sp
package require \fBpluginmgr \fR
.sp







|



|







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
.de MT
.QW ""
..
.BS
.SH NAME
doctools::idx::import \- Importing keyword indices
.SH SYNOPSIS
package require \fBdoctools::idx::import  ?0\&.2\&.1?\fR
.sp
package require \fBTcl  8\&.4\fR
.sp
package require \fBstruct::map \fR
.sp
package require \fBdoctools::idx::structure \fR
.sp
package require \fBsnit \fR
.sp
package require \fBpluginmgr \fR
.sp
749
750
751
752
753
754
755
756
757
758
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
conversion, docidx, documentation, import, index, json, keyword index, manpage, markup, parsing, plugin, reference, url
.SH CATEGORY
Documentation tools
.SH COPYRIGHT
.nf
Copyright (c) 2009-2018 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


749
750
751
752
753
754
755
756
757
758
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
conversion, docidx, documentation, import, index, json, keyword index, manpage, markup, parsing, plugin, reference, url
.SH CATEGORY
Documentation tools
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2idx/idx_import_json.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::import::json" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,


|

|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::import::json" n 0\&.2\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
.de MT
.QW ""
..
.BS
.SH NAME
doctools::idx::import::json \- JSON import plugin
.SH SYNOPSIS
package require \fBTcl  8\&.4\fR
.sp
package require \fBdoctools::idx::import::json  ?0\&.1?\fR
.sp
package require \fBdoctools::idx::structure \fR
.sp
package require \fBjson \fR
.sp
\fBimport\fR \fIstring\fR \fIconfiguration\fR
.sp







|

|







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
.de MT
.QW ""
..
.BS
.SH NAME
doctools::idx::import::json \- JSON import plugin
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBdoctools::idx::import::json  ?0\&.2\&.1?\fR
.sp
package require \fBdoctools::idx::structure \fR
.sp
package require \fBjson \fR
.sp
\fBimport\fR \fIstring\fR \fIconfiguration\fR
.sp
458
459
460
461
462
463
464
465
466
467
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
JSON, deserialization, doctools, import, index
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


458
459
460
461
462
463
464
465
466
467
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
JSON, deserialization, doctools, import, index
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2idx/idx_introduction.n.

369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389

                                    ~~~~~~~~~~~ doctools::idx ~~~~~~~~~~~
                                   ~~                   |               ~~
                doctools::idx::export ~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ doctools::idx::import
                        |                               |                       |
        +---------------+-------------------------+     |    +------------------+---------------+-----------------------+---------------+
        |               |                         |     |    |                  |               |                       |               |
doctools::config        =                         |     |    |                  =       doctools::include       doctools::config doctools::paths
                        |                         |     |    |                  |
                doctools::idx::export::<*>        |     |    |          doctools::idx::import::<*>
                        docidx                    |     |    |                  docidx, json
                        json                      |     |    |                  |           \\\\
                        html                      |     |    |          doctools::idx::parse \\\\
                        nroff                     |     |    |                  |             \\\\
                        wiki                      |     |    |  +---------------+              json
                        text                      |     |    |  |               |
                                                doctools::idx::structure        |
                                                                                |
                                                                        +-------+---------------+
                                                                        |                       |
          doctools::html  doctools::html::cssdefaults           doctools::tcl::parse    doctools::msgcat







|



|
|
|







369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389

                                    ~~~~~~~~~~~ doctools::idx ~~~~~~~~~~~
                                   ~~                   |               ~~
                doctools::idx::export ~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ doctools::idx::import
                        |                               |                       |
        +---------------+-------------------------+     |    +------------------+---------------+-----------------------+---------------+
        |               |                         |     |    |                  |               |                       |               |
struct::map             =                         |     |    |                  =       doctools::include       struct::map      fileutil::paths
                        |                         |     |    |                  |
                doctools::idx::export::<*>        |     |    |          doctools::idx::import::<*>
                        docidx                    |     |    |                  docidx, json
                        json                      |     |    |                  |           \\
                        html                      |     |    |          doctools::idx::parse \\
                        nroff                     |     |    |                  |             \\
                        wiki                      |     |    |  +---------------+              json
                        text                      |     |    |  |               |
                                                doctools::idx::structure        |
                                                                                |
                                                                        +-------+---------------+
                                                                        |                       |
          doctools::html  doctools::html::cssdefaults           doctools::tcl::parse    doctools::msgcat

Changes to idoc/man/files/modules/doctools2idx/import_docidx.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::import::docidx" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,


|

|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::idx::import::docidx" n 0\&.2\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
.de MT
.QW ""
..
.BS
.SH NAME
doctools::idx::import::docidx \- docidx import plugin
.SH SYNOPSIS
package require \fBTcl  8\&.4\fR
.sp
package require \fBdoctools::idx::import::docidx  ?0\&.1?\fR
.sp
package require \fBdoctools::idx::parse \fR
.sp
package require \fBdoctools::idx::structure \fR
.sp
package require \fBdoctools::msgcat \fR
.sp







|

|







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
.de MT
.QW ""
..
.BS
.SH NAME
doctools::idx::import::docidx \- docidx import plugin
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBdoctools::idx::import::docidx  ?0\&.2\&.1?\fR
.sp
package require \fBdoctools::idx::parse \fR
.sp
package require \fBdoctools::idx::structure \fR
.sp
package require \fBdoctools::msgcat \fR
.sp
440
441
442
443
444
445
446
447
448
449
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
deserialization, docidx, doctools, import, index
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


440
441
442
443
444
445
446
447
448
449
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
deserialization, docidx, doctools, import, index
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2toc/export_doctoc.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::export::doctoc" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,


|

|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::export::doctoc" n 0\&.2\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
doctools::toc::export::doctoc \- doctoc export plugin
.SH SYNOPSIS
package require \fBTcl  8\&.4\fR
.sp
package require \fBdoctools::toc::export::doctoc  ?0\&.1?\fR
.sp
\fBexport\fR \fIserial\fR \fIconfiguration\fR
.sp
.BE
.SH DESCRIPTION
This package implements the doctools table of contents export plugin
for the generation of doctoc markup\&.







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
doctools::toc::export::doctoc \- doctoc export plugin
.SH SYNOPSIS
package require \fBTcl  8\&.4\fR
.sp
package require \fBdoctools::toc::export::doctoc  ?0\&.2\&.1?\fR
.sp
\fBexport\fR \fIserial\fR \fIconfiguration\fR
.sp
.BE
.SH DESCRIPTION
This package implements the doctools table of contents export plugin
for the generation of doctoc markup\&.
491
492
493
494
495
496
497
498
499
500
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
doctoc, doctools, export, serialization, table of contents, toc
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


491
492
493
494
495
496
497
498
499
500
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
doctoc, doctools, export, serialization, table of contents, toc
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2toc/import_doctoc.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::import::doctoc" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,


|

|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::import::doctoc" n 0\&.2\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
.de MT
.QW ""
..
.BS
.SH NAME
doctools::toc::import::doctoc \- doctoc import plugin
.SH SYNOPSIS
package require \fBTcl  8\&.4\fR
.sp
package require \fBdoctools::toc::import::doctoc  ?0\&.1?\fR
.sp
package require \fBdoctools::toc::parse \fR
.sp
package require \fBdoctools::toc::structure \fR
.sp
package require \fBdoctools::msgcat \fR
.sp







|

|







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
.de MT
.QW ""
..
.BS
.SH NAME
doctools::toc::import::doctoc \- doctoc import plugin
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBdoctools::toc::import::doctoc  ?0\&.2\&.1?\fR
.sp
package require \fBdoctools::toc::parse \fR
.sp
package require \fBdoctools::toc::structure \fR
.sp
package require \fBdoctools::msgcat \fR
.sp
468
469
470
471
472
473
474
475
476
477
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
deserialization, doctoc, doctools, import, table of contents, toc
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


468
469
470
471
472
473
474
475
476
477
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
deserialization, doctoc, doctools, import, table of contents, toc
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2toc/toc_export.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'toc_export\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2018 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::export" n 0\&.2 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,


|

|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'toc_export\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::export" n 0\&.2\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
.de MT
.QW ""
..
.BS
.SH NAME
doctools::toc::export \- Exporting tables of contents
.SH SYNOPSIS
package require \fBdoctools::toc::export  ?0\&.2?\fR
.sp
package require \fBTcl  8\&.4\fR
.sp
package require \fBdoctools::config \fR
.sp
package require \fBdoctools::toc::structure \fR
.sp
package require \fBsnit \fR
.sp
package require \fBpluginmgr \fR
.sp







|



|







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
.de MT
.QW ""
..
.BS
.SH NAME
doctools::toc::export \- Exporting tables of contents
.SH SYNOPSIS
package require \fBdoctools::toc::export  ?0\&.2\&.1?\fR
.sp
package require \fBTcl  8\&.4\fR
.sp
package require \fBstruct::map \fR
.sp
package require \fBdoctools::toc::structure \fR
.sp
package require \fBsnit \fR
.sp
package require \fBpluginmgr \fR
.sp
687
688
689
690
691
692
693
694
695
696
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
HTML, conversion, doctoc, documentation, export, formatting, generation, json, manpage, markup, nroff, plugin, reference, table, table of contents, tcler's wiki, text, url, wiki
.SH CATEGORY
Documentation tools
.SH COPYRIGHT
.nf
Copyright (c) 2009-2018 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


687
688
689
690
691
692
693
694
695
696
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
HTML, conversion, doctoc, documentation, export, formatting, generation, json, manpage, markup, nroff, plugin, reference, table, table of contents, tcler's wiki, text, url, wiki
.SH CATEGORY
Documentation tools
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2toc/toc_export_html.n.

1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::export::html" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.


|







1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::export::html" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
541
542
543
544
545
546
547
548
549
550
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
HTML, doctools, export, serialization, table of contents, toc
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


541
542
543
544
545
546
547
548
549
550
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
HTML, doctools, export, serialization, table of contents, toc
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2toc/toc_export_json.n.

1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::export::json" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.


|







1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::export::json" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
529
530
531
532
533
534
535
536
537
538
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
JSON, doctools, export, serialization, table of contents, toc
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


529
530
531
532
533
534
535
536
537
538
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
JSON, doctools, export, serialization, table of contents, toc
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2toc/toc_export_nroff.n.

1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::export::nroff" n 0\&.2 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.


|







1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::export::nroff" n 0\&.2 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
460
461
462
463
464
465
466
467
468
469
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
doctools, export, nroff, serialization, table of contents, toc
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


460
461
462
463
464
465
466
467
468
469
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
doctools, export, nroff, serialization, table of contents, toc
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2toc/toc_export_text.n.

1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::export::text" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.


|







1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::export::text" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
443
444
445
446
447
448
449
450
451
452
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
doctools, export, plain text, serialization, table of contents, toc
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


443
444
445
446
447
448
449
450
451
452
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
doctools, export, plain text, serialization, table of contents, toc
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2toc/toc_export_wiki.n.

1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::export::wiki" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.


|







1
2
3
4
5
6
7
8
9
10
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::export::wiki" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
449
450
451
452
453
454
455
456
457
458
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
doctools, export, serialization, table of contents, toc, wiki
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


449
450
451
452
453
454
455
456
457
458
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
doctools, export, serialization, table of contents, toc, wiki
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2toc/toc_import.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'toc_import\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2018 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::import" n 0\&.2 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,


|

|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'toc_import\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::import" n 0\&.2\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
.de MT
.QW ""
..
.BS
.SH NAME
doctools::toc::import \- Importing keyword indices
.SH SYNOPSIS
package require \fBdoctools::toc::import  ?0\&.2?\fR
.sp
package require \fBTcl  8\&.4\fR
.sp
package require \fBdoctools::config \fR
.sp
package require \fBdoctools::toc::structure \fR
.sp
package require \fBsnit \fR
.sp
package require \fBpluginmgr \fR
.sp







|



|







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
.de MT
.QW ""
..
.BS
.SH NAME
doctools::toc::import \- Importing keyword indices
.SH SYNOPSIS
package require \fBdoctools::toc::import  ?0\&.2\&.1?\fR
.sp
package require \fBTcl  8\&.4\fR
.sp
package require \fBstruct::map \fR
.sp
package require \fBdoctools::toc::structure \fR
.sp
package require \fBsnit \fR
.sp
package require \fBpluginmgr \fR
.sp
768
769
770
771
772
773
774
775
776
777
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
conversion, doctoc, documentation, import, json, manpage, markup, parsing, plugin, reference, table, table of contents, url
.SH CATEGORY
Documentation tools
.SH COPYRIGHT
.nf
Copyright (c) 2009-2018 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


768
769
770
771
772
773
774
775
776
777
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
conversion, doctoc, documentation, import, json, manpage, markup, parsing, plugin, reference, table, table of contents, url
.SH CATEGORY
Documentation tools
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2toc/toc_import_json.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::import::json" n 0\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,


|

|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'plugin\&.inc' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "doctools::toc::import::json" n 0\&.2\&.1 tcllib "Documentation tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
.de MT
.QW ""
..
.BS
.SH NAME
doctools::toc::import::json \- JSON import plugin
.SH SYNOPSIS
package require \fBTcl  8\&.4\fR
.sp
package require \fBdoctools::toc::import::json  ?0\&.1?\fR
.sp
package require \fBdoctools::toc::structure \fR
.sp
package require \fBjson \fR
.sp
\fBimport\fR \fIstring\fR \fIconfiguration\fR
.sp







|

|







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
.de MT
.QW ""
..
.BS
.SH NAME
doctools::toc::import::json \- JSON import plugin
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBdoctools::toc::import::json  ?0\&.2\&.1?\fR
.sp
package require \fBdoctools::toc::structure \fR
.sp
package require \fBjson \fR
.sp
\fBimport\fR \fIstring\fR \fIconfiguration\fR
.sp
506
507
508
509
510
511
512
513
514
515
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
JSON, deserialization, doctools, import, table of contents, toc
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


506
507
508
509
510
511
512
513
514
515
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
JSON, deserialization, doctools, import, table of contents, toc
.SH CATEGORY
Text formatter plugin
.SH COPYRIGHT
.nf
Copyright (c) 2009-2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/doctools2toc/toc_introduction.n.

369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389

                                    ~~~~~~~~~~~ doctools::toc ~~~~~~~~~~~
                                   ~~                   |               ~~
                doctools::toc::export ~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ doctools::toc::import
                        |                               |                       |
        +---------------+-------------------------+     |    +------------------+---------------+-----------------------+---------------+
        |               |                         |     |    |                  |               |                       |               |
doctools::config        =                         |     |    |                  =       doctools::include       doctools::config doctools::paths
                        |                         |     |    |                  |
                doctools::toc::export::<*>        |     |    |          doctools::toc::import::<*>
                        doctoc                    |     |    |                  doctoc, json
                        json                      |     |    |                  |           \\\\
                        html                      |     |    |          doctools::toc::parse \\\\
                        nroff                     |     |    |                  |             \\\\
                        wiki                      |     |    |  +---------------+              json
                        text                      |     |    |  |               |
                                                doctools::toc::structure        |
                                                                                |
                                                                        +-------+---------------+
                                                                        |                       |
          doctools::html  doctools::html::cssdefaults           doctools::tcl::parse    doctools::msgcat







|



|
|
|







369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389

                                    ~~~~~~~~~~~ doctools::toc ~~~~~~~~~~~
                                   ~~                   |               ~~
                doctools::toc::export ~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ doctools::toc::import
                        |                               |                       |
        +---------------+-------------------------+     |    +------------------+---------------+-----------------------+---------------+
        |               |                         |     |    |                  |               |                       |               |
struct:map              =                         |     |    |                  =       doctools::include       struct::map      fileutil::paths
                        |                         |     |    |                  |
                doctools::toc::export::<*>        |     |    |          doctools::toc::import::<*>
                        doctoc                    |     |    |                  doctoc, json
                        json                      |     |    |                  |           \\
                        html                      |     |    |          doctools::toc::parse \\
                        nroff                     |     |    |                  |             \\
                        wiki                      |     |    |  +---------------+              json
                        text                      |     |    |  |               |
                                                doctools::toc::structure        |
                                                                                |
                                                                        +-------+---------------+
                                                                        |                       |
          doctools::html  doctools::html::cssdefaults           doctools::tcl::parse    doctools::msgcat

Changes to idoc/man/files/modules/fileutil/multiop.n.

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
.PP
.SH EXAMPLES
The following examples assume that the variable \fBF\fR contains a
reference to a multi-file operation object\&.
.CS


    $F do copy                       \\\\
	the  *\&.dll                    \\\\
	from c:/TDK/PrivateOpenSSL/bin \\\\
	to   [installdir_of tls]

.CE
.CS


    $F do move      \\\\
	the  *       \\\\
	from /sources \\\\
	into /scratch  \\\\
	but not *\&.html

    # Alternatively use 'except for *\&.html'\&.

.CE
.CS


    $F do           \\\\
	move         \\\\
	the  index    \\\\
	from /sources  \\\\
	into /scratch   \\\\
	as   pkgIndex\&.tcl

.CE
.CS


    $F do         \\\\
	remove     \\\\
	the *\&.txt  \\\\
	in /scratch

.CE
Note that the fact that most commands just modify the object state
allows us to use more off forms as specifications instead of just
nearly-natural language sentences\&.
For example the second example in this section can re-arranged into:
.CS


    $F do            \\\\
	from /sources \\\\
	into /scratch  \\\\
	but not *\&.html \\\\
	move           \\\\
	the  *

.CE
and the result is not only still a valid specification, but even stays
relatively readable\&.
.PP
Further note that the information collected by the commands \fBbut\fR,
\fBexcept\fR, and \fBas\fR is automatically reset after the associated
\fBthe\fR was executed\&. However no other state is reset in that
manner, allowing the user to avoid repetitions of unchanging
information\&. For example the second and third examples of this section
can be merged and rewritten into the equivalent:
.CS


$F do                   \\\\
    move                 \\\\
    the  *                \\\\
    from /sources          \\\\
    into /scratch           \\\\
    but not *\&.html not index \\\\
    the  index               \\\\
    as   pkgIndex\&.tcl

.CE
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fIfileutil\fR of the







|
|
|






|
|
|
|








|
|
|
|
|






|
|
|










|
|
|
|
|















|
|
|
|
|
|
|







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
.PP
.SH EXAMPLES
The following examples assume that the variable \fBF\fR contains a
reference to a multi-file operation object\&.
.CS


    $F do copy                       \\
	the  *\&.dll                    \\
	from c:/TDK/PrivateOpenSSL/bin \\
	to   [installdir_of tls]

.CE
.CS


    $F do move      \\
	the  *       \\
	from /sources \\
	into /scratch  \\
	but not *\&.html

    # Alternatively use 'except for *\&.html'\&.

.CE
.CS


    $F do           \\
	move         \\
	the  index    \\
	from /sources  \\
	into /scratch   \\
	as   pkgIndex\&.tcl

.CE
.CS


    $F do         \\
	remove     \\
	the *\&.txt  \\
	in /scratch

.CE
Note that the fact that most commands just modify the object state
allows us to use more off forms as specifications instead of just
nearly-natural language sentences\&.
For example the second example in this section can re-arranged into:
.CS


    $F do            \\
	from /sources \\
	into /scratch  \\
	but not *\&.html \\
	move           \\
	the  *

.CE
and the result is not only still a valid specification, but even stays
relatively readable\&.
.PP
Further note that the information collected by the commands \fBbut\fR,
\fBexcept\fR, and \fBas\fR is automatically reset after the associated
\fBthe\fR was executed\&. However no other state is reset in that
manner, allowing the user to avoid repetitions of unchanging
information\&. For example the second and third examples of this section
can be merged and rewritten into the equivalent:
.CS


$F do                   \\
    move                 \\
    the  *                \\
    from /sources          \\
    into /scratch           \\
    but not *\&.html not index \\
    the  index               \\
    as   pkgIndex\&.tcl

.CE
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fIfileutil\fR of the

Added idoc/man/files/modules/fileutil/paths.n.





























































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
'\"
'\" Generated from file 'paths\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "fileutil::paths" n 1 tcllib ""
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
.\"	and indent is equivalent to second arg of .IP (shouldn't ever be
.\"	needed;  use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\"	Give maximum sizes of arguments for setting tab stops.  Type and
.\"	name are examples of largest possible arguments that will be passed
.\"	to .AP later.  If args are omitted, default tab stops are used.
.\"
.\" .BS
.\"	Start box enclosure.  From here until next .BE, everything will be
.\"	enclosed in one large box.
.\"
.\" .BE
.\"	End of box enclosure.
.\"
.\" .CS
.\"	Begin code excerpt.
.\"
.\" .CE
.\"	End code excerpt.
.\"
.\" .VS ?version? ?br?
.\"	Begin vertical sidebar, for use in marking newly-changed parts
.\"	of man pages.  The first argument is ignored and used for recording
.\"	the version when the .VS was added, so that the sidebars can be
.\"	found and removed when they reach a certain age.  If another argument
.\"	is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\"	End of vertical sidebar.
.\"
.\" .DS
.\"	Begin an indented unfilled display.
.\"
.\" .DE
.\"	End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\"	Start of list of standard options for a Tk widget. The manpage
.\"	argument defines where to look up the standard options; if
.\"	omitted, defaults to "options". The options follow on successive
.\"	lines, in three columns separated by tabs.
.\"
.\" .SE
.\"	End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\"	Start of description of a specific option.  cmdName gives the
.\"	option's name as specified in the class command, dbName gives
.\"	the option's name in the option database, and dbClass gives
.\"	the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\"	Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\"	Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\"	Print an open parenthesis, arg1 in quotes, then arg2 normally
.\"	(for trailing punctuation) and then a closing parenthesis.
.\"
.\"	# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\"	# Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
.   ie !"\\$2"" .TP \\n()Cu
.   el          .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1	\\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\"	# define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\"	# BS - start boxed text
.\"	# ^y = starting y location
.\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\"	Draw four-sided box normally, but don't draw top of
.\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# VS - start vertical sidebar
.\"	# ^Y = starting y location
.\"	# ^v = 1 (for troff;  for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\"	# VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\"	# Special macro to handle page bottom:  finish off current
.\"	# box/sidebar if in box/sidebar mode, then invoked standard
.\"	# page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\"	Draw three-sided box if this is the box's first page,
.\"	draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\"	# DS - begin display
.de DS
.RS
.nf
.sp
..
.\"	# DE - end display
.de DE
.fi
.RE
.sp
..
.\"	# SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\"	# SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\"	# OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name:	\\fB\\$1\\fR
Database Name:	\\fB\\$2\\fR
Database Class:	\\fB\\$3\\fR
.fi
.IP
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
.\"	# UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\"	# QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\"	# PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\"	# QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
fileutil::paths \- Manage search path pools
.SH SYNOPSIS
package require \fBTcl  8\&.4\fR
.sp
package require \fBfileutil::paths  ?1?\fR
.sp
\fB::fileutil::paths\fR \fIpoolName\fR
.sp
\fBpoolName\fR \fBmethod\fR ?\fIarg arg \&.\&.\&.\fR?
.sp
\fIpoolName\fR \fBadd\fR \fIpath\fR
.sp
\fIpoolName\fR \fBclear\fR
.sp
\fIpoolName\fR \fBpaths\fR
.sp
\fIpoolName\fR \fBremove\fR \fIpath\fR
.sp
.BE
.SH DESCRIPTION
Provides a snit class whose instances manage a pool of (search) paths\&.
.SH API
The main command provides construction of search path pools:
.TP
\fB::fileutil::paths\fR \fIpoolName\fR
Creates a new, empty pool of search paths with an associated global
Tcl command whose name is \fIpoolName\fR\&.
It may be used to invoke various operations on the pool\&.
It has the following general form:
.RS
.TP
\fBpoolName\fR \fBmethod\fR ?\fIarg arg \&.\&.\&.\fR?
\fBmethod\fR and \fIarg\fRuments determine the exact behavior of
the command\&.
.RE
.IP
If \fIpoolName\fR is specified as \fB%AUTO%\fR a unique name will be
generated by the package itself\&.
The result of the command is the fully-qualified name of the instance
command\&.
.PP
.PP
The following commands are possible for pool objects:
.TP
\fIpoolName\fR \fBadd\fR \fIpath\fR
Adds the \fIpath\fR to the pool\&.
Nothing is done if the \fIpath\fR is already known to the pool\&.
The result of the command is the empty string\&.
.TP
\fIpoolName\fR \fBclear\fR
Clears the entire pool\&. In other words, removes all paths from it\&.
The result of the command is the empty string\&.
.TP
\fIpoolName\fR \fBpaths\fR
Returns the list of all paths known to the pool, in the order they
were added\&.
.TP
\fIpoolName\fR \fBremove\fR \fIpath\fR
Removes the \fIpath\fR from the pool, if it is known to the pool\&.
Unknown paths are ignored without error\&.
The result of the command is the empty string\&.
.PP
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fIfileutil\fR of the
\fITcllib Trackers\fR [http://core\&.tcl\&.tk/tcllib/reportlist]\&.
Please also report any ideas for enhancements you may have for either
package and/or documentation\&.
.PP
When proposing code changes, please provide \fIunified diffs\fR,
i\&.e the output of \fBdiff -u\fR\&.
.PP
Note further that \fIattachments\fR are strongly preferred over
inlined patches\&. Attachments can be made by going to the \fBEdit\fR
form of the ticket immediately after its creation, and then using the
left-most button in the secondary navigation bar\&.

Changes to idoc/man/files/modules/grammar_fa/fa.n.

545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
.CE
.sp
a possible serialization is
.sp
.CS


    grammar::fa \\\\
    {yellow red green red/yellow} \\\\
    {Drive     {0 0 {yellow     Brake}} \\\\
     Brake     {0 0 {red        Stop}} \\\\
     Stop      {1 0 {red/yellow Attention}} \\\\
     Attention {0 0 {green      Drive}}}

.CE
.sp
A possible one, because I did not care about creation order here
.TP
\fIfaName\fR \fBdeserialize\fR \fIserialization\fR







|
|
|
|
|







545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
.CE
.sp
a possible serialization is
.sp
.CS


    grammar::fa \\
    {yellow red green red/yellow} \\
    {Drive     {0 0 {yellow     Brake}} \\
     Brake     {0 0 {red        Stop}} \\
     Stop      {1 0 {red/yellow Attention}} \\
     Attention {0 0 {green      Drive}}}

.CE
.sp
A possible one, because I did not care about creation order here
.TP
\fIfaName\fR \fBdeserialize\fR \fIserialization\fR

Changes to idoc/man/files/modules/grammar_peg/peg.n.

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
.CE
.sp
a possible serialization is
.sp
.CS


    grammar::peg \\\\
    {Expression {/ {x ( Expression )} {x Factor {* {x MulOp Factor}}}} \\\\
     Factor     {x Term {* {x AddOp Term}}} \\\\
     Term       Number \\\\
     MulOp      {/ * /} \\\\
     AddOp      {/ + -} \\\\
     Number     {x {? Sign} {+ Digit}} \\\\
     Sign       {/ + -} \\\\
     Digit      {/ 0 1 2 3 4 5 6 7 8 9} \\\\
    } \\\\
    {Expression value     Factor     value \\\\
     Term       value     MulOp      value \\\\
     AddOp      value     Number     value \\\\
     Sign       value     Digit      value \\\\
    }
    Expression

.CE
.sp
A possible one, because the order of the nonterminals in the
dictionary is not relevant\&.







|
|
|
|
|
|
|
|
|
|
|
|
|
|







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
.CE
.sp
a possible serialization is
.sp
.CS


    grammar::peg \\
    {Expression {/ {x ( Expression )} {x Factor {* {x MulOp Factor}}}} \\
     Factor     {x Term {* {x AddOp Term}}} \\
     Term       Number \\
     MulOp      {/ * /} \\
     AddOp      {/ + -} \\
     Number     {x {? Sign} {+ Digit}} \\
     Sign       {/ + -} \\
     Digit      {/ 0 1 2 3 4 5 6 7 8 9} \\
    } \\
    {Expression value     Factor     value \\
     Term       value     MulOp      value \\
     AddOp      value     Number     value \\
     Sign       value     Digit      value \\
    }
    Expression

.CE
.sp
A possible one, because the order of the nonterminals in the
dictionary is not relevant\&.

Changes to idoc/man/files/modules/html/html.n.

1
2
3
4
5
6
7
8
9
10
11
'\"
'\" Generated from file 'html\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "html" n 1\&.4\&.4 tcllib "HTML Generation"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,



|







1
2
3
4
5
6
7
8
9
10
11
'\"
'\" Generated from file 'html\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "html" n 1\&.5 tcllib "HTML Generation"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
..
.BS
.SH NAME
html \- Procedures to generate HTML structures
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBhtml  ?1\&.4\&.4?\fR
.sp
\fB::html::author\fR \fIauthor\fR
.sp
\fB::html::bodyTag\fR \fIargs\fR
.sp
\fB::html::cell\fR \fIparam value\fR ?\fItag\fR?
.sp







|







271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
..
.BS
.SH NAME
html \- Procedures to generate HTML structures
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBhtml  ?1\&.5?\fR
.sp
\fB::html::author\fR \fIauthor\fR
.sp
\fB::html::bodyTag\fR \fIargs\fR
.sp
\fB::html::cell\fR \fIparam value\fR ?\fItag\fR?
.sp
341
342
343
344
345
346
347






348
349
350
351
352
353
354
.sp
\fB::html::keywords\fR \fIargs\fR
.sp
\fB::html::mailto\fR \fIemail\fR ?\fIsubject\fR?
.sp
\fB::html::meta\fR \fIargs\fR
.sp






\fB::html::css\fR \fIhref\fR
.sp
\fB::html::css-clear\fR
.sp
\fB::html::js\fR \fIhref\fR
.sp
\fB::html::js-clear\fR







>
>
>
>
>
>







341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
.sp
\fB::html::keywords\fR \fIargs\fR
.sp
\fB::html::mailto\fR \fIemail\fR ?\fIsubject\fR?
.sp
\fB::html::meta\fR \fIargs\fR
.sp
\fB::html::meta_name\fR \fIargs\fR
.sp
\fB::html::meta_equiv\fR \fIargs\fR
.sp
\fB::html::meta_charset\fR \fIcharset\fR
.sp
\fB::html::css\fR \fIhref\fR
.sp
\fB::html::css-clear\fR
.sp
\fB::html::js\fR \fIhref\fR
.sp
\fB::html::js-clear\fR
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
.sp
\fB::html::select\fR \fIname param choices\fR ?\fIcurrent\fR?
.sp
\fB::html::selectPlain\fR \fIname param choices\fR ?\fIcurrent\fR?
.sp
\fB::html::set\fR \fIvar val\fR
.sp
\fB::html::submit\fR \fIlabel\fR ?\fIname\fR?
.sp
\fB::html::tableFromArray\fR \fIarrname\fR ?\fIparam\fR? ?\fIpat\fR?
.sp
\fB::html::tableFromList\fR \fIquerylist\fR ?\fIparam\fR?
.sp
\fB::html::textarea\fR \fIname\fR ?\fIparam\fR? ?\fIcurrent\fR?
.sp
\fB::html::textInput\fR \fIname value args\fR
.sp
\fB::html::textInputRow\fR \fIlabel name value args\fR
.sp
\fB::html::varEmpty\fR \fIname\fR
.sp
\fB::html::while\fR \fItest body\fR
.sp
\fB::html::doctype\fR \fIid\fR


.sp
.BE
.SH DESCRIPTION
.PP
The package \fBhtml\fR provides commands that generate HTML\&.
These commands typically return an HTML string as their result\&. In
particular, they do not output their result to \fBstdout\fR\&.







|
















>
>







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
.sp
\fB::html::select\fR \fIname param choices\fR ?\fIcurrent\fR?
.sp
\fB::html::selectPlain\fR \fIname param choices\fR ?\fIcurrent\fR?
.sp
\fB::html::set\fR \fIvar val\fR
.sp
\fB::html::submit\fR \fIlabel\fR ?\fIname\fR? ?\fItitle\fR?
.sp
\fB::html::tableFromArray\fR \fIarrname\fR ?\fIparam\fR? ?\fIpat\fR?
.sp
\fB::html::tableFromList\fR \fIquerylist\fR ?\fIparam\fR?
.sp
\fB::html::textarea\fR \fIname\fR ?\fIparam\fR? ?\fIcurrent\fR?
.sp
\fB::html::textInput\fR \fIname value args\fR
.sp
\fB::html::textInputRow\fR \fIlabel name value args\fR
.sp
\fB::html::varEmpty\fR \fIname\fR
.sp
\fB::html::while\fR \fItest body\fR
.sp
\fB::html::doctype\fR \fIid\fR
.sp
\fB::html::wrapTag\fR \fItag\fR ?\fItext\fR? ?\fIargs\fR?
.sp
.BE
.SH DESCRIPTION
.PP
The package \fBhtml\fR provides commands that generate HTML\&.
These commands typically return an HTML string as their result\&. In
particular, they do not output their result to \fBstdout\fR\&.
585
586
587
588
589
590
591



592



















593
594
595
596
597
598
599
600
601
define a keyword \fImeta\fR tag for the page\&.  The \fImeta\fR tag
is included in the result of \fB::html::head\fR\&.
.TP
\fB::html::mailto\fR \fIemail\fR ?\fIsubject\fR?
Generate a hypertext link to a mailto: URL\&.
.TP
\fB::html::meta\fR \fIargs\fR



\fISide effect only\fR\&.  Call this before \fB::html::head\fR to



















define a \fImeta\fR tag for the page\&.  The \fIargs\fR is a Tcl-style name,
value list that is used for the name= and value= parameters for the
\fImeta\fR tag\&.  The \fImeta\fR tag is included in the result of
\fB::html::head\fR\&.
.TP
\fB::html::css\fR \fIhref\fR
\fISide effect only\fR\&.  Call this before \fB::html::head\fR to
define a \fIlink\fR tag for a linked CSS document\&.  The \fIhref\fR
value is a HTTP URL to a CSS document\&. The \fIlink\fR tag is included







>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|







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
define a keyword \fImeta\fR tag for the page\&.  The \fImeta\fR tag
is included in the result of \fB::html::head\fR\&.
.TP
\fB::html::mailto\fR \fIemail\fR ?\fIsubject\fR?
Generate a hypertext link to a mailto: URL\&.
.TP
\fB::html::meta\fR \fIargs\fR
Compatibility name for \fBhtml::meta_name\fR\&.
.TP
\fB::html::meta_name\fR \fIargs\fR
\fISide effect only\fR\&.
Call this before \fB::html::head\fR to define a \fImeta\fR tag for
the page\&.
The arguments (\fIargs\fR) are a Tcl-style name, value list that is
used for the \fBname=\fR and \fBcontent=\fR attributes of the
\fImeta\fR tag\&.  The \fImeta\fR tag is included in the result of
\fB::html::head\fR\&.
.TP
\fB::html::meta_equiv\fR \fIargs\fR
\fISide effect only\fR\&.
Call this before \fB::html::head\fR to define a \fImeta\fR tag for
the page\&.
The arguments (\fIargs\fR) are a Tcl-style name, value list that is
used for the \fBhttp-equiv=\fR and \fBcontent=\fR attributes of
the \fImeta\fR tag\&.  The \fImeta\fR tag is included in the result of
\fB::html::head\fR\&.
.TP
\fB::html::meta_charset\fR \fIcharset\fR
\fISide effect only\fR\&.
Call this before \fB::html::head\fR to
define a \fImeta\fR tag for the page\&.
The \fIcharset\fR is used with the \fBcharset=\fR attribute of the
\fImeta\fR tag\&.  The \fImeta\fR tag is included in the result of
\fB::html::head\fR\&.
.TP
\fB::html::css\fR \fIhref\fR
\fISide effect only\fR\&.  Call this before \fB::html::head\fR to
define a \fIlink\fR tag for a linked CSS document\&.  The \fIhref\fR
value is a HTTP URL to a CSS document\&. The \fIlink\fR tag is included
705
706
707
708
709
710
711
712
713



714
715
716
717
718
719
720
.TP
\fB::html::set\fR \fIvar val\fR
This procedure is similar to the built-in Tcl \fBset\fR command\&.  The
main difference is that it returns "" so it can be called from an HTML
template file without appending unwanted results\&.  The other
difference is that it must take two arguments\&.
.TP
\fB::html::submit\fR \fIlabel\fR ?\fIname\fR?
Generate an \fIinput\fR tag of type \fIsubmit\fR\&. \fIname\fR defaults to "submit"\&.



.TP
\fB::html::tableFromArray\fR \fIarrname\fR ?\fIparam\fR? ?\fIpat\fR?
Generate a two-column \fItable\fR and nested rows to display a Tcl array\&. The
table gets a heading that matches the array name, and each generated row
contains a name, value pair\&. The array names are sorted (\fBlsort\fR without
special options)\&. The argument \fIparam\fR is for the \fItable\fR tag and has
to contain a pre-formatted string\&. The \fIpat\fR is a \fBstring match\fR







|
|
>
>
>







735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
.TP
\fB::html::set\fR \fIvar val\fR
This procedure is similar to the built-in Tcl \fBset\fR command\&.  The
main difference is that it returns "" so it can be called from an HTML
template file without appending unwanted results\&.  The other
difference is that it must take two arguments\&.
.TP
\fB::html::submit\fR \fIlabel\fR ?\fIname\fR? ?\fItitle\fR?
Generate an \fIinput\fR tag of type \fIsubmit\fR\&.
The \fIname\fR defaults to "submit"\&.
When a non-empty \fItitle\fR string is specified the button gains a
\fBtitle=\fR attribute with that value\&.
.TP
\fB::html::tableFromArray\fR \fIarrname\fR ?\fIparam\fR? ?\fIpat\fR?
Generate a two-column \fItable\fR and nested rows to display a Tcl array\&. The
table gets a heading that matches the array name, and each generated row
contains a name, value pair\&. The array names are sorted (\fBlsort\fR without
special options)\&. The argument \fIparam\fR is for the \fItable\fR tag and has
to contain a pre-formatted string\&. The \fIpat\fR is a \fBstring match\fR
778
779
780
781
782
783
784







785
786
787
788
789
790
791
.IP [10]
XHTML10F
.IP [11]
XHTML11
.IP [12]
XHTMLB
.RE







.PP
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fIhtml\fR of the
\fITcllib Trackers\fR [http://core\&.tcl\&.tk/tcllib/reportlist]\&.
Please also report any ideas for enhancements you may have for either







>
>
>
>
>
>
>







811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
.IP [10]
XHTML10F
.IP [11]
XHTML11
.IP [12]
XHTMLB
.RE
.TP
\fB::html::wrapTag\fR \fItag\fR ?\fItext\fR? ?\fIargs\fR?
A helper to wrap a \fItext\fR in a pair of open/close \fItag\fRs\&.
The arguments (\fIargs\fR) are a Tcl-style name, value list that is
used to provide attributes and associated values to the opening tag\&.
The result is a string with the open \fItag\fR along with the optional
attributes, the optional text, and the closed tag\&.
.PP
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fIhtml\fR of the
\fITcllib Trackers\fR [http://core\&.tcl\&.tk/tcllib/reportlist]\&.
Please also report any ideas for enhancements you may have for either

Changes to idoc/man/files/modules/httpd/httpd.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'httpd\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2018 Sean Woods <yoda@etoyoc\&.com>
'\"
.TH "tool" n 4\&.1\&.1 tcllib "Tcl Web Server"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'httpd\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2018 Sean Woods <yoda@etoyoc\&.com>
'\"
.TH "httpd" n 4\&.3\&.4 tcllib "Tcl Web Server"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
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
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
tool \- A TclOO and coroutine based web server
.SH SYNOPSIS
package require \fBTcl  8\&.6\fR
.sp
package require \fBhttpd  ?4\&.1\&.1?\fR
.sp
package require \fBsha1 \fR
.sp
package require \fBdicttool \fR
.sp
package require \fBoo::meta \fR
.sp
package require \fBoo::dialect \fR
.sp
package require \fBtool \fR
.sp
package require \fBcoroutine \fR
.sp
package require \fBfileutil \fR
.sp
package require \fBfileutil::magic::filetype \fR
.sp
package require \fBwebsocket \fR
.sp
package require \fBmime \fR
.sp
package require \fBcron \fR
.sp
package require \fBuri \fR
.sp
package require \fBMarkdown \fR
.sp
constructor ?port ?port?? ?myaddr ?ipaddr?|all? ?server_string ?string?? ?server_name ?string??
.sp
method \fBadd_uri\fR \fIpattern\fR \fIdict\fR
.sp
method \fBconnect\fR \fIsock\fR \fIip\fR \fIport\fR
.sp
method \fBConnect\fR \fIuuid\fR \fIsock\fR \fIip\fR
.sp
method \fBcounter\fR \fIwhich\fR
.sp
method \fBCheckTimeout\fR
.sp
method \fBdispatch\fR \fIheader_dict\fR
.sp
method \fBlog\fR \fIargs\fR
.sp
method \fBport_listening\fR
.sp
method \fBPrefixNormalize\fR \fIprefix\fR
.sp
method \fBstart\fR
.sp
method \fBstop\fR
.sp
method \fBtemplate\fR \fIpage\fR
.sp
method \fBTemplateSearch\fR \fIpage\fR
.sp
method \fBValidate_Connection\fR \fIsock\fR \fIip\fR
.sp
method \fBENSEMBLE::add\fR \fIfield\fR \fIelement\fR
.sp
method \fBENSEMBLE::dump\fR
.sp
method \fBENSEMBLE::get\fR \fIfield\fR
.sp
method \fBENSEMBLE::reset\fR
.sp
method \fBENSEMBLE::remove\fR \fIfield\fR \fIelement\fR
.sp
method \fBENSEMBLE::replace\fR \fIkeyvaluelist\fR
.sp
method \fBENSEMBLE::reset\fR
.sp
method \fBENSEMBLE::set\fR \fIfield\fR \fIvalue\fR
.sp
method \fBhttp_info::netstring\fR
.sp
method \fBrequest::parse\fR \fIstring\fR
.sp
method \fBreply::output\fR
.sp
method \fBclose\fR
.sp
method \fBHttpHeaders\fR \fIsock\fR \fI?debug?\fR
.sp
method \fBdispatch\fR \fInewsock\fR \fIdatastate\fR
.sp






method \fBerror\fR \fIcode\fR \fI?message?\fR \fI?errorInfo?\fR
.sp
method \fBcontent\fR
.sp
method \fBEncodeStatus\fR \fIstatus\fR
.sp
method FormData
.sp
method MimeParse \fImimetext\fR
.sp
method \fBDoOutput\fR
.sp


method PostData \fIlength\fR
.sp


method \fBputs\fR \fIstring\fR






.sp
method \fBreset\fR
.sp
method \fBtimeOutCheck\fR
.sp
method \fBtimestamp\fR
.sp










































method \fBTransferComplete\fR \fIargs\fR
.sp
method \fBUrl_Decode\fR \fIstring\fR
.sp














method cgi_info




.sp
















option \fBpath\fR
.sp
option \fBprefix\fR
.sp




method proxy_info
.sp












method scgi_info


























.sp
.BE
.SH DESCRIPTION
.PP
This module implements a web server, suitable for embedding in an
application\&. The server is object oriented, and contains all of the
fundamentals needed for a full service website\&.
.PP
.SH "MINIMAL EXAMPLE"
Starting a web service requires starting a class of type
\fBhttpd::server\fR, and providing that server with one or more URIs
to service, and \fBhttpd::reply\fR derived classes to generate them\&.
.CS


tool::define ::reply\&.hello {
  method content {} {
    my puts "<HTML><HEAD><TITLE>IRM Dispatch Server</TITLE></HEAD><BODY>"
    my puts "<h1>Hello World!</h1>"
    my puts </BODY></HTML>
  }
}
::docserver::server create HTTPD port 8015 myaddr 127\&.0\&.0\&.1

HTTPD add_uri /* [list mixin reply\&.hello]





















.CE

.SH "CLASS ::HTTPD::SERVER"
This class is the root object of the webserver\&. It is responsible
for opening the socket and providing the initial connection negotiation\&.


.TP
constructor ?port ?port?? ?myaddr ?ipaddr?|all? ?server_string ?string?? ?server_name ?string??
Build a new server object\&. ?port? is the port to listen on

.TP
method \fBadd_uri\fR \fIpattern\fR \fIdict\fR
Set the hander for a URI pattern\&. Information given in the \fIdict\fR is stored
in the data structure the \fBdispatch\fR method uses\&. If a field called
\fImixin\fR is given, that class will be mixed into the reply object immediately
after construction\&.
.TP
method \fBconnect\fR \fIsock\fR \fIip\fR \fIport\fR

Reply to an open socket\&. This method builds a coroutine to manage the remainder
of the connection\&. The coroutine's operations are driven by the \fBConnect\fR method\&.
.TP
method \fBConnect\fR \fIuuid\fR \fIsock\fR \fIip\fR
This method reads HTTP headers, and then consults the \fBdispatch\fR method to
determine if the request is valid, and/or what kind of reply to generate\&. Under
normal cases, an object of class \fB::http::reply\fR is created\&.
Fields the server are looking for in particular are:
class: A class to use instead of the server's own \fIreply_class\fR
mixin: A class to be mixed into the new object after construction\&.
All other fields are passed along to the \fBhttp_info\fR structure of the
reply object\&.
After the class is created and the mixin is mixed in, the server invokes the
reply objects \fBdispatch\fR method\&. This action passes control of the socket to
the reply object\&. The reply object manages the rest of the transaction, including
closing the socket\&.
.TP
method \fBcounter\fR \fIwhich\fR
Increment an internal counter\&.
.TP
method \fBCheckTimeout\fR
Check open connections for a time out event\&.
.TP
method \fBdispatch\fR \fIheader_dict\fR
Given a key/value list of information, return a data structure describing how
the server should reply\&.
.TP
method \fBlog\fR \fIargs\fR
Log an event\&. The input for args is free form\&. This method is intended
to be replaced by the user, and is a noop for a stock http::server object\&.
.TP
method \fBport_listening\fR
Return the actual port that httpd is listening on\&.
.TP
method \fBPrefixNormalize\fR \fIprefix\fR
For the stock version, trim trailing /'s and *'s from a prefix\&. This
method can be replaced by the end user to perform any other transformations
needed for the application\&.
.TP
method \fBstart\fR
Open the socket listener\&.
.TP
method \fBstop\fR
Shut off the socket listener, and destroy any pending replies\&.
.TP
method \fBtemplate\fR \fIpage\fR
Return a template for the string \fIpage\fR
.TP
method \fBTemplateSearch\fR \fIpage\fR
Perform a search for the template that best matches \fIpage\fR\&. This
can include local file searches, in-memory structures, or even
database lookups\&. The stock implementation simply looks for files
with a \&.tml or \&.html extension in the ?doc_root? directory\&.
.TP
method \fBValidate_Connection\fR \fIsock\fR \fIip\fR
Given a socket and an ip address, return true if this connection should
be terminated, or false if it should be allowed to continue\&. The stock
implementation always returns 0\&. This is intended for applications to
be able to implement black lists and/or provide security based on IP
address\&.
.PP
.SH "CLASS ::HTTPD::REPLY"


A class which shephards a request through the process of generating a
reply\&.
The socket associated with the reply is available at all times as the \fIchan\fR
variable\&.
The process of generating a reply begins with an \fBhttpd::server\fR generating a
\fBhttp::class\fR object, mixing in a set of behaviors and then invoking the reply
object's \fBdispatch\fR method\&.







|



<
<
<
<
|

|
<
<
<
<

















<
<
<
<
<
<
|

|

|

|

|

|

<
<
|

|

|

|

<
<
<
<
|

|

|

<
<
|

|

<
<
|

|

|



|



>
>
>
>
>
>
|





|

|



>
>
|

>
>
|
>
>
>
>
>
>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

|

>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>















|






|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
|
|
<
>
>

<
<
>

|
<
|
<
<

|
>
|
<

|
<
<
<
<
<
<
<
<
<
<
<
<

|
<

|
<

|
|
|
<
|
<
<

|
|

<
<
<
<
<
|
<

|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
>
>







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
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
httpd \- A TclOO and coroutine based web server
.SH SYNOPSIS
package require \fBTcl  8\&.6\fR
.sp




package require \fBuuid \fR
.sp
package require \fBclay \fR




.sp
package require \fBcoroutine \fR
.sp
package require \fBfileutil \fR
.sp
package require \fBfileutil::magic::filetype \fR
.sp
package require \fBwebsocket \fR
.sp
package require \fBmime \fR
.sp
package require \fBcron \fR
.sp
package require \fBuri \fR
.sp
package require \fBMarkdown \fR
.sp






method \fBChannelCopy\fR \fIin\fR \fIout\fR ?\fIargs\fR?
.sp
method \fBhtml_header\fR ?\fItitle\fR \fB\fR? ?\fIargs\fR?
.sp
method \fBhtml_footer\fR ?\fIargs\fR?
.sp
method \fBhttp_code_string\fR \fIcode\fR
.sp
method \fBHttpHeaders\fR \fIsock\fR ?\fIdebug\fR \fB\fR?
.sp
method \fBHttpHeaders_Default\fR
.sp


method \fBHttpServerHeaders\fR
.sp
method \fBMimeParse\fR \fImimetext\fR
.sp
method \fBUrl_Decode\fR \fIdata\fR
.sp
method \fBUrl_PathCheck\fR \fIurlsuffix\fR
.sp




method \fBwait\fR \fImode\fR \fIsock\fR
.sp
variable \fBChannelRegister\fR
.sp
variable \fBreply\fR
.sp


variable \fBrequest\fR
.sp
delegate \fB<server>\fR
.sp


method \fBconstructor\fR \fIServerObj\fR ?\fIargs\fR?
.sp
method \fBdestructor\fR ?\fIdictargs\fR?
.sp
method \fBChannelRegister\fR ?\fIargs\fR?
.sp
method \fBclose\fR
.sp
method \fBLog_Dispatched\fR
.sp
method \fBdispatch\fR \fInewsock\fR \fIdatastate\fR
.sp
method \fBDispatch\fR
.sp
method \fBhtml_header\fR \fItitle\fR ?\fIargs\fR?
.sp
method \fBhtml_footer\fR ?\fIargs\fR?
.sp
method \fBerror\fR \fIcode\fR ?\fImsg\fR \fB\fR? ?\fIerrorInfo\fR \fB\fR?
.sp
method \fBcontent\fR
.sp
method \fBEncodeStatus\fR \fIstatus\fR
.sp
method \fBlog\fR \fItype\fR ?\fIinfo\fR \fB\fR?
.sp
method \fBCoroName\fR
.sp
method \fBDoOutput\fR
.sp
method \fBFormData\fR
.sp
method \fBPostData\fR \fIlength\fR
.sp
method \fBSession_Load\fR
.sp
method \fBputs\fR \fIline\fR
.sp
method \fBRequestFind\fR \fIfield\fR
.sp
method \fBrequest\fR \fIsubcommand\fR ?\fIargs\fR?
.sp
method \fBreply\fR \fIsubcommand\fR ?\fIargs\fR?
.sp
method \fBreset\fR
.sp
method \fBtimeOutCheck\fR
.sp
method \fBtimestamp\fR
.sp
variable \fBtemplate\fR
.sp
variable \fBurl_patterns\fR
.sp
method \fBconstructor\fR \fIargs\fR ?\fIport\fR \fBauto\fR? ?\fImyaddr\fR \fB127\&.0\&.0\&.1\fR? ?\fIstring\fR \fBauto\fR? ?\fIname\fR \fBauto\fR? ?\fIdoc_root\fR \fB\fR? ?\fIreverse_dns\fR \fB0\fR? ?\fIconfiguration_file\fR \fB\fR? ?\fIprotocol\fR \fBHTTP/1\&.1\fR?
.sp
method \fBdestructor\fR ?\fIdictargs\fR?
.sp
method \fBconnect\fR \fIsock\fR \fIip\fR \fIport\fR
.sp
method \fBServerHeaders\fR \fIip\fR \fIhttp_request\fR \fImimetxt\fR
.sp
method \fBConnect\fR \fIuuid\fR \fIsock\fR \fIip\fR
.sp
method \fBcounter\fR \fIwhich\fR
.sp
method \fBCheckTimeout\fR
.sp
method \fBdebug\fR ?\fIargs\fR?
.sp
method \fBdispatch\fR \fIdata\fR
.sp
method \fBDispatch_Default\fR \fIreply\fR
.sp
method \fBDispatch_Local\fR \fIdata\fR
.sp
method \fBHeaders_Local\fR \fIvarname\fR
.sp
method \fBHeaders_Process\fR \fIvarname\fR
.sp
method \fBHostName\fR \fIipaddr\fR
.sp
method \fBlog\fR ?\fIargs\fR?
.sp
method \fBplugin\fR \fIslot\fR ?\fIclass\fR \fB\fR?
.sp
method \fBport_listening\fR
.sp
method \fBPrefixNormalize\fR \fIprefix\fR
.sp
method \fBsource\fR \fIfilename\fR
.sp
method \fBstart\fR
.sp
method \fBstop\fR
.sp
method \fBSubObject {} db\fR
.sp
method \fBSubObject {} default\fR
.sp
method \fBtemplate\fR \fIpage\fR
.sp
method \fBTemplateSearch\fR \fIpage\fR
.sp
method \fBThread_start\fR
.sp
method \fBUuid_Generate\fR
.sp
method \fBValidate_Connection\fR \fIsock\fR \fIip\fR
.sp
method \fBreset\fR
.sp
method \fBcontent\fR
.sp
method \fBDispatch\fR
.sp
method \fBcontent\fR
.sp
method \fBFileName\fR
.sp
method \fBDirectoryListing\fR \fIlocal_file\fR
.sp
method \fBcontent\fR
.sp
method \fBDispatch\fR
.sp
variable \fBexename\fR
.sp
method \fBCgiExec\fR \fIexecname\fR \fIscript\fR \fIarglist\fR
.sp
method \fBCgi_Executable\fR \fIscript\fR
.sp
method \fBproxy_channel\fR
.sp
method \fBproxy_path\fR
.sp
method \fBProxyRequest\fR \fIchana\fR \fIchanb\fR
.sp
method \fBProxyReply\fR \fIchana\fR \fIchanb\fR ?\fIargs\fR?
.sp
method \fBDispatch\fR
.sp
method \fBFileName\fR
.sp
method \fBproxy_channel\fR
.sp
method \fBProxyRequest\fR \fIchana\fR \fIchanb\fR
.sp
method \fBProxyReply\fR \fIchana\fR \fIchanb\fR ?\fIargs\fR?
.sp
method \fBDirectoryListing\fR \fIlocal_file\fR
.sp
method \fBEncodeStatus\fR \fIstatus\fR
.sp
method \fBscgi_info\fR
.sp
method \fBproxy_channel\fR
.sp
method \fBProxyRequest\fR \fIchana\fR \fIchanb\fR
.sp
method \fBProxyReply\fR \fIchana\fR \fIchanb\fR ?\fIargs\fR?
.sp
method \fBdebug\fR ?\fIargs\fR?
.sp
method \fBConnect\fR \fIuuid\fR \fIsock\fR \fIip\fR
.sp
method \fBDispatch_Dict\fR \fIdata\fR
.sp
method \fBuri {} add\fR \fIvhosts\fR \fIpatterns\fR \fIinfo\fR
.sp
method \fBuri {} direct\fR \fIvhosts\fR \fIpatterns\fR \fIinfo\fR \fIbody\fR
.sp
method \fBoutput\fR
.sp
method \fBDoOutput\fR
.sp
method \fBclose\fR
.sp
method \fBlocal_memchan\fR \fIcommand\fR ?\fIargs\fR?
.sp
method \fBConnect_Local\fR \fIuuid\fR \fIsock\fR ?\fIargs\fR?
.sp
.BE
.SH DESCRIPTION
.PP
This module implements a web server, suitable for embedding in an
application\&. The server is object oriented, and contains all of the
fundamentals needed for a full service website\&.
.PP
.SH "MINIMAL EXAMPLE"
Starting a web service requires starting a class of type
\fBhttpd::server\fR, and providing that server with one or more URIs
to service, and \fBhttpd::reply\fR derived classes to generate them\&.
.CS


oo::class create ::reply\&.hello {
  method content {} {
    my puts "<HTML><HEAD><TITLE>IRM Dispatch Server</TITLE></HEAD><BODY>"
    my puts "<h1>Hello World!</h1>"
    my puts </BODY></HTML>
  }
}
::httpd::server create HTTPD port 8015 myaddr 127\&.0\&.0\&.1 doc_root ~/htdocs
HTTPD plugin dispatch httpd::server::dispatch
HTTPD uri add * /hello [list mixin reply\&.hello]

.CE
The bare module does have facilities to hose a files from a file system\&. Files that end in a \&.tml will be substituted in the style of Tclhttpd:
.CS


<!-- hello\&.tml -->
[my html_header {Hello World!}]
Your Server is running\&.
<p>
The time is now [clock format [clock seconds]]
[my html_footer]

.CE
A complete example of an httpd server is in the /examples directory of Tcllib\&. It also show how to dispatch URIs to other processes via SCGI and HTTP proxies\&.
.CS


cd ~/tcl/sandbox/tcllib
tclsh examples/httpd\&.tcl

.CE
.SH CLASSES
.SS "CLASS  HTTPD::MIME"
A metaclass for MIME handling behavior across a live socket

.PP
\fBMethods\fR
.TP


method \fBChannelCopy\fR \fIin\fR \fIout\fR ?\fIargs\fR?
.TP
method \fBhtml_header\fR ?\fItitle\fR \fB\fR? ?\fIargs\fR?

Returns a block of HTML


.TP
method \fBhtml_footer\fR ?\fIargs\fR?
.TP
method \fBhttp_code_string\fR \fIcode\fR

.TP
method \fBHttpHeaders\fR \fIsock\fR ?\fIdebug\fR \fB\fR?












.TP
method \fBHttpHeaders_Default\fR

.TP
method \fBHttpServerHeaders\fR

.TP
method \fBMimeParse\fR \fImimetext\fR
Converts a block of mime encoded text to a key/value list\&. If an exception is encountered,
the method will generate its own call to the \fBerror\fR method, and immediately invoke

the \fBoutput\fR method to produce an error code and close the connection\&.


.TP
method \fBUrl_Decode\fR \fIdata\fR
De-httpizes a string\&.
.TP





method \fBUrl_PathCheck\fR \fIurlsuffix\fR

.TP
method \fBwait\fR \fImode\fR \fIsock\fR

.PP















.PP
.SS "CLASS  HTTPD::REPLY"
\fIancestors\fR: \fBhttpd::mime\fR
.PP
A class which shephards a request through the process of generating a
reply\&.
The socket associated with the reply is available at all times as the \fIchan\fR
variable\&.
The process of generating a reply begins with an \fBhttpd::server\fR generating a
\fBhttp::class\fR object, mixing in a set of behaviors and then invoking the reply
object's \fBdispatch\fR method\&.
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
.IP [5]
Invokes the \fBcontent\fR method for the object, generating an call to the \fBerror\fR
method if an exception is raised\&.
.IP [6]
Invokes the \fBoutput\fR method for the object
.PP
.PP
.SH "REPLY METHOD ENSEMBLES"
The \fBhttp::reply\fR class and its derivatives maintain several variables as dictionaries
internally\&. Access to these dictionaries is managed through a dedicated ensemble\&. The
ensemble implements most of the same behaviors as the \fBdict\fR command\&.
Each ensemble implements the following methods above, beyond, or modifying standard dicts:
.TP
method \fBENSEMBLE::add\fR \fIfield\fR \fIelement\fR
Add \fIelement\fR to a list stored in \fIfield\fR, but only if it is not already present om the list\&.
.TP
method \fBENSEMBLE::dump\fR
Return the current contents of the data structure as a key/value list\&.
.TP
method \fBENSEMBLE::get\fR \fIfield\fR
Return the value of the field \fIfield\fR, or an empty string if it does not exist\&.
.TP
method \fBENSEMBLE::reset\fR
Return a key/value list of the default contents for this data structure\&.
.TP
method \fBENSEMBLE::remove\fR \fIfield\fR \fIelement\fR
Remove all instances of \fIelement\fR from the list stored in \fIfield\fR\&.
.TP
method \fBENSEMBLE::replace\fR \fIkeyvaluelist\fR
Replace the internal dict with the contents of \fIkeyvaluelist\fR
.TP
method \fBENSEMBLE::reset\fR
Replace the internal dict with the default state\&.
.TP
method \fBENSEMBLE::set\fR \fIfield\fR \fIvalue\fR
Set the value of \fIfield\fR to \fIvalue\fR\&.
.PP
.SH "REPLY METHOD ENSEMBLE: HTTP_INFO"
Manages HTTP headers passed in by the server\&.
Ensemble Methods:
.TP
method \fBhttp_info::netstring\fR
Return the contents of this data structure as a netstring encoded block\&.
.PP
.SH "REPLY METHOD ENSEMBLE: REQUEST"
Managed data from MIME headers of the request\&.
.TP
method \fBrequest::parse\fR \fIstring\fR
Replace the contents of the data structure with information encoded in a MIME
formatted block of text (\fIstring\fR)\&.
.PP
.SH "REPLY METHOD ENSEMBLE: REPLY"
Manage the headers sent in the reply\&.
.TP
method \fBreply::output\fR
Return the contents of this data structure as a MIME encoded block appropriate
for an HTTP response\&.
.PP
.SH "REPLY METHODS"
.TP
method \fBclose\fR
Terminate the transaction, and close the socket\&.
.TP
method \fBHttpHeaders\fR \fIsock\fR \fI?debug?\fR
Stream MIME headers from the socket \fIsock\fR, stopping at an empty line\&. Returns
the stream as a block of text\&.
.TP
method \fBdispatch\fR \fInewsock\fR \fIdatastate\fR
Take over control of the socket \fInewsock\fR, and store that as the \fIchan\fR variable
for the object\&. This method runs through all of the steps of reading HTTP headers, generating
content, and closing the connection\&. (See class writetup)\&.
.TP
method \fBerror\fR \fIcode\fR \fI?message?\fR \fI?errorInfo?\fR
Generate an error message of the specified \fIcode\fR, and display the \fImessage\fR as the
reason for the exception\&. \fIerrorInfo\fR is passed in from calls, but how or if it should be
displayed is a prerogative of the developer\&.
.TP
method \fBcontent\fR
Generate the content for the reply\&. This method is intended to be replaced by the mixin\&.
Developers have the option of streaming output to a buffer via the \fBputs\fR method of the
reply, or simply populating the \fIreply_body\fR variable of the object\&.
The information returned by the \fBcontent\fR method is not interpreted in any way\&.
If an exception is thrown (via the \fBerror\fR command in Tcl, for example) the caller will
auto-generate a 500 {Internal Error} message\&.
A typical implementation of \fBcontent\fR look like:
.CS



tool::define ::test::content\&.file {
	superclass ::httpd::content\&.file
	# Return a file
	# Note: this is using the content\&.file mixin which looks for the reply_file variable
	# and will auto-compute the Content-Type
	method content {} {
	  my reset
    set doc_root [my http_info get doc_root]
    my variable reply_file
    set reply_file [file join $doc_root index\&.html]
	}
}
tool::define ::test::content\&.time {
  # return the current system time
	method content {} {
		my variable reply_body
    my reply set Content-Type text/plain
		set reply_body [clock seconds]
	}
}
tool::define ::test::content\&.echo {
	method content {} {
		my variable reply_body
    my reply set Content-Type [my request get CONTENT_TYPE]
		set reply_body [my PostData [my request get CONTENT_LENGTH]]
	}
}
tool::define ::test::content\&.form_handler {
	method content {} {
	  set form [my FormData]
	  my reply set Content-Type {text/html; charset=UTF-8}
    my puts [my html header {My Dynamic Page}]
    my puts "<BODY>"
    my puts "You Sent<p>"
    my puts "<TABLE>"
    foreach {f v} $form {
      my puts "<TR><TH>$f</TH><TD><verbatim>$v</verbatim></TD>"
    }
    my puts "</TABLE><p>"
    my puts "Send some info:<p>"
    my puts "<FORM action=/[my http_info get REQUEST_PATH] method POST>"
    my puts "<TABLE>"
    foreach field {name rank serial_number} {
      set line "<TR><TH>$field</TH><TD><input name=\\"$field\\" "
      if {[dict exists $form $field]} {
        append line " value=\\"[dict get $form $field]\\"""
      }
      append line " /></TD></TR>"
      my puts $line
    }
    my puts "</TABLE>"
    my puts [my html footer]
	}
}


.CE


.TP


























































method \fBEncodeStatus\fR \fIstatus\fR
Formulate a standard HTTP status header from he string provided\&.
.TP








method FormData
For GET requests, converts the QUERY_DATA header into a key/value list\&.
For POST requests, reads the Post data and converts that information to
a key/value list for application/x-www-form-urlencoded posts\&. For multipart
posts, it composites all of the MIME headers of the post to a singular key/value
list, and provides MIME_* information as computed by the \fBmime\fR package, including
the MIME_TOKEN, which can be fed back into the mime package to read out the contents\&.
.TP
method MimeParse \fImimetext\fR
Converts a block of mime encoded text to a key/value list\&. If an exception is encountered,
the method will generate its own call to the \fBerror\fR method, and immediately invoke
the \fBoutput\fR method to produce an error code and close the connection\&.
.TP
method \fBDoOutput\fR
Generates the the HTTP reply, and streams that reply back across \fIchan\fR\&.
.TP
method PostData \fIlength\fR
Stream \fIlength\fR bytes from the \fIchan\fR socket, but only of the request is a
POST or PUSH\&. Returns an empty string otherwise\&.
.TP



method \fBputs\fR \fIstring\fR
Appends the value of \fIstring\fR to the end of \fIreply_body\fR, as well as a trailing newline
character\&.
.TP






method \fBreset\fR
Clear the contents of the \fIreply_body\fR variable, and reset all headers in the \fBreply\fR
structure back to the defaults for this object\&.
.TP
method \fBtimeOutCheck\fR
Called from the \fBhttp::server\fR object which spawned this reply\&. Checks to see
if too much time has elapsed while waiting for data or generating a reply, and issues
a timeout error to the request if it has, as well as destroy the object and close the
\fIchan\fR socket\&.
.TP
method \fBtimestamp\fR
Return the current system time in the format:
.CS

%a, %d %b %Y %T %Z
.CE







.TP


























































































method \fBTransferComplete\fR \fIargs\fR
Intended to be invoked from \fBchan copy\fR as a callback\&. This closes every channel
fed to it on the command line, and then destroys the object\&.
























.CS


    ###
    # Output the body
    ###
    chan configure $sock -translation binary -blocking 0 -buffering full -buffersize 4096
    chan configure $chan -translation binary -blocking 0 -buffering full -buffersize 4096
    if {$length} {
      ###
      # Send any POST/PUT/etc content
      ###
      chan copy $sock $chan -size $SIZE -command [info coroutine]
      yield
    }
    catch {close $sock}
    chan flush $chan


.CE
.TP

















method \fBUrl_Decode\fR \fIstring\fR




De-httpizes a string\&.
.PP





.SH "CLASS ::HTTPD::CONTENT"



The httpd module includes several ready to use implementations of content mixins
for common use cases\&. Options are passed in to the \fBadd_uri\fR method of the server\&.


.SH "CLASS ::HTTPD::CONTENT\&.CGI"
An implementation to relay requests to process which will accept post data
streamed in vie stdin, and sent a reply streamed to stdout\&.





.TP




method cgi_info

Mandatory method to be replaced by the end user\&. If needed, activates the
process to proxy, and then returns a list of three values:
\fIexec\fR - The arguments to send to exec to fire off the responding process, minus the stdin/stdout redirection\&.
.PP

.SH "CLASS ::HTTPD::CONTENT\&.FILE"
An implementation to deliver files from the local file system\&.


.TP
option \fBpath\fR
The root directory on the local file system to be exposed via http\&.



.TP


option \fBprefix\fR
The prefix of the URI portion to ignore when calculating relative file paths\&.
.PP

.SH "CLASS ::HTTPD::CONTENT\&.PROXY"
An implementation to relay requests to another HTTP server, and relay






the results back across the request channel\&.

















.TP
method proxy_info





Mandatory method to be replaced by the end user\&. If needed, activates the




process to proxy, and then returns a list of three values:
\fIproxyhost\fR - The hostname where the proxy is located
\fIproxyport\fR - The port to connect to
\fIproxyscript\fR - A pre-amble block of text to send prior to the mirrored request
.PP





.SH "CLASS ::HTTPD::CONTENT\&.SCGI"
An implementation to relay requests to a server listening on a socket
expecting SCGI encoded requests, and relay
the results back across the request channel\&.




.TP
method scgi_info

Mandatory method to be replaced by the end user\&. If needed, activates the
process to proxy, and then returns a list of three values:

\fIscgihost\fR - The hostname where the scgi listener is located













\fIscgiport\fR - The port to connect to
\fIscgiscript\fR - The contents of the \fISCRIPT_NAME\fR header to be sent
.PP

.SH "CLASS ::HTTPD::CONTENT\&.WEBSOCKET"
A placeholder for a future implementation to manage requests that can expect to be
promoted to a Websocket\&. Currently it is an empty class\&.
.SH "SCGI SERVER FUNCTIONS"
The HTTP module also provides an SCGI server implementation, as well as an HTTP
implementation\&. To use the SCGI functions, create an object of the \fBhttp::server\&.scgi\fR







class instead of the \fBhttp::server\fR class\&.






.SH "CLASS ::HTTPD::REPLY\&.SCGI"
An modified \fBhttp::reply\fR implementation that understands how to deal with


netstring encoded headers\&.








.SH "CLASS ::HTTPD::SERVER\&.SCGI"






A modified \fBhttp::server\fR which is tailored to replying to request according to


the SCGI standard instead of the HTTP standard\&.


.SH AUTHORS
Sean Woods
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fInetwork\fR of the
\fITcllib Trackers\fR [http://core\&.tcl\&.tk/tcllib/reportlist]\&.







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|



>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



>
>
>
>
>
>
>
>
|







<
<
<
<
<
|
<
<
<



>
>
>
|



>
>
>
>
>
>
















>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



<
<
<
<
<
<
<
<
<
<
<
<
<
<
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|

>
>
>
>
>
|
>
>
>
|
<
>
>
|
<
<
>
>
>
>
>

>
>
>
>
|
>
|
<
<

>
|
<
>
>

|
<
>
>
>

>
>
|
<

>
|
<
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
>
>
>
>
|
>
>
>
>
|
<
<
<

>
>
>
>
>
|
<
<
<
>
>
>
>

|
>
|
<
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<

>
|
|
|
|
|
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
|
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
|
>
>







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
.IP [5]
Invokes the \fBcontent\fR method for the object, generating an call to the \fBerror\fR
method if an exception is raised\&.
.IP [6]
Invokes the \fBoutput\fR method for the object
.PP
.PP








































































Developers have the option of streaming output to a buffer via the \fBputs\fR method of the
reply, or simply populating the \fIreply_body\fR variable of the object\&.
The information returned by the \fBcontent\fR method is not interpreted in any way\&.
If an exception is thrown (via the \fBerror\fR command in Tcl, for example) the caller will
auto-generate a 500 {Internal Error} message\&.
A typical implementation of \fBcontent\fR look like:
.CS



 clay::define ::test::content\&.file {
 	superclass ::httpd::content\&.file
 	# Return a file
 	# Note: this is using the content\&.file mixin which looks for the reply_file variable
 	# and will auto-compute the Content-Type
 	method content {} {
 	  my reset
     set doc_root [my request get DOCUMENT_ROOT]
     my variable reply_file
     set reply_file [file join $doc_root index\&.html]
 	}
 }
 clay::define ::test::content\&.time {
   # return the current system time
 	method content {} {
 		my variable reply_body
     my reply set Content-Type text/plain
 		set reply_body [clock seconds]
 	}
 }
 clay::define ::test::content\&.echo {
 	method content {} {
 		my variable reply_body
     my reply set Content-Type [my request get CONTENT_TYPE]
 		set reply_body [my PostData [my request get CONTENT_LENGTH]]
 	}
 }
 clay::define ::test::content\&.form_handler {
 	method content {} {
 	  set form [my FormData]
 	  my reply set Content-Type {text/html; charset=UTF-8}
     my puts [my html_header {My Dynamic Page}]
     my puts "<BODY>"
     my puts "You Sent<p>"
     my puts "<TABLE>"
     foreach {f v} $form {
       my puts "<TR><TH>$f</TH><TD><verbatim>$v</verbatim></TD>"
     }
     my puts "</TABLE><p>"
     my puts "Send some info:<p>"
     my puts "<FORM action=/[my request get REQUEST_PATH] method POST>"
     my puts "<TABLE>"
     foreach field {name rank serial_number} {
       set line "<TR><TH>$field</TH><TD><input name=\\"$field\\" "
       if {[dict exists $form $field]} {
         append line " value=\\"[dict get $form $field]\\"""
       }
       append line " /></TD></TR>"
       my puts $line
     }
     my puts "</TABLE>"
     my puts [my html footer]
 	}
 }


.CE
.PP
\fBVariable\fR
.TP
variable \fBChannelRegister\fR
.TP
variable \fBreply\fR
A dictionary which will converted into the MIME headers of the reply
.TP
variable \fBrequest\fR
A dictionary containing the SCGI transformed HTTP headers for the request
.PP
.PP
\fBDelegate\fR
.TP
delegate \fB<server>\fR
The server object which spawned this reply
.PP
.PP
\fBMethods\fR
.TP
method \fBconstructor\fR \fIServerObj\fR ?\fIargs\fR?
.TP
method \fBdestructor\fR ?\fIdictargs\fR?
clean up on exit
.TP
method \fBChannelRegister\fR ?\fIargs\fR?
Registers a channel to be closed by the close method
.TP
method \fBclose\fR
Close channels opened by this object
.TP
method \fBLog_Dispatched\fR
Record a dispatch event
.TP
method \fBdispatch\fR \fInewsock\fR \fIdatastate\fR
Accept the handoff from the server object of the socket
\fInewsock\fR and feed it the state \fIdatastate\fR\&.
Fields the \fIdatastate\fR are looking for in particular are:
.sp
* \fBmixin\fR - A key/value list of slots and classes to be mixed into the
object prior to invoking \fBDispatch\fR\&.
.sp
* \fBhttp\fR - A key/value list of values to populate the object's \fIrequest\fR
ensemble
.sp
All other fields are passed along to the \fBclay\fR structure of the object\&.
.TP
method \fBDispatch\fR
.TP
method \fBhtml_header\fR \fItitle\fR ?\fIargs\fR?
.TP
method \fBhtml_footer\fR ?\fIargs\fR?
.TP
method \fBerror\fR \fIcode\fR ?\fImsg\fR \fB\fR? ?\fIerrorInfo\fR \fB\fR?
.TP
method \fBcontent\fR
REPLACE ME:
This method is the "meat" of your application\&.
It writes to the result buffer via the "puts" method
and can tweak the headers via "clay put header_reply"
.TP
method \fBEncodeStatus\fR \fIstatus\fR
Formulate a standard HTTP status header from he string provided\&.
.TP
method \fBlog\fR \fItype\fR ?\fIinfo\fR \fB\fR?
.TP
method \fBCoroName\fR
.TP
method \fBDoOutput\fR
Generates the the HTTP reply, streams that reply back across \fIchan\fR,
and destroys the object\&.
.TP
method \fBFormData\fR
For GET requests, converts the QUERY_DATA header into a key/value list\&.
For POST requests, reads the Post data and converts that information to
a key/value list for application/x-www-form-urlencoded posts\&. For multipart
posts, it composites all of the MIME headers of the post to a singular key/value
list, and provides MIME_* information as computed by the \fBmime\fR package, including
the MIME_TOKEN, which can be fed back into the mime package to read out the contents\&.
.TP





method \fBPostData\fR \fIlength\fR



Stream \fIlength\fR bytes from the \fIchan\fR socket, but only of the request is a
POST or PUSH\&. Returns an empty string otherwise\&.
.TP
method \fBSession_Load\fR
Manage session data
.TP
method \fBputs\fR \fIline\fR
Appends the value of \fIstring\fR to the end of \fIreply_body\fR, as well as a trailing newline
character\&.
.TP
method \fBRequestFind\fR \fIfield\fR
.TP
method \fBrequest\fR \fIsubcommand\fR ?\fIargs\fR?
.TP
method \fBreply\fR \fIsubcommand\fR ?\fIargs\fR?
.TP
method \fBreset\fR
Clear the contents of the \fIreply_body\fR variable, and reset all headers in the \fBreply\fR
structure back to the defaults for this object\&.
.TP
method \fBtimeOutCheck\fR
Called from the \fBhttp::server\fR object which spawned this reply\&. Checks to see
if too much time has elapsed while waiting for data or generating a reply, and issues
a timeout error to the request if it has, as well as destroy the object and close the
\fIchan\fR socket\&.
.TP
method \fBtimestamp\fR
Return the current system time in the format:
.CS

%a, %d %b %Y %T %Z
.CE
.PP
.PP
.SS "CLASS  HTTPD::SERVER"
\fIancestors\fR: \fBhttpd::mime\fR
.PP
.PP
\fBVariable\fR
.TP
variable \fBtemplate\fR
.TP
variable \fBurl_patterns\fR
.PP
.PP
\fBMethods\fR
.TP
method \fBconstructor\fR \fIargs\fR ?\fIport\fR \fBauto\fR? ?\fImyaddr\fR \fB127\&.0\&.0\&.1\fR? ?\fIstring\fR \fBauto\fR? ?\fIname\fR \fBauto\fR? ?\fIdoc_root\fR \fB\fR? ?\fIreverse_dns\fR \fB0\fR? ?\fIconfiguration_file\fR \fB\fR? ?\fIprotocol\fR \fBHTTP/1\&.1\fR?
.TP
method \fBdestructor\fR ?\fIdictargs\fR?
.TP
method \fBconnect\fR \fIsock\fR \fIip\fR \fIport\fR
Reply to an open socket\&. This method builds a coroutine to manage the remainder
of the connection\&. The coroutine's operations are driven by the \fBConnect\fR method\&.
.TP
method \fBServerHeaders\fR \fIip\fR \fIhttp_request\fR \fImimetxt\fR
.TP
method \fBConnect\fR \fIuuid\fR \fIsock\fR \fIip\fR
This method reads HTTP headers, and then consults the \fBdispatch\fR method to
determine if the request is valid, and/or what kind of reply to generate\&. Under
normal cases, an object of class \fB::http::reply\fR is created, and that class's
\fBdispatch\fR method\&.
This action passes control of the socket to
the reply object\&. The reply object manages the rest of the transaction, including
closing the socket\&.
.TP
method \fBcounter\fR \fIwhich\fR
Increment an internal counter\&.
.TP
method \fBCheckTimeout\fR
Check open connections for a time out event\&.
.TP
method \fBdebug\fR ?\fIargs\fR?
.TP
method \fBdispatch\fR \fIdata\fR
Given a key/value list of information, return a data structure describing how
the server should reply\&.
.TP
method \fBDispatch_Default\fR \fIreply\fR
Method dispatch method of last resort before returning a 404 NOT FOUND error\&.
The default behavior is to look for a file in \fIDOCUMENT_ROOT\fR which
matches the query\&.
.TP
method \fBDispatch_Local\fR \fIdata\fR
Method dispatch method invoked prior to invoking methods implemented by plugins\&.
If this method returns a non-empty dictionary, that structure will be passed to
the reply\&. The default is an empty implementation\&.
.TP
method \fBHeaders_Local\fR \fIvarname\fR
Introspect and possibly modify a data structure destined for a reply\&. This
method is invoked before invoking Header methods implemented by plugins\&.
The default implementation is empty\&.
.TP
method \fBHeaders_Process\fR \fIvarname\fR
Introspect and possibly modify a data structure destined for a reply\&. This
method is built dynamically by the \fBplugin\fR method\&.
.TP
method \fBHostName\fR \fIipaddr\fR
Convert an ip address to a host name\&. If the server/ reverse_dns flag
is false, this method simply returns the IP address back\&.
Internally, this method uses the \fIdns\fR module from tcllib\&.
.TP
method \fBlog\fR ?\fIargs\fR?
Log an event\&. The input for args is free form\&. This method is intended
to be replaced by the user, and is a noop for a stock http::server object\&.
.TP
method \fBplugin\fR \fIslot\fR ?\fIclass\fR \fB\fR?
Incorporate behaviors from a plugin\&.
This method dynamically rebuilds the \fBDispatch\fR and \fBHeaders\fR
method\&. For every plugin, the server looks for the following entries in
\fIclay plugin/\fR:
.sp
\fIload\fR - A script to invoke in the server's namespace during the \fBplugin\fR method invokation\&.
.sp
\fIdispatch\fR - A script to stitch into the server's \fBDispatch\fR method\&.
.sp
\fIheaders\fR - A script to stitch into the server's \fBHeaders\fR method\&.
.sp
\fIthread\fR - A script to stitch into the server's \fBThread_start\fR method\&.
.TP
method \fBport_listening\fR
Return the actual port that httpd is listening on\&.
.TP
method \fBPrefixNormalize\fR \fIprefix\fR
For the stock version, trim trailing /'s and *'s from a prefix\&. This
method can be replaced by the end user to perform any other transformations
needed for the application\&.
.TP
method \fBsource\fR \fIfilename\fR
.TP
method \fBstart\fR

Open the socket listener\&.
.TP
method \fBstop\fR
Shut off the socket listener, and destroy any pending replies\&.
.TP
method \fBSubObject {} db\fR
.TP
method \fBSubObject {} default\fR
.TP
method \fBtemplate\fR \fIpage\fR
Return a template for the string \fIpage\fR
.TP
method \fBTemplateSearch\fR \fIpage\fR
Perform a search for the template that best matches \fIpage\fR\&. This
can include local file searches, in-memory structures, or even
database lookups\&. The stock implementation simply looks for files
with a \&.tml or \&.html extension in the ?doc_root? directory\&.
.TP
method \fBThread_start\fR
Built by the \fBplugin\fR method\&. Called by the \fBstart\fR method\&. Intended
to allow plugins to spawn worker threads\&.
.TP
method \fBUuid_Generate\fR
Generate a GUUID\&. Used to ensure every request has a unique ID\&.
The default implementation is:
.CS
















   return [::clay::uuid generate]

.CE
.TP
method \fBValidate_Connection\fR \fIsock\fR \fIip\fR
Given a socket and an ip address, return true if this connection should
be terminated, or false if it should be allowed to continue\&. The stock
implementation always returns 0\&. This is intended for applications to
be able to implement black lists and/or provide security based on IP
address\&.
.PP
.PP
.SS "CLASS  HTTPD::SERVER::DISPATCH"
\fIancestors\fR: \fBhttpd::server\fR
.PP
Provide a backward compadible alias
.PP
.SS "CLASS  HTTPD::CONTENT\&.REDIRECT"
.PP
\fBMethods\fR
.TP
method \fBreset\fR
.TP
method \fBcontent\fR
.PP
.PP
.SS "CLASS  HTTPD::CONTENT\&.CACHE"
.PP
\fBMethods\fR
.TP
method \fBDispatch\fR
.PP
.PP
.SS "CLASS  HTTPD::CONTENT\&.TEMPLATE"
.PP
\fBMethods\fR
.TP
method \fBcontent\fR

.PP
.PP
.SS "CLASS  HTTPD::CONTENT\&.FILE"


Class to deliver Static content
When utilized, this class is fed a local filename
by the dispatcher
.PP
\fBMethods\fR
.TP
method \fBFileName\fR
.TP
method \fBDirectoryListing\fR \fIlocal_file\fR
.TP
method \fBcontent\fR
.TP
method \fBDispatch\fR


.PP
.PP
.SS "CLASS  HTTPD::CONTENT\&.EXEC"

.PP
\fBVariable\fR
.TP
variable \fBexename\fR

.PP
.PP
\fBMethods\fR
.TP
method \fBCgiExec\fR \fIexecname\fR \fIscript\fR \fIarglist\fR
.TP
method \fBCgi_Executable\fR \fIscript\fR

.PP
.PP
.SS "CLASS  HTTPD::CONTENT\&.PROXY"

\fIancestors\fR: \fBhttpd::content\&.exec\fR
.PP
Return data from an proxy process
.PP
\fBMethods\fR
.TP
method \fBproxy_channel\fR
.TP
method \fBproxy_path\fR
.TP
method \fBProxyRequest\fR \fIchana\fR \fIchanb\fR
.TP
method \fBProxyReply\fR \fIchana\fR \fIchanb\fR ?\fIargs\fR?
.TP
method \fBDispatch\fR
.PP
.PP
.SS "CLASS  HTTPD::CONTENT\&.CGI"
\fIancestors\fR: \fBhttpd::content\&.proxy\fR
.PP
.PP
\fBMethods\fR
.TP
method \fBFileName\fR
.TP
method \fBproxy_channel\fR
.TP
method \fBProxyRequest\fR \fIchana\fR \fIchanb\fR
.TP
method \fBProxyReply\fR \fIchana\fR \fIchanb\fR ?\fIargs\fR?
.TP
method \fBDirectoryListing\fR \fIlocal_file\fR
For most CGI applications a directory list is vorboten
.PP
.PP
.SS "CLASS  HTTPD::PROTOCOL\&.SCGI"
Return data from an SCGI process



.PP
\fBMethods\fR
.TP
method \fBEncodeStatus\fR \fIstatus\fR
.PP
.PP
.SS "CLASS  HTTPD::CONTENT\&.SCGI"



\fIancestors\fR: \fBhttpd::content\&.proxy\fR
.PP
.PP
\fBMethods\fR
.TP
method \fBscgi_info\fR
.TP
method \fBproxy_channel\fR

.TP
method \fBProxyRequest\fR \fIchana\fR \fIchanb\fR
.TP
method \fBProxyReply\fR \fIchana\fR \fIchanb\fR ?\fIargs\fR?
.PP
.PP
.SS "CLASS  HTTPD::SERVER\&.SCGI"
\fIancestors\fR: \fBhttpd::server\fR
.PP
Act as an  SCGI Server
.PP
\fBMethods\fR
.TP
method \fBdebug\fR ?\fIargs\fR?
.TP
method \fBConnect\fR \fIuuid\fR \fIsock\fR \fIip\fR

.PP
.PP
.SS "CLASS  HTTPD::CONTENT\&.WEBSOCKET"
Upgrade a connection to a websocket
.PP
.SS "CLASS  HTTPD::PLUGIN"
httpd plugin template
.PP
.SS "CLASS  HTTPD::PLUGIN\&.DICT_DISPATCH"
A rudimentary plugin that dispatches URLs from a dict
data structure
.PP
\fBMethods\fR
.TP
method \fBDispatch_Dict\fR \fIdata\fR
Implementation of the dispatcher
.TP
method \fBuri {} add\fR \fIvhosts\fR \fIpatterns\fR \fIinfo\fR
.TP
method \fBuri {} direct\fR \fIvhosts\fR \fIpatterns\fR \fIinfo\fR \fIbody\fR
.PP
.PP
.SS "CLASS  HTTPD::REPLY\&.MEMCHAN"
\fIancestors\fR: \fBhttpd::reply\fR
.PP
.PP
\fBMethods\fR
.TP
method \fBoutput\fR
.TP
method \fBDoOutput\fR
.TP
method \fBclose\fR
.PP
.PP
.SS "CLASS  HTTPD::PLUGIN\&.LOCAL_MEMCHAN"
.PP
\fBMethods\fR
.TP
method \fBlocal_memchan\fR \fIcommand\fR ?\fIargs\fR?
.TP
method \fBConnect_Local\fR \fIuuid\fR \fIsock\fR ?\fIargs\fR?
A modified connection method that passes simple GET request to an object
and pulls data directly from the reply_body data variable in the object
Needed because memchan is bidirectional, and we can't seem to communicate that
the server is one side of the link and the reply is another
.PP
.PP
.SH AUTHORS
Sean Woods
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fInetwork\fR of the
\fITcllib Trackers\fR [http://core\&.tcl\&.tk/tcllib/reportlist]\&.

Changes to idoc/man/files/modules/imap4/imap4.n.

271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
..
.BS
.SH NAME
imap4 \- imap client-side tcl implementation of imap protocol
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBimap4  ?0\&.5\&.2?\fR
.sp
\fB::imap4::open\fR \fIhostname\fR ?\fIport\fR?
.sp
\fB::imap4::starttls\fR \fIchan\fR
.sp
\fB::imap4::login\fR \fIchan\fR \fIuser\fR \fIpass\fR
.sp







|







271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
..
.BS
.SH NAME
imap4 \- imap client-side tcl implementation of imap protocol
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBimap4  ?0\&.5\&.3?\fR
.sp
\fB::imap4::open\fR \fIhostname\fR ?\fIport\fR?
.sp
\fB::imap4::starttls\fR \fIchan\fR
.sp
\fB::imap4::login\fR \fIchan\fR \fIuser\fR \fIpass\fR
.sp
809
810
811
812
813
814
815


form of the ticket immediately after its creation, and then using the
left-most button in the secondary navigation bar\&.
Only a small part of rfc3501 implemented\&.
.SH "SEE ALSO"
ftp, http, imap, mime, pop3, tls
.SH KEYWORDS
email, imap, internet, mail, net, rfc3501, ssl, tls









>
>
809
810
811
812
813
814
815
816
817
form of the ticket immediately after its creation, and then using the
left-most button in the secondary navigation bar\&.
Only a small part of rfc3501 implemented\&.
.SH "SEE ALSO"
ftp, http, imap, mime, pop3, tls
.SH KEYWORDS
email, imap, internet, mail, net, rfc3501, ssl, tls
.SH CATEGORY
Networking

Changes to idoc/man/files/modules/log/loggerUtils.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'loggerUtils\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2005 Aamer Akhter <aakhter@cisco\&.com>
'\"
.TH "logger::utils" n 1\&.3 tcllib "Object Oriented logging facility"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'loggerUtils\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2005 Aamer Akhter <aakhter@cisco\&.com>
'\"
.TH "logger::utils" n 1\&.3\&.1 tcllib "Object Oriented logging facility"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
logger::utils \- Utilities for logger
.SH SYNOPSIS
package require \fBTcl  8\&.4\fR
.sp
package require \fBlogger::utils  ?1\&.3?\fR
.sp
\fB::logger::utils::createFormatCmd\fR \fIformatString\fR
.sp
\fB::logger::utils::createLogProc\fR \fB-procName\fR \fIprocName\fR ?\fIoptions\fR\&.\&.\&.?
.sp
\fB::logger::utils::applyAppender\fR \fB-appender\fR \fIappenderType\fR ?\fIoptions\fR\&.\&.\&.?
.sp







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
logger::utils \- Utilities for logger
.SH SYNOPSIS
package require \fBTcl  8\&.4\fR
.sp
package require \fBlogger::utils  ?1\&.3\&.1?\fR
.sp
\fB::logger::utils::createFormatCmd\fR \fIformatString\fR
.sp
\fB::logger::utils::createLogProc\fR \fB-procName\fR \fIprocName\fR ?\fIoptions\fR\&.\&.\&.?
.sp
\fB::logger::utils::applyAppender\fR \fB-appender\fR \fIappenderType\fR ?\fIoptions\fR\&.\&.\&.?
.sp

Changes to idoc/man/files/modules/markdown/markdown.n.

1
2
3
4
5
6
7
8
9
10
11
'\"
'\" Generated from file 'markdown\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "markdown" n 1\&.1 tcllib "Markdown to HTML Converter"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,



|







1
2
3
4
5
6
7
8
9
10
11
'\"
'\" Generated from file 'markdown\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "markdown" n 1\&.1\&.1 tcllib "Markdown to HTML Converter"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
..
.BS
.SH NAME
markdown \- Converts Markdown text to HTML
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBMarkdown  1\&.1\fR
.sp
package require \fBtextutil  ?0\&.8?\fR
.sp
\fB::Markdown::convert\fR \fImarkdown\fR
.sp
\fB::Markdown::register\fR \fIlangspec\fR \fIconverter\fR
.sp







|







271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
..
.BS
.SH NAME
markdown \- Converts Markdown text to HTML
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBMarkdown  1\&.1\&.1\fR
.sp
package require \fBtextutil  ?0\&.8?\fR
.sp
\fB::Markdown::convert\fR \fImarkdown\fR
.sp
\fB::Markdown::register\fR \fIlangspec\fR \fIconverter\fR
.sp

Changes to idoc/man/files/modules/math/math_geometry.n.

305
306
307
308
309
310
311






312
313
314
315
316
317
318
.sp
\fB::math::geometry::rect\fR \fInw\fR \fIse\fR
.sp
\fB::math::geometry::nwse\fR \fIrect\fR
.sp
\fB::math::geometry::angle\fR \fIline\fR
.sp






\fB::math::geometry::calculateDistanceToLine\fR \fIP\fR \fIline\fR
.sp
\fB::math::geometry::calculateDistanceToLineSegment\fR \fIP\fR \fIlinesegment\fR
.sp
\fB::math::geometry::calculateDistanceToPolyline\fR \fIP\fR \fIpolyline\fR
.sp
\fB::math::geometry::calculateDistanceToPolygon\fR \fIP\fR \fIpolygon\fR







>
>
>
>
>
>







305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
.sp
\fB::math::geometry::rect\fR \fInw\fR \fIse\fR
.sp
\fB::math::geometry::nwse\fR \fIrect\fR
.sp
\fB::math::geometry::angle\fR \fIline\fR
.sp
\fB::math::geometry::angleBetween\fR \fIvector1\fR \fIvector2\fR
.sp
\fB::math::geometry::inproduct\fR \fIvector1\fR \fIvector2\fR
.sp
\fB::math::geometry::areaParallellogram\fR \fIvector1\fR \fIvector2\fR
.sp
\fB::math::geometry::calculateDistanceToLine\fR \fIP\fR \fIline\fR
.sp
\fB::math::geometry::calculateDistanceToLineSegment\fR \fIP\fR \fIlinesegment\fR
.sp
\fB::math::geometry::calculateDistanceToPolyline\fR \fIP\fR \fIpolyline\fR
.sp
\fB::math::geometry::calculateDistanceToPolygon\fR \fIP\fR \fIpolygon\fR
509
510
511
512
513
514
515

































516
517
518
519
520
521
522
Calculate the angle from the positive x-axis to a given line
(in two dimensions only)\&.
.RS
.TP
list \fIline\fR
Coordinates of the line
.RE

































.sp
.TP
\fB::math::geometry::calculateDistanceToLine\fR \fIP\fR \fIline\fR
Calculate the distance of point P to the (infinite) line and return the
result
.RS
.TP







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
Calculate the angle from the positive x-axis to a given line
(in two dimensions only)\&.
.RS
.TP
list \fIline\fR
Coordinates of the line
.RE
.TP
\fB::math::geometry::angleBetween\fR \fIvector1\fR \fIvector2\fR
Calculate the angle between two vectors (in degrees)
.RS
.TP
list \fIvector1\fR
First vector
.TP
list \fIvector2\fR
Second vector
.RE
.TP
\fB::math::geometry::inproduct\fR \fIvector1\fR \fIvector2\fR
Calculate the inner product of two vectors
.RS
.TP
list \fIvector1\fR
First vector
.TP
list \fIvector2\fR
Second vector
.RE
.TP
\fB::math::geometry::areaParallellogram\fR \fIvector1\fR \fIvector2\fR
Calculate the area of the parallellogram with the two vectors as its sides
.RS
.TP
list \fIvector1\fR
First vector
.TP
list \fIvector2\fR
Second vector
.RE
.sp
.TP
\fB::math::geometry::calculateDistanceToLine\fR \fIP\fR \fIline\fR
Calculate the distance of point P to the (infinite) line and return the
result
.RS
.TP
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
Translate a polyline over a given vector
.RS
.TP
list \fIvector\fR
Translation vector
.TP
list \fIpolyline\fR
The polyline to be rotated
.RE
.sp
.TP
\fB::math::geometry::rotate\fR \fIangle\fR \fIpolyline\fR
Rotate a polyline over a given angle (degrees) around the origin
.RS
.TP
list \fIangle\fR
Angle over which to rotate the polyline (degrees)
.TP
list \fIpolyline\fR
The polyline to be translated
.RE
.sp
.TP
\fB::math::geometry::reflect\fR \fIangle\fR \fIpolyline\fR
Reflect a polyline in a line through the origin at a given angle (degrees) to the x-axis
.RS
.TP







|











|







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
Translate a polyline over a given vector
.RS
.TP
list \fIvector\fR
Translation vector
.TP
list \fIpolyline\fR
The polyline to be translated
.RE
.sp
.TP
\fB::math::geometry::rotate\fR \fIangle\fR \fIpolyline\fR
Rotate a polyline over a given angle (degrees) around the origin
.RS
.TP
list \fIangle\fR
Angle over which to rotate the polyline (degrees)
.TP
list \fIpolyline\fR
The polyline to be rotated
.RE
.sp
.TP
\fB::math::geometry::reflect\fR \fIangle\fR \fIpolyline\fR
Reflect a polyline in a line through the origin at a given angle (degrees) to the x-axis
.RS
.TP

Changes to idoc/man/files/modules/math/numtheory.n.

308
309
310
311
312
313
314


315
316
317
318
319
320
321
.sp
\fBmath::numtheory::numberPrimesGauss\fR \fIN\fR
.sp
\fBmath::numtheory::numberPrimesLegendre\fR \fIN\fR
.sp
\fBmath::numtheory::numberPrimesLegendreModified\fR \fIN\fR
.sp


.BE
.SH DESCRIPTION
.PP
This package is for collecting various number-theoretic operations, with
a slight bias to prime numbers\&.
.TP
\fBmath::numtheory::isprime\fR \fIN\fR ?\fIoption\fR \fIvalue\fR \&.\&.\&.?







>
>







308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
.sp
\fBmath::numtheory::numberPrimesGauss\fR \fIN\fR
.sp
\fBmath::numtheory::numberPrimesLegendre\fR \fIN\fR
.sp
\fBmath::numtheory::numberPrimesLegendreModified\fR \fIN\fR
.sp
\fBmath::numtheory::differenceNumberPrimesLegendreModified\fR \fIlower\fR \fIupper\fR
.sp
.BE
.SH DESCRIPTION
.PP
This package is for collecting various number-theoretic operations, with
a slight bias to prime numbers\&.
.TP
\fBmath::numtheory::isprime\fR \fIN\fR ?\fIoption\fR \fIvalue\fR \&.\&.\&.?
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
.RE
.TP
\fBmath::numtheory::numberPrimesGauss\fR \fIN\fR
Estimate the number of primes according the formula by Gauss\&.
.RS
.TP
integer \fIN\fR (in)
Number in question
.RE
.TP
\fBmath::numtheory::numberPrimesLegendre\fR \fIN\fR
Estimate the number of primes according the formula by Legendre\&.
.RS
.TP
integer \fIN\fR (in)
Number in question
.RE
.TP
\fBmath::numtheory::numberPrimesLegendreModified\fR \fIN\fR
Estimate the number of primes according the modified formula by Legendre\&.
.RS
.TP
integer \fIN\fR (in)
Number in question











.RE
.PP
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fImath :: numtheory\fR of the
\fITcllib Trackers\fR [http://core\&.tcl\&.tk/tcllib/reportlist]\&.







|







|







|
>
>
>
>
>
>
>
>
>
>
>







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
.RE
.TP
\fBmath::numtheory::numberPrimesGauss\fR \fIN\fR
Estimate the number of primes according the formula by Gauss\&.
.RS
.TP
integer \fIN\fR (in)
Number in question, should be larger than 0
.RE
.TP
\fBmath::numtheory::numberPrimesLegendre\fR \fIN\fR
Estimate the number of primes according the formula by Legendre\&.
.RS
.TP
integer \fIN\fR (in)
Number in question, should be larger than 0
.RE
.TP
\fBmath::numtheory::numberPrimesLegendreModified\fR \fIN\fR
Estimate the number of primes according the modified formula by Legendre\&.
.RS
.TP
integer \fIN\fR (in)
Number in question, should be larger than 0
.RE
.TP
\fBmath::numtheory::differenceNumberPrimesLegendreModified\fR \fIlower\fR \fIupper\fR
Estimate the number of primes between tow limits according the modified formula by Legendre\&.
.RS
.TP
integer \fIlower\fR (in)
Lower limit for the primes, should be larger than 0
.TP
integer \fIupper\fR (in)
Upper limit for the primes, should be larger than 0
.RE
.PP
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fImath :: numtheory\fR of the
\fITcllib Trackers\fR [http://core\&.tcl\&.tk/tcllib/reportlist]\&.

Added idoc/man/files/modules/math/quasirandom.n.





















































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
'\"
'\" Generated from file 'quasirandom\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "math::quasirandom" n 1 tcllib "Tcl Math Library"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
.\"	and indent is equivalent to second arg of .IP (shouldn't ever be
.\"	needed;  use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\"	Give maximum sizes of arguments for setting tab stops.  Type and
.\"	name are examples of largest possible arguments that will be passed
.\"	to .AP later.  If args are omitted, default tab stops are used.
.\"
.\" .BS
.\"	Start box enclosure.  From here until next .BE, everything will be
.\"	enclosed in one large box.
.\"
.\" .BE
.\"	End of box enclosure.
.\"
.\" .CS
.\"	Begin code excerpt.
.\"
.\" .CE
.\"	End code excerpt.
.\"
.\" .VS ?version? ?br?
.\"	Begin vertical sidebar, for use in marking newly-changed parts
.\"	of man pages.  The first argument is ignored and used for recording
.\"	the version when the .VS was added, so that the sidebars can be
.\"	found and removed when they reach a certain age.  If another argument
.\"	is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\"	End of vertical sidebar.
.\"
.\" .DS
.\"	Begin an indented unfilled display.
.\"
.\" .DE
.\"	End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\"	Start of list of standard options for a Tk widget. The manpage
.\"	argument defines where to look up the standard options; if
.\"	omitted, defaults to "options". The options follow on successive
.\"	lines, in three columns separated by tabs.
.\"
.\" .SE
.\"	End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\"	Start of description of a specific option.  cmdName gives the
.\"	option's name as specified in the class command, dbName gives
.\"	the option's name in the option database, and dbClass gives
.\"	the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\"	Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\"	Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\"	Print an open parenthesis, arg1 in quotes, then arg2 normally
.\"	(for trailing punctuation) and then a closing parenthesis.
.\"
.\"	# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\"	# Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
.   ie !"\\$2"" .TP \\n()Cu
.   el          .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1	\\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\"	# define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\"	# BS - start boxed text
.\"	# ^y = starting y location
.\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\"	Draw four-sided box normally, but don't draw top of
.\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# VS - start vertical sidebar
.\"	# ^Y = starting y location
.\"	# ^v = 1 (for troff;  for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\"	# VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\"	# Special macro to handle page bottom:  finish off current
.\"	# box/sidebar if in box/sidebar mode, then invoked standard
.\"	# page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\"	Draw three-sided box if this is the box's first page,
.\"	draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\"	# DS - begin display
.de DS
.RS
.nf
.sp
..
.\"	# DE - end display
.de DE
.fi
.RE
.sp
..
.\"	# SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\"	# SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\"	# OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name:	\\fB\\$1\\fR
Database Name:	\\fB\\$2\\fR
Database Class:	\\fB\\$3\\fR
.fi
.IP
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
.\"	# UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\"	# QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\"	# PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\"	# QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
math::quasirandom \- Quasi-random points for integration and Monte Carlo type methods
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBTclOO \fR
.sp
package require \fBmath::quasirandom  1\fR
.sp
\fB::math::quasirandom::qrpoint create\fR \fINAME\fR \fIDIM\fR ?ARGS?
.sp
\fBgen next\fR
.sp
\fBgen set-start\fR \fIindex\fR
.sp
\fBgen set-evaluations\fR \fInumber\fR
.sp
\fBgen integral\fR \fIfunc\fR \fIminmax\fR \fIargs\fR
.sp
.BE
.SH DESCRIPTION
.PP
In many applications pseudo-random numbers and pseudo-random points in a (limited)
sample space play an important role\&. For instance in any type of Monte Carlo simulation\&.
Pseudo-random numbers, however, may be too random and as a consequence a large
number of data points is required to reduce the error or fluctuation in the results
to the desired value\&.
.PP
Quasi-random numbers can be used as an alternative: instead of "completely" arbitrary
points, points are generated that are diverse enough to cover the entire sample space
in a more or less uniform way\&. As a consequence convergence to the limit can be
much faster, when such quasi-random numbers are well-chosen\&.
.PP
The package defines a \fIclass\fR "qrpoint" that creates a command to generate
quasi-random points in 1, 2 or more dimensions\&. The command can either generate
separate points, so that they can be used in a user-defined algorithm or use these
points to calculate integrals of functions defined over 1, 2 or more dimensions\&.
It also holds several other common algorithms\&. (NOTE: these are not implemented yet)
.PP
One particular characteristic of the generators is that there are no tuning parameters
involved, which makes the use particularly simple\&.
.SH COMMANDS
A quasi-random point generator is created using the \fIqrpoint\fR class:
.TP
\fB::math::quasirandom::qrpoint create\fR \fINAME\fR \fIDIM\fR ?ARGS?
This command takes the following arguments:
.RS
.TP
string \fINAME\fR
The name of the command to be created (alternatively: the \fInew\fR subcommand
will generate a unique name)
.TP
integer/string \fIDIM\fR
The number of dimensions or one of: "circle", "disk", "sphere" or "ball"
.TP
strings \fIARGS\fR
Zero or more key-value pairs\&. The supported options are:
.RS
.IP \(bu
\fI-start index\fR: The index for the next point to be generated (default: 1)
.IP \(bu
\fI-evaluations number\fR: The number of evaluations to be used by default (default: 100)
.RE
.RE
.PP
The points that are returned lie in the hyperblock [0,1[^n (n the number of dimensions)
or on the unit circle, within the unit disk, on the unit sphere or within the unit ball\&.
.PP
Each generator supports the following subcommands:
.TP
\fBgen next\fR
Return the coordinates of the next quasi-random point
.sp
.TP
\fBgen set-start\fR \fIindex\fR
Reset the index for the next quasi-random point\&. This is useful to control which list of points is returned\&.
Returns the new or the current value, if no value is given\&.
.sp
.TP
\fBgen set-evaluations\fR \fInumber\fR
Reset the default number of evaluations in compound algorithms\&. Note that the actual number is the
smallest 4-fold larger or equal to the given number\&. (The 4-fold plays a role in the detailed integration
routine\&.)
.sp
.TP
\fBgen integral\fR \fIfunc\fR \fIminmax\fR \fIargs\fR
Calculate the integral of the given function over the block (or the circle, sphere etc\&.)
.RS
.TP
string \fIfunc\fR
The name of the function to be integrated
.TP
list \fIminmax\fR
List of pairs of minimum and maximum coordinates\&. This can be used to
map the quasi-random coordinates to the desired hyper-block\&.
.sp
If the space is a circle, disk etc\&. then this argument should be a single value, the radius\&.
The circle, disk, etc\&. is centred at the origin\&. If this is not what is required, then a coordinate
transformation should be made within the function\&.
.TP
strings \fIargs\fR
Zero or more key-value pairs\&. The following options are supported:
.RS
.IP \(bu
\fI-evaluations number\fR: The number of evaluations to be used\&. If not specified use the
default of the generator object\&.
.RE
.RE
.PP
.SH TODO
Implement other algorithms and variants
.PP
Implement more unit tests\&.
.PP
Comparison to pseudo-random numbers for integration\&.
.SH REFERENCES
Various algorithms exist for generating quasi-random numbers\&. The generators created in this package are based on:
\fIhttp://extremelearning\&.com\&.au/unreasonable-effectiveness-of-quasirandom-sequences/\fR
.SH KEYWORDS
mathematics, quasi-random
.SH CATEGORY
Mathematics

Changes to idoc/man/files/modules/math/special.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'special\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2004 Arjen Markus <arjenmarkus@users\&.sourceforge\&.net>
'\"
.TH "math::special" n 0\&.3 tcllib "Tcl Math Library"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'special\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2004 Arjen Markus <arjenmarkus@users\&.sourceforge\&.net>
'\"
.TH "math::special" n 0\&.4 tcllib "Tcl Math Library"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
270
271
272
273
274
275
276
277
278
279
280
281
282




283


284
285
286
287
288
289
290
.de MT
.QW ""
..
.BS
.SH NAME
math::special \- Special mathematical functions
.SH SYNOPSIS
package require \fBTcl  ?8\&.3?\fR
.sp
package require \fBmath::special  ?0\&.3?\fR
.sp
\fB::math::special::Beta\fR \fIx\fR \fIy\fR
.sp




\fB::math::special::Gamma\fR \fIx\fR


.sp
\fB::math::special::erf\fR \fIx\fR
.sp
\fB::math::special::erfc\fR \fIx\fR
.sp
\fB::math::special::invnorm\fR \fIp\fR
.sp







|

|



>
>
>
>

>
>







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
.de MT
.QW ""
..
.BS
.SH NAME
math::special \- Special mathematical functions
.SH SYNOPSIS
package require \fBTcl  ?8\&.5?\fR
.sp
package require \fBmath::special  ?0\&.4?\fR
.sp
\fB::math::special::Beta\fR \fIx\fR \fIy\fR
.sp
\fB::math::special::incBeta\fR \fIa\fR \fIb\fR \fIx\fR
.sp
\fB::math::special::regIncBeta\fR \fIa\fR \fIb\fR \fIx\fR
.sp
\fB::math::special::Gamma\fR \fIx\fR
.sp
\fB::math::special::digamma\fR \fIx\fR
.sp
\fB::math::special::erf\fR \fIx\fR
.sp
\fB::math::special::erfc\fR \fIx\fR
.sp
\fB::math::special::invnorm\fR \fIp\fR
.sp
408
409
410
411
412
413
414





415
416
417
418
419
420
421
             |             |             |             |
Fresnel      | C           |  all of R   |     --      |   < 2\&.0e-3
integrals    | S           |  all of R   |     --      |   < 2\&.0e-3
             |             |             |             |
general      | Beta        | (see Gamma) |     --      |   < 1\&.0e-9
             | Gamma       |  x != 0,-1, |     --      |   < 1\&.0e-9
             |             |  -2, \&.\&.\&.    |             |





             | sinc        |  all of R   |     --      |   exact
             |             |             |             |
orthogonal   | Legendre    |  all of R   | n = 0,1,\&.\&.\&. |   exact
polynomials  | Chebyshev   |  all of R   | n = 0,1,\&.\&.\&. |   exact
             | Laguerre    |  all of R   | n = 0,1,\&.\&.\&. |   exact
             |             |             | alpha el\&. R |
             | Hermite     |  all of R   | n = 0,1,\&.\&.\&. |   exact







>
>
>
>
>







414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
             |             |             |             |
Fresnel      | C           |  all of R   |     --      |   < 2\&.0e-3
integrals    | S           |  all of R   |     --      |   < 2\&.0e-3
             |             |             |             |
general      | Beta        | (see Gamma) |     --      |   < 1\&.0e-9
             | Gamma       |  x != 0,-1, |     --      |   < 1\&.0e-9
             |             |  -2, \&.\&.\&.    |             |
             | incBeta     |             |  a, b > 0   |   < 1\&.0e-9
             | regIncBeta  |             |  a, b > 0   |   < 1\&.0e-9
             | digamma     |  x != 0,-1  |             |   < 1\&.0e-9
             |             |  -2, \&.\&.\&.    |             |
             |             |             |             |
             | sinc        |  all of R   |     --      |   exact
             |             |             |             |
orthogonal   | Legendre    |  all of R   | n = 0,1,\&.\&.\&. |   exact
polynomials  | Chebyshev   |  all of R   | n = 0,1,\&.\&.\&. |   exact
             | Laguerre    |  all of R   | n = 0,1,\&.\&.\&. |   exact
             |             |             | alpha el\&. R |
             | Hermite     |  all of R   | n = 0,1,\&.\&.\&. |   exact
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
.IP \(bu
Bessel functions of the second kind (Y_n, K_n)
.IP \(bu
Bessel functions of arbitrary order (and hence the Airy functions)
.IP \(bu
Chebyshev polynomials of the second kind (U_n)
.IP \(bu
The digamma function (psi)
.IP \(bu
The incomplete gamma and beta functions
.PP
.SH PROCEDURES
The package defines the following public procedures:
.TP
\fB::math::special::Beta\fR \fIx\fR \fIy\fR
Compute the Beta function for arguments "x" and "y"
.RS
.TP
float \fIx\fR
First argument for the Beta function
.TP
float \fIy\fR
Second argument for the Beta function
.RE
.sp






























.TP
\fB::math::special::Gamma\fR \fIx\fR
Compute the Gamma function for argument "x"
.RS
.TP
float \fIx\fR
Argument for the Gamma function
.RE









.sp
.TP
\fB::math::special::erf\fR \fIx\fR
Compute the error function for argument "x"
.RS
.TP
float \fIx\fR







<
<
|















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








>
>
>
>
>
>
>
>
>







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
.IP \(bu
Bessel functions of the second kind (Y_n, K_n)
.IP \(bu
Bessel functions of arbitrary order (and hence the Airy functions)
.IP \(bu
Chebyshev polynomials of the second kind (U_n)
.IP \(bu


The incomplete gamma function
.PP
.SH PROCEDURES
The package defines the following public procedures:
.TP
\fB::math::special::Beta\fR \fIx\fR \fIy\fR
Compute the Beta function for arguments "x" and "y"
.RS
.TP
float \fIx\fR
First argument for the Beta function
.TP
float \fIy\fR
Second argument for the Beta function
.RE
.sp
.TP
\fB::math::special::incBeta\fR \fIa\fR \fIb\fR \fIx\fR
Compute the incomplete Beta function for argument "x" with parameters "a" and "b"
.RS
.TP
float \fIa\fR
First parameter for the incomplete Beta function, a > 0
.TP
float \fIb\fR
Second parameter for the incomplete Beta function, b > 0
.TP
float \fIx\fR
Argument for the incomplete Beta function
.RE
.sp
.TP
\fB::math::special::regIncBeta\fR \fIa\fR \fIb\fR \fIx\fR
Compute the regularized incomplete Beta function for argument "x" with parameters "a" and "b"
.RS
.TP
float \fIa\fR
First parameter for the incomplete Beta function, a > 0
.TP
float \fIb\fR
Second parameter for the incomplete Beta function, b > 0
.TP
float \fIx\fR
Argument for the regularized incomplete Beta function
.RE
.sp
.TP
\fB::math::special::Gamma\fR \fIx\fR
Compute the Gamma function for argument "x"
.RS
.TP
float \fIx\fR
Argument for the Gamma function
.RE
.sp
.TP
\fB::math::special::digamma\fR \fIx\fR
Compute the digamma function (psi) for argument "x"
.RS
.TP
float \fIx\fR
Argument for the digamma function
.RE
.sp
.TP
\fB::math::special::erf\fR \fIx\fR
Compute the error function for argument "x"
.RS
.TP
float \fIx\fR

Changes to idoc/man/files/modules/math/statistics.n.

347
348
349
350
351
352
353




354
355
356
357
358
359
360
.sp
\fB::math::statistics::test-Rchart\fR \fIcontrol\fR \fIdata\fR
.sp
\fB::math::statistics::test-Kruskal-Wallis\fR \fIconfidence\fR \fIargs\fR
.sp
\fB::math::statistics::analyse-Kruskal-Wallis\fR \fIargs\fR
.sp




\fB::math::statistics::group-rank\fR \fIargs\fR
.sp
\fB::math::statistics::test-Wilcoxon\fR \fIsample_a\fR \fIsample_b\fR
.sp
\fB::math::statistics::spearman-rank\fR \fIsample_a\fR \fIsample_b\fR
.sp
\fB::math::statistics::spearman-rank-extended\fR \fIsample_a\fR \fIsample_b\fR







>
>
>
>







347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
.sp
\fB::math::statistics::test-Rchart\fR \fIcontrol\fR \fIdata\fR
.sp
\fB::math::statistics::test-Kruskal-Wallis\fR \fIconfidence\fR \fIargs\fR
.sp
\fB::math::statistics::analyse-Kruskal-Wallis\fR \fIargs\fR
.sp
\fB::math::statistics::test-Levene\fR \fIgroups\fR
.sp
\fB::math::statistics::test-Brown-Forsythe\fR \fIgroups\fR
.sp
\fB::math::statistics::group-rank\fR \fIargs\fR
.sp
\fB::math::statistics::test-Wilcoxon\fR \fIsample_a\fR \fIsample_b\fR
.sp
\fB::math::statistics::spearman-rank\fR \fIsample_a\fR \fIsample_b\fR
.sp
\fB::math::statistics::spearman-rank-extended\fR \fIsample_a\fR \fIsample_b\fR
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
.sp
\fB::math::statistics::pdf-lognormal\fR \fImean\fR \fIstdev\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-exponential\fR \fImean\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-uniform\fR \fIxmin\fR \fIxmax\fR \fIvalue\fR
.sp




\fB::math::statistics::pdf-gamma\fR \fIalpha\fR \fIbeta\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-poisson\fR \fImu\fR \fIk\fR
.sp
\fB::math::statistics::pdf-chisquare\fR \fIdf\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-student-t\fR \fIdf\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-gamma\fR \fIa\fR \fIb\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-beta\fR \fIa\fR \fIb\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-weibull\fR \fIscale\fR \fIshape\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-gumbel\fR \fIlocation\fR \fIscale\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-pareto\fR \fIscale\fR \fIshape\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-cauchy\fR \fIlocation\fR \fIscale\fR \fIvalue\fR
.sp






\fB::math::statistics::cdf-normal\fR \fImean\fR \fIstdev\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-lognormal\fR \fImean\fR \fIstdev\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-exponential\fR \fImean\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-uniform\fR \fIxmin\fR \fIxmax\fR \fIvalue\fR
.sp




\fB::math::statistics::cdf-students-t\fR \fIdegrees\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-gamma\fR \fIalpha\fR \fIbeta\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-poisson\fR \fImu\fR \fIk\fR
.sp
\fB::math::statistics::cdf-beta\fR \fIa\fR \fIb\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-weibull\fR \fIscale\fR \fIshape\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-gumbel\fR \fIlocation\fR \fIscale\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-pareto\fR \fIscale\fR \fIshape\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-cauchy\fR \fIlocation\fR \fIscale\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-F\fR \fInf1\fR \fInf2\fR \fIvalue\fR
.sp






\fB::math::statistics::empirical-distribution\fR \fIvalues\fR
.sp
\fB::math::statistics::random-normal\fR \fImean\fR \fIstdev\fR \fInumber\fR
.sp
\fB::math::statistics::random-lognormal\fR \fImean\fR \fIstdev\fR \fInumber\fR
.sp
\fB::math::statistics::random-exponential\fR \fImean\fR \fInumber\fR
.sp
\fB::math::statistics::random-uniform\fR \fIxmin\fR \fIxmax\fR \fInumber\fR
.sp




\fB::math::statistics::random-gamma\fR \fIalpha\fR \fIbeta\fR \fInumber\fR
.sp
\fB::math::statistics::random-poisson\fR \fImu\fR \fInumber\fR
.sp
\fB::math::statistics::random-chisquare\fR \fIdf\fR \fInumber\fR
.sp
\fB::math::statistics::random-student-t\fR \fIdf\fR \fInumber\fR
.sp
\fB::math::statistics::random-beta\fR \fIa\fR \fIb\fR \fInumber\fR
.sp
\fB::math::statistics::random-weibull\fR \fIscale\fR \fIshape\fR \fInumber\fR
.sp
\fB::math::statistics::random-gumbel\fR \fIlocation\fR \fIscale\fR \fInumber\fR
.sp
\fB::math::statistics::random-pareto\fR \fIscale\fR \fIshape\fR \fInumber\fR
.sp
\fB::math::statistics::random-cauchy\fR \fIlocation\fR \fIscale\fR \fInumber\fR






.sp
\fB::math::statistics::histogram-uniform\fR \fIxmin\fR \fIxmax\fR \fIlimits\fR \fInumber\fR
.sp
\fB::math::statistics::incompleteGamma\fR \fIx\fR \fIp\fR ?tol?
.sp
\fB::math::statistics::incompleteBeta\fR \fIa\fR \fIb\fR \fIx\fR ?tol?
.sp
\fB::math::statistics::estimate-pareto\fR \fIvalues\fR
.sp






\fB::math::statistics::filter\fR \fIvarname\fR \fIdata\fR \fIexpression\fR
.sp
\fB::math::statistics::map\fR \fIvarname\fR \fIdata\fR \fIexpression\fR
.sp
\fB::math::statistics::samplescount\fR \fIvarname\fR \fIlist\fR \fIexpression\fR
.sp
\fB::math::statistics::subdivide\fR







>
>
>
>




















>
>
>
>
>
>








>
>
>
>


















>
>
>
>
>
>










>
>
>
>

















>
>
>
>
>
>









>
>
>
>
>
>







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
.sp
\fB::math::statistics::pdf-lognormal\fR \fImean\fR \fIstdev\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-exponential\fR \fImean\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-uniform\fR \fIxmin\fR \fIxmax\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-triangular\fR \fIxmin\fR \fIxmax\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-symmetric-triangular\fR \fIxmin\fR \fIxmax\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-gamma\fR \fIalpha\fR \fIbeta\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-poisson\fR \fImu\fR \fIk\fR
.sp
\fB::math::statistics::pdf-chisquare\fR \fIdf\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-student-t\fR \fIdf\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-gamma\fR \fIa\fR \fIb\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-beta\fR \fIa\fR \fIb\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-weibull\fR \fIscale\fR \fIshape\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-gumbel\fR \fIlocation\fR \fIscale\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-pareto\fR \fIscale\fR \fIshape\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-cauchy\fR \fIlocation\fR \fIscale\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-laplace\fR \fIlocation\fR \fIscale\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-kumaraswamy\fR \fIa\fR \fIb\fR \fIvalue\fR
.sp
\fB::math::statistics::pdf-negative-binomial\fR \fIr\fR \fIp\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-normal\fR \fImean\fR \fIstdev\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-lognormal\fR \fImean\fR \fIstdev\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-exponential\fR \fImean\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-uniform\fR \fIxmin\fR \fIxmax\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-triangular\fR \fIxmin\fR \fIxmax\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-symmetric-triangular\fR \fIxmin\fR \fIxmax\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-students-t\fR \fIdegrees\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-gamma\fR \fIalpha\fR \fIbeta\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-poisson\fR \fImu\fR \fIk\fR
.sp
\fB::math::statistics::cdf-beta\fR \fIa\fR \fIb\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-weibull\fR \fIscale\fR \fIshape\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-gumbel\fR \fIlocation\fR \fIscale\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-pareto\fR \fIscale\fR \fIshape\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-cauchy\fR \fIlocation\fR \fIscale\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-F\fR \fInf1\fR \fInf2\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-laplace\fR \fIlocation\fR \fIscale\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-kumaraswamy\fR \fIa\fR \fIb\fR \fIvalue\fR
.sp
\fB::math::statistics::cdf-negative-binomial\fR \fIr\fR \fIp\fR \fIvalue\fR
.sp
\fB::math::statistics::empirical-distribution\fR \fIvalues\fR
.sp
\fB::math::statistics::random-normal\fR \fImean\fR \fIstdev\fR \fInumber\fR
.sp
\fB::math::statistics::random-lognormal\fR \fImean\fR \fIstdev\fR \fInumber\fR
.sp
\fB::math::statistics::random-exponential\fR \fImean\fR \fInumber\fR
.sp
\fB::math::statistics::random-uniform\fR \fIxmin\fR \fIxmax\fR \fInumber\fR
.sp
\fB::math::statistics::random-triangular\fR \fIxmin\fR \fIxmax\fR \fInumber\fR
.sp
\fB::math::statistics::random-symmetric-triangular\fR \fIxmin\fR \fIxmax\fR \fInumber\fR
.sp
\fB::math::statistics::random-gamma\fR \fIalpha\fR \fIbeta\fR \fInumber\fR
.sp
\fB::math::statistics::random-poisson\fR \fImu\fR \fInumber\fR
.sp
\fB::math::statistics::random-chisquare\fR \fIdf\fR \fInumber\fR
.sp
\fB::math::statistics::random-student-t\fR \fIdf\fR \fInumber\fR
.sp
\fB::math::statistics::random-beta\fR \fIa\fR \fIb\fR \fInumber\fR
.sp
\fB::math::statistics::random-weibull\fR \fIscale\fR \fIshape\fR \fInumber\fR
.sp
\fB::math::statistics::random-gumbel\fR \fIlocation\fR \fIscale\fR \fInumber\fR
.sp
\fB::math::statistics::random-pareto\fR \fIscale\fR \fIshape\fR \fInumber\fR
.sp
\fB::math::statistics::random-cauchy\fR \fIlocation\fR \fIscale\fR \fInumber\fR
.sp
\fB::math::statistics::random-laplace\fR \fIlocation\fR \fIscale\fR \fInumber\fR
.sp
\fB::math::statistics::random-kumaraswamy\fR \fIa\fR \fIb\fR \fInumber\fR
.sp
\fB::math::statistics::random-negative-binomial\fR \fIr\fR \fIp\fR \fInumber\fR
.sp
\fB::math::statistics::histogram-uniform\fR \fIxmin\fR \fIxmax\fR \fIlimits\fR \fInumber\fR
.sp
\fB::math::statistics::incompleteGamma\fR \fIx\fR \fIp\fR ?tol?
.sp
\fB::math::statistics::incompleteBeta\fR \fIa\fR \fIb\fR \fIx\fR ?tol?
.sp
\fB::math::statistics::estimate-pareto\fR \fIvalues\fR
.sp
\fB::math::statistics::estimate-exponential\fR \fIvalues\fR
.sp
\fB::math::statistics::estimate-laplace\fR \fIvalues\fR
.sp
\fB::math::statistics::estimante-negative-binomial\fR \fIr\fR \fIvalues\fR
.sp
\fB::math::statistics::filter\fR \fIvarname\fR \fIdata\fR \fIexpression\fR
.sp
\fB::math::statistics::map\fR \fIvarname\fR \fIdata\fR \fIexpression\fR
.sp
\fB::math::statistics::samplescount\fR \fIvarname\fR \fIlist\fR \fIexpression\fR
.sp
\fB::math::statistics::subdivide\fR
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
equal\&.
.RS
.TP
list \fIargs\fR
- Two or more lists of data
.RE
.sp

























.TP
\fB::math::statistics::group-rank\fR \fIargs\fR
Rank the groups of data with respect to the complete set\&.
Returns a list consisting of the group ID, the value and the rank
(possibly a rational number, in case of ties) for each data item\&.
.RS
.TP
list \fIargs\fR
- Two or more lists of data
.RE
.sp
.TP
\fB::math::statistics::test-Wilcoxon\fR \fIsample_a\fR \fIsample_b\fR
Compute the Wilcoxon test statistic to determine if two samples have the
same median or not\&. (The statistic can be regarded as standard normal, if the
sample sizes are both larger than 10\&. Returns the value of this statistic\&.
.RS
.TP
list \fIsample_a\fR
- List of data comprising the first sample
.TP
list \fIsample_b\fR
- List of data comprising the second sample







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>















|







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
equal\&.
.RS
.TP
list \fIargs\fR
- Two or more lists of data
.RE
.sp
.TP
\fB::math::statistics::test-Levene\fR \fIgroups\fR
Compute the Levene statistic to determine if groups of data have the
same variance (are homoscadastic) or not\&. The data are organised
in groups\&. This version uses the mean of the data as the measure
to determine the deviations\&. The statistic is equivalent to an
F statistic with degrees of freedom k-1 and N-k, k being the
number of groups and N the total number of data\&.
.RS
.TP
list \fIgroups\fR
- List of groups of data
.RE
.sp
.TP
\fB::math::statistics::test-Brown-Forsythe\fR \fIgroups\fR
Compute the Brown-Forsythe statistic to determine if groups of data have the
same variance (are homoscadastic) or not\&. Like the Levene test, but this
version uses the median of the data\&.
.RS
.TP
list \fIgroups\fR
- List of groups of data
.RE
.sp
.TP
\fB::math::statistics::group-rank\fR \fIargs\fR
Rank the groups of data with respect to the complete set\&.
Returns a list consisting of the group ID, the value and the rank
(possibly a rational number, in case of ties) for each data item\&.
.RS
.TP
list \fIargs\fR
- Two or more lists of data
.RE
.sp
.TP
\fB::math::statistics::test-Wilcoxon\fR \fIsample_a\fR \fIsample_b\fR
Compute the Wilcoxon test statistic to determine if two samples have the
same median or not\&. (The statistic can be regarded as standard normal, if the
sample sizes are both larger than 10\&.) Returns the value of this statistic\&.
.RS
.TP
list \fIsample_a\fR
- List of data comprising the first sample
.TP
list \fIsample_b\fR
- List of data comprising the second sample
1538
1539
1540
1541
1542
1543
1544


































1545
1546
1547
1548
1549
1550
1551
float \fIxmin\fR
- Maximum value of the distribution
.TP
float \fIvalue\fR
- Value for which the probability is required
.RE
.sp


































.TP
\fB::math::statistics::pdf-gamma\fR \fIalpha\fR \fIbeta\fR \fIvalue\fR
Return the probability of a given value for a Gamma
distribution with given shape and rate parameters
.RS
.TP
float \fIalpha\fR







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
float \fIxmin\fR
- Maximum value of the distribution
.TP
float \fIvalue\fR
- Value for which the probability is required
.RE
.sp
.TP
\fB::math::statistics::pdf-triangular\fR \fIxmin\fR \fIxmax\fR \fIvalue\fR
Return the probability of a given value for a triangular
distribution with given extremes\&. If the argument min is lower than the argument max, then smaller
values have higher probability and vice versa\&. In the first case the probability
density function is of the form \fIf(x) = 2(1-x)\fR and the other case it is of the form \fIf(x) = 2x\fR\&.
.RS
.TP
float \fIxmin\fR
- Minimum value of the distribution
.TP
float \fIxmin\fR
- Maximum value of the distribution
.TP
float \fIvalue\fR
- Value for which the probability is required
.RE
.sp
.TP
\fB::math::statistics::pdf-symmetric-triangular\fR \fIxmin\fR \fIxmax\fR \fIvalue\fR
Return the probability of a given value for a symmetric triangular
distribution with given extremes\&.
.RS
.TP
float \fIxmin\fR
- Minimum value of the distribution
.TP
float \fIxmin\fR
- Maximum value of the distribution
.TP
float \fIvalue\fR
- Value for which the probability is required
.RE
.sp
.TP
\fB::math::statistics::pdf-gamma\fR \fIalpha\fR \fIbeta\fR \fIvalue\fR
Return the probability of a given value for a Gamma
distribution with given shape and rate parameters
.RS
.TP
float \fIalpha\fR
1690
1691
1692
1693
1694
1695
1696



















































1697
1698
1699
1700
1701
1702
1703
float \fIscale\fR
- Shape parameter
.TP
float \fIvalue\fR
- Value for which the probability is required
.RE
.sp



















































.TP
\fB::math::statistics::cdf-normal\fR \fImean\fR \fIstdev\fR \fIvalue\fR
Return the cumulative probability of a given value for a normal
distribution with given mean and standard deviation, that is the
probability for values up to the given one\&.
.RS
.TP







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
float \fIscale\fR
- Shape parameter
.TP
float \fIvalue\fR
- Value for which the probability is required
.RE
.sp
.TP
\fB::math::statistics::pdf-laplace\fR \fIlocation\fR \fIscale\fR \fIvalue\fR
Return the probability of a given value for a Laplace
distribution with given location and shape parameters\&. The Laplace distribution
consists of two exponential functions, is peaked and has heavier tails than the
normal distribution\&.
.RS
.TP
float \fIlocation\fR
- Location parameter (mean)
.TP
float \fIscale\fR
- Shape parameter
.TP
float \fIvalue\fR
- Value for which the probability is required
.RE
.sp
.TP
\fB::math::statistics::pdf-kumaraswamy\fR \fIa\fR \fIb\fR \fIvalue\fR
Return the probability of a given value for a Kumaraswamy
distribution with given parameters a and b\&. The Kumaraswamy distribution
is related to the Beta distribution, but has a tractable cumulative distribution function\&.
.RS
.TP
float \fIa\fR
- Parameter a
.TP
float \fIb\fR
- Parameter b
.TP
float \fIvalue\fR
- Value for which the probability is required
.RE
.sp
.TP
\fB::math::statistics::pdf-negative-binomial\fR \fIr\fR \fIp\fR \fIvalue\fR
Return the probability of a given value for a negative binomial
distribution with an allowed number of failures and the probability of success\&.
.RS
.TP
int \fIr\fR
- Allowed number of failures (at least 1)
.TP
float \fIp\fR
- Probability of success
.TP
int \fIvalue\fR
- Number of successes for which the probability is to be returned
.RE
.sp
.TP
\fB::math::statistics::cdf-normal\fR \fImean\fR \fIstdev\fR \fIvalue\fR
Return the cumulative probability of a given value for a normal
distribution with given mean and standard deviation, that is the
probability for values up to the given one\&.
.RS
.TP
1742
1743
1744
1745
1746
1747
1748

































1749
1750
1751
1752
1753
1754
1755
.RE
.sp
.TP
\fB::math::statistics::cdf-uniform\fR \fIxmin\fR \fIxmax\fR \fIvalue\fR
Return the cumulative probability of a given value for a uniform
distribution with given extremes\&.
.RS

































.TP
float \fIxmin\fR
- Minimum value of the distribution
.TP
float \fIxmin\fR
- Maximum value of the distribution
.TP







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
.RE
.sp
.TP
\fB::math::statistics::cdf-uniform\fR \fIxmin\fR \fIxmax\fR \fIvalue\fR
Return the cumulative probability of a given value for a uniform
distribution with given extremes\&.
.RS
.TP
float \fIxmin\fR
- Minimum value of the distribution
.TP
float \fIxmin\fR
- Maximum value of the distribution
.TP
float \fIvalue\fR
- Value for which the probability is required
.RE
.sp
.TP
\fB::math::statistics::cdf-triangular\fR \fIxmin\fR \fIxmax\fR \fIvalue\fR
Return the cumulative probability of a given value for a triangular
distribution with given extremes\&. If xmin < xmax, then lower values have
a higher probability and vice versa, see also \fIpdf-triangular\fR
.RS
.TP
float \fIxmin\fR
- Minimum value of the distribution
.TP
float \fIxmin\fR
- Maximum value of the distribution
.TP
float \fIvalue\fR
- Value for which the probability is required
.RE
.sp
.TP
\fB::math::statistics::cdf-symmetric-triangular\fR \fIxmin\fR \fIxmax\fR \fIvalue\fR
Return the cumulative probability of a given value for a symmetric triangular
distribution with given extremes\&.
.RS
.TP
float \fIxmin\fR
- Minimum value of the distribution
.TP
float \fIxmin\fR
- Maximum value of the distribution
.TP
1891
1892
1893
1894
1895
1896
1897



















































1898
1899
1900
1901
1902
1903
1904
float \fInf2\fR
- Degrees of freedom for the denominator
.TP
float \fIvalue\fR
- Value for which the probability is required
.RE
.sp



















































.TP
\fB::math::statistics::empirical-distribution\fR \fIvalues\fR
Return a list of values and their empirical probability\&. The values are sorted in increasing order\&.
(The implementation follows the description at the corresponding Wikipedia page)
.RS
.TP
list \fIvalues\fR







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
float \fInf2\fR
- Degrees of freedom for the denominator
.TP
float \fIvalue\fR
- Value for which the probability is required
.RE
.sp
.TP
\fB::math::statistics::cdf-laplace\fR \fIlocation\fR \fIscale\fR \fIvalue\fR
Return the cumulative probability of a given value for a Laplace
distribution with given location and shape parameters\&. The Laplace distribution
consists of two exponential functions, is peaked and has heavier tails than the
normal distribution\&.
.RS
.TP
float \fIlocation\fR
- Location parameter (mean)
.TP
float \fIscale\fR
- Shape parameter
.TP
float \fIvalue\fR
- Value for which the probability is required
.RE
.sp
.TP
\fB::math::statistics::cdf-kumaraswamy\fR \fIa\fR \fIb\fR \fIvalue\fR
Return the cumulative probability of a given value for a Kumaraswamy
distribution with given parameters a and b\&. The Kumaraswamy distribution
is related to the Beta distribution, but has a tractable cumulative distribution function\&.
.RS
.TP
float \fIa\fR
- Parameter a
.TP
float \fIb\fR
- Parameter b
.TP
float \fIvalue\fR
- Value for which the probability is required
.RE
.sp
.TP
\fB::math::statistics::cdf-negative-binomial\fR \fIr\fR \fIp\fR \fIvalue\fR
Return the cumulative probability of a given value for a negative binomial
distribution with an allowed number of failures and the probability of success\&.
.RS
.TP
int \fIr\fR
- Allowed number of failures (at least 1)
.TP
float \fIp\fR
- Probability of success
.TP
int \fIvalue\fR
- Greatest number of successes
.RE
.sp
.TP
\fB::math::statistics::empirical-distribution\fR \fIvalues\fR
Return a list of values and their empirical probability\&. The values are sorted in increasing order\&.
(The implementation follows the description at the corresponding Wikipedia page)
.RS
.TP
list \fIvalues\fR
1951
1952
1953
1954
1955
1956
1957

































1958
1959
1960
1961
1962
1963
1964
.RE
.sp
.TP
\fB::math::statistics::random-uniform\fR \fIxmin\fR \fIxmax\fR \fInumber\fR
Return a list of "number" random values satisfying a uniform
distribution with given extremes\&.
.RS

































.TP
float \fIxmin\fR
- Minimum value of the distribution
.TP
float \fIxmax\fR
- Maximum value of the distribution
.TP







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
.RE
.sp
.TP
\fB::math::statistics::random-uniform\fR \fIxmin\fR \fIxmax\fR \fInumber\fR
Return a list of "number" random values satisfying a uniform
distribution with given extremes\&.
.RS
.TP
float \fIxmin\fR
- Minimum value of the distribution
.TP
float \fIxmax\fR
- Maximum value of the distribution
.TP
int \fInumber\fR
- Number of values to be returned
.RE
.sp
.TP
\fB::math::statistics::random-triangular\fR \fIxmin\fR \fIxmax\fR \fInumber\fR
Return a list of "number" random values satisfying a triangular
distribution with given extremes\&. If xmin < xmax, then lower values have a higher probability
and vice versa (see also \fIpdf-triangular\fR\&.
.RS
.TP
float \fIxmin\fR
- Minimum value of the distribution
.TP
float \fIxmax\fR
- Maximum value of the distribution
.TP
int \fInumber\fR
- Number of values to be returned
.RE
.sp
.TP
\fB::math::statistics::random-symmetric-triangular\fR \fIxmin\fR \fIxmax\fR \fInumber\fR
Return a list of "number" random values satisfying a symmetric triangular
distribution with given extremes\&.
.RS
.TP
float \fIxmin\fR
- Minimum value of the distribution
.TP
float \fIxmax\fR
- Maximum value of the distribution
.TP
2097
2098
2099
2100
2101
2102
2103


















































2104
2105
2106
2107
2108
2109
2110
float \fIscale\fR
- Scale parameter
.TP
int \fInumber\fR
- Number of values to be returned
.RE
.sp


















































.TP
\fB::math::statistics::histogram-uniform\fR \fIxmin\fR \fIxmax\fR \fIlimits\fR \fInumber\fR
Return the expected histogram for a uniform distribution\&.
.RS
.TP
float \fIxmin\fR
- Minimum value of the distribution







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
float \fIscale\fR
- Scale parameter
.TP
int \fInumber\fR
- Number of values to be returned
.RE
.sp
.TP
\fB::math::statistics::random-laplace\fR \fIlocation\fR \fIscale\fR \fInumber\fR
Return a list of "number" random values satisfying a Laplace
distribution with given location and shape parameters\&. The Laplace distribution
consists of two exponential functions, is peaked and has heavier tails than the
normal distribution\&.
.RS
.TP
float \fIlocation\fR
- Location parameter (mean)
.TP
float \fIscale\fR
- Shape parameter
.TP
int \fInumber\fR
- Number of values to be returned
.RE
.sp
.TP
\fB::math::statistics::random-kumaraswamy\fR \fIa\fR \fIb\fR \fInumber\fR
Return a list of "number" random values satisying a Kumaraswamy
distribution with given parameters a and b\&. The Kumaraswamy distribution
is related to the Beta distribution, but has a tractable cumulative distribution function\&.
.RS
.TP
float \fIa\fR
- Parameter a
.TP
float \fIb\fR
- Parameter b
.TP
int \fInumber\fR
- Number of values to be returned
.RE
.sp
.TP
\fB::math::statistics::random-negative-binomial\fR \fIr\fR \fIp\fR \fInumber\fR
Return a list of "number" random values satisying a negative binomial distribution\&.
.RS
.TP
int \fIr\fR
- Allowed number of failures (at least 1)
.TP
float \fIp\fR
- Probability of success
.TP
int \fInumber\fR
- Number of values to be returned
.RE
.sp
.TP
\fB::math::statistics::histogram-uniform\fR \fIxmin\fR \fIxmax\fR \fIlimits\fR \fInumber\fR
Return the expected histogram for a uniform distribution\&.
.RS
.TP
float \fIxmin\fR
- Minimum value of the distribution
2165
2166
2167
2168
2169
2170
2171

































2172
2173
2174
2175
2176
2177
2178
Estimate the parameters for the Pareto distribution that comes closest to the given values\&.
Returns the estimated scale and shape parameters, as well as the standard error for the shape parameter\&.
.RS
.TP
list \fIvalues\fR
- List of values, assumed to be distributed according to a Pareto distribution
.RE

































.sp
.PP
TO DO: more function descriptions to be added
.SH "DATA MANIPULATION"
The data manipulation procedures act on lists or lists of lists:
.TP
\fB::math::statistics::filter\fR \fIvarname\fR \fIdata\fR \fIexpression\fR







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
Estimate the parameters for the Pareto distribution that comes closest to the given values\&.
Returns the estimated scale and shape parameters, as well as the standard error for the shape parameter\&.
.RS
.TP
list \fIvalues\fR
- List of values, assumed to be distributed according to a Pareto distribution
.RE
.sp
.TP
\fB::math::statistics::estimate-exponential\fR \fIvalues\fR
Estimate the parameter for the exponential distribution that comes closest to the given values\&.
Returns an estimate of the one parameter and of the standard error\&.
.RS
.TP
list \fIvalues\fR
- List of values, assumed to be distributed according to an exponential distribution
.RE
.sp
.TP
\fB::math::statistics::estimate-laplace\fR \fIvalues\fR
Estimate the parameters for the Laplace distribution that comes closest to the given values\&.
Returns an estimate of respectively the location and scale parameters, based on maximum likelihood\&.
.RS
.TP
list \fIvalues\fR
- List of values, assumed to be distributed according to an exponential distribution
.RE
.sp
.TP
\fB::math::statistics::estimante-negative-binomial\fR \fIr\fR \fIvalues\fR
Estimate the probability of success for the negative binomial distribution that comes closest to the given values\&.
The allowed number of failures must be given\&.
.RS
.TP
int \fIr\fR
- Allowed number of failures (at least 1)
.TP
int \fInumber\fR
- List of values, assumed to be distributed according to a negative binomial distribution\&.
.RE
.sp
.PP
TO DO: more function descriptions to be added
.SH "DATA MANIPULATION"
The data manipulation procedures act on lists or lists of lists:
.TP
\fB::math::statistics::filter\fR \fIvarname\fR \fIdata\fR \fIexpression\fR

Changes to idoc/man/files/modules/mime/mime.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'mime\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 1999-2000 Marshall T\&. Rose
'\"
.TH "mime" n 1\&.6 tcllib "Mime"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'mime\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 1999-2000 Marshall T\&. Rose
'\"
.TH "mime" n 1\&.6\&.2 tcllib "Mime"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
mime \- Manipulation of MIME body parts
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBmime  ?1\&.6?\fR
.sp
\fB::mime::initialize\fR ?\fB-canonical\fR \fItype/subtype\fR ?\fB-param\fR {\fIkey value\fR}\&.\&.\&.? ?\fB-encoding\fR \fIvalue\fR? ?\fB-header\fR {\fIkey value\fR}\&.\&.\&.?? (\fB-file\fR \fIname\fR | \fB-string\fR \fIvalue\fR | \fB-parts\fR {\fItoken1\fR \&.\&.\&. \fItokenN\fR})
.sp
\fB::mime::finalize\fR \fItoken\fR ?\fB-subordinates\fR \fBall\fR | \fBdynamic\fR | \fBnone\fR?
.sp
\fB::mime::getproperty\fR \fItoken\fR ?\fIproperty\fR | \fB-names\fR?
.sp







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
mime \- Manipulation of MIME body parts
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBmime  ?1\&.6\&.2?\fR
.sp
\fB::mime::initialize\fR ?\fB-canonical\fR \fItype/subtype\fR ?\fB-param\fR {\fIkey value\fR}\&.\&.\&.? ?\fB-encoding\fR \fIvalue\fR? ?\fB-header\fR {\fIkey value\fR}\&.\&.\&.?? (\fB-file\fR \fIname\fR | \fB-string\fR \fIvalue\fR | \fB-parts\fR {\fItoken1\fR \&.\&.\&. \fItokenN\fR})
.sp
\fB::mime::finalize\fR \fItoken\fR ?\fB-subordinates\fR \fBall\fR | \fBdynamic\fR | \fBnone\fR?
.sp
\fB::mime::getproperty\fR \fItoken\fR ?\fIproperty\fR | \fB-names\fR?
.sp

Changes to idoc/man/files/modules/mime/smtp.n.

403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
.CS


proc send_simple_message {recipient email_server subject body} {
    package require smtp
    package require mime

    set token [mime::initialize -canonical text/plain \\\\
	-string $body]
    mime::setheader $token Subject $subject
    smtp::sendmessage $token \\\\
	-recipients $recipient -servers $email_server
    mime::finalize $token
}

send_simple_message someone@somewhere\&.com localhost \\\\
    "This is the subject\&." "This is the message\&."

.CE
.SH "TLS SECURITY CONSIDERATIONS"
.PP
This package uses the \fBTLS\fR package to handle the
security for \fBhttps\fR urls and other socket connections\&.







|


|




|







403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
.CS


proc send_simple_message {recipient email_server subject body} {
    package require smtp
    package require mime

    set token [mime::initialize -canonical text/plain \\
	-string $body]
    mime::setheader $token Subject $subject
    smtp::sendmessage $token \\
	-recipients $recipient -servers $email_server
    mime::finalize $token
}

send_simple_message someone@somewhere\&.com localhost \\
    "This is the subject\&." "This is the message\&."

.CE
.SH "TLS SECURITY CONSIDERATIONS"
.PP
This package uses the \fBTLS\fR package to handle the
security for \fBhttps\fR urls and other socket connections\&.

Changes to idoc/man/files/modules/ncgi/ncgi.n.

1
2
3
4
5
6
7
8
9
10
11
'\"
'\" Generated from file 'ncgi\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "ncgi" n 1\&.4\&.3 tcllib "CGI Support"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,



|







1
2
3
4
5
6
7
8
9
10
11
'\"
'\" Generated from file 'ncgi\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "ncgi" n 1\&.4\&.4 tcllib "CGI Support"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
..
.BS
.SH NAME
ncgi \- Procedures to manipulate CGI values\&.
.SH SYNOPSIS
package require \fBTcl  8\&.4\fR
.sp
package require \fBncgi  ?1\&.4\&.3?\fR
.sp
\fB::ncgi::cookie\fR \fIcookie\fR
.sp
\fB::ncgi::decode\fR \fIstr\fR
.sp
\fB::ncgi::empty\fR \fIname\fR
.sp







|







271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
..
.BS
.SH NAME
ncgi \- Procedures to manipulate CGI values\&.
.SH SYNOPSIS
package require \fBTcl  8\&.4\fR
.sp
package require \fBncgi  ?1\&.4\&.4?\fR
.sp
\fB::ncgi::cookie\fR \fIcookie\fR
.sp
\fB::ncgi::decode\fR \fIstr\fR
.sp
\fB::ncgi::empty\fR \fIname\fR
.sp

Changes to idoc/man/files/modules/oauth/oauth.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'oauth\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2014 Javi P\&. <hxm@eggdrop\&.es>
'\"
.TH "oauth" n 1\&.0\&.2 tcllib "oauth"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'oauth\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2014 Javi P\&. <hxm@eggdrop\&.es>
'\"
.TH "oauth" n 1\&.0\&.3 tcllib "oauth"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
oauth \- oauth API base signature
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBoauth  ?1\&.0\&.2?\fR
.sp
\fB::oauth::config\fR
.sp
\fB::oauth::config\fR ?\fIoptions\fR\&.\&.\&.?
.sp
\fB::oauth::header\fR \fIbaseURL\fR ?\fIpostQuery\fR?
.sp







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
oauth \- oauth API base signature
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBoauth  ?1\&.0\&.3?\fR
.sp
\fB::oauth::config\fR
.sp
\fB::oauth::config\fR ?\fIoptions\fR\&.\&.\&.?
.sp
\fB::oauth::header\fR \fIbaseURL\fR ?\fIpostQuery\fR?
.sp

Changes to idoc/man/files/modules/pki/pki.n.

345
346
347
348
349
350
351
352

353



354
355
356






357


358
359
360
361







362
363
364
365
366
367
368
.IP [1]
"openssl rsautl -decrypt" == "::pki::decrypt -binary -priv"
.IP [2]
"openssl rsautl -verify"  == "::pki::decrypt -binary -pub"
.RE
.TP
\fB::pki::sign\fR \fIinput\fR \fIkey\fR ?\fIalgo\fR?
Digitally sign message \fIinput\fR using the private \fIkey\fR\&.  If \fIalgo\fR

is ommited "sha1" is assumed\&.  Possible values for \fIalgo\fR include



"md5", "sha1", "sha256", and "raw"\&.  Specifyin "raw" for \fIalgo\fR will
inhibit the building of an ASN\&.1 structure to encode which hashing
algorithm was chosen\&.






The \fIinput\fR should be the plain text, hashing will be performed on it\&.


The \fIkey\fR should include the private key\&.
.TP
\fB::pki::verify\fR \fIsignedmessage\fR \fIplaintext\fR \fIkey\fR ?\fIalgo\fR?
Verify a digital signature using a public \fIkey\fR\&.  Returns true or false\&.







.TP
\fB::pki::key\fR \fIkey\fR ?\fIpassword\fR? ?\fIencodePem\fR?
Convert a key structure into a serialized PEM (default) or DER encoded private key suitable for other applications\&.  For RSA keys this means PKCS#1\&.
.TP
\fB::pki::pkcs::parse_key\fR \fIkey\fR ?\fIpassword\fR?
Convert a PKCS#1 private \fIkey\fR into a usable key, i\&.e\&. one which
can be used as argument for







|
>
|
>
>
>
|
|
|
>
>
>
>
>
>
|
>
>




>
>
>
>
>
>
>







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
.IP [1]
"openssl rsautl -decrypt" == "::pki::decrypt -binary -priv"
.IP [2]
"openssl rsautl -verify"  == "::pki::decrypt -binary -pub"
.RE
.TP
\fB::pki::sign\fR \fIinput\fR \fIkey\fR ?\fIalgo\fR?
Digitally sign message \fIinput\fR using the private \fIkey\fR\&.
.sp
If \fIalgo\fR is ommited "sha1" is assumed\&. Possible values for
\fIalgo\fR include "\fBmd5\fR", "\fBsha1\fR", "\fBsha256\fR",
and "\fBraw\fR"\&.
.sp
Specifying "\fBraw\fR" for \fIalgo\fR will inhibit the
building of an ASN\&.1 structure to encode which hashing algorithm was
chosen\&.
\fIAttention\fR: In this case the corresponding \fBpkgi::verify\fR
must be called \fBwith\fR algorithm information\&.
Conversely, specifying a non-"\fBraw\fR" algorithm here means that
the corresponding \fBpkgi::verify\fR invokation has to be made
\fIwithout\fR algorithm information\&.
.sp
The \fIinput\fR should be the plain text, hashing will be
performed on it\&.
.sp
The \fIkey\fR should include the private key\&.
.TP
\fB::pki::verify\fR \fIsignedmessage\fR \fIplaintext\fR \fIkey\fR ?\fIalgo\fR?
Verify a digital signature using a public \fIkey\fR\&.  Returns true or false\&.
.sp
\fIAttention\fR: The algorithm information \fIalgo\fR has to
be specified if and only if the \fBpki::sign\fR which generated the
\fIsignedmessage\fR was called with algorithm "\fBraw\fR"\&. This
inhibited the building of the ASN\&.1 structure encoding the chosen
hashing algorithm\&. Conversely, if a proper algorithm was specified
during signing then you \fImust not\fR specify an algorithm here\&.
.TP
\fB::pki::key\fR \fIkey\fR ?\fIpassword\fR? ?\fIencodePem\fR?
Convert a key structure into a serialized PEM (default) or DER encoded private key suitable for other applications\&.  For RSA keys this means PKCS#1\&.
.TP
\fB::pki::pkcs::parse_key\fR \fIkey\fR ?\fIpassword\fR?
Convert a PKCS#1 private \fIkey\fR into a usable key, i\&.e\&. one which
can be used as argument for

Changes to idoc/man/files/modules/pop3/pop3.n.

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
.CS


	package require tls
	tls::init -cafile /path/to/ca/cert -keyfile \&.\&.\&.

	# Create secured pop3 channel
	pop3::open -socketcmd tls::socket \\\\
		$thehost $theuser $thepassword

	\&.\&.\&.

.CE
The second method, option \fB-stls\fR, will connect to the standard POP3
port and then perform an STARTTLS handshake\&. This will only work for POP3
servers which have this capability\&. The package will confirm that the
server supports STARTTLS and the handshake was performed correctly before
proceeding with authentication\&.
.CS


	package require tls
	tls::init -cafile /path/to/ca/cert -keyfile \&.\&.\&.

	# Create secured pop3 channel
	pop3::open -stls 1 \\\\
		$thehost $theuser $thepassword

	\&.\&.\&.

.CE
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain







|

















|







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
.CS


	package require tls
	tls::init -cafile /path/to/ca/cert -keyfile \&.\&.\&.

	# Create secured pop3 channel
	pop3::open -socketcmd tls::socket \\
		$thehost $theuser $thepassword

	\&.\&.\&.

.CE
The second method, option \fB-stls\fR, will connect to the standard POP3
port and then perform an STARTTLS handshake\&. This will only work for POP3
servers which have this capability\&. The package will confirm that the
server supports STARTTLS and the handshake was performed correctly before
proceeding with authentication\&.
.CS


	package require tls
	tls::init -cafile /path/to/ca/cert -keyfile \&.\&.\&.

	# Create secured pop3 channel
	pop3::open -stls 1 \\
		$thehost $theuser $thepassword

	\&.\&.\&.

.CE
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain

Changes to idoc/man/files/modules/pop3d/pop3d.n.

489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
the package to override how the server opens its listening socket\&.
The envisioned main use is the specification of the \fBtls::socket\fR
command, see package \fBtls\fR, to secure the communication\&.
.CS


	package require tls
	tls::init \\\\
		\&.\&.\&.

	pop3d::new S -socket tls::socket
	\&.\&.\&.

.CE
.SH REFERENCES







|







489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
the package to override how the server opens its listening socket\&.
The envisioned main use is the specification of the \fBtls::socket\fR
command, see package \fBtls\fR, to secure the communication\&.
.CS


	package require tls
	tls::init \\
		\&.\&.\&.

	pop3d::new S -socket tls::socket
	\&.\&.\&.

.CE
.SH REFERENCES

Changes to idoc/man/files/modules/practcl/practcl.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'practcl\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2016-2018 Sean Woods <yoda@etoyoc\&.com>
'\"
.TH "practcl" n 0\&.11 tcllib "The The Proper Rational API for C to Tool Command Language Module"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'practcl\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2016-2018 Sean Woods <yoda@etoyoc\&.com>
'\"
.TH "practcl" n 0\&.16\&.4 tcllib "The The Proper Rational API for C to Tool Command Language Module"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
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
..
.BS
.SH NAME
practcl \- The Practcl Module
.SH SYNOPSIS
package require \fBTclOO  1\&.0\fR
.sp


























package require \fBpractcl  0\&.11\fR
.sp


























\fBCPUTS\fR \fIvarname\fR \fIbody\fR ?\fIbody\fR\&.\&.\&.?
































































































.sp




























\fBpractcl::_isdirectory\fR \fIpath\fR
.sp






























\fBpractcl::object\fR \fIparent\fR ?\fIkeyvaluelist\fR?
.sp










\fBpractcl::library\fR ?\fIkeyvaluelist\fR?














































































.sp








































\fBpractcl::exe\fR ?\fIkeyvaluelist\fR?
.sp






















































\fBpractcl::product\fR \fIparent\fR ?\fIkeyvaluelist\fR?
.sp














\fBpractcl::cheader\fR \fIparent\fR ?\fIkeyvaluelist\fR?






































.sp










\fBpractcl::csource\fR \fIparent\fR ?\fIkeyvaluelist\fR?
.sp
















































































\fBpractcl::module\fR \fIparent\fR ?\fIkeyvaluelist\fR?
.sp












\fBpractcl::submodule\fR \fIparent\fR ?\fIkeyvaluelist\fR?












































.sp
.BE
.SH DESCRIPTION
The Practcl module is a tool for integrating large modules for C API
Tcl code that requires custom Tcl types and TclOO objects\&.












.SH COMMANDS
.TP














































































































































































\fBCPUTS\fR \fIvarname\fR \fIbody\fR ?\fIbody\fR\&.\&.\&.?


Appends blocks of text to a buffer\&. This command tries to reduce the number
of line breaks between bodies\&.


.TP




















































































































\fBpractcl::_isdirectory\fR \fIpath\fR
Returns true if \fIpath\fR is a directory, using the test


.PP




















































































































.TP


























































\fBpractcl::object\fR \fIparent\fR ?\fIkeyvaluelist\fR?
















































































A generic Practcl object


.TP










\fBpractcl::library\fR ?\fIkeyvaluelist\fR?






































A Practcl object representing a library container
.TP











































































































\fBpractcl::exe\fR ?\fIkeyvaluelist\fR?
A Practcl object representing a wrapped executable
















.TP




\fBpractcl::product\fR \fIparent\fR ?\fIkeyvaluelist\fR?






































































A Practcl object representing a compiled product

.TP
































































































\fBpractcl::cheader\fR \fIparent\fR ?\fIkeyvaluelist\fR?










A Practcl object representing an externally generated c header








.TP









































































































\fBpractcl::csource\fR \fIparent\fR ?\fIkeyvaluelist\fR?




























A Practcl object representing an externally generated c source file





.TP

































\fBpractcl::module\fR \fIparent\fR ?\fIkeyvaluelist\fR?









A Practcl object representing a dynamically generated C/H/Tcl suite
.TP




\fBpractcl::submodule\fR \fIparent\fR ?\fIkeyvaluelist\fR?





















































A Practcl object representing a dynamically generated C/H/Tcl suite, subordinate to a module



































































.PP
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fIpractcl\fR of the
\fITcllib Trackers\fR [http://core\&.tcl\&.tk/tcllib/reportlist]\&.
Please also report any ideas for enhancements you may have for either







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
|
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>

>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|

>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
..
.BS
.SH NAME
practcl \- The Practcl Module
.SH SYNOPSIS
package require \fBTclOO  1\&.0\fR
.sp
proc \fBpractcl::cat\fR \fIfname\fR
.sp
proc \fBpractcl::docstrip\fR \fItext\fR
.sp
proc \fBputb\fR ?\fImap\fR? \fItext\fR
.sp
proc \fBProc\fR \fIname\fR \fIarglist\fR \fIbody\fR
.sp
proc \fBnoop\fR ?\fIargs\fR?
.sp
proc \fBpractcl::debug\fR ?\fIargs\fR?
.sp
proc \fBpractcl::doexec\fR ?\fIargs\fR?
.sp
proc \fBpractcl::doexec_in\fR \fIpath\fR ?\fIargs\fR?
.sp
proc \fBpractcl::dotclexec\fR ?\fIargs\fR?
.sp
proc \fBpractcl::domake\fR \fIpath\fR ?\fIargs\fR?
.sp
proc \fBpractcl::domake\&.tcl\fR \fIpath\fR ?\fIargs\fR?
.sp
proc \fBpractcl::fossil\fR \fIpath\fR ?\fIargs\fR?
.sp
proc \fBpractcl::fossil_status\fR \fIdir\fR
.sp
proc \fBpractcl::os\fR
.sp
proc \fBpractcl::mkzip\fR \fIexename\fR \fIbarekit\fR \fIvfspath\fR
.sp
proc \fBpractcl::sort_dict\fR \fIlist\fR
.sp
proc \fBpractcl::local_os\fR
.sp
proc \fBpractcl::config\&.tcl\fR \fIpath\fR
.sp
proc \fBpractcl::read_configuration\fR \fIpath\fR
.sp
proc \fBpractcl::tcllib_require\fR \fIpkg\fR ?\fIargs\fR?
.sp
proc \fBpractcl::platform::tcl_core_options\fR \fIos\fR
.sp
proc \fBpractcl::platform::tk_core_options\fR \fIos\fR
.sp
proc \fBpractcl::read_rc_file\fR \fIfilename\fR ?\fIlocaldat\fR \fB\fR?
.sp
proc \fBpractcl::read_sh_subst\fR \fIline\fR \fIinfo\fR
.sp
proc \fBpractcl::read_sh_file\fR \fIfilename\fR ?\fIlocaldat\fR \fB\fR?
.sp
proc \fBpractcl::read_Config\&.sh\fR \fIfilename\fR
.sp
proc \fBpractcl::read_Makefile\fR \fIfilename\fR
.sp
proc \fBpractcl::cputs\fR \fIvarname\fR ?\fIargs\fR?
.sp
proc \fBpractcl::tcl_to_c\fR \fIbody\fR
.sp
proc \fBpractcl::_tagblock\fR \fItext\fR ?\fIstyle\fR \fBtcl\fR? ?\fInote\fR \fB\fR?
.sp
proc \fBpractcl::de_shell\fR \fIdata\fR
.sp
proc \fBpractcl::grep\fR \fIpattern\fR ?\fIfiles\fR \fB\fR?
.sp
proc \fBpractcl::file_lexnormalize\fR \fIsp\fR
.sp
proc \fBpractcl::file_relative\fR \fIbase\fR \fIdst\fR
.sp
proc \fBpractcl::findByPattern\fR \fIbasedir\fR \fIpatterns\fR
.sp
proc \fBpractcl::log\fR \fIfname\fR \fIcomment\fR
.sp
proc \fBpractcl::_pkgindex_simpleIndex\fR \fIpath\fR
.sp
proc \fBpractcl::_pkgindex_directory\fR \fIpath\fR
.sp
proc \fBpractcl::_pkgindex_path_subdir\fR \fIpath\fR
.sp
proc \fBpractcl::pkgindex_path\fR ?\fIargs\fR?
.sp
proc \fBpractcl::installDir\fR \fId1\fR \fId2\fR
.sp
proc \fBpractcl::copyDir\fR \fId1\fR \fId2\fR ?\fItoplevel\fR \fB1\fR?
.sp
proc \fBpractcl::buildModule\fR \fImodpath\fR
.sp
proc \fBpractcl::installModule\fR \fImodpath\fR \fIDEST\fR
.sp
proc \fBpractcl::trigger\fR ?\fIargs\fR?
.sp
proc \fBpractcl::depends\fR ?\fIargs\fR?
.sp
proc \fBpractcl::target\fR \fIname\fR \fIinfo\fR ?\fIaction\fR \fB\fR?
.sp
method \fBconstructor\fR
.sp
method \fBargspec\fR \fIargspec\fR
.sp
method \fBcomment\fR \fIblock\fR
.sp
method \fBkeyword\&.Annotation\fR \fIresultvar\fR \fIcommentblock\fR \fItype\fR \fIname\fR \fIbody\fR
.sp
method \fBkeyword\&.Class\fR \fIresultvar\fR \fIcommentblock\fR \fIname\fR \fIbody\fR
.sp
method \fBkeyword\&.class\fR \fIresultvar\fR \fIcommentblock\fR \fIname\fR \fIbody\fR
.sp
method \fBkeyword\&.Class_Method\fR \fIresultvar\fR \fIcommentblock\fR \fIname\fR ?\fIargs\fR?
.sp
method \fBkeyword\&.method\fR \fIresultvar\fR \fIcommentblock\fR \fIname\fR ?\fIargs\fR?
.sp
method \fBkeyword\&.proc\fR \fIcommentblock\fR \fIname\fR \fIargspec\fR
.sp
method \fBreset\fR
.sp
method \fBMain\fR
.sp
method \fBsection\&.method\fR \fIkeyword\fR \fImethod\fR \fIminfo\fR
.sp
method \fBsection\&.annotation\fR \fItype\fR \fIname\fR \fIiinfo\fR
.sp
method \fBsection\&.class\fR \fIclass_name\fR \fIclass_info\fR
.sp
method \fBsection\&.command\fR \fIprocinfo\fR
.sp
method \fBmanpage\fR ?\fBheader \fIvalue\fR\fR? ?\fBfooter \fIvalue\fR\fR? ?\fBauthors \fIlist\fR\fR?
.sp
method \fBscan_text\fR \fItext\fR
.sp
method \fBscan_file\fR \fIfilename\fR
.sp
method \fB_MorphPatterns\fR
.sp
method \fBdefine\fR \fIsubmethod\fR ?\fIargs\fR?
.sp
method \fBgraft\fR ?\fIargs\fR?
.sp
method \fBinitialize\fR
.sp
method \fBlink\fR \fIcommand\fR ?\fIargs\fR?
.sp
method \fBmorph\fR \fIclassname\fR
.sp
method \fBscript\fR \fIscript\fR
.sp
method \fBselect\fR
.sp
method \fBsource\fR \fIfilename\fR
.sp
classmethod \fBselect\fR \fIobject\fR
.sp
method \fBconfig\&.sh\fR
.sp
method \fBBuildDir\fR \fIPWD\fR
.sp
method \fBMakeDir\fR \fIsrcdir\fR
.sp
method \fBread_configuration\fR
.sp
method \fBbuild-cflags\fR \fIPROJECT\fR \fIDEFS\fR \fInamevar\fR \fIversionvar\fR \fIdefsvar\fR
.sp
method \fBcritcl\fR ?\fIargs\fR?
.sp
method \fBAutoconf\fR
.sp
method \fBBuildDir\fR \fIPWD\fR
.sp
method \fBConfigureOpts\fR
.sp
method \fBMakeDir\fR \fIsrcdir\fR
.sp
method \fBmake {} autodetect\fR
.sp
method \fBmake {} clean\fR
.sp
method \fBmake {} compile\fR
.sp
method \fBmake {} install\fR \fIDEST\fR
.sp
method \fBbuild-compile-sources\fR \fIPROJECT\fR \fICOMPILE\fR \fICPPCOMPILE\fR \fIINCLUDES\fR
.sp
method \fBbuild-Makefile\fR \fIpath\fR \fIPROJECT\fR
.sp
method \fBbuild-library\fR \fIoutfile\fR \fIPROJECT\fR
.sp
method \fBbuild-tclsh\fR \fIoutfile\fR \fIPROJECT\fR ?\fIpath\fR \fBauto\fR?
.sp
method \fBBuildDir\fR \fIPWD\fR
.sp
method \fBmake {} autodetect\fR
.sp
method \fBmake {} clean\fR
.sp
method \fBmake {} compile\fR
.sp
method \fBmake {} install\fR \fIDEST\fR
.sp
method \fBMakeDir\fR \fIsrcdir\fR
.sp
method \fBNmakeOpts\fR
.sp
method \fBconstructor\fR \fImodule_object\fR \fIname\fR \fIinfo\fR ?\fIaction_body\fR \fB\fR?
.sp
method \fBdo\fR
.sp
method \fBcheck\fR
.sp
method \fBoutput\fR
.sp
method \fBreset\fR
.sp
method \fBtriggers\fR
.sp
method \fBconstructor\fR \fIparent\fR ?\fIargs\fR?
.sp
method \fBchild\fR \fImethod\fR
.sp
method \fBgo\fR
.sp
method \fBcstructure\fR \fIname\fR \fIdefinition\fR ?\fIargdat\fR \fB\fR?
.sp
method \fBinclude\fR \fIheader\fR
.sp
method \fBinclude_dir\fR ?\fIargs\fR?
.sp
method \fBinclude_directory\fR ?\fIargs\fR?
.sp
method \fBc_header\fR \fIbody\fR
.sp
method \fBc_code\fR \fIbody\fR
.sp
method \fBc_function\fR \fIheader\fR \fIbody\fR ?\fIinfo\fR \fB\fR?
.sp
method \fBc_tcloomethod\fR \fIname\fR \fIbody\fR ?\fIarginfo\fR \fB\fR?
.sp
method \fBcmethod\fR \fIname\fR \fIbody\fR ?\fIarginfo\fR \fB\fR?
.sp
method \fBc_tclproc_nspace\fR \fInspace\fR
.sp
method \fBc_tclcmd\fR \fIname\fR \fIbody\fR ?\fIarginfo\fR \fB\fR?
.sp
method \fBc_tclproc_raw\fR \fIname\fR \fIbody\fR ?\fIarginfo\fR \fB\fR?
.sp
method \fBtcltype\fR \fIname\fR \fIargdat\fR
.sp
method \fBproject-compile-products\fR
.sp
method \fBimplement\fR \fIpath\fR
.sp
method \fBinitialize\fR
.sp
method \fBlinktype\fR
.sp
method \fBgenerate-cfile-constant\fR
.sp
method \fBgenerate-cfile-header\fR
.sp
method \fBgenerate-cfile-tclapi\fR
.sp
method \fBgenerate-loader-module\fR
.sp
method \fBCollate_Source\fR \fICWD\fR
.sp
method \fBselect\fR
.sp
classmethod \fBselect\fR \fIobject\fR
.sp
method \fBcode\fR \fIsection\fR \fIbody\fR
.sp
method \fBCollate_Source\fR \fICWD\fR
.sp
method \fBproject-compile-products\fR
.sp
method \fBgenerate-debug\fR ?\fIspaces\fR \fB\fR?
.sp
method \fBgenerate-cfile-constant\fR
.sp
method \fBgenerate-cfile-public-structure\fR
.sp
method \fBgenerate-cfile-header\fR
.sp
method \fBgenerate-cfile-global\fR
.sp
method \fBgenerate-cfile-private-typedef\fR
.sp
method \fBgenerate-cfile-private-structure\fR
.sp
method \fBgenerate-cfile-functions\fR
.sp
method \fBgenerate-cfile-tclapi\fR
.sp
method \fBgenerate-hfile-public-define\fR
.sp
method \fBgenerate-hfile-public-macro\fR
.sp
method \fBgenerate-hfile-public-typedef\fR
.sp
method \fBgenerate-hfile-public-structure\fR
.sp
method \fBgenerate-hfile-public-headers\fR
.sp
method \fBgenerate-hfile-public-function\fR
.sp
method \fBgenerate-hfile-public-includes\fR
.sp
method \fBgenerate-hfile-public-verbatim\fR
.sp
method \fBgenerate-loader-external\fR
.sp
method \fBgenerate-loader-module\fR
.sp
method \fBgenerate-stub-function\fR
.sp
method \fBIncludeAdd\fR \fIheadervar\fR ?\fIargs\fR?
.sp
method \fBgenerate-tcl-loader\fR
.sp
method \fBgenerate-tcl-pre\fR
.sp
method \fBgenerate-tcl-post\fR
.sp
method \fBlinktype\fR
.sp
method \fBOfile\fR \fIfilename\fR
.sp
method \fBproject-static-packages\fR
.sp
method \fBtoolset-include-directory\fR
.sp
method \fBtarget\fR \fImethod\fR ?\fIargs\fR?
.sp
method \fBproject-compile-products\fR
.sp
method \fBgenerate-loader-module\fR
.sp
method \fBproject-compile-products\fR
.sp
method \fBlinker-products\fR \fIconfigdict\fR
.sp
method \fBinitialize\fR
.sp
variable \fBmake_object\fR
.sp
method \fB_MorphPatterns\fR
.sp
method \fBadd\fR ?\fIargs\fR?
.sp
method \fBinstall-headers\fR ?\fIargs\fR?
.sp
method \fBmake {} _preamble\fR
.sp
method \fBmake {} pkginfo\fR
.sp
method \fBmake {} objects\fR
.sp
method \fBmake {} object\fR \fIname\fR
.sp
method \fBmake {} reset\fR
.sp
method \fBmake {} trigger\fR ?\fIargs\fR?
.sp
method \fBmake {} depends\fR ?\fIargs\fR?
.sp
method \fBmake {} filename\fR \fIname\fR
.sp
method \fBmake {} target\fR \fIname\fR \fIInfo\fR \fIbody\fR
.sp
method \fBmake {} todo\fR
.sp
method \fBmake {} do\fR
.sp
method \fBchild\fR \fIwhich\fR
.sp
method \fBgenerate-c\fR
.sp
method \fBgenerate-h\fR
.sp
method \fBgenerate-loader\fR
.sp
method \fBinitialize\fR
.sp
method \fBimplement\fR \fIpath\fR
.sp
method \fBlinktype\fR
.sp
method \fB_MorphPatterns\fR
.sp
method \fBconstructor\fR ?\fIargs\fR?
.sp
method \fBadd_object\fR \fIobject\fR
.sp
method \fBadd_project\fR \fIpkg\fR \fIinfo\fR ?\fIoodefine\fR \fB\fR?
.sp
method \fBadd_tool\fR \fIpkg\fR \fIinfo\fR ?\fIoodefine\fR \fB\fR?
.sp
method \fBbuild-tclcore\fR
.sp
method \fBchild\fR \fIwhich\fR
.sp
method \fBlinktype\fR
.sp
method \fBproject\fR \fIpkg\fR ?\fIargs\fR?
.sp
method \fBtclcore\fR
.sp
method \fBtkcore\fR
.sp
method \fBtool\fR \fIpkg\fR ?\fIargs\fR?
.sp
method \fBclean\fR \fIPATH\fR
.sp
method \fBproject-compile-products\fR
.sp
method \fBgo\fR
.sp
method \fBgenerate-decls\fR \fIpkgname\fR \fIpath\fR
.sp
method \fBimplement\fR \fIpath\fR
.sp
method \fBgenerate-make\fR \fIpath\fR
.sp
method \fBlinktype\fR
.sp
method \fBpackage-ifneeded\fR ?\fIargs\fR?
.sp
method \fBshared_library\fR ?\fIfilename\fR \fB\fR?
.sp
method \fBstatic_library\fR ?\fIfilename\fR \fB\fR?
.sp
method \fBbuild-tclkit_main\fR \fIPROJECT\fR \fIPKG_OBJS\fR
.sp
method \fBCollate_Source\fR \fICWD\fR
.sp
method \fBwrap\fR \fIPWD\fR \fIexename\fR \fIvfspath\fR ?\fIargs\fR?
.sp
classmethod \fBSandbox\fR \fIobject\fR
.sp
classmethod \fBselect\fR \fIobject\fR
.sp
classmethod \fBclaim_option\fR
.sp
classmethod \fBclaim_object\fR \fIobject\fR
.sp
classmethod \fBclaim_path\fR \fIpath\fR
.sp
method \fBscm_info\fR
.sp
method \fBDistroMixIn\fR
.sp
method \fBSandbox\fR
.sp
method \fBSrcDir\fR
.sp
method \fBScmTag\fR
.sp
method \fBScmClone\fR
.sp
method \fBScmUnpack\fR
.sp
method \fBScmUpdate\fR
.sp
method \fBUnpack\fR
.sp
classmethod \fBclaim_object\fR \fIobject\fR
.sp
classmethod \fBclaim_option\fR
.sp
classmethod \fBclaim_path\fR \fIpath\fR
.sp
method \fBScmUnpack\fR
.sp
classmethod \fBclaim_object\fR \fIobj\fR
.sp
classmethod \fBclaim_option\fR
.sp
classmethod \fBclaim_path\fR \fIpath\fR
.sp
method \fBscm_info\fR
.sp
method \fBScmClone\fR
.sp
method \fBScmTag\fR
.sp
method \fBScmUnpack\fR
.sp
method \fBScmUpdate\fR
.sp
classmethod \fBclaim_object\fR \fIobj\fR
.sp
classmethod \fBclaim_option\fR
.sp
classmethod \fBclaim_path\fR \fIpath\fR
.sp
method \fBScmTag\fR
.sp
method \fBScmUnpack\fR
.sp
method \fBScmUpdate\fR
.sp
method \fB_MorphPatterns\fR
.sp
method \fBBuildDir\fR \fIPWD\fR
.sp
method \fBchild\fR \fIwhich\fR
.sp
method \fBcompile\fR
.sp
method \fBgo\fR
.sp
method \fBinstall\fR ?\fIargs\fR?
.sp
method \fBlinktype\fR
.sp
method \fBlinker-products\fR \fIconfigdict\fR
.sp
method \fBlinker-external\fR \fIconfigdict\fR
.sp
method \fBlinker-extra\fR \fIconfigdict\fR
.sp
method \fBenv-bootstrap\fR
.sp
method \fBenv-exec\fR
.sp
method \fBenv-install\fR
.sp
method \fBenv-load\fR
.sp
method \fBenv-present\fR
.sp
method \fBsources\fR
.sp
method \fBupdate\fR
.sp
method \fBunpack\fR
.sp
method \fBenv-bootstrap\fR
.sp
method \fBenv-present\fR
.sp
method \fBlinktype\fR
.sp
method \fBenv-bootstrap\fR
.sp
method \fBenv-install\fR
.sp
method \fBenv-present\fR
.sp
method \fBinstall\fR \fIDEST\fR
.sp
method \fBkettle\fR \fIpath\fR ?\fIargs\fR?
.sp
method \fBinstall\fR \fIDEST\fR
.sp
method \fBinstall\fR \fIDEST\fR
.sp
method \fBenv-bootstrap\fR
.sp
method \fBenv-install\fR
.sp
method \fBenv-present\fR
.sp
method \fBinstall\fR \fIDEST\fR
.sp
method \fBinstall-module\fR \fIDEST\fR ?\fIargs\fR?
.sp
method \fBenv-bootstrap\fR
.sp
method \fBenv-install\fR
.sp
method \fBinstall\fR \fIDEST\fR
.sp
method \fBinstall-module\fR \fIDEST\fR ?\fIargs\fR?
.sp
method \fBclean\fR
.sp
method \fBenv-install\fR
.sp
method \fBproject-compile-products\fR
.sp
method \fBComputeInstall\fR
.sp
method \fBgo\fR
.sp
method \fBlinker-products\fR \fIconfigdict\fR
.sp
method \fBproject-static-packages\fR
.sp
method \fBBuildDir\fR \fIPWD\fR
.sp
method \fBcompile\fR
.sp
method \fBConfigure\fR
.sp
method \fBinstall\fR \fIDEST\fR
.sp
method \fBinstall\fR \fIDEST\fR
.sp
method \fBinstall\fR \fIDEST\fR
.sp
method \fBenv-bootstrap\fR
.sp
method \fBenv-present\fR
.sp
method \fBenv-install\fR
.sp
method \fBgo\fR
.sp
method \fBlinktype\fR
.sp
.BE
.SH DESCRIPTION
The Practcl module is a tool for integrating large modules for C API
Tcl code that requires custom Tcl types and TclOO objects\&.
.PP
The concept with Practcl is that is a single file package that can
assist any tcl based project with distribution, compilation, linking,
VFS preparation, executable assembly, and installation\&. Practcl also
allows one project to invoke the build system from another project,
allowing complex projects such as a statically linked basekit to be
assembled with relative ease\&.
.PP
Practcl ships as a single file, and aside from a Tcl 8\&.6 interpreter,
has no external dependencies\&.
.PP
Making a practcl project
.SH COMMANDS
.TP
proc \fBpractcl::cat\fR \fIfname\fR
Concatenate a file
.TP
proc \fBpractcl::docstrip\fR \fItext\fR
Strip the global comments from tcl code\&. Used to
prevent the documentation markup comments from clogging
up files intended for distribution in machine readable format\&.
.TP
proc \fBputb\fR ?\fImap\fR? \fItext\fR
Append a line of text to a variable\&. Optionally apply a string mapping\&.
.TP
proc \fBProc\fR \fIname\fR \fIarglist\fR \fIbody\fR
Generate a proc if no command already exists by that name
.TP
proc \fBnoop\fR ?\fIargs\fR?
A command to do nothing\&. A handy way of
negating an instruction without
having to comment it completely out\&.
It's also a handy attachment point for
an object to be named later
.TP
proc \fBpractcl::debug\fR ?\fIargs\fR?
.TP
proc \fBpractcl::doexec\fR ?\fIargs\fR?
Drop in a static copy of Tcl
.TP
proc \fBpractcl::doexec_in\fR \fIpath\fR ?\fIargs\fR?
.TP
proc \fBpractcl::dotclexec\fR ?\fIargs\fR?
.TP
proc \fBpractcl::domake\fR \fIpath\fR ?\fIargs\fR?
.TP
proc \fBpractcl::domake\&.tcl\fR \fIpath\fR ?\fIargs\fR?
.TP
proc \fBpractcl::fossil\fR \fIpath\fR ?\fIargs\fR?
.TP
proc \fBpractcl::fossil_status\fR \fIdir\fR
.TP
proc \fBpractcl::os\fR
.TP
proc \fBpractcl::mkzip\fR \fIexename\fR \fIbarekit\fR \fIvfspath\fR
Build a zipfile\&. On tcl8\&.6 this invokes the native Zip implementation
on older interpreters this invokes zip via exec
.TP
proc \fBpractcl::sort_dict\fR \fIlist\fR
Dictionary sort a key/value list\&. Needed because pre tcl8\&.6
does not have \fIlsort -stride 2\fR
.TP
proc \fBpractcl::local_os\fR
Returns a dictionary describing the local operating system\&.
Fields return include:
.RS
.IP \(bu
download - Filesystem path where fossil repositories and source tarballs are downloaded for the current user
.IP \(bu
EXEEXT - The extension to give to executables\&. (i\&.e\&. \&.exe on windows)
.IP \(bu
fossil_mirror - A URI for a local network web server who acts as a fossil repository mirror
.IP \(bu
local_install - Filesystem path where packages for local consumption by the current user are installed
.IP \(bu
prefix - The prefix as given to the Tcl core/TEA for installation to local_install in \&./configure
.IP \(bu
sandbox - The file location where this project unpacks external projects
.IP \(bu
TEACUP_PROFILE - The ActiveState/Teacup canonical name for this platform (i\&.e\&. win32-ix86 macosx10\&.5-i386-x86_84)
.IP \(bu
TEACUP_OS - The local operating system (windows, macosx, openbsd, etc)\&. Gives the same answer as tcl\&.m4, except that macosx is given as macosx instead of Darwin\&.
.IP \(bu
TEA_PLATFORM - The platform returned by uname -s-uname -r (on Unix), or "windows" on Windows
.IP \(bu
TEACUP_ARCH - The processor architecture for the local os (i\&.e\&. ix86, x86_64)
.IP \(bu
TEACUP_ARCH - The processor architecture for the local os (i\&.e\&. ix86, x86_64)
.IP \(bu
teapot - Filesystem path where teapot package files are downloaded for the current user
.IP \(bu
userhome - File path to store localized preferences, cache download files, etc for the current user
.RE
.IP
This command uses a combination of local checks with Exec, any tclConfig\&.sh file that is
resident, autoconf data where already computed, and data gleaned from a file named
practcl\&.rc in userhome\&. The location for userhome varies by platform and operating system:
.RS
.IP \(bu
Windows: ::env(LOCALAPPDATA)/Tcl
.IP \(bu
Macos: ~/Library/Application Support/Tcl
.IP \(bu
Other: ~/tcl
.RE
.TP
proc \fBpractcl::config\&.tcl\fR \fIpath\fR
A transparent call to ::practcl::read_configuration to preserve backward compadibility
with older copies of Practcl
.TP
proc \fBpractcl::read_configuration\fR \fIpath\fR
Detect local platform\&. This command looks for data gleaned by autoconf or autosetup
in the path specified, or perform its own logic tests if neither has been run\&.
A file named config\&.site present in the location indicates that this project is
cross compiling, and the data stored in that file is used for the compiler and linker\&.
.sp
This command looks for information from the following files, in the following order:
.RS
.IP \(bu
config\&.tcl - A file generated by autoconf/configure in newer editions of TEA, encoded as a Tcl script\&.
.IP \(bu
config\&.site - A file containing cross compiler information, encoded as a SH script
.IP \(bu
::env(VisualStudioVersion) - On Windows, and environmental value that indicates MS Visual Studio is installed
.RE
.sp
This command returns a dictionary containing all of the data cleaned from the sources above\&.
In the absence of any guidance this command returns the same output as ::practcl::local_os\&.
In this mode, if the environmental variable VisualStudioVersion exists, this command
will provide a template of fields that are appropriate for compiling on Windows under
Microsoft Visual Studio\&. The USEMSVC flag in the dictionary is a boolean flag to indicate
if this is indeed the case\&.
.TP
proc \fBpractcl::tcllib_require\fR \fIpkg\fR ?\fIargs\fR?
Try to load  a package, and failing that
retrieve tcllib
.TP
proc \fBpractcl::platform::tcl_core_options\fR \fIos\fR
Return the string to pass to \&./configure to compile the Tcl core for the given OS\&.
.RS
.IP \(bu
windows: --with-tzdata --with-encoding utf-8
.IP \(bu
macosx: --enable-corefoundation=yes  --enable-framework=no --with-tzdata --with-encoding utf-8
.IP \(bu
other: --with-tzdata --with-encoding utf-8
.RE
.TP
proc \fBpractcl::platform::tk_core_options\fR \fIos\fR
.TP
proc \fBpractcl::read_rc_file\fR \fIfilename\fR ?\fIlocaldat\fR \fB\fR?
Read a stylized key/value list stored in a file
.TP
proc \fBpractcl::read_sh_subst\fR \fIline\fR \fIinfo\fR
Converts a XXX\&.sh file into a series of Tcl variables
.TP
proc \fBpractcl::read_sh_file\fR \fIfilename\fR ?\fIlocaldat\fR \fB\fR?
.TP
proc \fBpractcl::read_Config\&.sh\fR \fIfilename\fR
A simpler form of read_sh_file tailored
to pulling data from (tcl|tk)Config\&.sh
.TP
proc \fBpractcl::read_Makefile\fR \fIfilename\fR
A simpler form of read_sh_file tailored
to pulling data from a Makefile
.TP
proc \fBpractcl::cputs\fR \fIvarname\fR ?\fIargs\fR?
Append arguments to a buffer
The command works like puts in that each call will also insert
a line feed\&. Unlike puts, blank links in the interstitial are
suppressed
.TP
proc \fBpractcl::tcl_to_c\fR \fIbody\fR
.TP
proc \fBpractcl::_tagblock\fR \fItext\fR ?\fIstyle\fR \fBtcl\fR? ?\fInote\fR \fB\fR?
.TP
proc \fBpractcl::de_shell\fR \fIdata\fR
.TP
proc \fBpractcl::grep\fR \fIpattern\fR ?\fIfiles\fR \fB\fR?
Search for the pattern \fIpattern\fR amongst $files
.TP
proc \fBpractcl::file_lexnormalize\fR \fIsp\fR
.TP
proc \fBpractcl::file_relative\fR \fIbase\fR \fIdst\fR
Calculate a relative path between base and dst
.sp
Example:
.CS

  ::practcl::file_relative ~/build/tcl/unix ~/build/tcl/library
  > \&.\&./library



.CE
.TP
proc \fBpractcl::findByPattern\fR \fIbasedir\fR \fIpatterns\fR
.TP
proc \fBpractcl::log\fR \fIfname\fR \fIcomment\fR
Record an event in the practcl log
.TP
proc \fBpractcl::_pkgindex_simpleIndex\fR \fIpath\fR
.TP
proc \fBpractcl::_pkgindex_directory\fR \fIpath\fR
Return true if the pkgindex file contains
any statement other than "package ifneeded"
and/or if any package ifneeded loads a DLL
.TP
proc \fBpractcl::_pkgindex_path_subdir\fR \fIpath\fR
Helper function for ::practcl::pkgindex_path
.TP
proc \fBpractcl::pkgindex_path\fR ?\fIargs\fR?
Index all paths given as though they will end up in the same
virtual file system
.TP
proc \fBpractcl::installDir\fR \fId1\fR \fId2\fR
Delete the contents of \fId2\fR, and then
recusively Ccopy the contents of \fId1\fR to \fId2\fR\&.
.TP
proc \fBpractcl::copyDir\fR \fId1\fR \fId2\fR ?\fItoplevel\fR \fB1\fR?
Recursively copy the contents of \fId1\fR to \fId2\fR
.TP
proc \fBpractcl::buildModule\fR \fImodpath\fR
.TP
proc \fBpractcl::installModule\fR \fImodpath\fR \fIDEST\fR
Install a module from MODPATH to the directory specified\&.
\fIdpath\fR is assumed to be the fully qualified path where module is to be placed\&.
Any existing files will be deleted at that path\&.
If the path is symlink the process will return with no error and no action\&.
If the module has contents in the build/ directory that are newer than the
\&.tcl files in the module source directory, and a build/build\&.tcl file exists,
the build/build\&.tcl file is run\&.
If the source directory includes a file named index\&.tcl, the directory is assumed
to be in the tao style of modules, and the entire directory (and all subdirectories)
are copied verbatim\&.
If no index\&.tcl file is present, all \&.tcl files are copied from the module source
directory, and a pkgIndex\&.tcl file is generated if non yet exists\&.
I a folder named htdocs exists in the source directory, that directory is copied
verbatim to the destination\&.
.TP
proc \fBpractcl::trigger\fR ?\fIargs\fR?
Trigger build targets, and recompute dependencies
.sp
Internals:
.CS


  ::practcl::LOCAL make trigger {*}$args
  foreach {name obj} [::practcl::LOCAL make objects] {
    set ::make($name) [$obj do]
  }

.CE
.TP
proc \fBpractcl::depends\fR ?\fIargs\fR?
Calculate if a dependency for any of the arguments needs to
be fulfilled or rebuilt\&.
.sp
Internals:
.CS


  ::practcl::LOCAL make depends {*}$args

.CE
.TP
proc \fBpractcl::target\fR \fIname\fR \fIinfo\fR ?\fIaction\fR \fB\fR?
Declare a build product\&. This proc is just a shorthand for
\fI::practcl::LOCAL make task $name $info $action\fR
.sp
Registering a build product with this command will create
an entry in the global  array, and populate
a value in the global  array\&.
.sp
Internals:
.CS


  set obj [::practcl::LOCAL make task $name $info $action]
  set ::make($name) 0
  set filename [$obj define get filename]
  if {$filename ne {}} {
    set ::target($name) $filename
  }

.CE
.PP
.SH CLASSES
.SS "CLASS  PRACTCL::DOCTOOL"
.CS

{ set authors {
   {John Doe} {jdoe@illustrious\&.edu}
   {Tom RichardHarry} {tomdickharry@illustrius\&.edu}
 }
 # Create the object
 ::practcl::doctool create AutoDoc
 set fout [open [file join $moddir module\&.tcl] w]
 foreach file [glob [file join $srcdir *\&.tcl]] {
   set content [::practcl::cat [file join $srcdir $file]]
    # Scan the file
    AutoDoc scan_text $content
    # Strip the comments from the distribution
    puts $fout [::practcl::docstrip $content]
 }
 # Write out the manual page
 set manout [open [file join $moddir module\&.man] w]
 dict set args header [string map $modmap [::practcl::cat [file join $srcdir manual\&.txt]]]
 dict set args footer [string map $modmap [::practcl::cat [file join $srcdir footer\&.txt]]]
 dict set args authors $authors
 puts $manout [AutoDoc manpage {*}$args]
 close $manout


}
.CE
.PP
Tool for build scripts to dynamically generate manual files from comments
in source code files
.PP
\fBMethods\fR
.TP
method \fBconstructor\fR
.TP
method \fBargspec\fR \fIargspec\fR
Process an argument list into an informational dict\&.
This method also understands non-positional
arguments expressed in the notation of Tip 471
\fIhttps://core\&.tcl-lang\&.org/tips/doc/trunk/tip/479\&.md\fR\&.
.sp
The output will be a dictionary of all of the fields and whether the fields
are \fBpositional\fR, \fBmandatory\fR, and whether they have a
\fBdefault\fR value\&.
.sp
.sp
Example:
.CS

   my argspec {a b {c 10}}

   > a {positional 1 mandatory 1} b {positional 1 mandatory 1} c {positional 1 mandatory 0 default 10}



.CE
.TP
method \fBcomment\fR \fIblock\fR
Convert a block of comments into an informational dictionary\&.
If lines in the comment start with a single word ending in a colon,
all subsequent lines are appended to a dictionary field of that name\&.
If no fields are given, all of the text is appended to the \fBdescription\fR
field\&.
.sp
Example:
.CS

 my comment {Does something cool}
 > description {Does something cool}

 my comment {
 title : Something really cool
 author : Sean Woods
 author : John Doe
 description :
 This does something really cool!
 }
 > description {This does something really cool!}
   title {Something really cool}
   author {Sean Woods
   John Doe}



.CE
.TP
method \fBkeyword\&.Annotation\fR \fIresultvar\fR \fIcommentblock\fR \fItype\fR \fIname\fR \fIbody\fR
.TP
method \fBkeyword\&.Class\fR \fIresultvar\fR \fIcommentblock\fR \fIname\fR \fIbody\fR
Process an oo::objdefine call that modifies the class object
itself
.TP
method \fBkeyword\&.class\fR \fIresultvar\fR \fIcommentblock\fR \fIname\fR \fIbody\fR
Process an oo::define, clay::define, etc statement\&.
.TP
method \fBkeyword\&.Class_Method\fR \fIresultvar\fR \fIcommentblock\fR \fIname\fR ?\fIargs\fR?
Process a statement for a clay style class method
.TP
method \fBkeyword\&.method\fR \fIresultvar\fR \fIcommentblock\fR \fIname\fR ?\fIargs\fR?
Process a statement for a tcloo style object method
.TP
method \fBkeyword\&.proc\fR \fIcommentblock\fR \fIname\fR \fIargspec\fR
Process a proc statement
.TP
method \fBreset\fR
Reset the state of the object and its embedded coroutine
.TP
method \fBMain\fR
Main body of the embedded coroutine for the object
.TP
method \fBsection\&.method\fR \fIkeyword\fR \fImethod\fR \fIminfo\fR
Generate the manual page text for a method or proc
.TP
method \fBsection\&.annotation\fR \fItype\fR \fIname\fR \fIiinfo\fR
.TP
method \fBsection\&.class\fR \fIclass_name\fR \fIclass_info\fR
Generate the manual page text for a class
.TP
method \fBsection\&.command\fR \fIprocinfo\fR
Generate the manual page text for the commands section
.TP
method \fBmanpage\fR ?\fBheader \fIvalue\fR\fR? ?\fBfooter \fIvalue\fR\fR? ?\fBauthors \fIlist\fR\fR?
Generate the manual page\&. Returns the completed text suitable for saving in \&.man file\&.
The header argument is a block of doctools text to go in before the machine generated
section\&. footer is a block of doctools text to go in after the machine generated
section\&. authors is a list of individual authors and emails in the form of AUTHOR EMAIL ?AUTHOR EMAIL?\&.\&.\&.
.TP
method \fBscan_text\fR \fItext\fR
Scan a block of text
.TP
method \fBscan_file\fR \fIfilename\fR
Scan a file of text
.PP
.PP
.SS "CLASS  PRACTCL::METACLASS"
The metaclass for all practcl objects
.PP
\fBMethods\fR
.TP
method \fB_MorphPatterns\fR
.TP
method \fBdefine\fR \fIsubmethod\fR ?\fIargs\fR?
.TP
method \fBgraft\fR ?\fIargs\fR?
.TP
method \fBinitialize\fR
.TP
method \fBlink\fR \fIcommand\fR ?\fIargs\fR?
.TP
method \fBmorph\fR \fIclassname\fR
.TP
method \fBscript\fR \fIscript\fR
.TP
method \fBselect\fR
.TP
method \fBsource\fR \fIfilename\fR
.PP
.PP
.SS "CLASS  PRACTCL::TOOLSET"
Ancestor-less class intended to be a mixin
which defines a family of build related behaviors
that are modified when targetting either gcc or msvc
.PP
\fBClass Methods\fR
.TP
classmethod \fBselect\fR \fIobject\fR
Perform the selection for the toolset mixin
.PP
.PP
\fBMethods\fR
.TP
method \fBconfig\&.sh\fR
find or fake a key/value list describing this project
.TP
method \fBBuildDir\fR \fIPWD\fR
Compute the location where the product will be built
.TP
method \fBMakeDir\fR \fIsrcdir\fR
Return where the Makefile is located relative to \fIsrcdir\fR\&.
For this implementation the MakeDir is always srcdir\&.
.TP
method \fBread_configuration\fR
Read information about the build process for this package\&.
For this implementation, data is sought in the following locations
in the following order:
config\&.tcl (generated by practcl\&.) PKGConfig\&.sh\&. The Makefile
.sp
If the Makefile needs to be consulted, but does not exist, the
Configure method is invoked
.TP
method \fBbuild-cflags\fR \fIPROJECT\fR \fIDEFS\fR \fInamevar\fR \fIversionvar\fR \fIdefsvar\fR
method DEFS
This method populates 4 variables:
name - The name of the package
version - The version of the package
defs - C flags passed to the compiler
includedir - A list of paths to feed to the compiler for finding headers
.TP
method \fBcritcl\fR ?\fIargs\fR?
Invoke critcl in an external process
.PP
.PP
.SS "CLASS  PRACTCL::TOOLSET\&.GCC"
\fIancestors\fR: \fBpractcl::toolset\fR
.PP
.PP
\fBMethods\fR
.TP
method \fBAutoconf\fR
.TP
method \fBBuildDir\fR \fIPWD\fR
.TP
method \fBConfigureOpts\fR
.TP
method \fBMakeDir\fR \fIsrcdir\fR
Detect what directory contains the Makefile template
.TP
method \fBmake {} autodetect\fR
.TP
method \fBmake {} clean\fR
.TP
method \fBmake {} compile\fR
.TP
method \fBmake {} install\fR \fIDEST\fR
.TP
method \fBbuild-compile-sources\fR \fIPROJECT\fR \fICOMPILE\fR \fICPPCOMPILE\fR \fIINCLUDES\fR
.TP
method \fBbuild-Makefile\fR \fIpath\fR \fIPROJECT\fR
.TP
method \fBbuild-library\fR \fIoutfile\fR \fIPROJECT\fR
Produce a static or dynamic library
.TP
method \fBbuild-tclsh\fR \fIoutfile\fR \fIPROJECT\fR ?\fIpath\fR \fBauto\fR?
Produce a static executable
.PP
.PP
.SS "CLASS  PRACTCL::TOOLSET\&.MSVC"
\fIancestors\fR: \fBpractcl::toolset\fR
.PP
.PP
\fBMethods\fR
.TP
method \fBBuildDir\fR \fIPWD\fR
MSVC always builds in the source directory
.TP
method \fBmake {} autodetect\fR
Do nothing
.TP
method \fBmake {} clean\fR
.TP
method \fBmake {} compile\fR
.TP
method \fBmake {} install\fR \fIDEST\fR
.TP
method \fBMakeDir\fR \fIsrcdir\fR
Detect what directory contains the Makefile template
.TP
method \fBNmakeOpts\fR
.PP
.PP
.SS "CLASS  PRACTCL::MAKE_OBJ"
\fIancestors\fR: \fBpractcl::metaclass\fR
.PP
A build deliverable object\&. Normally an object file, header, or tcl script
which must be compiled or generated in some way
.PP
\fBMethods\fR
.TP
method \fBconstructor\fR \fImodule_object\fR \fIname\fR \fIinfo\fR ?\fIaction_body\fR \fB\fR?
.TP
method \fBdo\fR
.TP
method \fBcheck\fR
.TP
method \fBoutput\fR
.TP
method \fBreset\fR
.TP
method \fBtriggers\fR
.PP
.PP
.SS "CLASS  PRACTCL::OBJECT"
\fIancestors\fR: \fBpractcl::metaclass\fR
.PP
A generic Practcl object
.PP
\fBMethods\fR
.TP
method \fBconstructor\fR \fIparent\fR ?\fIargs\fR?
.TP
method \fBchild\fR \fImethod\fR
.TP
method \fBgo\fR
.PP
.PP
.SS "CLASS  PRACTCL::DYNAMIC"
Dynamic blocks do not generate their own \&.c files,
instead the contribute to the amalgamation
of the main library file
.PP
\fBMethods\fR
.TP
method \fBcstructure\fR \fIname\fR \fIdefinition\fR ?\fIargdat\fR \fB\fR?
Parser functions
.TP
method \fBinclude\fR \fIheader\fR
.TP
method \fBinclude_dir\fR ?\fIargs\fR?
.TP
method \fBinclude_directory\fR ?\fIargs\fR?
.TP
method \fBc_header\fR \fIbody\fR
.TP
method \fBc_code\fR \fIbody\fR
.TP
method \fBc_function\fR \fIheader\fR \fIbody\fR ?\fIinfo\fR \fB\fR?
.TP
method \fBc_tcloomethod\fR \fIname\fR \fIbody\fR ?\fIarginfo\fR \fB\fR?
.TP
method \fBcmethod\fR \fIname\fR \fIbody\fR ?\fIarginfo\fR \fB\fR?
Alias to classic name
.TP
method \fBc_tclproc_nspace\fR \fInspace\fR
.TP
method \fBc_tclcmd\fR \fIname\fR \fIbody\fR ?\fIarginfo\fR \fB\fR?
.TP
method \fBc_tclproc_raw\fR \fIname\fR \fIbody\fR ?\fIarginfo\fR \fB\fR?
Alias to classic name
.TP
method \fBtcltype\fR \fIname\fR \fIargdat\fR
.TP
method \fBproject-compile-products\fR
Module interactions
.TP
method \fBimplement\fR \fIpath\fR
.TP
method \fBinitialize\fR
Practcl internals
.TP
method \fBlinktype\fR
.TP
method \fBgenerate-cfile-constant\fR
.TP
method \fBgenerate-cfile-header\fR
.TP
method \fBgenerate-cfile-tclapi\fR
Generate code that provides implements Tcl API
calls
.TP
method \fBgenerate-loader-module\fR
Generate code that runs when the package/module is
initialized into the interpreter
.TP
method \fBCollate_Source\fR \fICWD\fR
.TP
method \fBselect\fR
Once an object marks itself as some
flavor of dynamic, stop trying to morph
it into something else
.PP
.PP
.SS "CLASS  PRACTCL::PRODUCT"
A deliverable for the build system
.PP
\fBClass Methods\fR
.TP
classmethod \fBselect\fR \fIobject\fR
.PP
.PP
\fBMethods\fR
.TP
method \fBcode\fR \fIsection\fR \fIbody\fR
.TP
method \fBCollate_Source\fR \fICWD\fR
.TP
method \fBproject-compile-products\fR
.TP
method \fBgenerate-debug\fR ?\fIspaces\fR \fB\fR?
.TP
method \fBgenerate-cfile-constant\fR
.TP
method \fBgenerate-cfile-public-structure\fR
Populate const static data structures
.TP
method \fBgenerate-cfile-header\fR
.TP
method \fBgenerate-cfile-global\fR
.TP
method \fBgenerate-cfile-private-typedef\fR
.TP
method \fBgenerate-cfile-private-structure\fR
.TP
method \fBgenerate-cfile-functions\fR
Generate code that provides subroutines called by
Tcl API methods
.TP
method \fBgenerate-cfile-tclapi\fR
Generate code that provides implements Tcl API
calls
.TP
method \fBgenerate-hfile-public-define\fR
.TP
method \fBgenerate-hfile-public-macro\fR
.TP
method \fBgenerate-hfile-public-typedef\fR
.TP
method \fBgenerate-hfile-public-structure\fR
.TP
method \fBgenerate-hfile-public-headers\fR
.TP
method \fBgenerate-hfile-public-function\fR
.TP
method \fBgenerate-hfile-public-includes\fR
.TP
method \fBgenerate-hfile-public-verbatim\fR
.TP
method \fBgenerate-loader-external\fR
.TP
method \fBgenerate-loader-module\fR
.TP
method \fBgenerate-stub-function\fR
.TP
method \fBIncludeAdd\fR \fIheadervar\fR ?\fIargs\fR?
.TP
method \fBgenerate-tcl-loader\fR
.TP
method \fBgenerate-tcl-pre\fR
This methods generates any Tcl script file
which is required to pre-initialize the C library
.TP
method \fBgenerate-tcl-post\fR
.TP
method \fBlinktype\fR
.TP
method \fBOfile\fR \fIfilename\fR
.TP
method \fBproject-static-packages\fR
Methods called by the master project
.TP
method \fBtoolset-include-directory\fR
Methods called by the toolset
.TP
method \fBtarget\fR \fImethod\fR ?\fIargs\fR?
.PP
.PP
.SS "CLASS  PRACTCL::PRODUCT\&.CHEADER"
\fIancestors\fR: \fBpractcl::product\fR

.PP
A product which generated from a C header file\&. Which is to say, nothing\&.
.PP
\fBMethods\fR
.TP
method \fBproject-compile-products\fR
.TP
method \fBgenerate-loader-module\fR
.PP
.PP
.SS "CLASS  PRACTCL::PRODUCT\&.CSOURCE"
\fIancestors\fR: \fBpractcl::product\fR
.PP
A product which generated from a C source file\&. Normally an object (\&.o) file\&.
.PP
\fBMethods\fR
.TP
method \fBproject-compile-products\fR
.PP
.PP
.SS "CLASS  PRACTCL::PRODUCT\&.CLIBRARY"
\fIancestors\fR: \fBpractcl::product\fR
.PP
A product which is generated from a compiled C library\&.
Usually a \&.a or a \&.dylib file, but in complex cases may
actually just be a conduit for one project to integrate the
source code of another
.PP
\fBMethods\fR
.TP
method \fBlinker-products\fR \fIconfigdict\fR
.PP
.PP
.SS "CLASS  PRACTCL::PRODUCT\&.DYNAMIC"
\fIancestors\fR: \fBpractcl::dynamic\fR \fBpractcl::product\fR
.PP
A product which is generated from C code that itself is generated
by practcl or some other means\&. This C file may or may not produce
its own \&.o file, depending on whether it is eligible to become part
of an amalgamation
.PP
\fBMethods\fR
.TP
method \fBinitialize\fR
.PP
.PP
.SS "CLASS  PRACTCL::PRODUCT\&.CRITCL"
\fIancestors\fR: \fBpractcl::dynamic\fR \fBpractcl::product\fR
.PP
A binary product produced by critcl\&. Note: The implementation is not
written yet, this class does nothing\&.
.PP
.SS "CLASS  PRACTCL::MODULE"
\fIancestors\fR: \fBpractcl::object\fR \fBpractcl::product\&.dynamic\fR
.PP
In the end, all C code must be loaded into a module
This will either be a dynamically loaded library implementing
a tcl extension, or a compiled in segment of a custom shell/app
.PP
\fBVariable\fR
.TP
variable \fBmake_object\fR
.PP
.PP
\fBMethods\fR
.TP
method \fB_MorphPatterns\fR
.TP
method \fBadd\fR ?\fIargs\fR?
.TP
method \fBinstall-headers\fR ?\fIargs\fR?
.TP
method \fBmake {} _preamble\fR
.TP
method \fBmake {} pkginfo\fR
.TP
method \fBmake {} objects\fR
Return a dictionary of all handles and associated objects
.TP
method \fBmake {} object\fR \fIname\fR
Return the object associated with handle \fIname\fR
.TP
method \fBmake {} reset\fR
Reset all deputy objects
.TP
method \fBmake {} trigger\fR ?\fIargs\fR?
Exercise the triggers method for all handles listed
.TP
method \fBmake {} depends\fR ?\fIargs\fR?
Exercise the check method for all handles listed
.TP
method \fBmake {} filename\fR \fIname\fR
Return the file name of the build product for the listed
handle
.TP
method \fBmake {} target\fR \fIname\fR \fIInfo\fR \fIbody\fR
.TP
method \fBmake {} todo\fR
Return a list of handles for object which return true for the
do method
.TP
method \fBmake {} do\fR
For each target exercise the action specified in the \fIaction\fR
definition if the \fIdo\fR method returns true
.TP
method \fBchild\fR \fIwhich\fR
.TP
method \fBgenerate-c\fR
This methods generates the contents of an amalgamated \&.c file
which implements the loader for a batch of tools
.TP
method \fBgenerate-h\fR
This methods generates the contents of an amalgamated \&.h file
which describes the public API of this module
.TP
method \fBgenerate-loader\fR
.TP
method \fBinitialize\fR
.TP
method \fBimplement\fR \fIpath\fR
.TP
method \fBlinktype\fR
.PP
.PP
.SS "CLASS  PRACTCL::PROJECT"
\fIancestors\fR: \fBpractcl::module\fR
.PP
A toplevel project that is a collection of other projects
.PP
\fBMethods\fR
.TP
method \fB_MorphPatterns\fR
.TP
method \fBconstructor\fR ?\fIargs\fR?
.TP
method \fBadd_object\fR \fIobject\fR
.TP
method \fBadd_project\fR \fIpkg\fR \fIinfo\fR ?\fIoodefine\fR \fB\fR?
.TP
method \fBadd_tool\fR \fIpkg\fR \fIinfo\fR ?\fIoodefine\fR \fB\fR?
.TP
method \fBbuild-tclcore\fR
Compile the Tcl core\&. If the define \fItk\fR is true, compile the
Tk core as well
.TP
method \fBchild\fR \fIwhich\fR
.TP
method \fBlinktype\fR
.TP
method \fBproject\fR \fIpkg\fR ?\fIargs\fR?
Exercise the methods of a sub-object
.TP
method \fBtclcore\fR
.TP
method \fBtkcore\fR
.TP
method \fBtool\fR \fIpkg\fR ?\fIargs\fR?
.PP
.PP
.SS "CLASS  PRACTCL::LIBRARY"
\fIancestors\fR: \fBpractcl::project\fR
.PP
A toplevel project that produces a library
.PP
\fBMethods\fR
.TP
method \fBclean\fR \fIPATH\fR
.TP
method \fBproject-compile-products\fR
.TP
method \fBgo\fR
.TP
method \fBgenerate-decls\fR \fIpkgname\fR \fIpath\fR
.TP
method \fBimplement\fR \fIpath\fR
.TP
method \fBgenerate-make\fR \fIpath\fR
Backward compadible call
.TP
method \fBlinktype\fR
.TP
method \fBpackage-ifneeded\fR ?\fIargs\fR?
Create a "package ifneeded"
Args are a list of aliases for which this package will answer to
.TP
method \fBshared_library\fR ?\fIfilename\fR \fB\fR?
.TP
method \fBstatic_library\fR ?\fIfilename\fR \fB\fR?
.PP
.PP
.SS "CLASS  PRACTCL::TCLKIT"
\fIancestors\fR: \fBpractcl::library\fR
.PP
A toplevel project that produces a self-contained executable
.PP
\fBMethods\fR
.TP
method \fBbuild-tclkit_main\fR \fIPROJECT\fR \fIPKG_OBJS\fR
.TP
method \fBCollate_Source\fR \fICWD\fR
.TP
method \fBwrap\fR \fIPWD\fR \fIexename\fR \fIvfspath\fR ?\fIargs\fR?
Wrap an executable
.PP
.PP
.SS "CLASS  PRACTCL::DISTRIBUTION"
Standalone class to manage code distribution
This class is intended to be mixed into another class
(Thus the lack of ancestors)
.PP
\fBClass Methods\fR
.TP
classmethod \fBSandbox\fR \fIobject\fR
.TP
classmethod \fBselect\fR \fIobject\fR
.TP
classmethod \fBclaim_option\fR
.TP
classmethod \fBclaim_object\fR \fIobject\fR
.TP
classmethod \fBclaim_path\fR \fIpath\fR
.PP
.PP
\fBMethods\fR
.TP
method \fBscm_info\fR
.TP
method \fBDistroMixIn\fR
.TP
method \fBSandbox\fR
.TP
method \fBSrcDir\fR
.TP
method \fBScmTag\fR
.TP
method \fBScmClone\fR
.TP
method \fBScmUnpack\fR
.TP
method \fBScmUpdate\fR
.TP
method \fBUnpack\fR
.PP
.PP
.SS "CLASS  PRACTCL::DISTRIBUTION\&.SNAPSHOT"
\fIancestors\fR: \fBpractcl::distribution\fR
.PP
A file distribution from zip, tarball, or other non-scm archive format
.PP
\fBClass Methods\fR
.TP
classmethod \fBclaim_object\fR \fIobject\fR
.TP
classmethod \fBclaim_option\fR
.TP
classmethod \fBclaim_path\fR \fIpath\fR
.PP
.PP
\fBMethods\fR
.TP
method \fBScmUnpack\fR
.PP
.PP
.SS "CLASS  PRACTCL::DISTRIBUTION\&.FOSSIL"
\fIancestors\fR: \fBpractcl::distribution\fR
.PP
A file distribution based on fossil
.PP
\fBClass Methods\fR
.TP
classmethod \fBclaim_object\fR \fIobj\fR
Check for markers in the metadata
.TP
classmethod \fBclaim_option\fR
.TP
classmethod \fBclaim_path\fR \fIpath\fR
Check for markers in the source root
.PP
.PP
\fBMethods\fR
.TP
method \fBscm_info\fR
.TP
method \fBScmClone\fR
Clone the source
.TP
method \fBScmTag\fR
.TP
method \fBScmUnpack\fR
.TP
method \fBScmUpdate\fR
.PP
.PP
.SS "CLASS  PRACTCL::DISTRIBUTION\&.GIT"
\fIancestors\fR: \fBpractcl::distribution\fR
.PP
A file distribution based on git
.PP
\fBClass Methods\fR
.TP
classmethod \fBclaim_object\fR \fIobj\fR
.TP
classmethod \fBclaim_option\fR
.TP
classmethod \fBclaim_path\fR \fIpath\fR
.PP
.PP
\fBMethods\fR
.TP
method \fBScmTag\fR
.TP
method \fBScmUnpack\fR
.TP
method \fBScmUpdate\fR
.PP
.PP
.SS "CLASS  PRACTCL::SUBPROJECT"
\fIancestors\fR: \fBpractcl::module\fR
.PP
A subordinate project
.PP
\fBMethods\fR
.TP
method \fB_MorphPatterns\fR
.TP
method \fBBuildDir\fR \fIPWD\fR
.TP
method \fBchild\fR \fIwhich\fR
.TP
method \fBcompile\fR
.TP
method \fBgo\fR
.TP
method \fBinstall\fR ?\fIargs\fR?
Install project into the local build system
.TP
method \fBlinktype\fR
.TP
method \fBlinker-products\fR \fIconfigdict\fR
.TP
method \fBlinker-external\fR \fIconfigdict\fR
.TP
method \fBlinker-extra\fR \fIconfigdict\fR
.TP
method \fBenv-bootstrap\fR
Methods for packages/tools that can be downloaded
possibly built and used internally by this Practcl
process
Load the facility into the interpreter
.TP
method \fBenv-exec\fR
Return a file path that exec can call
.TP
method \fBenv-install\fR
Install the tool into the local environment
.TP
method \fBenv-load\fR
Do whatever is necessary to get the tool
into the local environment
.TP
method \fBenv-present\fR
Check if tool is available for load/already loaded
.TP
method \fBsources\fR
.TP
method \fBupdate\fR
.TP
method \fBunpack\fR
.PP
.PP
.SS "CLASS  PRACTCL::SUBPROJECT\&.SOURCE"
\fIancestors\fR: \fBpractcl::subproject\fR \fBpractcl::library\fR
.PP
A project which the kit compiles and integrates
the source for itself
.PP
\fBMethods\fR
.TP
method \fBenv-bootstrap\fR
.TP
method \fBenv-present\fR
.TP
method \fBlinktype\fR
.PP
.PP
.SS "CLASS  PRACTCL::SUBPROJECT\&.TEAPOT"
\fIancestors\fR: \fBpractcl::subproject\fR
.PP
a copy from the teapot
.PP
\fBMethods\fR
.TP
method \fBenv-bootstrap\fR
.TP
method \fBenv-install\fR
.TP
method \fBenv-present\fR
.TP
method \fBinstall\fR \fIDEST\fR
.PP
.PP
.SS "CLASS  PRACTCL::SUBPROJECT\&.KETTLE"
\fIancestors\fR: \fBpractcl::subproject\fR
.PP
.PP
\fBMethods\fR
.TP
method \fBkettle\fR \fIpath\fR ?\fIargs\fR?
.TP
method \fBinstall\fR \fIDEST\fR
.PP
.PP
.SS "CLASS  PRACTCL::SUBPROJECT\&.CRITCL"
\fIancestors\fR: \fBpractcl::subproject\fR
.PP
.PP
\fBMethods\fR
.TP
method \fBinstall\fR \fIDEST\fR
.PP
.PP
.SS "CLASS  PRACTCL::SUBPROJECT\&.SAK"
\fIancestors\fR: \fBpractcl::subproject\fR
.PP
.PP
\fBMethods\fR
.TP
method \fBenv-bootstrap\fR
.TP
method \fBenv-install\fR
.TP
method \fBenv-present\fR
.TP
method \fBinstall\fR \fIDEST\fR
.TP
method \fBinstall-module\fR \fIDEST\fR ?\fIargs\fR?
.PP
.PP
.SS "CLASS  PRACTCL::SUBPROJECT\&.PRACTCL"
\fIancestors\fR: \fBpractcl::subproject\fR
.PP
.PP
\fBMethods\fR
.TP
method \fBenv-bootstrap\fR
.TP
method \fBenv-install\fR
.TP
method \fBinstall\fR \fIDEST\fR
.TP
method \fBinstall-module\fR \fIDEST\fR ?\fIargs\fR?
.PP
.PP
.SS "CLASS  PRACTCL::SUBPROJECT\&.BINARY"
\fIancestors\fR: \fBpractcl::subproject\fR
.PP
A subordinate binary package
.PP
\fBMethods\fR
.TP
method \fBclean\fR
.TP
method \fBenv-install\fR
.TP
method \fBproject-compile-products\fR
.TP
method \fBComputeInstall\fR
.TP
method \fBgo\fR
.TP
method \fBlinker-products\fR \fIconfigdict\fR
.TP
method \fBproject-static-packages\fR
.TP
method \fBBuildDir\fR \fIPWD\fR
.TP
method \fBcompile\fR
.TP
method \fBConfigure\fR
.TP
method \fBinstall\fR \fIDEST\fR
.PP
.PP
.SS "CLASS  PRACTCL::SUBPROJECT\&.TEA"
\fIancestors\fR: \fBpractcl::subproject\&.binary\fR
.PP
A subordinate TEA based binary package
.PP
.SS "CLASS  PRACTCL::SUBPROJECT\&.LIBRARY"
\fIancestors\fR: \fBpractcl::subproject\&.binary\fR \fBpractcl::library\fR
.PP
A subordinate C library built by this project
.PP
\fBMethods\fR
.TP
method \fBinstall\fR \fIDEST\fR
.PP
.PP
.SS "CLASS  PRACTCL::SUBPROJECT\&.EXTERNAL"
\fIancestors\fR: \fBpractcl::subproject\&.binary\fR
.PP
A subordinate external C library
.PP
\fBMethods\fR
.TP
method \fBinstall\fR \fIDEST\fR
.PP
.PP
.SS "CLASS  PRACTCL::SUBPROJECT\&.CORE"
\fIancestors\fR: \fBpractcl::subproject\&.binary\fR
.PP
.PP
\fBMethods\fR
.TP
method \fBenv-bootstrap\fR
.TP
method \fBenv-present\fR
.TP
method \fBenv-install\fR
.TP
method \fBgo\fR
.TP
method \fBlinktype\fR
.PP
.PP
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fIpractcl\fR of the
\fITcllib Trackers\fR [http://core\&.tcl\&.tk/tcllib/reportlist]\&.
Please also report any ideas for enhancements you may have for either

Changes to idoc/man/files/modules/profiler/profiler.n.

1
2
3
4
5
6
7
8
9
10
11
'\"
'\" Generated from file 'profiler\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "profiler" n 0\&.3 tcllib "Tcl Profiler"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,



|







1
2
3
4
5
6
7
8
9
10
11
'\"
'\" Generated from file 'profiler\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "profiler" n 0\&.5 tcllib "Tcl Profiler"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
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
..
.BS
.SH NAME
profiler \- Tcl source code profiler
.SH SYNOPSIS
package require \fBTcl  8\&.3\fR
.sp
package require \fBprofiler  ?0\&.3?\fR
.sp
\fB::profiler::init\fR
.sp
\fB::profiler::dump\fR \fIpattern\fR
.sp
\fB::profiler::print\fR ?\fIpattern\fR?
.sp
\fB::profiler::reset\fR ?\fIpattern\fR?
.sp
\fB::profiler::suspend\fR ?\fIpattern\fR?
.sp
\fB::profiler::resume\fR ?\fIpattern\fR?




.sp
\fB::profiler::sortFunctions\fR \fIkey\fR
.sp
.BE
.SH DESCRIPTION
.PP
The \fBprofiler\fR package provides a simple Tcl source code







|












>
>
>
>







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
..
.BS
.SH NAME
profiler \- Tcl source code profiler
.SH SYNOPSIS
package require \fBTcl  8\&.3\fR
.sp
package require \fBprofiler  ?0\&.5?\fR
.sp
\fB::profiler::init\fR
.sp
\fB::profiler::dump\fR \fIpattern\fR
.sp
\fB::profiler::print\fR ?\fIpattern\fR?
.sp
\fB::profiler::reset\fR ?\fIpattern\fR?
.sp
\fB::profiler::suspend\fR ?\fIpattern\fR?
.sp
\fB::profiler::resume\fR ?\fIpattern\fR?
.sp
\fB::profiler::new-disabled\fR
.sp
\fB::profiler::new-enabled\fR
.sp
\fB::profiler::sortFunctions\fR \fIkey\fR
.sp
.BE
.SH DESCRIPTION
.PP
The \fBprofiler\fR package provides a simple Tcl source code
361
362
363
364
365
366
367












368
369
370
371
372
373
374
.TP
\fB::profiler::resume\fR ?\fIpattern\fR?
Resume profiling for all functions matching \fIpattern\fR\&.  If no
pattern is specified, profiling will be resumed for all functions\&.
This command should be invoked after suspending the profiler in the
code\&.
.TP












\fB::profiler::sortFunctions\fR \fIkey\fR
Return a list of functions sorted by a particular profiling statistic\&.
Supported values for \fIkey\fR are: \fBcalls\fR,
\fBexclusiveTime\fR, \fBcompileTime\fR, \fBnonCompileTime\fR,
\fBtotalRuntime\fR, \fBavgExclusiveTime\fR, and
\fBavgRuntime\fR\&.  The return result is a list of lists, where each
sublist consists of a function name and the value of \fIkey\fR for







>
>
>
>
>
>
>
>
>
>
>
>







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
.TP
\fB::profiler::resume\fR ?\fIpattern\fR?
Resume profiling for all functions matching \fIpattern\fR\&.  If no
pattern is specified, profiling will be resumed for all functions\&.
This command should be invoked after suspending the profiler in the
code\&.
.TP
\fB::profiler::new-disabled\fR
Change the initial profiling state for new procedures\&. Invoking this
command disables profiling for all procedures created after this
command until \fBnew-enabled\fR is invoked\&. Activate profiling of
specific procedures via \fBresume\fR\&.
.TP
\fB::profiler::new-enabled\fR
Change the initial profiling state for new procedures\&. Invoking this
command enables profiling for all procedures created after this
command until \fBnew-disabled\fR is invoked\&. Prevent profiling of
specific procedures via \fBsuspend\fR\&.
.TP
\fB::profiler::sortFunctions\fR \fIkey\fR
Return a list of functions sorted by a particular profiling statistic\&.
Supported values for \fIkey\fR are: \fBcalls\fR,
\fBexclusiveTime\fR, \fBcompileTime\fR, \fBnonCompileTime\fR,
\fBtotalRuntime\fR, \fBavgExclusiveTime\fR, and
\fBavgRuntime\fR\&.  The return result is a list of lists, where each
sublist consists of a function name and the value of \fIkey\fR for

Changes to idoc/man/files/modules/pt/pt_peg_export.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'pt_peg_export\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "pt::peg::export" n 1 tcllib "Parser Tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'pt_peg_export\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "pt::peg::export" n 1\&.0\&.1 tcllib "Parser Tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
.SH NAME
pt::peg::export \- PEG Export
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBsnit \fR
.sp
package require \fBconfiguration \fR
.sp
package require \fBpt::peg \fR
.sp
package require \fBpluginmgr \fR
.sp
package require \fBpt::peg::export  ?1?\fR
.sp
\fB::pt::peg::export\fR \fIobjectName\fR
.sp
\fBobjectName\fR \fBmethod\fR ?\fIarg arg \&.\&.\&.\fR?
.sp
\fIobjectName\fR \fBdestroy\fR
.sp







|





|







274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
.SH NAME
pt::peg::export \- PEG Export
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBsnit \fR
.sp
package require \fBstruct::map \fR
.sp
package require \fBpt::peg \fR
.sp
package require \fBpluginmgr \fR
.sp
package require \fBpt::peg::export  ?1\&.0\&.1?\fR
.sp
\fB::pt::peg::export\fR \fIobjectName\fR
.sp
\fBobjectName\fR \fBmethod\fR ?\fIarg arg \&.\&.\&.\fR?
.sp
\fIobjectName\fR \fBdestroy\fR
.sp

Changes to idoc/man/files/modules/pt/pt_peg_import.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'pt_peg_import\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "pt::peg::import" n 1 tcllib "Parser Tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'pt_peg_import\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "pt::peg::import" n 1\&.0\&.1 tcllib "Parser Tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
272
273
274
275
276
277
278
279
280
281


282
283
284
285
286
287
288
289
290
291
292
293
294
..
.BS
.SH NAME
pt::peg::import \- PEG Import
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBsnit \fR
.sp
package require \fBconfiguration \fR


.sp
package require \fBpt::peg \fR
.sp
package require \fBpluginmgr \fR
.sp
package require \fBpt::peg::import  ?1?\fR
.sp
\fB::pt::peg::import\fR \fIobjectName\fR
.sp
\fBobjectName\fR \fBmethod\fR ?\fIarg arg \&.\&.\&.\fR?
.sp
\fIobjectName\fR \fBdestroy\fR
.sp







|

|
>
>





|







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
..
.BS
.SH NAME
pt::peg::import \- PEG Import
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBTcl  8\&.5\fR
.sp
package require \fBsnit \fR
.sp
package require \fBfileutil::paths \fR
.sp
package require \fBpt::peg \fR
.sp
package require \fBpluginmgr \fR
.sp
package require \fBpt::peg::import  ?1\&.0\&.1?\fR
.sp
\fB::pt::peg::import\fR \fIobjectName\fR
.sp
\fBobjectName\fR \fBmethod\fR ?\fIarg arg \&.\&.\&.\fR?
.sp
\fIobjectName\fR \fBdestroy\fR
.sp

Changes to idoc/man/files/modules/sha1/sha1.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'sha1\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2005, Pat Thoyts <patthoyts@users\&.sourceforge\&.net>
'\"
.TH "sha1" n 2\&.0\&.3 tcllib "SHA-x Message-Digest Algorithm"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'sha1\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2005, Pat Thoyts <patthoyts@users\&.sourceforge\&.net>
'\"
.TH "sha1" n 2\&.0\&.4 tcllib "SHA-x Message-Digest Algorithm"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
sha1 \- SHA1 Message-Digest Algorithm
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBsha1  ?2\&.0\&.3?\fR
.sp
\fB::sha1::sha1\fR ?\fB-hex|-bin\fR? [ \fB-channel channel\fR | \fB-file filename\fR | ?\fB--\fR? \fIstring\fR ]
.sp
\fB::sha1::hmac\fR \fIkey\fR \fIstring\fR
.sp
\fB::sha1::hmac\fR ?\fB-hex|-bin\fR? \fB-key key\fR [ \fB-channel channel\fR | \fB-file filename\fR | ?\fB--\fR? \fIstring\fR ]
.sp







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
sha1 \- SHA1 Message-Digest Algorithm
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBsha1  ?2\&.0\&.4?\fR
.sp
\fB::sha1::sha1\fR ?\fB-hex|-bin\fR? [ \fB-channel channel\fR | \fB-file filename\fR | ?\fB--\fR? \fIstring\fR ]
.sp
\fB::sha1::hmac\fR \fIkey\fR \fIstring\fR
.sp
\fB::sha1::hmac\fR ?\fB-hex|-bin\fR? \fB-key key\fR [ \fB-channel channel\fR | \fB-file filename\fR | ?\fB--\fR? \fIstring\fR ]
.sp

Changes to idoc/man/files/modules/sha1/sha256.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'sha256\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2008, Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "sha256" n 1\&.0\&.3 tcllib "SHA-x Message-Digest Algorithm"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'sha256\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2008, Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "sha256" n 1\&.0\&.4 tcllib "SHA-x Message-Digest Algorithm"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
sha256 \- SHA256 Message-Digest Algorithm
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBsha256  ?1\&.0\&.3?\fR
.sp
\fB::sha2::sha256\fR ?\fB-hex|-bin\fR? [ \fB-channel channel\fR | \fB-file filename\fR | ?\fB--\fR? \fIstring\fR ]
.sp
\fB::sha2::sha224\fR ?\fB-hex|-bin\fR? [ \fB-channel channel\fR | \fB-file filename\fR | ?\fB--\fR? \fIstring\fR ]
.sp
\fB::sha2::hmac\fR \fIkey\fR \fIstring\fR
.sp







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
sha256 \- SHA256 Message-Digest Algorithm
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBsha256  ?1\&.0\&.4?\fR
.sp
\fB::sha2::sha256\fR ?\fB-hex|-bin\fR? [ \fB-channel channel\fR | \fB-file filename\fR | ?\fB--\fR? \fIstring\fR ]
.sp
\fB::sha2::sha224\fR ?\fB-hex|-bin\fR? [ \fB-channel channel\fR | \fB-file filename\fR | ?\fB--\fR? \fIstring\fR ]
.sp
\fB::sha2::hmac\fR \fIkey\fR \fIstring\fR
.sp

Changes to idoc/man/files/modules/simulation/simulation_random.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'simulation_random\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2004 Arjen Markus <arjenmarkus@users\&.sourceforge\&.net>
'\"
.TH "simulation::random" n 0\&.1 tcllib "Tcl Simulation Tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'simulation_random\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2004 Arjen Markus <arjenmarkus@users\&.sourceforge\&.net>
'\"
.TH "simulation::random" n 0\&.4 tcllib "Tcl Simulation Tools"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288




289
290
291
292
293
294
295
..
.BS
.SH NAME
simulation::random \- Pseudo-random number generators
.SH SYNOPSIS
package require \fBTcl  ?8\&.4?\fR
.sp
package require \fBsimulation::random  0\&.1\fR
.sp
\fB::simulation::random::prng_Bernoulli\fR \fIp\fR
.sp
\fB::simulation::random::prng_Discrete\fR \fIn\fR
.sp
\fB::simulation::random::prng_Poisson\fR \fIlambda\fR
.sp
\fB::simulation::random::prng_Uniform\fR \fImin\fR \fImax\fR
.sp




\fB::simulation::random::prng_Exponential\fR \fImin\fR \fImean\fR
.sp
\fB::simulation::random::prng_Normal\fR \fImean\fR \fIstdev\fR
.sp
\fB::simulation::random::prng_Pareto\fR \fImin\fR \fIsteep\fR
.sp
\fB::simulation::random::prng_Gumbel\fR \fImin\fR \fIf\fR







|









>
>
>
>







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
..
.BS
.SH NAME
simulation::random \- Pseudo-random number generators
.SH SYNOPSIS
package require \fBTcl  ?8\&.4?\fR
.sp
package require \fBsimulation::random  0\&.4\fR
.sp
\fB::simulation::random::prng_Bernoulli\fR \fIp\fR
.sp
\fB::simulation::random::prng_Discrete\fR \fIn\fR
.sp
\fB::simulation::random::prng_Poisson\fR \fIlambda\fR
.sp
\fB::simulation::random::prng_Uniform\fR \fImin\fR \fImax\fR
.sp
\fB::simulation::random::prng_Triangular\fR \fImin\fR \fImax\fR
.sp
\fB::simulation::random::prng_SymmTriangular\fR \fImin\fR \fImax\fR
.sp
\fB::simulation::random::prng_Exponential\fR \fImin\fR \fImean\fR
.sp
\fB::simulation::random::prng_Normal\fR \fImean\fR \fIstdev\fR
.sp
\fB::simulation::random::prng_Pareto\fR \fImin\fR \fIsteep\fR
.sp
\fB::simulation::random::prng_Gumbel\fR \fImin\fR \fIf\fR
362
363
364
365
366
367
368




























369
370
371
372
373
374
375
.PP
The package defines the following public procedures for \fIcontinuous\fR distributions:
.TP
\fB::simulation::random::prng_Uniform\fR \fImin\fR \fImax\fR
Create a command (PRNG) that generates uniformly distributed numbers
between "min" and "max"\&.
.RS




























.TP
float \fImin\fR
Minimum number that will be generated
.TP
float \fImax\fR
Maximum number that will be generated
.RE







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
.PP
The package defines the following public procedures for \fIcontinuous\fR distributions:
.TP
\fB::simulation::random::prng_Uniform\fR \fImin\fR \fImax\fR
Create a command (PRNG) that generates uniformly distributed numbers
between "min" and "max"\&.
.RS
.TP
float \fImin\fR
Minimum number that will be generated
.TP
float \fImax\fR
Maximum number that will be generated
.RE
.sp
.TP
\fB::simulation::random::prng_Triangular\fR \fImin\fR \fImax\fR
Create a command (PRNG) that generates triangularly distributed numbers
between "min" and "max"\&. If the argument min is lower than the argument max, then smaller
values have higher probability and vice versa\&. In the first case the probability
density function is of the form \fIf(x) = 2(1-x)\fR and the other case it is of the form \fIf(x) = 2x\fR\&.
.RS
.TP
float \fImin\fR
Minimum number that will be generated
.TP
float \fImax\fR
Maximum number that will be generated
.RE
.sp
.TP
\fB::simulation::random::prng_SymmTriangular\fR \fImin\fR \fImax\fR
Create a command (PRNG) that generates numbers distributed according to a symmetric triangle
around the mean of "min" and "max"\&.
.RS
.TP
float \fImin\fR
Minimum number that will be generated
.TP
float \fImax\fR
Maximum number that will be generated
.RE

Changes to idoc/man/files/modules/struct/graph.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'graph\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2002-2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "struct::graph" n 2\&.4\&.1 tcllib "Tcl Data Structures"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,


|

|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'graph\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2002-2009,2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "struct::graph" n 2\&.4\&.3 tcllib "Tcl Data Structures"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
struct::graph \- Create and manipulate directed graph objects
.SH SYNOPSIS
package require \fBTcl  8\&.4\fR
.sp
package require \fBstruct::graph  ?2\&.4\&.1?\fR
.sp
package require \fBstruct::list  ?1\&.5?\fR
.sp
package require \fBstruct::set  ?2\&.2\&.3?\fR
.sp
\fB::struct::graph\fR ?\fIgraphName\fR? ?\fB=\fR|\fB:=\fR|\fBas\fR|\fBdeserialize\fR \fIsource\fR?
.sp







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
struct::graph \- Create and manipulate directed graph objects
.SH SYNOPSIS
package require \fBTcl  8\&.4\fR
.sp
package require \fBstruct::graph  ?2\&.4\&.3?\fR
.sp
package require \fBstruct::list  ?1\&.5?\fR
.sp
package require \fBstruct::set  ?2\&.2\&.3?\fR
.sp
\fB::struct::graph\fR ?\fIgraphName\fR? ?\fB=\fR|\fB:=\fR|\fBas\fR|\fBdeserialize\fR \fIsource\fR?
.sp
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
of returned arcs based on the nodes that are connected by the arc, on
the keyed values associated with the arc, or both\&. A general filter
command can be used as well\&. The restrictions that involve connected
nodes take a variable number of nodes as argument, specified after the
name of the restriction itself\&.
.sp
The restrictions imposed by either \fB-in\fR, \fB-out\fR,
\fB-adj\fR, \fB-inner\fR, or \fB-embedded\fR are applied
first\&. Specifying more than one of them is illegal\&.
.sp
After that the restrictions set via \fB-key\fR (and
\fB-value\fR) are applied\&. Specifying more than one \fB-key\fR
(and \fB-value\fR) is illegal\&. Specifying \fB-value\fR alone,
without \fB-key\fR is illegal as well\&.
.sp







|







723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
of returned arcs based on the nodes that are connected by the arc, on
the keyed values associated with the arc, or both\&. A general filter
command can be used as well\&. The restrictions that involve connected
nodes take a variable number of nodes as argument, specified after the
name of the restriction itself\&.
.sp
The restrictions imposed by either \fB-in\fR, \fB-out\fR,
\fB-adj\fR, \fB-inner\fR, or \fB-embedding\fR are applied
first\&. Specifying more than one of them is illegal\&.
.sp
After that the restrictions set via \fB-key\fR (and
\fB-value\fR) are applied\&. Specifying more than one \fB-key\fR
(and \fB-value\fR) is illegal\&. Specifying \fB-value\fR alone,
without \fB-key\fR is illegal as well\&.
.sp
762
763
764
765
766
767
768











769
770
771
772
773
774
775
the set\&. This is the set of arcs in the subgraph spawned by the
specified nodes\&.
.TP
\fB-embedding\fR
Return a list of all arcs adjacent to exactly one of the nodes in the
set\&. This is the set of arcs connecting the subgraph spawned by the
specified nodes to the rest of the graph\&.











.TP
\fB-key\fR \fIkey\fR
Limit the list of arcs that are returned to those arcs that have an
associated key \fIkey\fR\&.
.TP
\fB-value\fR \fIvalue\fR
This restriction can only be used in combination with







>
>
>
>
>
>
>
>
>
>
>







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
the set\&. This is the set of arcs in the subgraph spawned by the
specified nodes\&.
.TP
\fB-embedding\fR
Return a list of all arcs adjacent to exactly one of the nodes in the
set\&. This is the set of arcs connecting the subgraph spawned by the
specified nodes to the rest of the graph\&.
.RE
.IP
\fIAttention\fR: After the above options any word with a leading dash
which is not a valid option is treated as a node name instead of an
invalid option to error out on\&. This condition holds until either a
valid option terminates the list of nodes, or the end of the command
is reached, whichever comes first\&.
.sp
The remaining filter options are:
.sp
.RS
.TP
\fB-key\fR \fIkey\fR
Limit the list of arcs that are returned to those arcs that have an
associated key \fIkey\fR\&.
.TP
\fB-value\fR \fIvalue\fR
This restriction can only be used in combination with
892
893
894
895
896
897
898
899
900




901
902
903
904
905
906
907
908
\fIgraphName\fR \fBnodes\fR ?-key \fIkey\fR? ?-value \fIvalue\fR? ?-filter \fIcmdprefix\fR? ?-in|-out|-adj|-inner|-embedding \fInode\fR \fInode\fR\&.\&.\&.?
Return a list of nodes in the graph\&. Restrictions can limit the list
of returned nodes based on neighboring nodes, or based on the keyed
values associated with the node\&. The restrictions that involve
neighboring nodes have a list of nodes as argument, specified after
the name of the restriction itself\&.
.sp
The possible restrictions are the same as for method
\fBarcs\fR\&. The exact meanings change slightly, as they operate on




nodes instead of arcs\&. The command recognizes:
.RS
.TP
\fB-in\fR
Return a list of all nodes with at least one outgoing arc ending in a
node found in the specified set of nodes\&. Alternatively specified as
the set of source nodes for the \fB-in\fR arcs of the node set\&. The
\fIincoming neighbours\fR\&.







|
|
>
>
>
>
|







903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
\fIgraphName\fR \fBnodes\fR ?-key \fIkey\fR? ?-value \fIvalue\fR? ?-filter \fIcmdprefix\fR? ?-in|-out|-adj|-inner|-embedding \fInode\fR \fInode\fR\&.\&.\&.?
Return a list of nodes in the graph\&. Restrictions can limit the list
of returned nodes based on neighboring nodes, or based on the keyed
values associated with the node\&. The restrictions that involve
neighboring nodes have a list of nodes as argument, specified after
the name of the restriction itself\&.
.sp
The possible restrictions are the same as for method \fBarcs\fR\&.
Note that while the exact meanings change slightly, as they operate on
nodes instead of arcs, the general behaviour is the same, especially
when it comes to the handling of words with a leading dash in node
lists\&.
.sp
The command recognizes:
.RS
.TP
\fB-in\fR
Return a list of all nodes with at least one outgoing arc ending in a
node found in the specified set of nodes\&. Alternatively specified as
the set of source nodes for the \fB-in\fR arcs of the node set\&. The
\fIincoming neighbours\fR\&.
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
relevance, nor has the order of the arcs per node\&.
.CS


    # A possible serialization for the graph structure
    #
    #        d -----> %2
    #       /         ^ \\\\
    #      /         /   \\\\
    #     /         b     \\\\
    #    /         /       \\\\
    #  %1 <- a - %0         e
    #    ^         \\\\      /
    #     \\\\        c     /
    #      \\\\        \\\\  /
    #       \\\\        v v
    #        f ------ %3
    # is







|
|
|
|







1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
relevance, nor has the order of the arcs per node\&.
.CS


    # A possible serialization for the graph structure
    #
    #        d -----> %2
    #       /         ^ \\
    #      /         /   \\
    #     /         b     \\
    #    /         /       \\
    #  %1 <- a - %0         e
    #    ^         \\\\      /
    #     \\\\        c     /
    #      \\\\        \\\\  /
    #       \\\\        v v
    #        f ------ %3
    # is
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
adjacent, arc, cgraph, degree, edge, graph, loop, neighbour, node, serialization, subgraph, vertex
.SH CATEGORY
Data structures
.SH COPYRIGHT
.nf
Copyright (c) 2002-2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
adjacent, arc, cgraph, degree, edge, graph, loop, neighbour, node, serialization, subgraph, vertex
.SH CATEGORY
Data structures
.SH COPYRIGHT
.nf
Copyright (c) 2002-2009,2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/struct/matrix.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'matrix\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2002-2013 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "struct::matrix" n 2\&.0\&.3 tcllib "Tcl Data Structures"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,


|

|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'matrix\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2002-2013,2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "struct::matrix" n 2\&.0\&.4 tcllib "Tcl Data Structures"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
struct::matrix \- Create and manipulate matrix objects
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBstruct::matrix  ?2\&.0\&.3?\fR
.sp
\fB::struct::matrix\fR ?\fImatrixName\fR? ?\fB=\fR|\fB:=\fR|\fBas\fR|\fBdeserialize\fR \fIsource\fR?
.sp
\fBmatrixName\fR \fIoption\fR ?\fIarg arg \&.\&.\&.\fR?
.sp
\fImatrixName\fR \fB=\fR \fIsourcematrix\fR
.sp







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
struct::matrix \- Create and manipulate matrix objects
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBstruct::matrix  ?2\&.0\&.4?\fR
.sp
\fB::struct::matrix\fR ?\fImatrixName\fR? ?\fB=\fR|\fB:=\fR|\fBas\fR|\fBdeserialize\fR \fIsource\fR?
.sp
\fBmatrixName\fR \fIoption\fR ?\fIarg arg \&.\&.\&.\fR?
.sp
\fImatrixName\fR \fB=\fR \fIsourcematrix\fR
.sp
846
847
848
849
850
851
852
853
854
855
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
matrix
.SH CATEGORY
Data structures
.SH COPYRIGHT
.nf
Copyright (c) 2002-2013 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


846
847
848
849
850
851
852
853
854
855
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
matrix
.SH CATEGORY
Data structures
.SH COPYRIGHT
.nf
Copyright (c) 2002-2013,2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/struct/matrix1.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'matrix1\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2002 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "struct::matrix_v1" n 1\&.2\&.1 tcllib "Tcl Data Structures"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,


|

|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'matrix1\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2002,2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "struct::matrix_v1" n 1\&.2\&.2 tcllib "Tcl Data Structures"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
struct::matrix_v1 \- Create and manipulate matrix objects
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBstruct::matrix  ?1\&.2\&.1?\fR
.sp
\fBmatrixName\fR \fIoption\fR ?\fIarg arg \&.\&.\&.\fR?
.sp
\fImatrixName\fR \fBadd column\fR ?\fIvalues\fR?
.sp
\fImatrixName\fR \fBadd row\fR ?\fIvalues\fR?
.sp







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
struct::matrix_v1 \- Create and manipulate matrix objects
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBstruct::matrix  ?1\&.2\&.2?\fR
.sp
\fBmatrixName\fR \fIoption\fR ?\fIarg arg \&.\&.\&.\fR?
.sp
\fImatrixName\fR \fBadd column\fR ?\fIvalues\fR?
.sp
\fImatrixName\fR \fBadd row\fR ?\fIvalues\fR?
.sp
682
683
684
685
686
687
688
689
690
691
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
matrix
.SH CATEGORY
Data structures
.SH COPYRIGHT
.nf
Copyright (c) 2002 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


682
683
684
685
686
687
688
689
690
691
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
matrix
.SH CATEGORY
Data structures
.SH COPYRIGHT
.nf
Copyright (c) 2002,2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/struct/record.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'record\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2002, Brett Schwarz <brett_schwarz@yahoo\&.com>
'\"
.TH "struct::record" n 1\&.2\&.1 tcllib "Tcl Data Structures"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'record\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2002, Brett Schwarz <brett_schwarz@yahoo\&.com>
'\"
.TH "struct::record" n 1\&.2\&.2 tcllib "Tcl Data Structures"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
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
..
.BS
.SH NAME
struct::record \- Define and create records (similar to 'C' structures)
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBstruct::record  ?1\&.2\&.1?\fR
.sp
\fBrecord define\fR \fIrecordName\fR \fIrecordMembers\fR ?\fIinstanceName1 instanceName2 \&.\&.\&.\fR?
.sp
\fBrecord show\fR \fIrecord\fR
.sp
\fBrecord show\fR \fIinstances\fR \fIrecordName\fR
.sp
\fBrecord show\fR \fImembers\fR \fIrecordName\fR
.sp
\fBrecord show\fR \fIvalues\fR \fIinstanceName\fR
.sp
\fBrecord exists\fR \fIrecord\fR \fIrecordName\fR
.sp
\fBrecord exists\fR \fIinstance\fR \fIinstanceName\fR
.sp
\fBrecord delete\fR \fIrecord\fR \fIrecordName\fR
.sp
\fBrecord delete\fR \fIinstance\fR \fIinstanceName\fR
.sp














\fIrecordName\fR \fB\fIinstanceName|#auto\fR\fR ?\fI-member1 value1 -member2 value2 \&.\&.\&.\fR?
.sp
\fIinstanceName\fR \fBcget\fR ?\fI-member1 -member2 \&.\&.\&.\fR?
.sp
\fIinstanceName\fR \fBconfigure\fR ?\fI-member1 value1 -member2 value2 \&.\&.\&.\fR?
.sp
.BE
.SH DESCRIPTION
The \fB::struct::record\fR package provides a mechanism to group variables together
as one data structure, similar to a 'C' structure\&. The members of a

record can be variables or other records\&. However, a record can not contain circular
record, i\&.e\&. records that contain the same record as a
member\&.
.PP
This package was structured so that it is very similar to how Tk objects work\&. Each record

definition creates a record object that encompasses that definition\&. Subsequently, that
record object can create instances of that record\&. These instances can then
be manipulated with the \fBcget\fR and \fBconfigure\fR methods\&.
.PP
The package only contains one top level command, but several sub commands (see below)\&. It also obeys the namespace in which the record was define, hence the objects returned are fully qualified\&.


.TP
\fBrecord define\fR \fIrecordName\fR \fIrecordMembers\fR ?\fIinstanceName1 instanceName2 \&.\&.\&.\fR?
Defines a record\&. \fIrecordName\fR is the name of the record, and is also
used as an object command\&. This object command is used to create instances of the
record definition\&. \fIrecordMembers\fR are the members of
the record that make up the record definition\&. These are variables
and other record\&. If optional \fIinstanceName\fR args are given, then an instance

is generated after the definition is created for each \fIinstanceName\fR\&.
.TP
\fBrecord show\fR \fIrecord\fR
Returns a list of records that have been defined\&.
.TP
\fBrecord show\fR \fIinstances\fR \fIrecordName\fR
Returns the instances that have been instantiated by
\fIrecordName\fR\&.
.TP
\fBrecord show\fR \fImembers\fR \fIrecordName\fR
Returns the members that are defined for
record \fIrecordName\fR\&. It returns the same format as how the
records were defined\&.
.TP
\fBrecord show\fR \fIvalues\fR \fIinstanceName\fR
Returns a list of values that are set for the instance
\fIinstanceName\fR\&. The output is a list of key/value pairs\&. If there
are nested records, then the values of the nested records will
itself be a list\&.
.TP
\fBrecord exists\fR \fIrecord\fR \fIrecordName\fR
Tests for the existence of a \fIrecord\fR with the
name \fIrecordName\fR\&.
.TP
\fBrecord exists\fR \fIinstance\fR \fIinstanceName\fR
Tests for the existence of a \fIinstance\fR with the
name \fIinstanceName\fR\&.
.TP
\fBrecord delete\fR \fIrecord\fR \fIrecordName\fR
Deletes \fIrecordName\fR, and all instances of \fIrecordName\fR\&. It will return
an error if the record does not exist\&.
.TP
\fBrecord delete\fR \fIinstance\fR \fIinstanceName\fR
Deletes \fIinstance\fR with the name of \fIinstanceName\fR\&. It
will return an error if the instance does not exist\&.
.PP

.PP
.SH "RECORD MEMBERS"
Record members can either be variables, or other records, However, the
same record can not be nested witin itself (circular)\&. To define a
nested record, you need to specify the \fBrecord\fR keyword, along
the with name of the record, and the name of the instance of that
nested record\&. For example, it would look like this:

.PP
.CS


# this is the nested record
record define mynestedrecord {
    nest1
    nest2
}

# This is the main record
record define myrecord {
    mem1
    mem2
    {record mynestedrecord mem3}
}


.CE
You can also assign default or initial values to the members of a record,
by enclosing the member entry in braces:
.PP
.CS



record define myrecord {
    mem1
    {mem2 5}
}














































.CE
All instances created from this record definition, will initially have 5 as
the value for \fImem2\fR\&. If no default is given, then the value will be the empty string\&.
.PP
\fIGetting Values\fR
.PP
To get a value of a member, there are several ways to do this\&.
.IP [1]
To get a member value, then use the instance built-in \fBcget\fR method:
.sp
\fIinstanceName\fR \fBcget\fR -mem1
.IP [2]
To get multiple member values, you can specify them all in one command:
.sp
\fIinstanceName\fR \fBcget\fR -mem1 -mem2
.IP [3]
To get a list of the key/value of all of the members, there are 3 ways:
.sp
- \fIinstanceName\fR \fBcget\fR
.sp
- \fIinstanceName\fR \fBconfigure\fR
.sp
- \fIinstanceName\fR
.IP [4]
To get a value of a nested member, then use the dot notation:
.sp
\fIinstanceName\fR \fBcget\fR -mem3\&.nest1
.PP
.PP
\fISetting Values\fR
.PP
To set a value of a member, there are several ways to do this\&.
.IP [1]
To set a member value, then use the instance built-in \fBconfigure\fR method:
.sp
\fIinstanceName\fR \fBconfigure\fR -mem1 val1
.IP [2]
To set multiple member values, you can specify them all in one command:
.sp
\fIinstanceName\fR \fBconfigure\fR -mem1 va1 -mem2 val2
.IP [3]
To set a value of a nested member, then use the dot notation:
.sp
\fIinstanceName\fR \fBconfigure\fR -mem3\&.nest1 value
.PP
.PP
\fIAlias access\fR
.PP
In the original implementation, access was done by using dot notation similar to how 'C' structures are accessed\&. However,

there was a concensus to make the interface more Tcl like, which made sense\&. However, the original alias access still

exists\&. It might prove to be helpful to some\&.
.PP
Basically, for every member of every instance, an alias is created\&. This alias is used to get and set values for that

member\&. An example will illustrate the point, using the above defined records:
.PP
.CS


# Create an instance first
% myrecord inst1
::inst1

% # To get a member of an instance, just use the
% # alias (it behaves like a Tcl command):
% inst1\&.mem1
%
% # To set a member via the alias, just include
% # a value (optionally the equal sign - syntactic sugar)
% inst1\&.mem1 = 5
5

% inst1\&.mem1
5

% # For nested records, just continue with the
% # dot notation (note no equal sign)
% inst1\&.mem3\&.nest1 10
10

% inst1\&.mem3\&.nest1
10

% # just the instance by itself gives all
% # member/values pairs for that instance
% inst1
-mem1 5 -mem2 {} -mem3 {-nest1 10 -nest2 {}}

% # and to get all members within the nested record
% inst1\&.mem3
-nest1 10 -nest2 {}
%


.CE
.SH "RECORD COMMAND"
The following subcommands and corresponding arguments are available to any
record command:
.TP
\fIrecordName\fR \fB\fIinstanceName|#auto\fR\fR ?\fI-member1 value1 -member2 value2 \&.\&.\&.\fR?
Using the \fIrecordName\fR object command that was created from the record definition,
instances of the record definition can be created\&. Once a instance is

created, then it inherits the members of the record definition, very

similar to how objects work\&. During instance generation, an object command for the instance
is created as well, using \fIinstanceName\fR\&. This object command is used

to access the data members of the instance\&. During the instantiation, values for


that instance can be given, \fIbut\fR all values must be given, and be given

in key/value pairs\&. Nested records, need to be in list format\&.
.sp
Optionally, \fI#auto\fR can be used in place of \fIinstanceName\fR\&. When #auto is used,

then a instance name will automatically be generated, of the form recordName<integer>, where

<integer> is a unique integer (starting at 0) that is generated\&.
.PP
.PP
.SH "INSTANCE COMMAND"
The following subcommands and corresponding arguments are available to
any record instance command:
.TP
\fIinstanceName\fR \fBcget\fR ?\fI-member1 -member2 \&.\&.\&.\fR?
Each instance has the sub command \fBcget\fR associated with it\&. This
is very similar to how Tk widget's cget command works\&. It queries
the values of the member for that particular instance\&. If
no arguments are given, then a key/value list is returned\&.
.TP
\fIinstanceName\fR \fBconfigure\fR ?\fI-member1 value1 -member2 value2 \&.\&.\&.\fR?
Each instance has the sub command \fBconfigure\fR associated with it\&. This
is very similar to how Tk widget's configure command works\&. It sets
the values of the particular member for that particular instance\&. If
no arguments are given, then a key/value list is returned\&.
.PP
.SH EXAMPLES
Two examples are provided to give an good illustration on how to use
this package\&.
.PP
\fIExample 1\fR
.PP
Probably the most obvious example would be to hold contact information,
such as addresses, phone numbers, comments, etc\&. Since a person can have
multiple phone numbers, multiple email addresses, etc, we will use nested
records to define these\&. So, the first thing we do is define the nested
records:
.PP
.CS



##
##  This is an interactive example, to see what is
##  returned by each command as well\&.
##

% namespace import ::struct::record::*

% # define a nested record\&. Notice that country has default 'USA'\&.
% record define locations {
    street







|



















>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







|
|
>
|
|
<

|
>
|
|
|

|
>
>


|
|
|
|
|
>
|









|
|
<
















|
|


|
|
<
>






|
>

















<

|
|


<







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
|
<
<

<
|
<
|
>
|
>
|

|
>
|




|


>
|
|

|
|
|


>


>
|
|


>


>
|
|


>



<




|
|

|
|
|
>
|
>
|
|
>
|
>
>
|
>
|

|
>
|
>
|







|
|
|
|


|
|
|
|


|

|
<
<
|
|
|
|
|






|
|







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
..
.BS
.SH NAME
struct::record \- Define and create records (similar to 'C' structures)
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBstruct::record  ?1\&.2\&.2?\fR
.sp
\fBrecord define\fR \fIrecordName\fR \fIrecordMembers\fR ?\fIinstanceName1 instanceName2 \&.\&.\&.\fR?
.sp
\fBrecord show\fR \fIrecord\fR
.sp
\fBrecord show\fR \fIinstances\fR \fIrecordName\fR
.sp
\fBrecord show\fR \fImembers\fR \fIrecordName\fR
.sp
\fBrecord show\fR \fIvalues\fR \fIinstanceName\fR
.sp
\fBrecord exists\fR \fIrecord\fR \fIrecordName\fR
.sp
\fBrecord exists\fR \fIinstance\fR \fIinstanceName\fR
.sp
\fBrecord delete\fR \fIrecord\fR \fIrecordName\fR
.sp
\fBrecord delete\fR \fIinstance\fR \fIinstanceName\fR
.sp
\fIinstanceName\fR \fBcget\fR -\fImember\fR
.sp
\fIinstanceName\fR \fBcget\fR -\fImember1\fR -\fImember2\fR
.sp
\fIinstanceName\fR \fBcget\fR
.sp
\fIinstanceName\fR \fBconfigure\fR
.sp
\fIinstanceName\fR
.sp
\fIinstanceName\fR \fBconfigure\fR -\fImember\fR \fIvalue\fR
.sp
\fIinstanceName\fR \fBconfigure\fR -\fImember1\fR \fIvalue1\fR -\fImember2\fR \fIvalue2\fR
.sp
\fIrecordName\fR \fIinstanceName\fR|\fB#auto\fR ?\fI-member1 value1 -member2 value2 \&.\&.\&.\fR?
.sp
\fIinstanceName\fR \fBcget\fR ?\fI-member1 -member2 \&.\&.\&.\fR?
.sp
\fIinstanceName\fR \fBconfigure\fR ?\fI-member1 value1 -member2 value2 \&.\&.\&.\fR?
.sp
.BE
.SH DESCRIPTION
The \fB::struct::record\fR package provides a mechanism to group
variables together as one data structure, similar to a \fIC\fR
structure\&. The members of a record can be variables or other
records\&. However, a record can not contain circular records,
i\&.e\&. records that contain the same record as a member\&.

.PP
This package was structured so that it is very similar to how
Tk objects work\&. Each record definition creates a record object that
encompasses that definition\&. Subsequently, that record object can
create instances of that record\&. These instances can then be
manipulated with the \fBcget\fR and \fBconfigure\fR methods\&.
.PP
The package only contains one top level command, but several
sub commands (see below)\&. It also obeys the namespace in which the
record was defined, hence the objects returned are fully qualified\&.
.TP
\fBrecord define\fR \fIrecordName\fR \fIrecordMembers\fR ?\fIinstanceName1 instanceName2 \&.\&.\&.\fR?
Defines a record\&. \fIrecordName\fR is the name of the record, and is
also used as an object command\&. This object command is used to create
instances of the record definition\&. The \fIrecordMembers\fR are the
members of the record that make up the record definition\&. These are
variables and other records\&. If optional \fIinstanceName\fR args are
specified, then an instance is generated after the definition is
created for each \fIinstanceName\fR\&.
.TP
\fBrecord show\fR \fIrecord\fR
Returns a list of records that have been defined\&.
.TP
\fBrecord show\fR \fIinstances\fR \fIrecordName\fR
Returns the instances that have been instantiated by
\fIrecordName\fR\&.
.TP
\fBrecord show\fR \fImembers\fR \fIrecordName\fR
Returns the members that are defined for record \fIrecordName\fR\&.
It returns the same format as how the records were defined\&.

.TP
\fBrecord show\fR \fIvalues\fR \fIinstanceName\fR
Returns a list of values that are set for the instance
\fIinstanceName\fR\&. The output is a list of key/value pairs\&. If there
are nested records, then the values of the nested records will
itself be a list\&.
.TP
\fBrecord exists\fR \fIrecord\fR \fIrecordName\fR
Tests for the existence of a \fIrecord\fR with the
name \fIrecordName\fR\&.
.TP
\fBrecord exists\fR \fIinstance\fR \fIinstanceName\fR
Tests for the existence of a \fIinstance\fR with the
name \fIinstanceName\fR\&.
.TP
\fBrecord delete\fR \fIrecord\fR \fIrecordName\fR
Deletes \fIrecordName\fR, and all instances of \fIrecordName\fR\&.
It will return an error if the record does not exist\&.
.TP
\fBrecord delete\fR \fIinstance\fR \fIinstanceName\fR
Deletes \fIinstance\fR with the name of \fIinstanceName\fR\&. It will
return an error if the instance does not exist\&. Note that this

recursively deletes any nested instances as well\&.
.PP
.SH "RECORD MEMBERS"
Record members can either be variables, or other records, However, the
same record can not be nested witin itself (circular)\&. To define a
nested record, you need to specify the \fBrecord\fR keyword, along
the with name of the record, and the name of the instance of that
nested record (within the container)\&. For example, it would look like
this:
.PP
.CS


# this is the nested record
record define mynestedrecord {
    nest1
    nest2
}

# This is the main record
record define myrecord {
    mem1
    mem2
    {record mynestedrecord mem3}
}


.CE
You can also assign default or initial values to the members of a
record, by enclosing the member entry in braces:
.PP
.CS



record define myrecord {
    mem1
    {mem2 5}
}

.CE
All instances created from this record definition will initially have
\fB5\fR as the value for member \fImem2\fR\&. If no default is given,
then the value will be the empty string\&.
.SS "GETTING VALUES"
To get a value of a member, there are several ways to do this\&.
.TP
\fIinstanceName\fR \fBcget\fR -\fImember\fR
In this form the built-in \fBcget\fR instance method returns the
value of the specified \fImember\fR\&. Note the leading dash\&.
.sp
To reach a nested member use \fIdot notation\fR:
.CS


\fIinstanceName\fR \fBcget\fR -mem3\&.nest1

.CE
.TP
\fIinstanceName\fR \fBcget\fR -\fImember1\fR -\fImember2\fR
In this form the built-in \fBcget\fR instance method returns a list
containing the values of both specified members, in the order of specification\&.
.TP
\fIinstanceName\fR \fBcget\fR
.TP
\fIinstanceName\fR \fBconfigure\fR
.TP
\fIinstanceName\fR
These forms are all equivalent\&. They return a dictionary of all
members and the associated values\&.
.PP
.SS "SETTING VALUES"
To set a value of a member, there are several ways to do this\&.
.TP
\fIinstanceName\fR \fBconfigure\fR -\fImember\fR \fIvalue\fR
In this form the built-in \fBconfigure\fR instance method sets the
specified \fImember\fR to the given \fIvalue\fR\&. Note the leading
dash\&.
.sp
To reach a nested member use \fIdot notation\fR:
.CS


\fIinstanceName\fR \fBconfigure\fR -mem3\&.nest1 value

.CE


.TP































\fIinstanceName\fR \fBconfigure\fR -\fImember1\fR \fIvalue1\fR -\fImember2\fR \fIvalue2\fR



In this form the built-in \fBconfigure\fR instance method sets all

specified members to the associated values\&.


.PP

.SS "ALIAS ACCESS"

In the original implementation, access was done by using dot notation
similar to how \fIC\fR structures are accessed\&. However, there was a
concensus to make the interface more Tcl like, which made sense\&.
However, the original alias access still exists\&. It might prove to be
helpful to some\&.
.PP
Basically, for every member of every instance, an alias is
created\&. This alias is used to get and set values for that member\&.
An example will illustrate the point, using the above defined records:
.PP
.CS


% # Create an instance first
% myrecord inst1
::inst1

% # To get a member of an instance, just use the alias\&. It behaves
% # like a Tcl command:
% inst1\&.mem1

% # To set a member via the alias, just include a value\&. And optionally
% # the equal sign - syntactic sugar\&.
% inst1\&.mem1 = 5
5

% inst1\&.mem1
5

% # For nested records, just continue with the dot notation\&.
% # note, no equal sign\&.
% inst1\&.mem3\&.nest1 10
10

% inst1\&.mem3\&.nest1
10

% # just the instance by itself gives all member/values pairs for that
% # instance
% inst1
-mem1 5 -mem2 {} -mem3 {-nest1 10 -nest2 {}}

% # and to get all members within the nested record
% inst1\&.mem3
-nest1 10 -nest2 {}



.CE
.SH "RECORD COMMAND"
The following subcommands and corresponding arguments are available to
any record command:
.TP
\fIrecordName\fR \fIinstanceName\fR|\fB#auto\fR ?\fI-member1 value1 -member2 value2 \&.\&.\&.\fR?
Using the \fIrecordName\fR object command that was created from the
record definition, instances of the record definition can be
created\&.
Once an instance is created, it inherits the members of the record
definition, very similar to how objects work\&.
During instance generation, an object command for the instance is
created as well, using \fIinstanceName\fR\&.
.sp
This object command is used to access the data members of the
instance\&.
During the instantiation, while values for that instance may be given,
when done, \fIall\fR values must be given, and be given as
key/value pairs, like for method \fBconfigure\fR\&. Nested records
have to be in list format\&.
.sp
Optionally, \fB#auto\fR can be used in place of
\fIinstanceName\fR\&. When \fB#auto\fR is used, the instance name will
be automatically generated, and of the form
\fBrecordName\fBN\fR\fR, where \fBN\fR is a unique integer (starting
at 0) that is generated\&.
.PP
.PP
.SH "INSTANCE COMMAND"
The following subcommands and corresponding arguments are available to
any record instance command:
.TP
\fIinstanceName\fR \fBcget\fR ?\fI-member1 -member2 \&.\&.\&.\fR?
Each instance has the method \fBcget\fR\&. This is very similar to
how Tk widget's \fBcget\fR command works\&. It queries the values of
the members for that particular instance\&. If no arguments are given,
then a dictionary is returned\&.
.TP
\fIinstanceName\fR \fBconfigure\fR ?\fI-member1 value1 -member2 value2 \&.\&.\&.\fR?
Each instance has the method \fBconfigure\fR\&. This is very similar
to how Tk widget's \fBconfigure\fR command works\&. It sets the
values of the particular members for that particular instance\&. If no
arguments are given, then a dictionary list is returned\&.
.PP
.SH EXAMPLES
Two examples are provided to give a good illustration on how to use
this package\&.
.SS "EXAMPLE 1 - CONTACT INFORMATION"


Probably the most obvious example would be to hold contact
information, such as addresses, phone numbers, comments, etc\&. Since a
person can have multiple phone numbers, multiple email addresses, etc,
we will use nested records to define these\&. So, the first thing we do
is define the nested records:
.PP
.CS



##
##  This is an interactive example, to see what is returned by
##  each command as well\&.
##

% namespace import ::struct::record::*

% # define a nested record\&. Notice that country has default 'USA'\&.
% record define locations {
    street
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
% record show members contacts2
first middle last {record locations home} {record locations work}
% record show members contacts
first middle last {record locations home} {record locations work}
%

.CE
.PP
\fIExample 1\fR
.PP
This next example just illustrates a simple linked list
.PP
.CS



% # define a very simple record for linked list
% record define llist {
    value
    next
}
::llist
% llist lstart
::lstart
% lstart config -value 1 -next [llist #auto]
% [lstart cget -next] config -value 2 -next [llist #auto]
% [[lstart cget -next] cget -next] config -value 3 -next "end"
% set next lstart
lstart
% while 1 {
lappend values [$next cget -value]
set next [$next cget -next]
if {[string match "end" $next]} {break}
}
% puts "$values"
1 2 3
% # cleanup linked list
% # We could just use delete record llist also
% foreach I [record show instances llist] {
record delete instance $I
}
% record show instances llist
%


.CE
.PP
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fIstruct :: record\fR of the
\fITcllib Trackers\fR [http://core\&.tcl\&.tk/tcllib/reportlist]\&.
Please also report any ideas for enhancements you may have for either
package and/or documentation\&.







|
<
<





<

|



|
|

|
|




|
|
|




|
|
|

|


<

<







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
% record show members contacts2
first middle last {record locations home} {record locations work}
% record show members contacts
first middle last {record locations home} {record locations work}
%

.CE
.SS "EXAMPLE 2 - LINKED LIST"


This next example just illustrates a simple linked list
.PP
.CS



% # define a very simple record for linked list
% record define linkedlist {
    value
    next
}
::linkedlist
% linkedlist lstart
::lstart
% lstart config -value 1 -next [linkedlist #auto]
% [lstart cget -next] config -value 2 -next [linkedlist #auto]
% [[lstart cget -next] cget -next] config -value 3 -next "end"
% set next lstart
lstart
% while 1 {
    lappend values [$next cget -value]
    set next [$next cget -next]
    if {[string match "end" $next]} break
}
% puts "$values"
1 2 3
% # cleanup linked list
% # We could just use delete record linkedlist also
% foreach I [record show instances linkedlist] {
    record delete instance $I
}
% record show instances linkedlist
%


.CE

.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fIstruct :: record\fR of the
\fITcllib Trackers\fR [http://core\&.tcl\&.tk/tcllib/reportlist]\&.
Please also report any ideas for enhancements you may have for either
package and/or documentation\&.

Added idoc/man/files/modules/struct/struct_map.n.



























































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
'\"
'\" Generated from file 'struct_map\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "struct::map" n 1 tcllib ""
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
.\"	and indent is equivalent to second arg of .IP (shouldn't ever be
.\"	needed;  use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\"	Give maximum sizes of arguments for setting tab stops.  Type and
.\"	name are examples of largest possible arguments that will be passed
.\"	to .AP later.  If args are omitted, default tab stops are used.
.\"
.\" .BS
.\"	Start box enclosure.  From here until next .BE, everything will be
.\"	enclosed in one large box.
.\"
.\" .BE
.\"	End of box enclosure.
.\"
.\" .CS
.\"	Begin code excerpt.
.\"
.\" .CE
.\"	End code excerpt.
.\"
.\" .VS ?version? ?br?
.\"	Begin vertical sidebar, for use in marking newly-changed parts
.\"	of man pages.  The first argument is ignored and used for recording
.\"	the version when the .VS was added, so that the sidebars can be
.\"	found and removed when they reach a certain age.  If another argument
.\"	is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\"	End of vertical sidebar.
.\"
.\" .DS
.\"	Begin an indented unfilled display.
.\"
.\" .DE
.\"	End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\"	Start of list of standard options for a Tk widget. The manpage
.\"	argument defines where to look up the standard options; if
.\"	omitted, defaults to "options". The options follow on successive
.\"	lines, in three columns separated by tabs.
.\"
.\" .SE
.\"	End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\"	Start of description of a specific option.  cmdName gives the
.\"	option's name as specified in the class command, dbName gives
.\"	the option's name in the option database, and dbClass gives
.\"	the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\"	Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\"	Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\"	Print an open parenthesis, arg1 in quotes, then arg2 normally
.\"	(for trailing punctuation) and then a closing parenthesis.
.\"
.\"	# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\"	# Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
.   ie !"\\$2"" .TP \\n()Cu
.   el          .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1	\\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\"	# define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\"	# BS - start boxed text
.\"	# ^y = starting y location
.\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\"	Draw four-sided box normally, but don't draw top of
.\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# VS - start vertical sidebar
.\"	# ^Y = starting y location
.\"	# ^v = 1 (for troff;  for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\"	# VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\"	# Special macro to handle page bottom:  finish off current
.\"	# box/sidebar if in box/sidebar mode, then invoked standard
.\"	# page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\"	Draw three-sided box if this is the box's first page,
.\"	draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\"	# DS - begin display
.de DS
.RS
.nf
.sp
..
.\"	# DE - end display
.de DE
.fi
.RE
.sp
..
.\"	# SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\"	# SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\"	# OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name:	\\fB\\$1\\fR
Database Name:	\\fB\\$2\\fR
Database Class:	\\fB\\$3\\fR
.fi
.IP
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
.\"	# UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\"	# QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\"	# PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\"	# QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
struct::map \- Manage key/value maps
.SH SYNOPSIS
package require \fBstruct::map  ?1?\fR
.sp
\fB::struct::map\fR \fImapName\fR
.sp
\fBmapName\fR \fBmethod\fR ?\fIarg arg \&.\&.\&.\fR?
.sp
\fImapName\fR \fBget\fR
.sp
\fImapName\fR \fBnames\fR
.sp
\fImapName\fR \fBset\fR \fIname\fR ?\fIvalue\fR?
.sp
\fImapName\fR \fBunset\fR ?\fIpattern\fR\&.\&.\&.?
.sp
.BE
.SH DESCRIPTION
Provides a snit class whose instances manage a key/value map\&.
In other words, an object wrapper around Tcl arrays\&.
.SH API
The main command provides construction of maps:
.TP
\fB::struct::map\fR \fImapName\fR
Creates a new, empty map with an associated global Tcl command whose
name is \fImapName\fR\&.
It may be used to invoke various operations on the map\&.
It has the following general form:
.RS
.TP
\fBmapName\fR \fBmethod\fR ?\fIarg arg \&.\&.\&.\fR?
\fBmethod\fR and \fIarg\fRuments determine the exact behavior of
the command\&.
.RE
.IP
If \fImapName\fR is specified as \fB%AUTO%\fR a unique name will be
generated by the package itself\&.
The result of the command is the fully-qualified name of the instance
command\&.
.PP
.PP
The following commands are possible for map objects:
.TP
\fImapName\fR \fBget\fR
Returns the entire map as a Tcl dictionary\&.
.TP
\fImapName\fR \fBnames\fR
Returns the list of all keys known to the map, in arbitrary order\&.
.TP
\fImapName\fR \fBset\fR \fIname\fR ?\fIvalue\fR?
Sets key \fIname\fR to the specified \fIvalue\fR, if the value specified\&.
Returns the value for the key\&.
Throws an error if the key is not known\&.
.TP
\fImapName\fR \fBunset\fR ?\fIpattern\fR\&.\&.\&.?
Removes all keys matching at least one of the glob \fIpattern\fRs from
the map\&.
If no pattern is specified all keys are removed\&.
In other words, the default pattern is \fB*\fR\&.
The result of the command is the empty string\&.
.PP
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fIstruct :: list\fR of the
\fITcllib Trackers\fR [http://core\&.tcl\&.tk/tcllib/reportlist]\&.
Please also report any ideas for enhancements you may have for either
package and/or documentation\&.
.PP
When proposing code changes, please provide \fIunified diffs\fR,
i\&.e the output of \fBdiff -u\fR\&.
.PP
Note further that \fIattachments\fR are strongly preferred over
inlined patches\&. Attachments can be made by going to the \fBEdit\fR
form of the ticket immediately after its creation, and then using the
left-most button in the secondary navigation bar\&.

Added idoc/man/files/modules/textutil/patch.n.



















































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
'\"
'\" Generated from file 'patch\&.man' by tcllib/doctools with format 'nroff'
'\"
.TH "textutil::patch" n 0\&.1 tcllib "Text and string utilities"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
.\"	and indent is equivalent to second arg of .IP (shouldn't ever be
.\"	needed;  use .AS below instead)
.\"
.\" .AS ?type? ?name?
.\"	Give maximum sizes of arguments for setting tab stops.  Type and
.\"	name are examples of largest possible arguments that will be passed
.\"	to .AP later.  If args are omitted, default tab stops are used.
.\"
.\" .BS
.\"	Start box enclosure.  From here until next .BE, everything will be
.\"	enclosed in one large box.
.\"
.\" .BE
.\"	End of box enclosure.
.\"
.\" .CS
.\"	Begin code excerpt.
.\"
.\" .CE
.\"	End code excerpt.
.\"
.\" .VS ?version? ?br?
.\"	Begin vertical sidebar, for use in marking newly-changed parts
.\"	of man pages.  The first argument is ignored and used for recording
.\"	the version when the .VS was added, so that the sidebars can be
.\"	found and removed when they reach a certain age.  If another argument
.\"	is present, then a line break is forced before starting the sidebar.
.\"
.\" .VE
.\"	End of vertical sidebar.
.\"
.\" .DS
.\"	Begin an indented unfilled display.
.\"
.\" .DE
.\"	End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\"	Start of list of standard options for a Tk widget. The manpage
.\"	argument defines where to look up the standard options; if
.\"	omitted, defaults to "options". The options follow on successive
.\"	lines, in three columns separated by tabs.
.\"
.\" .SE
.\"	End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\"	Start of description of a specific option.  cmdName gives the
.\"	option's name as specified in the class command, dbName gives
.\"	the option's name in the option database, and dbClass gives
.\"	the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\"	Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\"	Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\"	Print an open parenthesis, arg1 in quotes, then arg2 normally
.\"	(for trailing punctuation) and then a closing parenthesis.
.\"
.\"	# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\"	# Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
.   ie !"\\$2"" .TP \\n()Cu
.   el          .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1	\\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\"	# define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\"	# BS - start boxed text
.\"	# ^y = starting y location
.\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\"	Draw four-sided box normally, but don't draw top of
.\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# VS - start vertical sidebar
.\"	# ^Y = starting y location
.\"	# ^v = 1 (for troff;  for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\"	# VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\"	# Special macro to handle page bottom:  finish off current
.\"	# box/sidebar if in box/sidebar mode, then invoked standard
.\"	# page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\"	Draw three-sided box if this is the box's first page,
.\"	draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\"	# DS - begin display
.de DS
.RS
.nf
.sp
..
.\"	# DE - end display
.de DE
.fi
.RE
.sp
..
.\"	# SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\"	# SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\"	# OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name:	\\fB\\$1\\fR
Database Name:	\\fB\\$2\\fR
Database Class:	\\fB\\$3\\fR
.fi
.IP
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
.\"	# UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\"	# QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\"	# PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\"	# QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
.BS
.SH NAME
textutil::patch \- Application of uni-diff patches to directory trees
.SH SYNOPSIS
package require \fBTcl  8\&.2\fR
.sp
package require \fBtextutil::patch  ?0\&.1?\fR
.sp
\fB::textutil::patch::apply\fR \fIbasedirectory\fR \fIstriplevel\fR \fIpatch\fR \fIreportcmd\fR
.sp
\fB{*}reportcmd\fR \fBapply\fR \fIfilename\fR
.sp
\fB{*}reportcmd\fR \fBfail\fR \fIfilename\fR \fIhunk\fR \fIexpected\fR \fIseen\fR
.sp
\fB{*}reportcmd\fR \fBfail-already\fR \fIfilename\fR \fIhunk\fR
.sp
.BE
.SH DESCRIPTION
This package provides a single command which applies a patch in
\fIunified format\fR [https://www\&.gnu\&.org/software/diffutils/manual/html_node/Detailed-Unified\&.html]
to a directory tree\&.
.TP
\fB::textutil::patch::apply\fR \fIbasedirectory\fR \fIstriplevel\fR \fIpatch\fR \fIreportcmd\fR
Applies the \fIpatch\fR (text of the path, not file) to the files in
the \fIbasedirectory\fR using the specified \fIstriplevel\fR\&.
The result of the command is the empty string\&.
.sp
The \fIstriplevel\fR argument is equivalent to option
\fB-p\fR of the \fBpatch\fR command\&.
.sp
Errors are thrown when the \fIpatch\fR does not parse, and
nothing is done to the files in \fIbasedirectory\fR\&.
.sp
All activities during the application of the patch, including
the inability to apply a hunk are reported through the command prefix
\fIreportcmd\fR instead\&. Files with problems are left unchanged\&.  Note
however that this does \fInot prevent\fR changes to files with no
problems, before and after the problematic file(s)\&.
.sp
The command prefix is called in 3 possible forms:
.RS
.TP
\fB{*}reportcmd\fR \fBapply\fR \fIfilename\fR
The caller begins operation on file \fIfname\fR, applying all hunks
collected for said file\&.
.TP
\fB{*}reportcmd\fR \fBfail\fR \fIfilename\fR \fIhunk\fR \fIexpected\fR \fIseen\fR
Application of hunk number \fIhunk\fR of file \fIfilename\fR has failed\&.
The command expected to find the text \fIexpected\fR, and saw \fIseen\fR instead\&.
.TP
\fB{*}reportcmd\fR \fBfail-already\fR \fIfilename\fR \fIhunk\fR
Application of hunk number \fIhunk\fR of file \fIfilename\fR has failed\&.
The command believes that this hunk has already been applied to the file\&.
.RE
.PP
.SH "BUGS, IDEAS, FEEDBACK"
This document, and the package it describes, will undoubtedly contain
bugs and other problems\&.
Please report such in the category \fItextutil\fR of the
\fITcllib Trackers\fR [http://core\&.tcl\&.tk/tcllib/reportlist]\&.
Please also report any ideas for enhancements you may have for either
package and/or documentation\&.
.PP
When proposing code changes, please provide \fIunified diffs\fR,
i\&.e the output of \fBdiff -u\fR\&.
.PP
Note further that \fIattachments\fR are strongly preferred over
inlined patches\&. Attachments can be made by going to the \fBEdit\fR
form of the ticket immediately after its creation, and then using the
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
diff -ruN, diff, unified format, fossil, git, patch, unified format diff
.SH CATEGORY
Text processing

Changes to idoc/man/files/modules/treeql/treeql.n.

404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
    #   have such an attribute\&.
    # - And returns this information\&.

    # Below we can see the same query, but rewritten
    # to show the structure as it is seen by the query
    # interpreter\&.

    q query \\\\
	    root \\\\
	    children \\\\
	    get data

.CE
.sp
The operators of the TreeQL language available for this are explained
in the section about \fBThe Tree Query Language\fR\&. This section
also explains the term \fInode set\fR used above\&.







|
|
|







404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
    #   have such an attribute\&.
    # - And returns this information\&.

    # Below we can see the same query, but rewritten
    # to show the structure as it is seen by the query
    # interpreter\&.

    q query \\
	    root \\
	    children \\
	    get data

.CE
.sp
The operators of the TreeQL language available for this are explained
in the section about \fBThe Tree Query Language\fR\&. This section
also explains the term \fInode set\fR used above\&.

Changes to idoc/man/files/modules/virtchannel_base/cat.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'cat\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2011 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "tcl::chan::cat" n 1 tcllib "Reflected/virtual channel support"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'cat\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2011 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "tcl::chan::cat" n 1\&.0\&.3 tcllib "Reflected/virtual channel support"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBTclOO \fR
.sp
package require \fBtcl::chan::core  ?1?\fR
.sp
package require \fBtcl::chan::cat  ?1?\fR
.sp
\fB::tcl::chan::cat\fR \fIchan\fR\&.\&.\&.
.sp
.BE
.SH DESCRIPTION
.PP
The \fBtcl::chan::cat\fR package provides a command creating







|







276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBTclOO \fR
.sp
package require \fBtcl::chan::core  ?1?\fR
.sp
package require \fBtcl::chan::cat  ?1\&.0\&.3?\fR
.sp
\fB::tcl::chan::cat\fR \fIchan\fR\&.\&.\&.
.sp
.BE
.SH DESCRIPTION
.PP
The \fBtcl::chan::cat\fR package provides a command creating

Changes to idoc/man/files/modules/virtchannel_base/halfpipe.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'halfpipe\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "tcl::chan::halfpipe" n 1 tcllib "Reflected/virtual channel support"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,


|

|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'halfpipe\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009, 2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>
'\"
.TH "tcl::chan::halfpipe" n 1\&.0\&.1 tcllib "Reflected/virtual channel support"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBTclOO \fR
.sp
package require \fBtcl::chan::events  ?1?\fR
.sp
package require \fBtcl::chan::halfpipe  ?1?\fR
.sp
package require \fBtcl::chan::halfpipe  ?1?\fR
.sp
\fB::tcl::chan::halfpipe\fR ?\fB-option\fR \fIvalue\fR\&.\&.\&.?
.sp
\fIobjectCmd\fR \fBput\fR \fIbytes\fR
.sp
.BE
.SH DESCRIPTION







|
<
<







276
277
278
279
280
281
282
283


284
285
286
287
288
289
290
.SH SYNOPSIS
package require \fBTcl  8\&.5\fR
.sp
package require \fBTclOO \fR
.sp
package require \fBtcl::chan::events  ?1?\fR
.sp
package require \fBtcl::chan::halfpipe  ?1\&.0\&.1?\fR


.sp
\fB::tcl::chan::halfpipe\fR ?\fB-option\fR \fIvalue\fR\&.\&.\&.?
.sp
\fIobjectCmd\fR \fBput\fR \fIbytes\fR
.sp
.BE
.SH DESCRIPTION
351
352
353
354
355
356
357
358
359
360
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
callbacks, fifo, in-memory channel, reflected channel, tip 219, virtual channel
.SH CATEGORY
Channels
.SH COPYRIGHT
.nf
Copyright (c) 2009 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi







|


349
350
351
352
353
354
355
356
357
358
left-most button in the secondary navigation bar\&.
.SH KEYWORDS
callbacks, fifo, in-memory channel, reflected channel, tip 219, virtual channel
.SH CATEGORY
Channels
.SH COPYRIGHT
.nf
Copyright (c) 2009, 2019 Andreas Kupries <andreas_kupries@users\&.sourceforge\&.net>

.fi

Changes to idoc/man/files/modules/zip/mkzip.n.

1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'mkzip\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Pat Thoyts
'\"
.TH "zipfile::mkzip" n 1\&.2 tcllib "Zip archive creation"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,




|







1
2
3
4
5
6
7
8
9
10
11
12
'\"
'\" Generated from file 'mkzip\&.man' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2009 Pat Thoyts
'\"
.TH "zipfile::mkzip" n 1\&.2\&.1 tcllib "Zip archive creation"
.\" The -*- nroff -*- definitions below are for supplemental macros used
.\" in Tcl/Tk manual entries.
.\"
.\" .AP type name in/out ?indent?
.\"	Start paragraph describing an argument to a library procedure.
.\"	type is type of argument (int, etc.), in/out is either "in", "out",
.\"	or "in/out" to describe whether procedure reads or modifies arg,
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
zipfile::mkzip \- Build a zip archive
.SH SYNOPSIS
package require \fBTcl  8\&.6\fR
.sp
package require \fBzipfile::mkzip  ?1\&.2?\fR
.sp
\fB::zipfile::mkzip::mkzip\fR \fIzipfile\fR ?\fB-zipkit\fR? ?\fB-runtime\fR \fIprefix\fR? ?\fB-comment\fR \fIstring\fR? ?\fB-directory\fR \fIrootpath\fR? ?\fB-exclude\fR \fIexclude\fR? ?\fB--\fR? ?\fIpath\fR\&.\&.\&.?
.sp
.BE
.SH DESCRIPTION
.PP
This package utilizes the zlib functions in Tcl 8\&.6 to build zip







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
..
.BS
.SH NAME
zipfile::mkzip \- Build a zip archive
.SH SYNOPSIS
package require \fBTcl  8\&.6\fR
.sp
package require \fBzipfile::mkzip  ?1\&.2\&.1?\fR
.sp
\fB::zipfile::mkzip::mkzip\fR \fIzipfile\fR ?\fB-zipkit\fR? ?\fB-runtime\fR \fIprefix\fR? ?\fB-comment\fR \fIstring\fR? ?\fB-directory\fR \fIrootpath\fR? ?\fB-exclude\fR \fIexclude\fR? ?\fB--\fR? ?\fIpath\fR\&.\&.\&.?
.sp
.BE
.SH DESCRIPTION
.PP
This package utilizes the zlib functions in Tcl 8\&.6 to build zip

Changes to idoc/man/index.n.

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
.RS
.TP
\fBfiles/modules/doctools2base/tcl_parse\&.n\fR
doctools::tcl::parse
.RE
TclOO
.RS






.TP
\fBfiles/modules/tool/meta\&.n\fR
oo::util
.TP
\fBfiles/modules/ooutil/ooutil\&.n\fR
oo::util
.TP
\fBfiles/modules/oometa/oometa\&.n\fR
oometa
.TP
\fBfiles/modules/tool/tool\&.n\fR
tool
.TP
\fBfiles/modules/httpd/httpd\&.n\fR
tool
.TP
\fBfiles/modules/tool/tool_dict_ensemble\&.n\fR
tool::dict_ensemble
.RE
TeX
.RS
.TP
\fBfiles/modules/textutil/textutil\&.n\fR







>
>
>
>
>
>













<
<
<







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
.RS
.TP
\fBfiles/modules/doctools2base/tcl_parse\&.n\fR
doctools::tcl::parse
.RE
TclOO
.RS
.TP
\fBfiles/modules/clay/clay\&.n\fR
clay
.TP
\fBfiles/modules/httpd/httpd\&.n\fR
httpd
.TP
\fBfiles/modules/tool/meta\&.n\fR
oo::util
.TP
\fBfiles/modules/ooutil/ooutil\&.n\fR
oo::util
.TP
\fBfiles/modules/oometa/oometa\&.n\fR
oometa
.TP
\fBfiles/modules/tool/tool\&.n\fR
tool
.TP



\fBfiles/modules/tool/tool_dict_ensemble\&.n\fR
tool::dict_ensemble
.RE
TeX
.RS
.TP
\fBfiles/modules/textutil/textutil\&.n\fR
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
\fBfiles/modules/valtype/verhoeff\&.n\fR
valtype::verhoeff
.RE
WWW
.RS
.TP
\fBfiles/modules/httpd/httpd\&.n\fR
tool
.RE
XGoogleToken
.RS
.TP
\fBfiles/modules/sasl/gtoken\&.n\fR
SASL::XGoogleToken
.RE







|







1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
\fBfiles/modules/valtype/verhoeff\&.n\fR
valtype::verhoeff
.RE
WWW
.RS
.TP
\fBfiles/modules/httpd/httpd\&.n\fR
httpd
.RE
XGoogleToken
.RS
.TP
\fBfiles/modules/sasl/gtoken\&.n\fR
SASL::XGoogleToken
.RE
3520
3521
3522
3523
3524
3525
3526












3527
3528
3529
3530
3531
3532
3533
.RE
diff -n format
.RS
.TP
\fBfiles/modules/rcs/rcs\&.n\fR
rcs
.RE












difference
.RS
.TP
\fBfiles/modules/struct/struct_set\&.n\fR
struct::set
.RE
differential







>
>
>
>
>
>
>
>
>
>
>
>







3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
.RE
diff -n format
.RS
.TP
\fBfiles/modules/rcs/rcs\&.n\fR
rcs
.RE
diff -ruN
.RS
.TP
\fBfiles/modules/textutil/patch\&.n\fR
textutil::patch
.RE
diff, unified format
.RS
.TP
\fBfiles/modules/textutil/patch\&.n\fR
textutil::patch
.RE
difference
.RS
.TP
\fBfiles/modules/struct/struct_set\&.n\fR
struct::set
.RE
differential
4801
4802
4803
4804
4805
4806
4807






4808
4809
4810
4811
4812
4813
4814
.TP
\fBfiles/modules/doctools/doctoc_plugin_apiref\&.n\fR
doctoc_plugin_apiref
.TP
\fBfiles/modules/doctools/doctools_plugin_apiref\&.n\fR
doctools_plugin_apiref
.RE






frame
.RS
.TP
\fBfiles/modules/term/ansi_cmacros\&.n\fR
term::ansi::code::macros
.RE
framework







>
>
>
>
>
>







4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
.TP
\fBfiles/modules/doctools/doctoc_plugin_apiref\&.n\fR
doctoc_plugin_apiref
.TP
\fBfiles/modules/doctools/doctools_plugin_apiref\&.n\fR
doctools_plugin_apiref
.RE
fossil
.RS
.TP
\fBfiles/modules/textutil/patch\&.n\fR
textutil::patch
.RE
frame
.RS
.TP
\fBfiles/modules/term/ansi_cmacros\&.n\fR
term::ansi::code::macros
.RE
framework
4915
4916
4917
4918
4919
4920
4921






4922
4923
4924
4925
4926
4927
4928
.TP
\fBfiles/modules/coroutine/tcllib_coroutine\&.n\fR
coroutine
.TP
\fBfiles/modules/coroutine/coro_auto\&.n\fR
coroutine::auto
.RE






global
.RS
.TP
\fBfiles/modules/coroutine/tcllib_coroutine\&.n\fR
coroutine
.TP
\fBfiles/modules/coroutine/coro_auto\&.n\fR







>
>
>
>
>
>







4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
.TP
\fBfiles/modules/coroutine/tcllib_coroutine\&.n\fR
coroutine
.TP
\fBfiles/modules/coroutine/coro_auto\&.n\fR
coroutine::auto
.RE
git
.RS
.TP
\fBfiles/modules/textutil/patch\&.n\fR
textutil::patch
.RE
global
.RS
.TP
\fBfiles/modules/coroutine/tcllib_coroutine\&.n\fR
coroutine
.TP
\fBfiles/modules/coroutine/coro_auto\&.n\fR
5262
5263
5264
5265
5266
5267
5268



5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
ncgi
.RE
http
.RS
.TP
\fBfiles/modules/http/autoproxy\&.n\fR
autoproxy



.TP
\fBfiles/modules/map/map_geocode_nominatim\&.n\fR
map::geocode::nominatim
.TP
\fBfiles/modules/map/map_slippy_fetcher\&.n\fR
map::slippy::fetcher
.TP
\fBfiles/modules/httpd/httpd\&.n\fR
tool
.TP
\fBfiles/modules/uri/uri\&.n\fR
uri
.TP
\fBfiles/modules/websocket/websocket\&.n\fR
websocket
.RE
httpd
.RS
.TP
\fBfiles/modules/httpd/httpd\&.n\fR
tool
.RE
https
.RS
.TP
\fBfiles/modules/uri/uri\&.n\fR
uri
.RE
httpserver
.RS
.TP
\fBfiles/modules/httpd/httpd\&.n\fR
tool
.RE
huddle
.RS
.TP
\fBfiles/modules/yaml/huddle\&.n\fR
huddle
.TP







>
>
>







<
<
<










|











|







5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305



5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
ncgi
.RE
http
.RS
.TP
\fBfiles/modules/http/autoproxy\&.n\fR
autoproxy
.TP
\fBfiles/modules/httpd/httpd\&.n\fR
httpd
.TP
\fBfiles/modules/map/map_geocode_nominatim\&.n\fR
map::geocode::nominatim
.TP
\fBfiles/modules/map/map_slippy_fetcher\&.n\fR
map::slippy::fetcher
.TP



\fBfiles/modules/uri/uri\&.n\fR
uri
.TP
\fBfiles/modules/websocket/websocket\&.n\fR
websocket
.RE
httpd
.RS
.TP
\fBfiles/modules/httpd/httpd\&.n\fR
httpd
.RE
https
.RS
.TP
\fBfiles/modules/uri/uri\&.n\fR
uri
.RE
httpserver
.RS
.TP
\fBfiles/modules/httpd/httpd\&.n\fR
httpd
.RE
huddle
.RS
.TP
\fBfiles/modules/yaml/huddle\&.n\fR
huddle
.TP
6603
6604
6605
6606
6607
6608
6609



6610
6611
6612
6613
6614
6615
6616
simulation::random
.RE
mathematics
.RS
.TP
\fBfiles/modules/math/fourier\&.n\fR
math::fourier



.TP
\fBfiles/modules/math/statistics\&.n\fR
math::statistics
.RE
matrices
.RS
.TP







>
>
>







6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
simulation::random
.RE
mathematics
.RS
.TP
\fBfiles/modules/math/fourier\&.n\fR
math::fourier
.TP
\fBfiles/modules/math/quasirandom\&.n\fR
math::quasirandom
.TP
\fBfiles/modules/math/statistics\&.n\fR
math::statistics
.RE
matrices
.RS
.TP
7279
7280
7281
7282
7283
7284
7285






7286
7287
7288
7289
7290
7291
7292
.RE
one time pad
.RS
.TP
\fBfiles/modules/virtchannel_transform/vt_otp\&.n\fR
tcl::transform::otp
.RE






optimization
.RS
.TP
\fBfiles/modules/math/optimize\&.n\fR
math::optimize
.TP
\fBfiles/modules/simulation/annealing\&.n\fR







>
>
>
>
>
>







7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
.RE
one time pad
.RS
.TP
\fBfiles/modules/virtchannel_transform/vt_otp\&.n\fR
tcl::transform::otp
.RE
oo
.RS
.TP
\fBfiles/modules/clay/clay\&.n\fR
clay
.RE
optimization
.RS
.TP
\fBfiles/modules/math/optimize\&.n\fR
math::optimize
.TP
\fBfiles/modules/simulation/annealing\&.n\fR
7935
7936
7937
7938
7939
7940
7941



7942
7943
7944
7945
7946
7947
7948
otp
.RE
patch
.RS
.TP
\fBfiles/modules/docstrip/docstrip_util\&.n\fR
docstrip_util



.RE
patching
.RS
.TP
\fBfiles/modules/rcs/rcs\&.n\fR
rcs
.RE







>
>
>







7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
otp
.RE
patch
.RS
.TP
\fBfiles/modules/docstrip/docstrip_util\&.n\fR
docstrip_util
.TP
\fBfiles/modules/textutil/patch\&.n\fR
textutil::patch
.RE
patching
.RS
.TP
\fBfiles/modules/rcs/rcs\&.n\fR
rcs
.RE
8410
8411
8412
8413
8414
8415
8416






8417
8418
8419
8420
8421
8422
8423
.TP
\fBfiles/modules/pt/pt_parser_api\&.n\fR
pt_parser_api
.TP
\fBfiles/modules/pt/pt_peg_op\&.n\fR
pt_peg_op
.RE






queue
.RS
.TP
\fBfiles/modules/csv/csv\&.n\fR
csv
.TP
\fBfiles/modules/htmlparse/htmlparse\&.n\fR







>
>
>
>
>
>







8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
.TP
\fBfiles/modules/pt/pt_parser_api\&.n\fR
pt_parser_api
.TP
\fBfiles/modules/pt/pt_peg_op\&.n\fR
pt_peg_op
.RE
quasi-random
.RS
.TP
\fBfiles/modules/math/quasirandom\&.n\fR
math::quasirandom
.RE
queue
.RS
.TP
\fBfiles/modules/csv/csv\&.n\fR
csv
.TP
\fBfiles/modules/htmlparse/htmlparse\&.n\fR
9579
9580
9581
9582
9583
9584
9585



9586
9587
9588
9589
9590
9591
9592
9593
9594
9595
9596
9597
9598
logger
.RE
services
.RS
.TP
\fBfiles/modules/ftpd/ftpd\&.n\fR
ftpd



.TP
\fBfiles/modules/smtpd/smtpd\&.n\fR
smtpd
.TP
\fBfiles/modules/httpd/httpd\&.n\fR
tool
.RE
set
.RS
.TP
\fBfiles/modules/struct/queue\&.n\fR
struct::queue
.TP







>
>
>



<
<
<







9624
9625
9626
9627
9628
9629
9630
9631
9632
9633
9634
9635
9636



9637
9638
9639
9640
9641
9642
9643
logger
.RE
services
.RS
.TP
\fBfiles/modules/ftpd/ftpd\&.n\fR
ftpd
.TP
\fBfiles/modules/httpd/httpd\&.n\fR
httpd
.TP
\fBfiles/modules/smtpd/smtpd\&.n\fR
smtpd



.RE
set
.RS
.TP
\fBfiles/modules/struct/queue\&.n\fR
struct::queue
.TP
11268
11269
11270
11271
11272
11273
11274






11275
11276
11277
11278
11279
11280
11281
stringprep::data
.TP
\fBfiles/modules/stringprep/unicode\&.n\fR
unicode
.TP
\fBfiles/modules/stringprep/unicode_data\&.n\fR
unicode::data






.RE
union
.RS
.TP
\fBfiles/modules/struct/disjointset\&.n\fR
struct::disjointset
.TP







>
>
>
>
>
>







11313
11314
11315
11316
11317
11318
11319
11320
11321
11322
11323
11324
11325
11326
11327
11328
11329
11330
11331
11332
stringprep::data
.TP
\fBfiles/modules/stringprep/unicode\&.n\fR
unicode
.TP
\fBfiles/modules/stringprep/unicode_data\&.n\fR
unicode::data
.RE
unified format diff
.RS
.TP
\fBfiles/modules/textutil/patch\&.n\fR
textutil::patch
.RE
union
.RS
.TP
\fBfiles/modules/struct/disjointset\&.n\fR
struct::disjointset
.TP

Changes to idoc/man/toc.n.

329
330
331
332
333
334
335



336
337
338
339
340
341
342
.TP
\fBcache::async\fR
\fIfiles/modules/cache/async\&.n\fR: Asynchronous in-memory cache
.TP
\fBcksum\fR
\fIfiles/modules/crc/cksum\&.n\fR: Calculate a cksum(1) compatible checksum
.TP



\fBclock_iso8601\fR
\fIfiles/modules/clock/iso8601\&.n\fR: Parsing ISO 8601 dates/times
.TP
\fBclock_rfc2822\fR
\fIfiles/modules/clock/rfc2822\&.n\fR: Parsing ISO 8601 dates/times
.TP
\fBcmdline\fR







>
>
>







329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
.TP
\fBcache::async\fR
\fIfiles/modules/cache/async\&.n\fR: Asynchronous in-memory cache
.TP
\fBcksum\fR
\fIfiles/modules/crc/cksum\&.n\fR: Calculate a cksum(1) compatible checksum
.TP
\fBclay\fR
\fIfiles/modules/clay/clay\&.n\fR: A minimalist framework for large scale OO Projects
.TP
\fBclock_iso8601\fR
\fIfiles/modules/clock/iso8601\&.n\fR: Parsing ISO 8601 dates/times
.TP
\fBclock_rfc2822\fR
\fIfiles/modules/clock/rfc2822\&.n\fR: Parsing ISO 8601 dates/times
.TP
\fBcmdline\fR
620
621
622
623
624
625
626



627
628
629
630
631
632
633
.TP
\fBfileutil::multi\fR
\fIfiles/modules/fileutil/multi\&.n\fR: Multi-file operation, scatter/gather, standard object
.TP
\fBfileutil::multi::op\fR
\fIfiles/modules/fileutil/multiop\&.n\fR: Multi-file operation, scatter/gather
.TP



\fBfileutil_traverse\fR
\fIfiles/modules/fileutil/traverse\&.n\fR: Iterative directory traversal
.TP
\fBftp\fR
\fIfiles/modules/ftp/ftp\&.n\fR: Client-side tcl implementation of the ftp protocol
.TP
\fBftp::geturl\fR







>
>
>







623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
.TP
\fBfileutil::multi\fR
\fIfiles/modules/fileutil/multi\&.n\fR: Multi-file operation, scatter/gather, standard object
.TP
\fBfileutil::multi::op\fR
\fIfiles/modules/fileutil/multiop\&.n\fR: Multi-file operation, scatter/gather
.TP
\fBfileutil::paths\fR
\fIfiles/modules/fileutil/paths\&.n\fR: Manage search path pools
.TP
\fBfileutil_traverse\fR
\fIfiles/modules/fileutil/traverse\&.n\fR: Iterative directory traversal
.TP
\fBftp\fR
\fIfiles/modules/ftp/ftp\&.n\fR: Client-side tcl implementation of the ftp protocol
.TP
\fBftp::geturl\fR
692
693
694
695
696
697
698



699
700
701
702
703
704
705
.TP
\fBhtml\fR
\fIfiles/modules/html/html\&.n\fR: Procedures to generate HTML structures
.TP
\fBhtmlparse\fR
\fIfiles/modules/htmlparse/htmlparse\&.n\fR: Procedures to parse HTML strings
.TP



\fBhuddle\fR
\fIfiles/modules/yaml/huddle\&.n\fR: Create and manipulate huddle object
.TP
\fBident\fR
\fIfiles/modules/ident/ident\&.n\fR: Ident protocol client
.TP
\fBimap4\fR







>
>
>







698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
.TP
\fBhtml\fR
\fIfiles/modules/html/html\&.n\fR: Procedures to generate HTML structures
.TP
\fBhtmlparse\fR
\fIfiles/modules/htmlparse/htmlparse\&.n\fR: Procedures to parse HTML strings
.TP
\fBhttpd\fR
\fIfiles/modules/httpd/httpd\&.n\fR: A TclOO and coroutine based web server
.TP
\fBhuddle\fR
\fIfiles/modules/yaml/huddle\&.n\fR: Create and manipulate huddle object
.TP
\fBident\fR
\fIfiles/modules/ident/ident\&.n\fR: Ident protocol client
.TP
\fBimap4\fR
824
825
826
827
828
829
830



831
832
833
834
835
836
837
.TP
\fBmath::PCA\fR
\fIfiles/modules/math/pca\&.n\fR: Package for Principal Component Analysis
.TP
\fBmath::polynomials\fR
\fIfiles/modules/math/polynomials\&.n\fR: Polynomial functions
.TP



\fBmath::rationalfunctions\fR
\fIfiles/modules/math/rational_funcs\&.n\fR: Polynomial functions
.TP
\fBmath::roman\fR
\fIfiles/modules/math/roman\&.n\fR: Tools for creating and manipulating roman numerals
.TP
\fBmath::special\fR







>
>
>







833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
.TP
\fBmath::PCA\fR
\fIfiles/modules/math/pca\&.n\fR: Package for Principal Component Analysis
.TP
\fBmath::polynomials\fR
\fIfiles/modules/math/polynomials\&.n\fR: Polynomial functions
.TP
\fBmath::quasirandom\fR
\fIfiles/modules/math/quasirandom\&.n\fR: Quasi-random points for integration and Monte Carlo type methods
.TP
\fBmath::rationalfunctions\fR
\fIfiles/modules/math/rational_funcs\&.n\fR: Polynomial functions
.TP
\fBmath::roman\fR
\fIfiles/modules/math/roman\&.n\fR: Tools for creating and manipulating roman numerals
.TP
\fBmath::special\fR
1196
1197
1198
1199
1200
1201
1202



1203
1204
1205
1206
1207
1208
1209
.TP
\fBstruct::graph_v1\fR
\fIfiles/modules/struct/graph1\&.n\fR: Create and manipulate directed graph objects
.TP
\fBstruct::list\fR
\fIfiles/modules/struct/struct_list\&.n\fR: Procedures for manipulating lists
.TP



\fBstruct::matrix\fR
\fIfiles/modules/struct/matrix\&.n\fR: Create and manipulate matrix objects
.TP
\fBstruct::matrix_v1\fR
\fIfiles/modules/struct/matrix1\&.n\fR: Create and manipulate matrix objects
.TP
\fBstruct::pool\fR







>
>
>







1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
.TP
\fBstruct::graph_v1\fR
\fIfiles/modules/struct/graph1\&.n\fR: Create and manipulate directed graph objects
.TP
\fBstruct::list\fR
\fIfiles/modules/struct/struct_list\&.n\fR: Procedures for manipulating lists
.TP
\fBstruct::map\fR
\fIfiles/modules/struct/struct_map\&.n\fR: Manage key/value maps
.TP
\fBstruct::matrix\fR
\fIfiles/modules/struct/matrix\&.n\fR: Create and manipulate matrix objects
.TP
\fBstruct::matrix_v1\fR
\fIfiles/modules/struct/matrix1\&.n\fR: Create and manipulate matrix objects
.TP
\fBstruct::pool\fR
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
.TP
\fBtcl::transform::spacer\fR
\fIfiles/modules/virtchannel_transform/spacer\&.n\fR: Space insertation and removal
.TP
\fBtcl::transform::zlib\fR
\fIfiles/modules/virtchannel_transform/tcllib_zlib\&.n\fR: zlib (de)compression
.TP



\fBtclDES\fR
\fIfiles/modules/des/tcldes\&.n\fR: Implementation of the DES and triple-DES ciphers
.TP
\fBtclDESjr\fR
\fIfiles/modules/des/tcldesjr\&.n\fR: Implementation of the DES and triple-DES ciphers
.TP
\fBtcldocstrip\fR
\fIfiles/apps/tcldocstrip\&.n\fR: Tcl-based Docstrip Processor
.TP






\fBtcllib_ip\fR
\fIfiles/modules/dns/tcllib_ip\&.n\fR: IPv4 and IPv6 address manipulation
.TP









\fBtclrep/machineparameters\fR
\fIfiles/modules/math/machineparameters\&.n\fR: Compute double precision machine parameters\&.
.TP
\fBtepam\fR
\fIfiles/modules/tepam/tepam_introduction\&.n\fR: An introduction into TEPAM, Tcl's Enhanced Procedure and Argument Manager
.TP
\fBtepam::argument_dialogbox\fR







>
>
>









>
>
>
>
>
>



>
>
>
>
>
>
>
>
>







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
.TP
\fBtcl::transform::spacer\fR
\fIfiles/modules/virtchannel_transform/spacer\&.n\fR: Space insertation and removal
.TP
\fBtcl::transform::zlib\fR
\fIfiles/modules/virtchannel_transform/tcllib_zlib\&.n\fR: zlib (de)compression
.TP
\fBtcl_community_communication\fR
\fIfiles/devdoc/tcl_community_communication\&.n\fR: Tcl Community - Kind Communication
.TP
\fBtclDES\fR
\fIfiles/modules/des/tcldes\&.n\fR: Implementation of the DES and triple-DES ciphers
.TP
\fBtclDESjr\fR
\fIfiles/modules/des/tcldesjr\&.n\fR: Implementation of the DES and triple-DES ciphers
.TP
\fBtcldocstrip\fR
\fIfiles/apps/tcldocstrip\&.n\fR: Tcl-based Docstrip Processor
.TP
\fBtcllib_devguide\fR
\fIfiles/devdoc/tcllib_devguide\&.n\fR: Tcllib - The Developer's Guide
.TP
\fBtcllib_install_guide\fR
\fIfiles/devdoc/tcllib_installer\&.n\fR: Tcllib - The Installer's Guide
.TP
\fBtcllib_ip\fR
\fIfiles/modules/dns/tcllib_ip\&.n\fR: IPv4 and IPv6 address manipulation
.TP
\fBtcllib_license\fR
\fIfiles/devdoc/tcllib_license\&.n\fR: Tcllib - License
.TP
\fBtcllib_releasemgr\fR
\fIfiles/devdoc/tcllib_releasemgr\&.n\fR: Tcllib - The Release Manager's Guide
.TP
\fBtcllib_sources\fR
\fIfiles/devdoc/tcllib_sources\&.n\fR: Tcllib - How To Get The Sources
.TP
\fBtclrep/machineparameters\fR
\fIfiles/modules/math/machineparameters\&.n\fR: Compute double precision machine parameters\&.
.TP
\fBtepam\fR
\fIfiles/modules/tepam/tepam_introduction\&.n\fR: An introduction into TEPAM, Tcl's Enhanced Procedure and Argument Manager
.TP
\fBtepam::argument_dialogbox\fR
1400
1401
1402
1403
1404
1405
1406



1407
1408
1409
1410
1411
1412
1413
.TP
\fBtextutil::adjust\fR
\fIfiles/modules/textutil/adjust\&.n\fR: Procedures to adjust, indent, and undent paragraphs
.TP
\fBtextutil::expander\fR
\fIfiles/modules/textutil/expander\&.n\fR: Procedures to process templates and expand text\&.
.TP



\fBtextutil::repeat\fR
\fIfiles/modules/textutil/repeat\&.n\fR: Procedures to repeat strings\&.
.TP
\fBtextutil::split\fR
\fIfiles/modules/textutil/textutil_split\&.n\fR: Procedures to split texts
.TP
\fBtextutil::string\fR







>
>
>







1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
.TP
\fBtextutil::adjust\fR
\fIfiles/modules/textutil/adjust\&.n\fR: Procedures to adjust, indent, and undent paragraphs
.TP
\fBtextutil::expander\fR
\fIfiles/modules/textutil/expander\&.n\fR: Procedures to process templates and expand text\&.
.TP
\fBtextutil::patch\fR
\fIfiles/modules/textutil/patch\&.n\fR: Application of uni-diff patches to directory trees
.TP
\fBtextutil::repeat\fR
\fIfiles/modules/textutil/repeat\&.n\fR: Procedures to repeat strings\&.
.TP
\fBtextutil::split\fR
\fIfiles/modules/textutil/textutil_split\&.n\fR: Procedures to split texts
.TP
\fBtextutil::string\fR
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
.TP
\fBtiff\fR
\fIfiles/modules/tiff/tiff\&.n\fR: TIFF reading, writing, and querying and manipulation of meta data
.TP
\fBtool\fR
\fIfiles/modules/tool/tool\&.n\fR: TclOO Library (TOOL) Framework
.TP
\fBtool\fR
\fIfiles/modules/httpd/httpd\&.n\fR: A TclOO and coroutine based web server
.TP
\fBtool::dict_ensemble\fR
\fIfiles/modules/tool/tool_dict_ensemble\&.n\fR: Dictionary Tools
.TP
\fBtransfer::connect\fR
\fIfiles/modules/transfer/connect\&.n\fR: Connection setup
.TP
\fBtransfer::copy\fR







<
<
<







1466
1467
1468
1469
1470
1471
1472



1473
1474
1475
1476
1477
1478
1479
.TP
\fBtiff\fR
\fIfiles/modules/tiff/tiff\&.n\fR: TIFF reading, writing, and querying and manipulation of meta data
.TP
\fBtool\fR
\fIfiles/modules/tool/tool\&.n\fR: TclOO Library (TOOL) Framework
.TP



\fBtool::dict_ensemble\fR
\fIfiles/modules/tool/tool_dict_ensemble\&.n\fR: Dictionary Tools
.TP
\fBtransfer::connect\fR
\fIfiles/modules/transfer/connect\&.n\fR: Connection setup
.TP
\fBtransfer::copy\fR

Changes to idoc/www/index.html.

1016
1017
1018
1019
1020
1021
1022










1023
1024
1025
1026
1027
1028
1029
<a href="tcllib/files/modules/docstrip/docstrip_util.html"> docstrip_util </a> &#183; <a href="tcllib/files/modules/struct/struct_list.html"> struct::list </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="diff_n_format"> diff -n format </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/rcs/rcs.html"> rcs </a>
</td></tr>










<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="difference"> difference </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/struct_set.html"> struct::set </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="differential"> differential </a></td>







>
>
>
>
>
>
>
>
>
>







1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
<a href="tcllib/files/modules/docstrip/docstrip_util.html"> docstrip_util </a> &#183; <a href="tcllib/files/modules/struct/struct_list.html"> struct::list </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="diff_n_format"> diff -n format </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/rcs/rcs.html"> rcs </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="diff_run"> diff -ruN </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/textutil/patch.html"> textutil::patch </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="diff_unified_format"> diff, unified format </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/textutil/patch.html"> textutil::patch </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="difference"> difference </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/struct_set.html"> struct::set </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="differential"> differential </a></td>
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
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="formatting_engine"> formatting engine </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools/docidx_plugin_apiref.html"> docidx_plugin_apiref </a> &#183; <a href="tcllib/files/modules/doctools/doctoc_plugin_apiref.html"> doctoc_plugin_apiref </a> &#183; <a href="tcllib/files/modules/doctools/doctools_plugin_apiref.html"> doctools_plugin_apiref </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>





<td class="#doctools_idxleft" width="35%"><a name="fourier_transform"> Fourier transform </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/fourier.html"> math::fourier </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="fr"> FR </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools2idx/idx_msgcat_fr.html"> doctools::msgcat::idx::fr </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_msgcat_fr.html"> doctools::msgcat::toc::fr </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="frame"> frame </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/term/ansi_cmacros.html"> term::ansi::code::macros </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="framework"> framework </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/tool/tool.html"> tool </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="ftp"> ftp </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/ftp/ftp.html"> ftp </a> &#183; <a href="tcllib/files/modules/ftp/ftp_geturl.html"> ftp::geturl </a> &#183; <a href="tcllib/files/modules/ftpd/ftpd.html"> ftpd </a> &#183; <a href="tcllib/files/modules/uri/uri.html"> uri </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="ftpd"> ftpd </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/ftpd/ftpd.html"> ftpd </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="ftpserver"> ftpserver </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/ftpd/ftpd.html"> ftpd </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="full_outer_join"> full outer join </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/struct_list.html"> struct::list </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cG">Keywords: G</a>
</th></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="generate_event"> generate event </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uev/uevent.html"> uevent </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="generate_permutations"> generate permutations </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/struct_list.html"> struct::list </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="generation"> generation </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools2idx/idx_container.html"> doctools::idx </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_export.html"> doctools::idx::export </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_container.html"> doctools::toc </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_export.html"> doctools::toc::export </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="generator"> generator </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/generator/generator.html"> generator </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="geocoding"> geocoding </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/map/map_geocode_nominatim.html"> map::geocode::nominatim </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="geodesy"> geodesy </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/map/map_slippy.html"> map::slippy </a> &#183; <a href="tcllib/files/modules/mapproj/mapproj.html"> mapproj </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="geography"> geography </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/map/map_slippy.html"> map::slippy </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="get_character"> get character </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/term/receive.html"> term::receive </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="gets"> gets </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/coroutine/tcllib_coroutine.html"> coroutine </a> &#183; <a href="tcllib/files/modules/coroutine/coro_auto.html"> coroutine::auto </a>
</td></tr>





<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="global"> global </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/coroutine/tcllib_coroutine.html"> coroutine </a> &#183; <a href="tcllib/files/modules/coroutine/coro_auto.html"> coroutine::auto </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="golang"> golang </a></td>







>
>
>
>
>




|




|




|




|




|




|




|







|




|




|




|




|




|




|




|




|




>
>
>
>
>







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
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="formatting_engine"> formatting engine </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools/docidx_plugin_apiref.html"> docidx_plugin_apiref </a> &#183; <a href="tcllib/files/modules/doctools/doctoc_plugin_apiref.html"> doctoc_plugin_apiref </a> &#183; <a href="tcllib/files/modules/doctools/doctools_plugin_apiref.html"> doctools_plugin_apiref </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="fossil"> fossil </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/textutil/patch.html"> textutil::patch </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="fourier_transform"> Fourier transform </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/fourier.html"> math::fourier </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="fr"> FR </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools2idx/idx_msgcat_fr.html"> doctools::msgcat::idx::fr </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_msgcat_fr.html"> doctools::msgcat::toc::fr </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="frame"> frame </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/term/ansi_cmacros.html"> term::ansi::code::macros </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="framework"> framework </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/tool/tool.html"> tool </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="ftp"> ftp </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/ftp/ftp.html"> ftp </a> &#183; <a href="tcllib/files/modules/ftp/ftp_geturl.html"> ftp::geturl </a> &#183; <a href="tcllib/files/modules/ftpd/ftpd.html"> ftpd </a> &#183; <a href="tcllib/files/modules/uri/uri.html"> uri </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="ftpd"> ftpd </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/ftpd/ftpd.html"> ftpd </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="ftpserver"> ftpserver </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/ftpd/ftpd.html"> ftpd </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="full_outer_join"> full outer join </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/struct_list.html"> struct::list </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cG">Keywords: G</a>
</th></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="generate_event"> generate event </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uev/uevent.html"> uevent </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="generate_permutations"> generate permutations </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/struct_list.html"> struct::list </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="generation"> generation </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools2idx/idx_container.html"> doctools::idx </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_export.html"> doctools::idx::export </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_container.html"> doctools::toc </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_export.html"> doctools::toc::export </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="generator"> generator </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/generator/generator.html"> generator </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="geocoding"> geocoding </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/map/map_geocode_nominatim.html"> map::geocode::nominatim </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="geodesy"> geodesy </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/map/map_slippy.html"> map::slippy </a> &#183; <a href="tcllib/files/modules/mapproj/mapproj.html"> mapproj </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="geography"> geography </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/map/map_slippy.html"> map::slippy </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="get_character"> get character </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/term/receive.html"> term::receive </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="gets"> gets </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/coroutine/tcllib_coroutine.html"> coroutine </a> &#183; <a href="tcllib/files/modules/coroutine/coro_auto.html"> coroutine::auto </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="git"> git </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/textutil/patch.html"> textutil::patch </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="global"> global </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/coroutine/tcllib_coroutine.html"> coroutine </a> &#183; <a href="tcllib/files/modules/coroutine/coro_auto.html"> coroutine::auto </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="golang"> golang </a></td>
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
<td class="#doctools_idxleft" width="35%"><a name="html"> html </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/html/html.html"> html </a> &#183; <a href="tcllib/files/modules/htmlparse/htmlparse.html"> htmlparse </a> &#183; <a href="tcllib/files/modules/javascript/javascript.html"> javascript </a> &#183; <a href="tcllib/files/modules/ncgi/ncgi.html"> ncgi </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="http"> http </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/http/autoproxy.html"> autoproxy </a> &#183; <a href="tcllib/files/modules/map/map_geocode_nominatim.html"> map::geocode::nominatim </a> &#183; <a href="tcllib/files/modules/map/map_slippy_fetcher.html"> map::slippy::fetcher </a> &#183; <a href="tcllib/files/modules/httpd/httpd.html"> tool </a> &#183; <a href="tcllib/files/modules/uri/uri.html"> uri </a> &#183; <a href="tcllib/files/modules/websocket/websocket.html"> websocket </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="httpd"> httpd </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/httpd/httpd.html"> tool </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="https"> https </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uri/uri.html"> uri </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="httpserver"> httpserver </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/httpd/httpd.html"> tool </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="huddle"> huddle </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/yaml/huddle.html"> huddle </a> &#183; <a href="tcllib/files/modules/yaml/yaml.html"> yaml </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>







|




|









|







1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
<td class="#doctools_idxleft" width="35%"><a name="html"> html </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/html/html.html"> html </a> &#183; <a href="tcllib/files/modules/htmlparse/htmlparse.html"> htmlparse </a> &#183; <a href="tcllib/files/modules/javascript/javascript.html"> javascript </a> &#183; <a href="tcllib/files/modules/ncgi/ncgi.html"> ncgi </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="http"> http </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/http/autoproxy.html"> autoproxy </a> &#183; <a href="tcllib/files/modules/httpd/httpd.html"> httpd </a> &#183; <a href="tcllib/files/modules/map/map_geocode_nominatim.html"> map::geocode::nominatim </a> &#183; <a href="tcllib/files/modules/map/map_slippy_fetcher.html"> map::slippy::fetcher </a> &#183; <a href="tcllib/files/modules/uri/uri.html"> uri </a> &#183; <a href="tcllib/files/modules/websocket/websocket.html"> websocket </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="httpd"> httpd </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/httpd/httpd.html"> httpd </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="https"> https </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uri/uri.html"> uri </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="httpserver"> httpserver </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/httpd/httpd.html"> httpd </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="huddle"> huddle </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/yaml/huddle.html"> huddle </a> &#183; <a href="tcllib/files/modules/yaml/yaml.html"> yaml </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
<td class="#doctools_idxleft" width="35%"><a name="math"> math </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/math.html"> math </a> &#183; <a href="tcllib/files/modules/math/bigfloat.html"> math::bigfloat </a> &#183; <a href="tcllib/files/modules/math/bignum.html"> math::bignum </a> &#183; <a href="tcllib/files/modules/math/calculus.html"> math::calculus </a> &#183; <a href="tcllib/files/modules/math/qcomplex.html"> math::complexnumbers </a> &#183; <a href="tcllib/files/modules/math/constants.html"> math::constants </a> &#183; <a href="tcllib/files/modules/math/decimal.html"> math::decimal </a> &#183; <a href="tcllib/files/modules/math/fuzzy.html"> math::fuzzy </a> &#183; <a href="tcllib/files/modules/math/math_geometry.html"> math::geometry </a> &#183; <a href="tcllib/files/modules/math/interpolate.html"> math::interpolate </a> &#183; <a href="tcllib/files/modules/math/linalg.html"> math::linearalgebra </a> &#183; <a href="tcllib/files/modules/math/optimize.html"> math::optimize </a> &#183; <a href="tcllib/files/modules/math/pca.html"> math::PCA </a> &#183; <a href="tcllib/files/modules/math/polynomials.html"> math::polynomials </a> &#183; <a href="tcllib/files/modules/math/rational_funcs.html"> math::rationalfunctions </a> &#183; <a href="tcllib/files/modules/math/special.html"> math::special </a> &#183; <a href="tcllib/files/modules/math/trig.html"> math::trig </a> &#183; <a href="tcllib/files/modules/simulation/annealing.html"> simulation::annealing </a> &#183; <a href="tcllib/files/modules/simulation/montecarlo.html"> simulation::montecarlo </a> &#183; <a href="tcllib/files/modules/simulation/simulation_random.html"> simulation::random </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="mathematics"> mathematics </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/fourier.html"> math::fourier </a> &#183; <a href="tcllib/files/modules/math/statistics.html"> math::statistics </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="matrices"> matrices </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/linalg.html"> math::linearalgebra </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>







|







2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
<td class="#doctools_idxleft" width="35%"><a name="math"> math </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/math.html"> math </a> &#183; <a href="tcllib/files/modules/math/bigfloat.html"> math::bigfloat </a> &#183; <a href="tcllib/files/modules/math/bignum.html"> math::bignum </a> &#183; <a href="tcllib/files/modules/math/calculus.html"> math::calculus </a> &#183; <a href="tcllib/files/modules/math/qcomplex.html"> math::complexnumbers </a> &#183; <a href="tcllib/files/modules/math/constants.html"> math::constants </a> &#183; <a href="tcllib/files/modules/math/decimal.html"> math::decimal </a> &#183; <a href="tcllib/files/modules/math/fuzzy.html"> math::fuzzy </a> &#183; <a href="tcllib/files/modules/math/math_geometry.html"> math::geometry </a> &#183; <a href="tcllib/files/modules/math/interpolate.html"> math::interpolate </a> &#183; <a href="tcllib/files/modules/math/linalg.html"> math::linearalgebra </a> &#183; <a href="tcllib/files/modules/math/optimize.html"> math::optimize </a> &#183; <a href="tcllib/files/modules/math/pca.html"> math::PCA </a> &#183; <a href="tcllib/files/modules/math/polynomials.html"> math::polynomials </a> &#183; <a href="tcllib/files/modules/math/rational_funcs.html"> math::rationalfunctions </a> &#183; <a href="tcllib/files/modules/math/special.html"> math::special </a> &#183; <a href="tcllib/files/modules/math/trig.html"> math::trig </a> &#183; <a href="tcllib/files/modules/simulation/annealing.html"> simulation::annealing </a> &#183; <a href="tcllib/files/modules/simulation/montecarlo.html"> simulation::montecarlo </a> &#183; <a href="tcllib/files/modules/simulation/simulation_random.html"> simulation::random </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="mathematics"> mathematics </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/fourier.html"> math::fourier </a> &#183; <a href="tcllib/files/modules/math/quasirandom.html"> math::quasirandom </a> &#183; <a href="tcllib/files/modules/math/statistics.html"> math::statistics </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="matrices"> matrices </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/linalg.html"> math::linearalgebra </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
2620
2621
2622
2623
2624
2625
2626





2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936





2937
2938
2939
2940
2941
2942
2943
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="one_time_pad"> one time pad </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/virtchannel_transform/vt_otp.html"> tcl::transform::otp </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>





<td class="#doctools_idxleft" width="35%"><a name="optimization"> optimization </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/optimize.html"> math::optimize </a> &#183; <a href="tcllib/files/modules/simulation/annealing.html"> simulation::annealing </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="ordered_list"> ordered list </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/prioqueue.html"> struct::prioqueue </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="otp"> otp </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/virtchannel_transform/vt_otp.html"> tcl::transform::otp </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="outer_join"> outer join </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/struct_list.html"> struct::list </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cP">Keywords: P</a>
</th></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="package"> package </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/csv/csv.html"> csv </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="package_indexing"> package indexing </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/docstrip/docstrip_util.html"> docstrip_util </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="page"> page </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/page/page_intro.html"> page_intro </a> &#183; <a href="tcllib/files/modules/page/page_pluginmgr.html"> page_pluginmgr </a> &#183; <a href="tcllib/files/modules/page/page_util_flow.html"> page_util_flow </a> &#183; <a href="tcllib/files/modules/page/page_util_norm_lemon.html"> page_util_norm_lemon </a> &#183; <a href="tcllib/files/modules/page/page_util_norm_peg.html"> page_util_norm_peg </a> &#183; <a href="tcllib/files/modules/page/page_util_peg.html"> page_util_peg </a> &#183; <a href="tcllib/files/modules/page/page_util_quote.html"> page_util_quote </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="pager"> pager </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/term/ipager.html"> term::interact::pager </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="paragraph"> paragraph </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/textutil/textutil.html"> textutil </a> &#183; <a href="tcllib/files/modules/textutil/adjust.html"> textutil::adjust </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="param"> PARAM </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/pt/pt_peg_to_param.html"> pt::peg::to::param </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="parameter_entry_form"> parameter entry form </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/tepam/tepam_introduction.html"> tepam </a> &#183; <a href="tcllib/files/modules/tepam/tepam_argument_dialogbox.html"> tepam::argument_dialogbox </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="parser"> parser </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools2idx/idx_parse.html"> doctools::idx::parse </a> &#183; <a href="tcllib/files/modules/doctools2base/tcl_parse.html"> doctools::tcl::parse </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_parse.html"> doctools::toc::parse </a> &#183; <a href="tcllib/files/modules/grammar_aycock/aycock.html"> grammar::aycock </a> &#183; <a href="tcllib/files/apps/pt.html"> pt </a> &#183; <a href="tcllib/files/modules/pt/pt_astree.html"> pt::ast </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_critcl.html"> pt::cparam::configuration::critcl </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_tea.html"> pt::cparam::configuration::tea </a> &#183; <a href="tcllib/files/modules/pt/pt_json_language.html"> pt::json_language </a> &#183; <a href="tcllib/files/modules/pt/pt_param.html"> pt::param </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpression.html"> pt::pe </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpr_op.html"> pt::pe::op </a> &#183; <a href="tcllib/files/modules/pt/pt_pegrammar.html"> pt::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container.html"> pt::peg::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container_peg.html"> pt::peg::container::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export.html"> pt::peg::export </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_container.html"> pt::peg::export::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_json.html"> pt::peg::export::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_peg.html"> pt::peg::export::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_container.html"> pt::peg::from::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_json.html"> pt::peg::from::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_peg.html"> pt::peg::from::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import.html"> pt::peg::import </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_container.html"> pt::peg::import::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_json.html"> pt::peg::import::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_peg.html"> pt::peg::import::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_interp.html"> pt::peg::interp </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_container.html"> pt::peg::to::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_cparam.html"> pt::peg::to::cparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_json.html"> pt::peg::to::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_param.html"> pt::peg::to::param </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_peg.html"> pt::peg::to::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_tclparam.html"> pt::peg::to::tclparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_language.html"> pt::peg_language </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_introduction.html"> pt::pegrammar </a> &#183; <a href="tcllib/files/modules/pt/pt_pgen.html"> pt::pgen </a> &#183; <a href="tcllib/files/modules/pt/pt_rdengine.html"> pt::rde </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_nx.html"> pt::tclparam::configuration::nx </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_snit.html"> pt::tclparam::configuration::snit </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_tcloo.html"> pt::tclparam::configuration::tcloo </a> &#183; <a href="tcllib/files/modules/pt/pt_util.html"> pt::util </a> &#183; <a href="tcllib/files/modules/pt/pt_to_api.html"> pt_export_api </a> &#183; <a href="tcllib/files/modules/pt/pt_from_api.html"> pt_import_api </a> &#183; <a href="tcllib/files/modules/pt/pt_introduction.html"> pt_introduction </a> &#183; <a href="tcllib/files/modules/pt/pt_parse_peg.html"> pt_parse_peg </a> &#183; <a href="tcllib/files/modules/pt/pt_parser_api.html"> pt_parser_api </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_op.html"> pt_peg_op </a> &#183; <a href="tcllib/files/modules/amazon-s3/xsxp.html"> xsxp </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="parser_generator"> parser generator </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/apps/page.html"> page </a> &#183; <a href="tcllib/files/modules/page/page_intro.html"> page_intro </a> &#183; <a href="tcllib/files/modules/page/page_pluginmgr.html"> page_pluginmgr </a> &#183; <a href="tcllib/files/modules/page/page_util_flow.html"> page_util_flow </a> &#183; <a href="tcllib/files/modules/page/page_util_norm_lemon.html"> page_util_norm_lemon </a> &#183; <a href="tcllib/files/modules/page/page_util_norm_peg.html"> page_util_norm_peg </a> &#183; <a href="tcllib/files/modules/page/page_util_peg.html"> page_util_peg </a> &#183; <a href="tcllib/files/modules/page/page_util_quote.html"> page_util_quote </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="parsing"> parsing </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/bench/bench_read.html"> bench::in </a> &#183; <a href="tcllib/files/modules/bibtex/bibtex.html"> bibtex </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_introduction.html"> doctools2idx_introduction </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_introduction.html"> doctools2toc_introduction </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_container.html"> doctools::idx </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_import.html"> doctools::idx::import </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_container.html"> doctools::toc </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_import.html"> doctools::toc::import </a> &#183; <a href="tcllib/files/modules/grammar_aycock/aycock.html"> grammar::aycock </a> &#183; <a href="tcllib/files/modules/grammar_fa/fa.html"> grammar::fa </a> &#183; <a href="tcllib/files/modules/grammar_fa/dacceptor.html"> grammar::fa::dacceptor </a> &#183; <a href="tcllib/files/modules/grammar_fa/dexec.html"> grammar::fa::dexec </a> &#183; <a href="tcllib/files/modules/grammar_fa/faop.html"> grammar::fa::op </a> &#183; <a href="tcllib/files/modules/grammar_me/me_cpu.html"> grammar::me::cpu </a> &#183; <a href="tcllib/files/modules/grammar_me/me_cpucore.html"> grammar::me::cpu::core </a> &#183; <a href="tcllib/files/modules/grammar_me/gasm.html"> grammar::me::cpu::gasm </a> &#183; <a href="tcllib/files/modules/grammar_me/me_tcl.html"> grammar::me::tcl </a> &#183; <a href="tcllib/files/modules/grammar_me/me_intro.html"> grammar::me_intro </a> &#183; <a href="tcllib/files/modules/grammar_me/me_vm.html"> grammar::me_vm </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg.html"> grammar::peg </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg_interp.html"> grammar::peg::interp </a> &#183; <a href="tcllib/files/modules/htmlparse/htmlparse.html"> htmlparse </a> &#183; <a href="tcllib/files/modules/yaml/huddle.html"> huddle </a> &#183; <a href="tcllib/files/modules/string/token_shell.html"> string::token::shell </a> &#183; <a href="tcllib/files/modules/yaml/yaml.html"> yaml </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="parsing_expression"> parsing expression </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/grammar_peg/peg.html"> grammar::peg </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg_interp.html"> grammar::peg::interp </a> &#183; <a href="tcllib/files/apps/pt.html"> pt </a> &#183; <a href="tcllib/files/modules/pt/pt_astree.html"> pt::ast </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_critcl.html"> pt::cparam::configuration::critcl </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_tea.html"> pt::cparam::configuration::tea </a> &#183; <a href="tcllib/files/modules/pt/pt_json_language.html"> pt::json_language </a> &#183; <a href="tcllib/files/modules/pt/pt_param.html"> pt::param </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpression.html"> pt::pe </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpr_op.html"> pt::pe::op </a> &#183; <a href="tcllib/files/modules/pt/pt_pegrammar.html"> pt::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container.html"> pt::peg::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container_peg.html"> pt::peg::container::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export.html"> pt::peg::export </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_container.html"> pt::peg::export::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_json.html"> pt::peg::export::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_peg.html"> pt::peg::export::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_container.html"> pt::peg::from::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_json.html"> pt::peg::from::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_peg.html"> pt::peg::from::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import.html"> pt::peg::import </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_container.html"> pt::peg::import::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_json.html"> pt::peg::import::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_peg.html"> pt::peg::import::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_interp.html"> pt::peg::interp </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_container.html"> pt::peg::to::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_cparam.html"> pt::peg::to::cparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_json.html"> pt::peg::to::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_param.html"> pt::peg::to::param </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_peg.html"> pt::peg::to::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_tclparam.html"> pt::peg::to::tclparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_language.html"> pt::peg_language </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_introduction.html"> pt::pegrammar </a> &#183; <a href="tcllib/files/modules/pt/pt_pgen.html"> pt::pgen </a> &#183; <a href="tcllib/files/modules/pt/pt_rdengine.html"> pt::rde </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_nx.html"> pt::tclparam::configuration::nx </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_snit.html"> pt::tclparam::configuration::snit </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_tcloo.html"> pt::tclparam::configuration::tcloo </a> &#183; <a href="tcllib/files/modules/pt/pt_util.html"> pt::util </a> &#183; <a href="tcllib/files/modules/pt/pt_to_api.html"> pt_export_api </a> &#183; <a href="tcllib/files/modules/pt/pt_from_api.html"> pt_import_api </a> &#183; <a href="tcllib/files/modules/pt/pt_introduction.html"> pt_introduction </a> &#183; <a href="tcllib/files/modules/pt/pt_parse_peg.html"> pt_parse_peg </a> &#183; <a href="tcllib/files/modules/pt/pt_parser_api.html"> pt_parser_api </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_op.html"> pt_peg_op </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="parsing_expression_grammar"> parsing expression grammar </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/grammar_me/me_intro.html"> grammar::me_intro </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg.html"> grammar::peg </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg_interp.html"> grammar::peg::interp </a> &#183; <a href="tcllib/files/modules/page/page_util_peg.html"> page_util_peg </a> &#183; <a href="tcllib/files/apps/pt.html"> pt </a> &#183; <a href="tcllib/files/modules/pt/pt_astree.html"> pt::ast </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_critcl.html"> pt::cparam::configuration::critcl </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_tea.html"> pt::cparam::configuration::tea </a> &#183; <a href="tcllib/files/modules/pt/pt_json_language.html"> pt::json_language </a> &#183; <a href="tcllib/files/modules/pt/pt_param.html"> pt::param </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpression.html"> pt::pe </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpr_op.html"> pt::pe::op </a> &#183; <a href="tcllib/files/modules/pt/pt_pegrammar.html"> pt::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container.html"> pt::peg::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container_peg.html"> pt::peg::container::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export.html"> pt::peg::export </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_container.html"> pt::peg::export::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_json.html"> pt::peg::export::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_peg.html"> pt::peg::export::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_container.html"> pt::peg::from::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_json.html"> pt::peg::from::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_peg.html"> pt::peg::from::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import.html"> pt::peg::import </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_container.html"> pt::peg::import::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_json.html"> pt::peg::import::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_peg.html"> pt::peg::import::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_interp.html"> pt::peg::interp </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_container.html"> pt::peg::to::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_cparam.html"> pt::peg::to::cparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_json.html"> pt::peg::to::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_param.html"> pt::peg::to::param </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_peg.html"> pt::peg::to::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_tclparam.html"> pt::peg::to::tclparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_language.html"> pt::peg_language </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_introduction.html"> pt::pegrammar </a> &#183; <a href="tcllib/files/modules/pt/pt_pgen.html"> pt::pgen </a> &#183; <a href="tcllib/files/modules/pt/pt_rdengine.html"> pt::rde </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_nx.html"> pt::tclparam::configuration::nx </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_snit.html"> pt::tclparam::configuration::snit </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_tcloo.html"> pt::tclparam::configuration::tcloo </a> &#183; <a href="tcllib/files/modules/pt/pt_util.html"> pt::util </a> &#183; <a href="tcllib/files/modules/pt/pt_to_api.html"> pt_export_api </a> &#183; <a href="tcllib/files/modules/pt/pt_from_api.html"> pt_import_api </a> &#183; <a href="tcllib/files/modules/pt/pt_introduction.html"> pt_introduction </a> &#183; <a href="tcllib/files/modules/pt/pt_parse_peg.html"> pt_parse_peg </a> &#183; <a href="tcllib/files/modules/pt/pt_parser_api.html"> pt_parser_api </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_op.html"> pt_peg_op </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="partial_application"> partial application </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/lambda/lambda.html"> lambda </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="partition"> partition </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/disjointset.html"> struct::disjointset </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="partitioned_set"> partitioned set </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/disjointset.html"> struct::disjointset </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="passive"> passive </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/transfer/connect.html"> transfer::connect </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="password"> password </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/otp/otp.html"> otp </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="patch"> patch </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/docstrip/docstrip_util.html"> docstrip_util </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="patching"> patching </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/rcs/rcs.html"> rcs </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="pca"> PCA </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/pca.html"> math::PCA </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="peg"> PEG </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/grammar_me/me_intro.html"> grammar::me_intro </a> &#183; <a href="tcllib/files/modules/page/page_util_norm_peg.html"> page_util_norm_peg </a> &#183; <a href="tcllib/files/modules/page/page_util_peg.html"> page_util_peg </a> &#183; <a href="tcllib/files/apps/pt.html"> pt </a> &#183; <a href="tcllib/files/modules/pt/pt_astree.html"> pt::ast </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_critcl.html"> pt::cparam::configuration::critcl </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_tea.html"> pt::cparam::configuration::tea </a> &#183; <a href="tcllib/files/modules/pt/pt_json_language.html"> pt::json_language </a> &#183; <a href="tcllib/files/modules/pt/pt_param.html"> pt::param </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpression.html"> pt::pe </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpr_op.html"> pt::pe::op </a> &#183; <a href="tcllib/files/modules/pt/pt_pegrammar.html"> pt::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container.html"> pt::peg::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container_peg.html"> pt::peg::container::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export.html"> pt::peg::export </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_container.html"> pt::peg::export::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_json.html"> pt::peg::export::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_peg.html"> pt::peg::export::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_container.html"> pt::peg::from::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_json.html"> pt::peg::from::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_peg.html"> pt::peg::from::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import.html"> pt::peg::import </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_container.html"> pt::peg::import::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_json.html"> pt::peg::import::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_peg.html"> pt::peg::import::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_interp.html"> pt::peg::interp </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_container.html"> pt::peg::to::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_cparam.html"> pt::peg::to::cparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_json.html"> pt::peg::to::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_param.html"> pt::peg::to::param </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_peg.html"> pt::peg::to::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_tclparam.html"> pt::peg::to::tclparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_language.html"> pt::peg_language </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_introduction.html"> pt::pegrammar </a> &#183; <a href="tcllib/files/modules/pt/pt_pgen.html"> pt::pgen </a> &#183; <a href="tcllib/files/modules/pt/pt_rdengine.html"> pt::rde </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_nx.html"> pt::tclparam::configuration::nx </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_snit.html"> pt::tclparam::configuration::snit </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_tcloo.html"> pt::tclparam::configuration::tcloo </a> &#183; <a href="tcllib/files/modules/pt/pt_util.html"> pt::util </a> &#183; <a href="tcllib/files/modules/pt/pt_to_api.html"> pt_export_api </a> &#183; <a href="tcllib/files/modules/pt/pt_from_api.html"> pt_import_api </a> &#183; <a href="tcllib/files/modules/pt/pt_introduction.html"> pt_introduction </a> &#183; <a href="tcllib/files/modules/pt/pt_parse_peg.html"> pt_parse_peg </a> &#183; <a href="tcllib/files/modules/pt/pt_parser_api.html"> pt_parser_api </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_op.html"> pt_peg_op </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="performance"> performance </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/bench/bench.html"> bench </a> &#183; <a href="tcllib/files/modules/bench/bench_read.html"> bench::in </a> &#183; <a href="tcllib/files/modules/bench/bench_wcsv.html"> bench::out::csv </a> &#183; <a href="tcllib/files/modules/bench/bench_wtext.html"> bench::out::text </a> &#183; <a href="tcllib/files/modules/bench/bench_intro.html"> bench_intro </a> &#183; <a href="tcllib/files/modules/bench/bench_lang_intro.html"> bench_lang_intro </a> &#183; <a href="tcllib/files/modules/bench/bench_lang_spec.html"> bench_lang_spec </a> &#183; <a href="tcllib/files/modules/profiler/profiler.html"> profiler </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="permutation"> permutation </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/struct_list.html"> struct::list </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="persistence"> persistence </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/tie/tie_std.html"> tie </a> &#183; <a href="tcllib/files/modules/tie/tie.html"> tie </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="phone"> phone </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/valtype/imei.html"> valtype::imei </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="pi"> pi </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/constants.html"> math::constants </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="plain_text"> plain text </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools2idx/idx_export_text.html"> doctools::idx::export::text </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_export_text.html"> doctools::toc::export::text </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="plane_geometry"> plane geometry </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/math_geometry.html"> math::geometry </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="plugin"> plugin </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools/docidx_plugin_apiref.html"> docidx_plugin_apiref </a> &#183; <a href="tcllib/files/modules/doctools/doctoc_plugin_apiref.html"> doctoc_plugin_apiref </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_introduction.html"> doctools2idx_introduction </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_introduction.html"> doctools2toc_introduction </a> &#183; <a href="tcllib/files/modules/doctools2base/html_cssdefaults.html"> doctools::html::cssdefaults </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_container.html"> doctools::idx </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_export.html"> doctools::idx::export </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_import.html"> doctools::idx::import </a> &#183; <a href="tcllib/files/modules/doctools2base/nroff_manmacros.html"> doctools::nroff::man_macros </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_container.html"> doctools::toc </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_export.html"> doctools::toc::export </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_import.html"> doctools::toc::import </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_container.html"> pt::peg::export::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_json.html"> pt::peg::export::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_peg.html"> pt::peg::export::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_json.html"> pt::peg::import::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_peg.html"> pt::peg::import::peg </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="plugin_management"> plugin management </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/pluginmgr/pluginmgr.html"> pluginmgr </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="plugin_search"> plugin search </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/pluginmgr/pluginmgr.html"> pluginmgr </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="png"> png </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/png/png.html"> png </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="point"> point </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/math_geometry.html"> math::geometry </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="polynomial_functions"> polynomial functions </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/polynomials.html"> math::polynomials </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="pool"> pool </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/pool.html"> struct::pool </a> &#183; <a href="tcllib/files/modules/struct/queue.html"> struct::queue </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="pop"> pop </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/pop3/pop3.html"> pop3 </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="pop3"> pop3 </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/pop3/pop3.html"> pop3 </a> &#183; <a href="tcllib/files/modules/pop3d/pop3d.html"> pop3d </a> &#183; <a href="tcllib/files/modules/pop3d/pop3d_dbox.html"> pop3d::dbox </a> &#183; <a href="tcllib/files/modules/pop3d/pop3d_udb.html"> pop3d::udb </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="post_order"> post-order </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/struct_tree.html"> struct::tree </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="practcl"> practcl </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/practcl/practcl.html"> practcl </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="pre_order"> pre-order </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/struct_tree.html"> struct::tree </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="prefix"> prefix </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/textutil/textutil_string.html"> textutil::string </a> &#183; <a href="tcllib/files/modules/textutil/trim.html"> textutil::trim </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="prime"> prime </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/numtheory.html"> math::numtheory </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="prioqueue"> prioqueue </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/prioqueue.html"> struct::prioqueue </a> &#183; <a href="tcllib/files/modules/struct/queue.html"> struct::queue </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="priority_queue"> priority queue </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/prioqueue.html"> struct::prioqueue </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="proc"> proc </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/lambda/lambda.html"> lambda </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="procedure"> procedure </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/interp/deleg_proc.html"> deleg_proc </a> &#183; <a href="tcllib/files/modules/tepam/tepam_introduction.html"> tepam </a> &#183; <a href="tcllib/files/modules/tepam/tepam_procedure.html"> tepam::procedure </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="procedure_documentation"> procedure documentation </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/tepam/tepam_doc_gen.html"> tepam::doc_gen </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="processman"> processman </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/processman/processman.html"> processman </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="producer"> producer </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/hook/hook.html"> hook </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="profile"> profile </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/profiler/profiler.html"> profiler </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="projection"> projection </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/mapproj/mapproj.html"> mapproj </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="prospero"> prospero </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uri/uri.html"> uri </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="protocol"> protocol </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/asn/asn.html"> asn </a> &#183; <a href="tcllib/files/modules/ldap/ldap.html"> ldap </a> &#183; <a href="tcllib/files/modules/ldap/ldapx.html"> ldapx </a> &#183; <a href="tcllib/files/modules/nns/nns_protocol.html"> nameserv::protocol </a> &#183; <a href="tcllib/files/modules/pop3d/pop3d.html"> pop3d </a> &#183; <a href="tcllib/files/modules/pop3d/pop3d_dbox.html"> pop3d::dbox </a> &#183; <a href="tcllib/files/modules/pop3d/pop3d_udb.html"> pop3d::udb </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="proxy"> proxy </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/http/autoproxy.html"> autoproxy </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="public_key_cipher"> public key cipher </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/pki/pki.html"> pki </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="publisher"> publisher </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/hook/hook.html"> hook </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="push_down_automaton"> push down automaton </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/grammar_me/me_intro.html"> grammar::me_intro </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg.html"> grammar::peg </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg_interp.html"> grammar::peg::interp </a> &#183; <a href="tcllib/files/apps/pt.html"> pt </a> &#183; <a href="tcllib/files/modules/pt/pt_astree.html"> pt::ast </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_critcl.html"> pt::cparam::configuration::critcl </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_tea.html"> pt::cparam::configuration::tea </a> &#183; <a href="tcllib/files/modules/pt/pt_json_language.html"> pt::json_language </a> &#183; <a href="tcllib/files/modules/pt/pt_param.html"> pt::param </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpression.html"> pt::pe </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpr_op.html"> pt::pe::op </a> &#183; <a href="tcllib/files/modules/pt/pt_pegrammar.html"> pt::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container.html"> pt::peg::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container_peg.html"> pt::peg::container::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export.html"> pt::peg::export </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_container.html"> pt::peg::export::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_json.html"> pt::peg::export::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_peg.html"> pt::peg::export::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_container.html"> pt::peg::from::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_json.html"> pt::peg::from::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_peg.html"> pt::peg::from::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import.html"> pt::peg::import </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_container.html"> pt::peg::import::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_json.html"> pt::peg::import::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_peg.html"> pt::peg::import::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_interp.html"> pt::peg::interp </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_container.html"> pt::peg::to::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_cparam.html"> pt::peg::to::cparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_json.html"> pt::peg::to::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_param.html"> pt::peg::to::param </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_peg.html"> pt::peg::to::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_tclparam.html"> pt::peg::to::tclparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_language.html"> pt::peg_language </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_introduction.html"> pt::pegrammar </a> &#183; <a href="tcllib/files/modules/pt/pt_pgen.html"> pt::pgen </a> &#183; <a href="tcllib/files/modules/pt/pt_rdengine.html"> pt::rde </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_nx.html"> pt::tclparam::configuration::nx </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_snit.html"> pt::tclparam::configuration::snit </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_tcloo.html"> pt::tclparam::configuration::tcloo </a> &#183; <a href="tcllib/files/modules/pt/pt_util.html"> pt::util </a> &#183; <a href="tcllib/files/modules/pt/pt_to_api.html"> pt_export_api </a> &#183; <a href="tcllib/files/modules/pt/pt_from_api.html"> pt_import_api </a> &#183; <a href="tcllib/files/modules/pt/pt_introduction.html"> pt_introduction </a> &#183; <a href="tcllib/files/modules/pt/pt_parse_peg.html"> pt_parse_peg </a> &#183; <a href="tcllib/files/modules/pt/pt_parser_api.html"> pt_parser_api </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_op.html"> pt_peg_op </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cQ">Keywords: Q</a>
</th></tr>





<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="queue"> queue </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/csv/csv.html"> csv </a> &#183; <a href="tcllib/files/modules/htmlparse/htmlparse.html"> htmlparse </a> &#183; <a href="tcllib/files/modules/struct/stack.html"> struct::stack </a> &#183; <a href="tcllib/files/modules/transfer/tqueue.html"> transfer::copy::queue </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="quoting"> quoting </a></td>







>
>
>
>
>




|




|




|







|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|


|

|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|




|







>
>
>
>
>







2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="one_time_pad"> one time pad </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/virtchannel_transform/vt_otp.html"> tcl::transform::otp </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="oo"> oo </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/clay/clay.html"> clay </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="optimization"> optimization </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/optimize.html"> math::optimize </a> &#183; <a href="tcllib/files/modules/simulation/annealing.html"> simulation::annealing </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="ordered_list"> ordered list </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/prioqueue.html"> struct::prioqueue </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="otp"> otp </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/virtchannel_transform/vt_otp.html"> tcl::transform::otp </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="outer_join"> outer join </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/struct_list.html"> struct::list </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cP">Keywords: P</a>
</th></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="package"> package </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/csv/csv.html"> csv </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="package_indexing"> package indexing </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/docstrip/docstrip_util.html"> docstrip_util </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="page"> page </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/page/page_intro.html"> page_intro </a> &#183; <a href="tcllib/files/modules/page/page_pluginmgr.html"> page_pluginmgr </a> &#183; <a href="tcllib/files/modules/page/page_util_flow.html"> page_util_flow </a> &#183; <a href="tcllib/files/modules/page/page_util_norm_lemon.html"> page_util_norm_lemon </a> &#183; <a href="tcllib/files/modules/page/page_util_norm_peg.html"> page_util_norm_peg </a> &#183; <a href="tcllib/files/modules/page/page_util_peg.html"> page_util_peg </a> &#183; <a href="tcllib/files/modules/page/page_util_quote.html"> page_util_quote </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="pager"> pager </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/term/ipager.html"> term::interact::pager </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="paragraph"> paragraph </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/textutil/textutil.html"> textutil </a> &#183; <a href="tcllib/files/modules/textutil/adjust.html"> textutil::adjust </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="param"> PARAM </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/pt/pt_peg_to_param.html"> pt::peg::to::param </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="parameter_entry_form"> parameter entry form </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/tepam/tepam_introduction.html"> tepam </a> &#183; <a href="tcllib/files/modules/tepam/tepam_argument_dialogbox.html"> tepam::argument_dialogbox </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="parser"> parser </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools2idx/idx_parse.html"> doctools::idx::parse </a> &#183; <a href="tcllib/files/modules/doctools2base/tcl_parse.html"> doctools::tcl::parse </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_parse.html"> doctools::toc::parse </a> &#183; <a href="tcllib/files/modules/grammar_aycock/aycock.html"> grammar::aycock </a> &#183; <a href="tcllib/files/apps/pt.html"> pt </a> &#183; <a href="tcllib/files/modules/pt/pt_astree.html"> pt::ast </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_critcl.html"> pt::cparam::configuration::critcl </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_tea.html"> pt::cparam::configuration::tea </a> &#183; <a href="tcllib/files/modules/pt/pt_json_language.html"> pt::json_language </a> &#183; <a href="tcllib/files/modules/pt/pt_param.html"> pt::param </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpression.html"> pt::pe </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpr_op.html"> pt::pe::op </a> &#183; <a href="tcllib/files/modules/pt/pt_pegrammar.html"> pt::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container.html"> pt::peg::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container_peg.html"> pt::peg::container::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export.html"> pt::peg::export </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_container.html"> pt::peg::export::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_json.html"> pt::peg::export::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_peg.html"> pt::peg::export::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_container.html"> pt::peg::from::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_json.html"> pt::peg::from::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_peg.html"> pt::peg::from::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import.html"> pt::peg::import </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_container.html"> pt::peg::import::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_json.html"> pt::peg::import::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_peg.html"> pt::peg::import::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_interp.html"> pt::peg::interp </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_container.html"> pt::peg::to::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_cparam.html"> pt::peg::to::cparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_json.html"> pt::peg::to::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_param.html"> pt::peg::to::param </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_peg.html"> pt::peg::to::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_tclparam.html"> pt::peg::to::tclparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_language.html"> pt::peg_language </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_introduction.html"> pt::pegrammar </a> &#183; <a href="tcllib/files/modules/pt/pt_pgen.html"> pt::pgen </a> &#183; <a href="tcllib/files/modules/pt/pt_rdengine.html"> pt::rde </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_nx.html"> pt::tclparam::configuration::nx </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_snit.html"> pt::tclparam::configuration::snit </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_tcloo.html"> pt::tclparam::configuration::tcloo </a> &#183; <a href="tcllib/files/modules/pt/pt_util.html"> pt::util </a> &#183; <a href="tcllib/files/modules/pt/pt_to_api.html"> pt_export_api </a> &#183; <a href="tcllib/files/modules/pt/pt_from_api.html"> pt_import_api </a> &#183; <a href="tcllib/files/modules/pt/pt_introduction.html"> pt_introduction </a> &#183; <a href="tcllib/files/modules/pt/pt_parse_peg.html"> pt_parse_peg </a> &#183; <a href="tcllib/files/modules/pt/pt_parser_api.html"> pt_parser_api </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_op.html"> pt_peg_op </a> &#183; <a href="tcllib/files/modules/amazon-s3/xsxp.html"> xsxp </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="parser_generator"> parser generator </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/apps/page.html"> page </a> &#183; <a href="tcllib/files/modules/page/page_intro.html"> page_intro </a> &#183; <a href="tcllib/files/modules/page/page_pluginmgr.html"> page_pluginmgr </a> &#183; <a href="tcllib/files/modules/page/page_util_flow.html"> page_util_flow </a> &#183; <a href="tcllib/files/modules/page/page_util_norm_lemon.html"> page_util_norm_lemon </a> &#183; <a href="tcllib/files/modules/page/page_util_norm_peg.html"> page_util_norm_peg </a> &#183; <a href="tcllib/files/modules/page/page_util_peg.html"> page_util_peg </a> &#183; <a href="tcllib/files/modules/page/page_util_quote.html"> page_util_quote </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="parsing"> parsing </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/bench/bench_read.html"> bench::in </a> &#183; <a href="tcllib/files/modules/bibtex/bibtex.html"> bibtex </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_introduction.html"> doctools2idx_introduction </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_introduction.html"> doctools2toc_introduction </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_container.html"> doctools::idx </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_import.html"> doctools::idx::import </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_container.html"> doctools::toc </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_import.html"> doctools::toc::import </a> &#183; <a href="tcllib/files/modules/grammar_aycock/aycock.html"> grammar::aycock </a> &#183; <a href="tcllib/files/modules/grammar_fa/fa.html"> grammar::fa </a> &#183; <a href="tcllib/files/modules/grammar_fa/dacceptor.html"> grammar::fa::dacceptor </a> &#183; <a href="tcllib/files/modules/grammar_fa/dexec.html"> grammar::fa::dexec </a> &#183; <a href="tcllib/files/modules/grammar_fa/faop.html"> grammar::fa::op </a> &#183; <a href="tcllib/files/modules/grammar_me/me_cpu.html"> grammar::me::cpu </a> &#183; <a href="tcllib/files/modules/grammar_me/me_cpucore.html"> grammar::me::cpu::core </a> &#183; <a href="tcllib/files/modules/grammar_me/gasm.html"> grammar::me::cpu::gasm </a> &#183; <a href="tcllib/files/modules/grammar_me/me_tcl.html"> grammar::me::tcl </a> &#183; <a href="tcllib/files/modules/grammar_me/me_intro.html"> grammar::me_intro </a> &#183; <a href="tcllib/files/modules/grammar_me/me_vm.html"> grammar::me_vm </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg.html"> grammar::peg </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg_interp.html"> grammar::peg::interp </a> &#183; <a href="tcllib/files/modules/htmlparse/htmlparse.html"> htmlparse </a> &#183; <a href="tcllib/files/modules/yaml/huddle.html"> huddle </a> &#183; <a href="tcllib/files/modules/string/token_shell.html"> string::token::shell </a> &#183; <a href="tcllib/files/modules/yaml/yaml.html"> yaml </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="parsing_expression"> parsing expression </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/grammar_peg/peg.html"> grammar::peg </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg_interp.html"> grammar::peg::interp </a> &#183; <a href="tcllib/files/apps/pt.html"> pt </a> &#183; <a href="tcllib/files/modules/pt/pt_astree.html"> pt::ast </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_critcl.html"> pt::cparam::configuration::critcl </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_tea.html"> pt::cparam::configuration::tea </a> &#183; <a href="tcllib/files/modules/pt/pt_json_language.html"> pt::json_language </a> &#183; <a href="tcllib/files/modules/pt/pt_param.html"> pt::param </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpression.html"> pt::pe </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpr_op.html"> pt::pe::op </a> &#183; <a href="tcllib/files/modules/pt/pt_pegrammar.html"> pt::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container.html"> pt::peg::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container_peg.html"> pt::peg::container::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export.html"> pt::peg::export </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_container.html"> pt::peg::export::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_json.html"> pt::peg::export::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_peg.html"> pt::peg::export::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_container.html"> pt::peg::from::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_json.html"> pt::peg::from::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_peg.html"> pt::peg::from::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import.html"> pt::peg::import </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_container.html"> pt::peg::import::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_json.html"> pt::peg::import::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_peg.html"> pt::peg::import::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_interp.html"> pt::peg::interp </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_container.html"> pt::peg::to::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_cparam.html"> pt::peg::to::cparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_json.html"> pt::peg::to::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_param.html"> pt::peg::to::param </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_peg.html"> pt::peg::to::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_tclparam.html"> pt::peg::to::tclparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_language.html"> pt::peg_language </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_introduction.html"> pt::pegrammar </a> &#183; <a href="tcllib/files/modules/pt/pt_pgen.html"> pt::pgen </a> &#183; <a href="tcllib/files/modules/pt/pt_rdengine.html"> pt::rde </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_nx.html"> pt::tclparam::configuration::nx </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_snit.html"> pt::tclparam::configuration::snit </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_tcloo.html"> pt::tclparam::configuration::tcloo </a> &#183; <a href="tcllib/files/modules/pt/pt_util.html"> pt::util </a> &#183; <a href="tcllib/files/modules/pt/pt_to_api.html"> pt_export_api </a> &#183; <a href="tcllib/files/modules/pt/pt_from_api.html"> pt_import_api </a> &#183; <a href="tcllib/files/modules/pt/pt_introduction.html"> pt_introduction </a> &#183; <a href="tcllib/files/modules/pt/pt_parse_peg.html"> pt_parse_peg </a> &#183; <a href="tcllib/files/modules/pt/pt_parser_api.html"> pt_parser_api </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_op.html"> pt_peg_op </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="parsing_expression_grammar"> parsing expression grammar </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/grammar_me/me_intro.html"> grammar::me_intro </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg.html"> grammar::peg </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg_interp.html"> grammar::peg::interp </a> &#183; <a href="tcllib/files/modules/page/page_util_peg.html"> page_util_peg </a> &#183; <a href="tcllib/files/apps/pt.html"> pt </a> &#183; <a href="tcllib/files/modules/pt/pt_astree.html"> pt::ast </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_critcl.html"> pt::cparam::configuration::critcl </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_tea.html"> pt::cparam::configuration::tea </a> &#183; <a href="tcllib/files/modules/pt/pt_json_language.html"> pt::json_language </a> &#183; <a href="tcllib/files/modules/pt/pt_param.html"> pt::param </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpression.html"> pt::pe </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpr_op.html"> pt::pe::op </a> &#183; <a href="tcllib/files/modules/pt/pt_pegrammar.html"> pt::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container.html"> pt::peg::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container_peg.html"> pt::peg::container::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export.html"> pt::peg::export </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_container.html"> pt::peg::export::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_json.html"> pt::peg::export::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_peg.html"> pt::peg::export::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_container.html"> pt::peg::from::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_json.html"> pt::peg::from::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_peg.html"> pt::peg::from::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import.html"> pt::peg::import </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_container.html"> pt::peg::import::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_json.html"> pt::peg::import::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_peg.html"> pt::peg::import::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_interp.html"> pt::peg::interp </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_container.html"> pt::peg::to::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_cparam.html"> pt::peg::to::cparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_json.html"> pt::peg::to::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_param.html"> pt::peg::to::param </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_peg.html"> pt::peg::to::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_tclparam.html"> pt::peg::to::tclparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_language.html"> pt::peg_language </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_introduction.html"> pt::pegrammar </a> &#183; <a href="tcllib/files/modules/pt/pt_pgen.html"> pt::pgen </a> &#183; <a href="tcllib/files/modules/pt/pt_rdengine.html"> pt::rde </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_nx.html"> pt::tclparam::configuration::nx </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_snit.html"> pt::tclparam::configuration::snit </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_tcloo.html"> pt::tclparam::configuration::tcloo </a> &#183; <a href="tcllib/files/modules/pt/pt_util.html"> pt::util </a> &#183; <a href="tcllib/files/modules/pt/pt_to_api.html"> pt_export_api </a> &#183; <a href="tcllib/files/modules/pt/pt_from_api.html"> pt_import_api </a> &#183; <a href="tcllib/files/modules/pt/pt_introduction.html"> pt_introduction </a> &#183; <a href="tcllib/files/modules/pt/pt_parse_peg.html"> pt_parse_peg </a> &#183; <a href="tcllib/files/modules/pt/pt_parser_api.html"> pt_parser_api </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_op.html"> pt_peg_op </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="partial_application"> partial application </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/lambda/lambda.html"> lambda </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="partition"> partition </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/disjointset.html"> struct::disjointset </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="partitioned_set"> partitioned set </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/disjointset.html"> struct::disjointset </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="passive"> passive </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/transfer/connect.html"> transfer::connect </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="password"> password </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/otp/otp.html"> otp </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="patch"> patch </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/docstrip/docstrip_util.html"> docstrip_util </a> &#183; <a href="tcllib/files/modules/textutil/patch.html"> textutil::patch </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="patching"> patching </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/rcs/rcs.html"> rcs </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="pca"> PCA </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/pca.html"> math::PCA </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="peg"> PEG </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/grammar_me/me_intro.html"> grammar::me_intro </a> &#183; <a href="tcllib/files/modules/page/page_util_norm_peg.html"> page_util_norm_peg </a> &#183; <a href="tcllib/files/modules/page/page_util_peg.html"> page_util_peg </a> &#183; <a href="tcllib/files/apps/pt.html"> pt </a> &#183; <a href="tcllib/files/modules/pt/pt_astree.html"> pt::ast </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_critcl.html"> pt::cparam::configuration::critcl </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_tea.html"> pt::cparam::configuration::tea </a> &#183; <a href="tcllib/files/modules/pt/pt_json_language.html"> pt::json_language </a> &#183; <a href="tcllib/files/modules/pt/pt_param.html"> pt::param </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpression.html"> pt::pe </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpr_op.html"> pt::pe::op </a> &#183; <a href="tcllib/files/modules/pt/pt_pegrammar.html"> pt::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container.html"> pt::peg::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container_peg.html"> pt::peg::container::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export.html"> pt::peg::export </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_container.html"> pt::peg::export::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_json.html"> pt::peg::export::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_peg.html"> pt::peg::export::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_container.html"> pt::peg::from::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_json.html"> pt::peg::from::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_peg.html"> pt::peg::from::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import.html"> pt::peg::import </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_container.html"> pt::peg::import::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_json.html"> pt::peg::import::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_peg.html"> pt::peg::import::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_interp.html"> pt::peg::interp </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_container.html"> pt::peg::to::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_cparam.html"> pt::peg::to::cparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_json.html"> pt::peg::to::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_param.html"> pt::peg::to::param </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_peg.html"> pt::peg::to::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_tclparam.html"> pt::peg::to::tclparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_language.html"> pt::peg_language </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_introduction.html"> pt::pegrammar </a> &#183; <a href="tcllib/files/modules/pt/pt_pgen.html"> pt::pgen </a> &#183; <a href="tcllib/files/modules/pt/pt_rdengine.html"> pt::rde </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_nx.html"> pt::tclparam::configuration::nx </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_snit.html"> pt::tclparam::configuration::snit </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_tcloo.html"> pt::tclparam::configuration::tcloo </a> &#183; <a href="tcllib/files/modules/pt/pt_util.html"> pt::util </a> &#183; <a href="tcllib/files/modules/pt/pt_to_api.html"> pt_export_api </a> &#183; <a href="tcllib/files/modules/pt/pt_from_api.html"> pt_import_api </a> &#183; <a href="tcllib/files/modules/pt/pt_introduction.html"> pt_introduction </a> &#183; <a href="tcllib/files/modules/pt/pt_parse_peg.html"> pt_parse_peg </a> &#183; <a href="tcllib/files/modules/pt/pt_parser_api.html"> pt_parser_api </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_op.html"> pt_peg_op </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="performance"> performance </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/bench/bench.html"> bench </a> &#183; <a href="tcllib/files/modules/bench/bench_read.html"> bench::in </a> &#183; <a href="tcllib/files/modules/bench/bench_wcsv.html"> bench::out::csv </a> &#183; <a href="tcllib/files/modules/bench/bench_wtext.html"> bench::out::text </a> &#183; <a href="tcllib/files/modules/bench/bench_intro.html"> bench_intro </a> &#183; <a href="tcllib/files/modules/bench/bench_lang_intro.html"> bench_lang_intro </a> &#183; <a href="tcllib/files/modules/bench/bench_lang_spec.html"> bench_lang_spec </a> &#183; <a href="tcllib/files/modules/profiler/profiler.html"> profiler </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="permutation"> permutation </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/struct_list.html"> struct::list </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="persistence"> persistence </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/tie/tie_std.html"> tie </a> &#183; <a href="tcllib/files/modules/tie/tie.html"> tie </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="phone"> phone </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/valtype/imei.html"> valtype::imei </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="pi"> pi </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/constants.html"> math::constants </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="plain_text"> plain text </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools2idx/idx_export_text.html"> doctools::idx::export::text </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_export_text.html"> doctools::toc::export::text </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="plane_geometry"> plane geometry </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/math_geometry.html"> math::geometry </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="plugin"> plugin </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools/docidx_plugin_apiref.html"> docidx_plugin_apiref </a> &#183; <a href="tcllib/files/modules/doctools/doctoc_plugin_apiref.html"> doctoc_plugin_apiref </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_introduction.html"> doctools2idx_introduction </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_introduction.html"> doctools2toc_introduction </a> &#183; <a href="tcllib/files/modules/doctools2base/html_cssdefaults.html"> doctools::html::cssdefaults </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_container.html"> doctools::idx </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_export.html"> doctools::idx::export </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_import.html"> doctools::idx::import </a> &#183; <a href="tcllib/files/modules/doctools2base/nroff_manmacros.html"> doctools::nroff::man_macros </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_container.html"> doctools::toc </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_export.html"> doctools::toc::export </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_import.html"> doctools::toc::import </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_container.html"> pt::peg::export::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_json.html"> pt::peg::export::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_peg.html"> pt::peg::export::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_json.html"> pt::peg::import::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_peg.html"> pt::peg::import::peg </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="plugin_management"> plugin management </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/pluginmgr/pluginmgr.html"> pluginmgr </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="plugin_search"> plugin search </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/pluginmgr/pluginmgr.html"> pluginmgr </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="png"> png </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/png/png.html"> png </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="point"> point </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/math_geometry.html"> math::geometry </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="polynomial_functions"> polynomial functions </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/polynomials.html"> math::polynomials </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="pool"> pool </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/pool.html"> struct::pool </a> &#183; <a href="tcllib/files/modules/struct/queue.html"> struct::queue </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="pop"> pop </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/pop3/pop3.html"> pop3 </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="pop3"> pop3 </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/pop3/pop3.html"> pop3 </a> &#183; <a href="tcllib/files/modules/pop3d/pop3d.html"> pop3d </a> &#183; <a href="tcllib/files/modules/pop3d/pop3d_dbox.html"> pop3d::dbox </a> &#183; <a href="tcllib/files/modules/pop3d/pop3d_udb.html"> pop3d::udb </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="post_order"> post-order </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/struct_tree.html"> struct::tree </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="practcl"> practcl </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/practcl/practcl.html"> practcl </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="pre_order"> pre-order </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/struct_tree.html"> struct::tree </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="prefix"> prefix </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/textutil/textutil_string.html"> textutil::string </a> &#183; <a href="tcllib/files/modules/textutil/trim.html"> textutil::trim </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="prime"> prime </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/numtheory.html"> math::numtheory </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="prioqueue"> prioqueue </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/prioqueue.html"> struct::prioqueue </a> &#183; <a href="tcllib/files/modules/struct/queue.html"> struct::queue </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="priority_queue"> priority queue </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/prioqueue.html"> struct::prioqueue </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="proc"> proc </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/lambda/lambda.html"> lambda </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="procedure"> procedure </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/interp/deleg_proc.html"> deleg_proc </a> &#183; <a href="tcllib/files/modules/tepam/tepam_introduction.html"> tepam </a> &#183; <a href="tcllib/files/modules/tepam/tepam_procedure.html"> tepam::procedure </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="procedure_documentation"> procedure documentation </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/tepam/tepam_doc_gen.html"> tepam::doc_gen </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="processman"> processman </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/processman/processman.html"> processman </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="producer"> producer </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/hook/hook.html"> hook </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="profile"> profile </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/profiler/profiler.html"> profiler </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="projection"> projection </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/mapproj/mapproj.html"> mapproj </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="prospero"> prospero </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uri/uri.html"> uri </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="protocol"> protocol </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/asn/asn.html"> asn </a> &#183; <a href="tcllib/files/modules/ldap/ldap.html"> ldap </a> &#183; <a href="tcllib/files/modules/ldap/ldapx.html"> ldapx </a> &#183; <a href="tcllib/files/modules/nns/nns_protocol.html"> nameserv::protocol </a> &#183; <a href="tcllib/files/modules/pop3d/pop3d.html"> pop3d </a> &#183; <a href="tcllib/files/modules/pop3d/pop3d_dbox.html"> pop3d::dbox </a> &#183; <a href="tcllib/files/modules/pop3d/pop3d_udb.html"> pop3d::udb </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="proxy"> proxy </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/http/autoproxy.html"> autoproxy </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="public_key_cipher"> public key cipher </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/pki/pki.html"> pki </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="publisher"> publisher </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/hook/hook.html"> hook </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="push_down_automaton"> push down automaton </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/grammar_me/me_intro.html"> grammar::me_intro </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg.html"> grammar::peg </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg_interp.html"> grammar::peg::interp </a> &#183; <a href="tcllib/files/apps/pt.html"> pt </a> &#183; <a href="tcllib/files/modules/pt/pt_astree.html"> pt::ast </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_critcl.html"> pt::cparam::configuration::critcl </a> &#183; <a href="tcllib/files/modules/pt/pt_cparam_config_tea.html"> pt::cparam::configuration::tea </a> &#183; <a href="tcllib/files/modules/pt/pt_json_language.html"> pt::json_language </a> &#183; <a href="tcllib/files/modules/pt/pt_param.html"> pt::param </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpression.html"> pt::pe </a> &#183; <a href="tcllib/files/modules/pt/pt_pexpr_op.html"> pt::pe::op </a> &#183; <a href="tcllib/files/modules/pt/pt_pegrammar.html"> pt::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container.html"> pt::peg::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_container_peg.html"> pt::peg::container::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export.html"> pt::peg::export </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_container.html"> pt::peg::export::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_json.html"> pt::peg::export::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_export_peg.html"> pt::peg::export::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_container.html"> pt::peg::from::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_json.html"> pt::peg::from::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_from_peg.html"> pt::peg::from::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import.html"> pt::peg::import </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_container.html"> pt::peg::import::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_json.html"> pt::peg::import::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_import_peg.html"> pt::peg::import::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_interp.html"> pt::peg::interp </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_container.html"> pt::peg::to::container </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_cparam.html"> pt::peg::to::cparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_json.html"> pt::peg::to::json </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_param.html"> pt::peg::to::param </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_peg.html"> pt::peg::to::peg </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_to_tclparam.html"> pt::peg::to::tclparam </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_language.html"> pt::peg_language </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_introduction.html"> pt::pegrammar </a> &#183; <a href="tcllib/files/modules/pt/pt_pgen.html"> pt::pgen </a> &#183; <a href="tcllib/files/modules/pt/pt_rdengine.html"> pt::rde </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_nx.html"> pt::tclparam::configuration::nx </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_snit.html"> pt::tclparam::configuration::snit </a> &#183; <a href="tcllib/files/modules/pt/pt_tclparam_config_tcloo.html"> pt::tclparam::configuration::tcloo </a> &#183; <a href="tcllib/files/modules/pt/pt_util.html"> pt::util </a> &#183; <a href="tcllib/files/modules/pt/pt_to_api.html"> pt_export_api </a> &#183; <a href="tcllib/files/modules/pt/pt_from_api.html"> pt_import_api </a> &#183; <a href="tcllib/files/modules/pt/pt_introduction.html"> pt_introduction </a> &#183; <a href="tcllib/files/modules/pt/pt_parse_peg.html"> pt_parse_peg </a> &#183; <a href="tcllib/files/modules/pt/pt_parser_api.html"> pt_parser_api </a> &#183; <a href="tcllib/files/modules/pt/pt_peg_op.html"> pt_peg_op </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cQ">Keywords: Q</a>
</th></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="quasi_random"> quasi-random </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/quasirandom.html"> math::quasirandom </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="queue"> queue </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/csv/csv.html"> csv </a> &#183; <a href="tcllib/files/modules/htmlparse/htmlparse.html"> htmlparse </a> &#183; <a href="tcllib/files/modules/struct/stack.html"> struct::stack </a> &#183; <a href="tcllib/files/modules/transfer/tqueue.html"> transfer::copy::queue </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="quoting"> quoting </a></td>
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
<td class="#doctools_idxleft" width="35%"><a name="service"> service </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/log/logger.html"> logger </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="services"> services </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/ftpd/ftpd.html"> ftpd </a> &#183; <a href="tcllib/files/modules/smtpd/smtpd.html"> smtpd </a> &#183; <a href="tcllib/files/modules/httpd/httpd.html"> tool </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="set"> set </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/queue.html"> struct::queue </a> &#183; <a href="tcllib/files/modules/struct/struct_set.html"> struct::set </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>







|







3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
<td class="#doctools_idxleft" width="35%"><a name="service"> service </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/log/logger.html"> logger </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="services"> services </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/ftpd/ftpd.html"> ftpd </a> &#183; <a href="tcllib/files/modules/httpd/httpd.html"> httpd </a> &#183; <a href="tcllib/files/modules/smtpd/smtpd.html"> smtpd </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="set"> set </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/queue.html"> struct::queue </a> &#183; <a href="tcllib/files/modules/struct/struct_set.html"> struct::set </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
<td class="#doctools_idxleft" width="35%"><a name="tcllib"> tcllib </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/csv/csv.html"> csv </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="tcloo"> TclOO </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/tool/meta.html"> oo::util </a> &#183; <a href="tcllib/files/modules/ooutil/ooutil.html"> oo::util </a> &#183; <a href="tcllib/files/modules/oometa/oometa.html"> oometa </a> &#183; <a href="tcllib/files/modules/httpd/httpd.html"> tool </a> &#183; <a href="tcllib/files/modules/tool/tool.html"> tool </a> &#183; <a href="tcllib/files/modules/tool/tool_dict_ensemble.html"> tool::dict_ensemble </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="tclparam"> TCLPARAM </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/pt/pt_peg_to_tclparam.html"> pt::peg::to::tclparam </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>







|







3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
<td class="#doctools_idxleft" width="35%"><a name="tcllib"> tcllib </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/csv/csv.html"> csv </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="tcloo"> TclOO </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/clay/clay.html"> clay </a> &#183; <a href="tcllib/files/modules/httpd/httpd.html"> httpd </a> &#183; <a href="tcllib/files/modules/tool/meta.html"> oo::util </a> &#183; <a href="tcllib/files/modules/ooutil/ooutil.html"> oo::util </a> &#183; <a href="tcllib/files/modules/oometa/oometa.html"> oometa </a> &#183; <a href="tcllib/files/modules/tool/tool.html"> tool </a> &#183; <a href="tcllib/files/modules/tool/tool_dict_ensemble.html"> tool::dict_ensemble </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="tclparam"> TCLPARAM </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/pt/pt_peg_to_tclparam.html"> pt::peg::to::tclparam </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
4118
4119
4120
4121
4122
4123
4124





4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="unicode"> unicode </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/stringprep/stringprep.html"> stringprep </a> &#183; <a href="tcllib/files/modules/stringprep/stringprep_data.html"> stringprep::data </a> &#183; <a href="tcllib/files/modules/stringprep/unicode.html"> unicode </a> &#183; <a href="tcllib/files/modules/stringprep/unicode_data.html"> unicode::data </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>





<td class="#doctools_idxleft" width="35%"><a name="union"> union </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/disjointset.html"> struct::disjointset </a> &#183; <a href="tcllib/files/modules/struct/struct_set.html"> struct::set </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="unit"> unit </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/units/units.html"> units </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="unknown_hooking"> unknown hooking </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/namespacex/namespacex.html"> namespacex </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="untie"> untie </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/tie/tie_std.html"> tie </a> &#183; <a href="tcllib/files/modules/tie/tie.html"> tie </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="update"> update </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/coroutine/tcllib_coroutine.html"> coroutine </a> &#183; <a href="tcllib/files/modules/coroutine/coro_auto.html"> coroutine::auto </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="uri"> uri </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uri/uri.html"> uri </a> &#183; <a href="tcllib/files/modules/uri/urn-scheme.html"> uri_urn </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="url"> url </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools2idx/idx_container.html"> doctools::idx </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_export.html"> doctools::idx::export </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_import.html"> doctools::idx::import </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_export.html"> doctools::toc::export </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_import.html"> doctools::toc::import </a> &#183; <a href="tcllib/files/modules/map/map_geocode_nominatim.html"> map::geocode::nominatim </a> &#183; <a href="tcllib/files/modules/map/map_slippy_fetcher.html"> map::slippy::fetcher </a> &#183; <a href="tcllib/files/modules/uri/uri.html"> uri </a> &#183; <a href="tcllib/files/modules/uri/urn-scheme.html"> uri_urn </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="urn"> urn </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uri/urn-scheme.html"> uri_urn </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="us_npi"> US-NPI </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/valtype/usnpi.html"> valtype::usnpi </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="utilities"> utilities </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/namespacex/namespacex.html"> namespacex </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="uuencode"> uuencode </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/base64/uuencode.html"> uuencode </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="uuid"> UUID </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uuid/uuid.html"> uuid </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cV">Keywords: V</a>
</th></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="validation"> Validation </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/valtype/valtype_common.html"> valtype::common </a> &#183; <a href="tcllib/files/modules/valtype/cc_amex.html"> valtype::creditcard::amex </a> &#183; <a href="tcllib/files/modules/valtype/cc_discover.html"> valtype::creditcard::discover </a> &#183; <a href="tcllib/files/modules/valtype/cc_mastercard.html"> valtype::creditcard::mastercard </a> &#183; <a href="tcllib/files/modules/valtype/cc_visa.html"> valtype::creditcard::visa </a> &#183; <a href="tcllib/files/modules/valtype/ean13.html"> valtype::gs1::ean13 </a> &#183; <a href="tcllib/files/modules/valtype/iban.html"> valtype::iban </a> &#183; <a href="tcllib/files/modules/valtype/imei.html"> valtype::imei </a> &#183; <a href="tcllib/files/modules/valtype/isbn.html"> valtype::isbn </a> &#183; <a href="tcllib/files/modules/valtype/luhn.html"> valtype::luhn </a> &#183; <a href="tcllib/files/modules/valtype/luhn5.html"> valtype::luhn5 </a> &#183; <a href="tcllib/files/modules/valtype/usnpi.html"> valtype::usnpi </a> &#183; <a href="tcllib/files/modules/valtype/verhoeff.html"> valtype::verhoeff </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="value_checking"> Value checking </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/valtype/valtype_common.html"> valtype::common </a> &#183; <a href="tcllib/files/modules/valtype/cc_amex.html"> valtype::creditcard::amex </a> &#183; <a href="tcllib/files/modules/valtype/cc_discover.html"> valtype::creditcard::discover </a> &#183; <a href="tcllib/files/modules/valtype/cc_mastercard.html"> valtype::creditcard::mastercard </a> &#183; <a href="tcllib/files/modules/valtype/cc_visa.html"> valtype::creditcard::visa </a> &#183; <a href="tcllib/files/modules/valtype/ean13.html"> valtype::gs1::ean13 </a> &#183; <a href="tcllib/files/modules/valtype/iban.html"> valtype::iban </a> &#183; <a href="tcllib/files/modules/valtype/imei.html"> valtype::imei </a> &#183; <a href="tcllib/files/modules/valtype/isbn.html"> valtype::isbn </a> &#183; <a href="tcllib/files/modules/valtype/luhn.html"> valtype::luhn </a> &#183; <a href="tcllib/files/modules/valtype/luhn5.html"> valtype::luhn5 </a> &#183; <a href="tcllib/files/modules/valtype/usnpi.html"> valtype::usnpi </a> &#183; <a href="tcllib/files/modules/valtype/verhoeff.html"> valtype::verhoeff </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="vectors"> vectors </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/linalg.html"> math::linearalgebra </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="verhoeff"> verhoeff </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/valtype/verhoeff.html"> valtype::verhoeff </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="vertex"> vertex </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/graph.html"> struct::graph </a> &#183; <a href="tcllib/files/modules/struct/graphops.html"> struct::graph::op </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="vertex_cover"> vertex cover </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/graphops.html"> struct::graph::op </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="virtual_channel"> virtual channel </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/virtchannel_base/cat.html"> tcl::chan::cat </a> &#183; <a href="tcllib/files/modules/virtchannel_core/core.html"> tcl::chan::core </a> &#183; <a href="tcllib/files/modules/virtchannel_core/events.html"> tcl::chan::events </a> &#183; <a href="tcllib/files/modules/virtchannel_base/facade.html"> tcl::chan::facade </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_fifo.html"> tcl::chan::fifo </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_fifo2.html"> tcl::chan::fifo2 </a> &#183; <a href="tcllib/files/modules/virtchannel_base/halfpipe.html"> tcl::chan::halfpipe </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_memchan.html"> tcl::chan::memchan </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_null.html"> tcl::chan::null </a> &#183; <a href="tcllib/files/modules/virtchannel_base/nullzero.html"> tcl::chan::nullzero </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_random.html"> tcl::chan::random </a> &#183; <a href="tcllib/files/modules/virtchannel_base/std.html"> tcl::chan::std </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_string.html"> tcl::chan::string </a> &#183; <a href="tcllib/files/modules/virtchannel_base/textwindow.html"> tcl::chan::textwindow </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_variable.html"> tcl::chan::variable </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_zero.html"> tcl::chan::zero </a> &#183; <a href="tcllib/files/modules/virtchannel_base/randseed.html"> tcl::randomseed </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/adler32.html"> tcl::transform::adler32 </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/vt_base64.html"> tcl::transform::base64 </a> &#183; <a href="tcllib/files/modules/virtchannel_core/transformcore.html"> tcl::transform::core </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/vt_counter.html"> tcl::transform::counter </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/vt_crc32.html"> tcl::transform::crc32 </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/hex.html"> tcl::transform::hex </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/identity.html"> tcl::transform::identity </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/limitsize.html"> tcl::transform::limitsize </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/observe.html"> tcl::transform::observe </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/vt_otp.html"> tcl::transform::otp </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/rot.html"> tcl::transform::rot </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/spacer.html"> tcl::transform::spacer </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/tcllib_zlib.html"> tcl::transform::zlib </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="virtual_machine"> virtual machine </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/grammar_me/me_cpu.html"> grammar::me::cpu </a> &#183; <a href="tcllib/files/modules/grammar_me/me_cpucore.html"> grammar::me::cpu::core </a> &#183; <a href="tcllib/files/modules/grammar_me/gasm.html"> grammar::me::cpu::gasm </a> &#183; <a href="tcllib/files/modules/grammar_me/me_tcl.html"> grammar::me::tcl </a> &#183; <a href="tcllib/files/modules/grammar_me/me_intro.html"> grammar::me_intro </a> &#183; <a href="tcllib/files/modules/grammar_me/me_vm.html"> grammar::me_vm </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg_interp.html"> grammar::peg::interp </a> &#183; <a href="tcllib/files/modules/pt/pt_param.html"> pt::param </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="visa"> VISA </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/valtype/cc_visa.html"> valtype::creditcard::visa </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="vwait"> vwait </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/coroutine/tcllib_coroutine.html"> coroutine </a> &#183; <a href="tcllib/files/modules/coroutine/coro_auto.html"> coroutine::auto </a> &#183; <a href="tcllib/files/modules/smtpd/smtpd.html"> smtpd </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cW">Keywords: W</a>
</th></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="wais"> wais </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uri/uri.html"> uri </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="widget"> widget </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/snit/snit.html"> snit </a> &#183; <a href="tcllib/files/modules/snit/snitfaq.html"> snitfaq </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="widget_adaptors"> widget adaptors </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/snit/snit.html"> snit </a> &#183; <a href="tcllib/files/modules/snit/snitfaq.html"> snitfaq </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="wiki"> wiki </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools/docidx.html"> doctools::idx </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_container.html"> doctools::idx </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_export.html"> doctools::idx::export </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_export_wiki.html"> doctools::idx::export::wiki </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_container.html"> doctools::toc </a> &#183; <a href="tcllib/files/modules/doctools/doctoc.html"> doctools::toc </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_export.html"> doctools::toc::export </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_export_wiki.html"> doctools::toc::export::wiki </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="word"> word </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools2base/tcl_parse.html"> doctools::tcl::parse </a> &#183; <a href="tcllib/files/modules/wip/wip.html"> wip </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="www"> WWW </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/httpd/httpd.html"> tool </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="www"> www </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uri/uri.html"> uri </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cX">Keywords: X</a>
</th></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="x_208"> x.208 </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/asn/asn.html"> asn </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="x_209"> x.209 </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/asn/asn.html"> asn </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="x_500"> x.500 </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/ldap/ldap.html"> ldap </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="xgoogletoken"> XGoogleToken </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/sasl/gtoken.html"> SASL::XGoogleToken </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="xml"> xml </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/amazon-s3/xsxp.html"> xsxp </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="xor"> xor </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/virtchannel_transform/vt_otp.html"> tcl::transform::otp </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="xpath"> XPath </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/treeql/treeql.html"> treeql </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="xslt"> XSLT </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/treeql/treeql.html"> treeql </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cY">Keywords: Y</a>
</th></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="yaml"> yaml </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/yaml/huddle.html"> huddle </a> &#183; <a href="tcllib/files/modules/yaml/yaml.html"> yaml </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="ydecode"> ydecode </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/base64/yencode.html"> yencode </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="yenc"> yEnc </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/base64/yencode.html"> yencode </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="yencode"> yencode </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/base64/yencode.html"> yencode </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cZ">Keywords: Z</a>
</th></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="zero"> zero </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/virtchannel_base/nullzero.html"> tcl::chan::nullzero </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_zero.html"> tcl::chan::zero </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="zip"> zip </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/zip/decode.html"> zipfile::decode </a> &#183; <a href="tcllib/files/modules/zip/encode.html"> zipfile::encode </a> &#183; <a href="tcllib/files/modules/zip/mkzip.html"> zipfile::mkzip </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="zlib"> zlib </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/virtchannel_transform/tcllib_zlib.html"> tcl::transform::zlib </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="zoom"> zoom </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/map/map_slippy.html"> map::slippy </a> &#183; <a href="tcllib/files/modules/map/map_slippy_cache.html"> map::slippy::cache </a> &#183; <a href="tcllib/files/modules/map/map_slippy_fetcher.html"> map::slippy::fetcher </a>
</td></tr>
</table>
</body></html>







>
>
>
>
>




|




|




|




|




|




|




|




|




|




|




|







|




|




|




|




|




|




|




|




|




|







|




|




|




|




|




|


|

|







|




|




|




|




|




|




|




|







|




|




|




|







|




|




|




|






4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="unicode"> unicode </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/stringprep/stringprep.html"> stringprep </a> &#183; <a href="tcllib/files/modules/stringprep/stringprep_data.html"> stringprep::data </a> &#183; <a href="tcllib/files/modules/stringprep/unicode.html"> unicode </a> &#183; <a href="tcllib/files/modules/stringprep/unicode_data.html"> unicode::data </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="unified_format_diff"> unified format diff </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/textutil/patch.html"> textutil::patch </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="union"> union </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/disjointset.html"> struct::disjointset </a> &#183; <a href="tcllib/files/modules/struct/struct_set.html"> struct::set </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="unit"> unit </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/units/units.html"> units </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="unknown_hooking"> unknown hooking </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/namespacex/namespacex.html"> namespacex </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="untie"> untie </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/tie/tie_std.html"> tie </a> &#183; <a href="tcllib/files/modules/tie/tie.html"> tie </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="update"> update </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/coroutine/tcllib_coroutine.html"> coroutine </a> &#183; <a href="tcllib/files/modules/coroutine/coro_auto.html"> coroutine::auto </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="uri"> uri </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uri/uri.html"> uri </a> &#183; <a href="tcllib/files/modules/uri/urn-scheme.html"> uri_urn </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="url"> url </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools2idx/idx_container.html"> doctools::idx </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_export.html"> doctools::idx::export </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_import.html"> doctools::idx::import </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_export.html"> doctools::toc::export </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_import.html"> doctools::toc::import </a> &#183; <a href="tcllib/files/modules/map/map_geocode_nominatim.html"> map::geocode::nominatim </a> &#183; <a href="tcllib/files/modules/map/map_slippy_fetcher.html"> map::slippy::fetcher </a> &#183; <a href="tcllib/files/modules/uri/uri.html"> uri </a> &#183; <a href="tcllib/files/modules/uri/urn-scheme.html"> uri_urn </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="urn"> urn </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uri/urn-scheme.html"> uri_urn </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="us_npi"> US-NPI </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/valtype/usnpi.html"> valtype::usnpi </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="utilities"> utilities </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/namespacex/namespacex.html"> namespacex </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="uuencode"> uuencode </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/base64/uuencode.html"> uuencode </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="uuid"> UUID </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uuid/uuid.html"> uuid </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cV">Keywords: V</a>
</th></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="validation"> Validation </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/valtype/valtype_common.html"> valtype::common </a> &#183; <a href="tcllib/files/modules/valtype/cc_amex.html"> valtype::creditcard::amex </a> &#183; <a href="tcllib/files/modules/valtype/cc_discover.html"> valtype::creditcard::discover </a> &#183; <a href="tcllib/files/modules/valtype/cc_mastercard.html"> valtype::creditcard::mastercard </a> &#183; <a href="tcllib/files/modules/valtype/cc_visa.html"> valtype::creditcard::visa </a> &#183; <a href="tcllib/files/modules/valtype/ean13.html"> valtype::gs1::ean13 </a> &#183; <a href="tcllib/files/modules/valtype/iban.html"> valtype::iban </a> &#183; <a href="tcllib/files/modules/valtype/imei.html"> valtype::imei </a> &#183; <a href="tcllib/files/modules/valtype/isbn.html"> valtype::isbn </a> &#183; <a href="tcllib/files/modules/valtype/luhn.html"> valtype::luhn </a> &#183; <a href="tcllib/files/modules/valtype/luhn5.html"> valtype::luhn5 </a> &#183; <a href="tcllib/files/modules/valtype/usnpi.html"> valtype::usnpi </a> &#183; <a href="tcllib/files/modules/valtype/verhoeff.html"> valtype::verhoeff </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="value_checking"> Value checking </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/valtype/valtype_common.html"> valtype::common </a> &#183; <a href="tcllib/files/modules/valtype/cc_amex.html"> valtype::creditcard::amex </a> &#183; <a href="tcllib/files/modules/valtype/cc_discover.html"> valtype::creditcard::discover </a> &#183; <a href="tcllib/files/modules/valtype/cc_mastercard.html"> valtype::creditcard::mastercard </a> &#183; <a href="tcllib/files/modules/valtype/cc_visa.html"> valtype::creditcard::visa </a> &#183; <a href="tcllib/files/modules/valtype/ean13.html"> valtype::gs1::ean13 </a> &#183; <a href="tcllib/files/modules/valtype/iban.html"> valtype::iban </a> &#183; <a href="tcllib/files/modules/valtype/imei.html"> valtype::imei </a> &#183; <a href="tcllib/files/modules/valtype/isbn.html"> valtype::isbn </a> &#183; <a href="tcllib/files/modules/valtype/luhn.html"> valtype::luhn </a> &#183; <a href="tcllib/files/modules/valtype/luhn5.html"> valtype::luhn5 </a> &#183; <a href="tcllib/files/modules/valtype/usnpi.html"> valtype::usnpi </a> &#183; <a href="tcllib/files/modules/valtype/verhoeff.html"> valtype::verhoeff </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="vectors"> vectors </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/math/linalg.html"> math::linearalgebra </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="verhoeff"> verhoeff </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/valtype/verhoeff.html"> valtype::verhoeff </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="vertex"> vertex </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/graph.html"> struct::graph </a> &#183; <a href="tcllib/files/modules/struct/graphops.html"> struct::graph::op </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="vertex_cover"> vertex cover </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/struct/graphops.html"> struct::graph::op </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="virtual_channel"> virtual channel </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/virtchannel_base/cat.html"> tcl::chan::cat </a> &#183; <a href="tcllib/files/modules/virtchannel_core/core.html"> tcl::chan::core </a> &#183; <a href="tcllib/files/modules/virtchannel_core/events.html"> tcl::chan::events </a> &#183; <a href="tcllib/files/modules/virtchannel_base/facade.html"> tcl::chan::facade </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_fifo.html"> tcl::chan::fifo </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_fifo2.html"> tcl::chan::fifo2 </a> &#183; <a href="tcllib/files/modules/virtchannel_base/halfpipe.html"> tcl::chan::halfpipe </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_memchan.html"> tcl::chan::memchan </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_null.html"> tcl::chan::null </a> &#183; <a href="tcllib/files/modules/virtchannel_base/nullzero.html"> tcl::chan::nullzero </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_random.html"> tcl::chan::random </a> &#183; <a href="tcllib/files/modules/virtchannel_base/std.html"> tcl::chan::std </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_string.html"> tcl::chan::string </a> &#183; <a href="tcllib/files/modules/virtchannel_base/textwindow.html"> tcl::chan::textwindow </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_variable.html"> tcl::chan::variable </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_zero.html"> tcl::chan::zero </a> &#183; <a href="tcllib/files/modules/virtchannel_base/randseed.html"> tcl::randomseed </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/adler32.html"> tcl::transform::adler32 </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/vt_base64.html"> tcl::transform::base64 </a> &#183; <a href="tcllib/files/modules/virtchannel_core/transformcore.html"> tcl::transform::core </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/vt_counter.html"> tcl::transform::counter </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/vt_crc32.html"> tcl::transform::crc32 </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/hex.html"> tcl::transform::hex </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/identity.html"> tcl::transform::identity </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/limitsize.html"> tcl::transform::limitsize </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/observe.html"> tcl::transform::observe </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/vt_otp.html"> tcl::transform::otp </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/rot.html"> tcl::transform::rot </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/spacer.html"> tcl::transform::spacer </a> &#183; <a href="tcllib/files/modules/virtchannel_transform/tcllib_zlib.html"> tcl::transform::zlib </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="virtual_machine"> virtual machine </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/grammar_me/me_cpu.html"> grammar::me::cpu </a> &#183; <a href="tcllib/files/modules/grammar_me/me_cpucore.html"> grammar::me::cpu::core </a> &#183; <a href="tcllib/files/modules/grammar_me/gasm.html"> grammar::me::cpu::gasm </a> &#183; <a href="tcllib/files/modules/grammar_me/me_tcl.html"> grammar::me::tcl </a> &#183; <a href="tcllib/files/modules/grammar_me/me_intro.html"> grammar::me_intro </a> &#183; <a href="tcllib/files/modules/grammar_me/me_vm.html"> grammar::me_vm </a> &#183; <a href="tcllib/files/modules/grammar_peg/peg_interp.html"> grammar::peg::interp </a> &#183; <a href="tcllib/files/modules/pt/pt_param.html"> pt::param </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="visa"> VISA </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/valtype/cc_visa.html"> valtype::creditcard::visa </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="vwait"> vwait </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/coroutine/tcllib_coroutine.html"> coroutine </a> &#183; <a href="tcllib/files/modules/coroutine/coro_auto.html"> coroutine::auto </a> &#183; <a href="tcllib/files/modules/smtpd/smtpd.html"> smtpd </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cW">Keywords: W</a>
</th></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="wais"> wais </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uri/uri.html"> uri </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="widget"> widget </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/snit/snit.html"> snit </a> &#183; <a href="tcllib/files/modules/snit/snitfaq.html"> snitfaq </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="widget_adaptors"> widget adaptors </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/snit/snit.html"> snit </a> &#183; <a href="tcllib/files/modules/snit/snitfaq.html"> snitfaq </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="wiki"> wiki </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools/docidx.html"> doctools::idx </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_container.html"> doctools::idx </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_export.html"> doctools::idx::export </a> &#183; <a href="tcllib/files/modules/doctools2idx/idx_export_wiki.html"> doctools::idx::export::wiki </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_container.html"> doctools::toc </a> &#183; <a href="tcllib/files/modules/doctools/doctoc.html"> doctools::toc </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_export.html"> doctools::toc::export </a> &#183; <a href="tcllib/files/modules/doctools2toc/toc_export_wiki.html"> doctools::toc::export::wiki </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="word"> word </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/doctools2base/tcl_parse.html"> doctools::tcl::parse </a> &#183; <a href="tcllib/files/modules/wip/wip.html"> wip </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="www"> WWW </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/httpd/httpd.html"> httpd </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="www"> www </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/uri/uri.html"> uri </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cX">Keywords: X</a>
</th></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="x_208"> x.208 </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/asn/asn.html"> asn </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="x_209"> x.209 </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/asn/asn.html"> asn </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="x_500"> x.500 </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/ldap/ldap.html"> ldap </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="xgoogletoken"> XGoogleToken </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/sasl/gtoken.html"> SASL::XGoogleToken </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="xml"> xml </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/amazon-s3/xsxp.html"> xsxp </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="xor"> xor </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/virtchannel_transform/vt_otp.html"> tcl::transform::otp </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="xpath"> XPath </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/treeql/treeql.html"> treeql </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="xslt"> XSLT </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/treeql/treeql.html"> treeql </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cY">Keywords: Y</a>
</th></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="yaml"> yaml </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/yaml/huddle.html"> huddle </a> &#183; <a href="tcllib/files/modules/yaml/yaml.html"> yaml </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="ydecode"> ydecode </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/base64/yencode.html"> yencode </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="yenc"> yEnc </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/base64/yencode.html"> yencode </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="yencode"> yencode </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/base64/yencode.html"> yencode </a>
</td></tr>
<tr class="#doctools_idxheader"><th colspan="2">
<a name="cZ">Keywords: Z</a>
</th></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="zero"> zero </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/virtchannel_base/nullzero.html"> tcl::chan::nullzero </a> &#183; <a href="tcllib/files/modules/virtchannel_base/tcllib_zero.html"> tcl::chan::zero </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="zip"> zip </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/zip/decode.html"> zipfile::decode </a> &#183; <a href="tcllib/files/modules/zip/encode.html"> zipfile::encode </a> &#183; <a href="tcllib/files/modules/zip/mkzip.html"> zipfile::mkzip </a>
</td></tr>
<tr class="#doctools_idxodd" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="zlib"> zlib </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/virtchannel_transform/tcllib_zlib.html"> tcl::transform::zlib </a>
</td></tr>
<tr class="#doctools_idxeven" valign=top>
<td class="#doctools_idxleft" width="35%"><a name="zoom"> zoom </a></td>
<td class="#doctools_idxright" width="65%">
<a href="tcllib/files/modules/map/map_slippy.html"> map::slippy </a> &#183; <a href="tcllib/files/modules/map/map_slippy_cache.html"> map::slippy::cache </a> &#183; <a href="tcllib/files/modules/map/map_slippy_fetcher.html"> map::slippy::fetcher </a>
</td></tr>
</table>
</body></html>

Added idoc/www/tcllib/files/devdoc/tcl_community_communication.html.























































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
<!DOCTYPE html><html><head>
<title>tcl_community_communication - </title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
	color:	 	black;
    }
    DIV.doctools {
	margin-left:	10%;
	margin-right:	10%;
    }
    DIV.doctools H1,DIV.doctools H2 {
	margin-left:	-5%;
    }
    H1, H2, H3, H4 {
	margin-top: 	1em;
	font-family:	sans-serif;
	font-size:	large;
	color:		#005A9C;
	background: 	transparent;
	text-align:		left;
    }
    H1.doctools_title {
	text-align: center;
    }
    UL,OL {
	margin-right: 0em;
	margin-top: 3pt;
	margin-bottom: 3pt;
    }
    UL LI {
	list-style: disc;
    }
    OL LI {
	list-style: decimal;
    }
    DT {
	padding-top: 	1ex;
    }
    UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
	font:		normal 12pt/14pt sans-serif;
	list-style:	none;
    }
    LI.doctools_section, LI.doctools_subsection {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding: 	0em;
    }
    PRE {
	display: 	block;
	font-family:	monospace;
	white-space:	pre;
	margin:		0%;
	padding-top:	0.5ex;
	padding-bottom:	0.5ex;
	padding-left:	1ex;
	padding-right:	1ex;
	width:		100%;
    }
    PRE.doctools_example {
	color: 		black;
	background: 	#f5dcb3;
	border:		1px solid black;
    }
    UL.doctools_requirements LI, UL.doctools_syntax LI {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding:	0em;
    }
    DIV.doctools_synopsis {
	color: 		black;
	background: 	#80ffff;
	border:		1px solid black;
	font-family:	serif;
	margin-top: 	1em;
	margin-bottom: 	1em;
    }
    UL.doctools_syntax {
	margin-top: 	1em;
	border-top:	1px solid black;
    }
    UL.doctools_requirements {
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'tcl_community_communication.man' by tcllib/doctools with format 'html'
   -->
<!-- tcl_community_communication.n
   -->
<body><hr> [
   <a href="../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../toc.html">Table Of Contents</a>
&#124; <a href="../../../index.html">Keyword Index</a>
&#124; <a href="../../../toc0.html">Categories</a>
&#124; <a href="../../../toc1.html">Modules</a>
&#124; <a href="../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">tcl_community_communication(n) 1 tcllib &quot;&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>tcl_community_communication - Tcl Community - Kind Communication</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Signatories</a></li>
<li class="doctools_section"><a href="#section3">Authors</a></li>
</ul>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>The Tcl Community encourages contributions from anyone who wishes to
advance the development of:</p>
<ul class="doctools_itemized">
<li><p>The Tcl Language</p></li>
<li><p>Tcl derived languages</p></li>
<li><p>Tcl related libraries</p></li>
<li><p>Tcl extensions</p></li>
<li><p>External Projects that Integrate Tcl</p></li>
</ul>
<p>We welcome those contributions from anyone. We are blind to
gender, race, religion, cultural background, cybernetic nature, and
any other demographic characteristics, as well as personal political
views.</p>
<p>A community lives and dies by communications. And occasionally
our communications are peppered with patterns that are harsh,
unfriendly, unwelcoming and/or otherwise unkind. As a volunteer
community, we need all of the help we can get. Therefore, we ask all
contributors to make a conscious effort, in Tcl Community discussions,
to communicate in ways that are welcoming. Ways that are
friendly. Ways that are, in a word: kind.</p>
<p>These guidelines suggest specific ways to accomplish that goal.</p>
<p>Please note: for the balance of this document any reference to
&quot;People&quot;, &quot;Persons&quot;, &quot;anybody&quot; or &quot;somebody&quot; can refer to any sentient
being, not merely corporeal members of the species Homo Sapien.</p>
<dl class="doctools_definitions">
<dt>We are a Sanctuary not a Clubhouse</dt>
<dd><p>The Tcl Community is a collective of amateurs and professionals who
code, test, and use tools. Our community is open to all. There is no
velvet rope. There is no bouncer at the door. There are no secret
handshakes. Any sentient being who enters our midst is welcome. If
someone is ever asked to leave, it is only because they are being
disruptive to the functioning of the community.</p></dd>
<dt>We Merit Ideas, Not People</dt>
<dd><p>A good idea can come from anyone, regardless of how little time they
have been with us. A bad idea can come from anyone, regardless of how
much time or how little time they have been with us. We judge a
concept by how it stands up to scrutiny of logic, implementation, and
regression testing. We don’t judge ideas based on who had the idea
first, who agrees with the idea, or who disagrees with it.</p></dd>
<dt>Treat Everyone with Respect</dt>
<dd><p>Everyone is deserving of respect and courtesy at all times.</p></dd>
<dt>Refer to people by the names they use.</dt>
<dd><p>If grammar requires you to state a gender for a person, honor their
preferences about their gender identity. If you are unsure as to the
gender of an individual, ask. If someone had to guess about your
gender and got it wrong, please correct them and do not take it
personally.</p></dd>
<dt>Do not take a harsh tone towards other participants.</dt>
<dd><p>Do not make personal attacks against anyone (participant or not.)</p>
<p>Criticize statements and actions, never people.</p></dd>
<dt>Don’t Take Things Personally</dt>
<dd><p>When in doubt, assume the best in people. A criticism of your
statements is not a personal attack on you.</p></dd>
<dt>Persons, not People</dt>
<dd><p>Stereotypes are an unhelpful tool on many accounts. They are generally
oversimplified. They are usually flat out wrong. And even if &quot;right&quot;
they are of absolutely no utility in determining the capabilities,
motivations, or fitness of an individual.</p>
<p>Don’t use them in Tcl Community communications.</p></dd>
<dt>Mistakes Happen</dt>
<dd><p>The human condition is a series of trials and errors. Progress is when
we get one more trial than error. Being wrong or making a mistake is
the default state of humanity. Accept the errors of your fellow
sentient beings, and be aware that you are also fallible.</p></dd>
<dt>Keep it Real</dt>
<dd><p>Please respond to what people actually say. We are all amazing
individuals, but none among us are mind readers. If you find yourself
responding to what you imagine someone is thinking, odds are you are
going to be wrong.</p>
<p>If you must criticize someone, stick to things they have
actually done. Never criticize for something you speculate they have
done. Or imagine they have done. Or something someone who shares some
attribute with them has done in the past.</p>
<p>Keep discussions about any non-Tcl subjects to what can be
stated factually and without emotion or judgement.</p></dd>
<dt>When Trouble Arises, Don’t Escalate</dt>
<dd><p>If you feel you are being personally attacked or offended, take the
high road. Punching back in a public forum will only makes things
worse. Address the matter in a private correspondence. Be
polite. Express your feelings, but note that you are expressing your
feelings. When writing, look for a way to calm matters down. And when
in doubt, sleep on your letter before pressing send. And when not in
doubt, sleep on it for another day after that.</p>
<p>If you are a spectator to a fight in progress, politely request
the two parties take the matter to a more private forum.</p></dd>
<dt>Always get the Last Word: I’m Sorry</dt>
<dd><p>If an personal argument does arise, be the first to apologize. An
apology does not concede a logical point. It merely acknowledges that
at some point the discussion left either logic, community decency, or
both. Return to the topic when cooler heads can prevail.</p></dd>
<dt>Nobody is Keeping Score</dt>
<dd><p>There is no prize for being right. There is no cost for being wrong. A
hard sell is not going to advance your idea along any more than a
logical argument. You aren’t running for office. This isn’t debate
club. If you find yourself continuing a discussion beyond where a
topic can be logically discussed, stop.</p></dd>
<dt>No Evangelizing</dt>
<dd><p>The Tcl Community is not the place to promote your chosen operating
system, political outlook, religion, marketing scheme, or economic
model. Period.</p>
<p>(And if you do bring it up, be prepared to have your chosen
topic discussed logically. And odds are, not favorably.)</p></dd>
<dt>Respect the Community</dt>
<dd><p>If the Community has come to a decision on a course of action, please
stop arguing.</p>
<p>If someone complains about how you are expressing your ideas,
listen.</p>
<p>If your words are hurting people, stop. There is no amount of
being &quot;right&quot; that makes up for someone leaving our midst because they
felt insulted, threatened, or ignored.</p></dd>
</dl>
<p>By following these guidelines, we will build our community, encourage
more contribution to our projects, and our discussions will be
friendlier and reach conclusions more easily.</p>
<p>Thank You.</p>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">Signatories</a></h2>
<ul class="doctools_itemized">
<li><p>Sean &quot;the Hypnotoad&quot; Woods</p></li>
<li><p>Andreas Kupries</p></li>
</ul>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">Authors</a></h2>
<dl class="doctools_definitions">
<dt>Primary</dt>
<dd><p>Sean &quot;the Hypnotoad&quot; Woods</p></dd>
<dt>Light editing</dt>
<dd><p>Andreas Kupries</p></dd>
</dl>
</div>
</div></body></html>

Added idoc/www/tcllib/files/devdoc/tcllib_devguide.html.













































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
<!DOCTYPE html><html><head>
<title>tcllib_devguide - </title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
	color:	 	black;
    }
    DIV.doctools {
	margin-left:	10%;
	margin-right:	10%;
    }
    DIV.doctools H1,DIV.doctools H2 {
	margin-left:	-5%;
    }
    H1, H2, H3, H4 {
	margin-top: 	1em;
	font-family:	sans-serif;
	font-size:	large;
	color:		#005A9C;
	background: 	transparent;
	text-align:		left;
    }
    H1.doctools_title {
	text-align: center;
    }
    UL,OL {
	margin-right: 0em;
	margin-top: 3pt;
	margin-bottom: 3pt;
    }
    UL LI {
	list-style: disc;
    }
    OL LI {
	list-style: decimal;
    }
    DT {
	padding-top: 	1ex;
    }
    UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
	font:		normal 12pt/14pt sans-serif;
	list-style:	none;
    }
    LI.doctools_section, LI.doctools_subsection {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding: 	0em;
    }
    PRE {
	display: 	block;
	font-family:	monospace;
	white-space:	pre;
	margin:		0%;
	padding-top:	0.5ex;
	padding-bottom:	0.5ex;
	padding-left:	1ex;
	padding-right:	1ex;
	width:		100%;
    }
    PRE.doctools_example {
	color: 		black;
	background: 	#f5dcb3;
	border:		1px solid black;
    }
    UL.doctools_requirements LI, UL.doctools_syntax LI {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding:	0em;
    }
    DIV.doctools_synopsis {
	color: 		black;
	background: 	#80ffff;
	border:		1px solid black;
	font-family:	serif;
	margin-top: 	1em;
	margin-bottom: 	1em;
    }
    UL.doctools_syntax {
	margin-top: 	1em;
	border-top:	1px solid black;
    }
    UL.doctools_requirements {
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'tcllib_devguide.man' by tcllib/doctools with format 'html'
   -->
<!-- tcllib_devguide.n
   -->
<body><hr> [
   <a href="../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../toc.html">Table Of Contents</a>
&#124; <a href="../../../index.html">Keyword Index</a>
&#124; <a href="../../../toc0.html">Categories</a>
&#124; <a href="../../../toc1.html">Modules</a>
&#124; <a href="../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">tcllib_devguide(n) 1 tcllib &quot;&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>tcllib_devguide - Tcllib - The Developer's Guide</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Commitments</a>
<ul>
<li class="doctools_subsection"><a href="#subsection1">Contributor</a></li>
<li class="doctools_subsection"><a href="#subsection2">Maintainer</a></li>
</ul>
</li>
<li class="doctools_section"><a href="#section3">Branching and Workflow</a>
<ul>
<li class="doctools_subsection"><a href="#subsection3">Package Dependencies</a></li>
<li class="doctools_subsection"><a href="#subsection4">Trunk</a></li>
<li class="doctools_subsection"><a href="#subsection5">Branches</a></li>
<li class="doctools_subsection"><a href="#subsection6">Working with Branches</a></li>
<li class="doctools_subsection"><a href="#subsection7">Version numbers</a></li>
</ul>
</li>
<li class="doctools_section"><a href="#section4">Structural Overview</a>
<ul>
<li class="doctools_subsection"><a href="#subsection8">Main Directories</a></li>
<li class="doctools_subsection"><a href="#subsection9">More Directories</a></li>
<li class="doctools_subsection"><a href="#subsection10">Top Files</a></li>
<li class="doctools_subsection"><a href="#subsection11">File Types</a></li>
</ul>
</li>
<li class="doctools_section"><a href="#section5">Testsuite Tooling</a>
<ul>
<li class="doctools_subsection"><a href="#subsection12">Invoke the testsuites of a specific module</a></li>
<li class="doctools_subsection"><a href="#subsection13">Invoke the testsuites of all modules</a></li>
<li class="doctools_subsection"><a href="#subsection14">Detailed Test Logs</a></li>
<li class="doctools_subsection"><a href="#subsection15">Shell Selection</a></li>
<li class="doctools_subsection"><a href="#subsection16">Help</a></li>
</ul>
</li>
<li class="doctools_section"><a href="#section6">Documentation Tooling</a>
<ul>
<li class="doctools_subsection"><a href="#subsection17">Generate documentation for a specific module</a></li>
<li class="doctools_subsection"><a href="#subsection18">Generate documentation for all modules</a></li>
<li class="doctools_subsection"><a href="#subsection19">Available output formats, help</a></li>
<li class="doctools_subsection"><a href="#subsection20">Validation without output</a></li>
</ul>
</li>
<li class="doctools_section"><a href="#section7">Notes On Writing A Testsuite</a></li>
<li class="doctools_section"><a href="#section8">Installation Tooling</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd"><a href="../../../index.html#module">Module</a></b> <i class="arg">name</i> <i class="arg">code-action</i> <i class="arg">doc-action</i> <i class="arg">example-action</i></a></li>
<li><a href="#2"><b class="cmd"><a href="../../../index.html#application">Application</a></b> <i class="arg">name</i></a></li>
<li><a href="#3"><b class="cmd">Exclude</b> <i class="arg">name</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>Welcome to Tcllib, the Tcl Standard Library. Note that Tcllib is not a
package itself. It is a collection of (semi-independent) <i class="term"><a href="../../../index.html#tcl">Tcl</a></i>
packages that provide utility functions useful to a large collection
of Tcl programmers.</p>
<p>This document is a guide for developers working on Tcllib,
i.e. maintainers fixing bugs, extending the collection's
functionality, etc.</p>
<p>Please read</p>
<ol class="doctools_enumerated">
<li><p><i class="term"><a href="tcllib_sources.html">Tcllib - How To Get The Sources</a></i> and</p></li>
<li><p><i class="term"><a href="tcllib_installer.html">Tcllib - The Installer's Guide</a></i></p></li>
</ol>
<p>first, if that was not done already.</p>
<p>Here we assume that the sources are already available in a
directory of your choice, and that you not only know how to build and
install them, but also have all the necessary requisites to actually
do so. The guide to the sources in particular also explains which
source code management system is used, where to find it, how to set it
up, etc.</p>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">Commitments</a></h2>
<div id="subsection1" class="doctools_subsection"><h3><a name="subsection1">Contributor</a></h3>
<p>As a contributor to Tcllib you are committing yourself to:</p>
<ol class="doctools_enumerated">
<li><p>keep the guidelines written down in
       <i class="term"><a href="tcl_community_communication.html">Tcl Community - Kind Communication</a></i> in your mind.
       The main point to take away from there is
       <em>to be kind to each other</em>.</p></li>
<li><p>Your contributions getting distributed under a BSD/MIT license.
       For the details see <i class="term"><a href="tcllib_license.html">Tcllib - License</a></i></p></li>
</ol>
<p>Contributions are made by entering tickets into our tracker, providing
patches, bundles or branches of code for inclusion, or posting to the
Tcllib related mailing lists.</p>
</div>
<div id="subsection2" class="doctools_subsection"><h3><a name="subsection2">Maintainer</a></h3>
<p>When contributing one or more packages for full inclusion into Tcllib
you are committing yourself to</p>
<ol class="doctools_enumerated">
<li><p>Keep the guidelines written down in
       <i class="term"><a href="tcl_community_communication.html">Tcl Community - Kind Communication</a></i>
       (as any contributor) in your mind. The main point to take away
       from there is <em>to be kind to each other</em>.</p></li>
<li><p>Your packages getting distributed under a BSD/MIT license.  For
       the details see <i class="term"><a href="tcllib_license.html">Tcllib - License</a></i></p></li>
<li><p>Maintenance of the new packages for a period of two years under
       the following rules, and responsibilities:</p>
<ol class="doctools_enumerated">
       
<li><p>A maintainer may step down after the mandatory period as
       	      they see fit.</p></li>
<li><p>A maintainer may step down before the end of the
      	      mandatory period, under the condition that a replacement
      	      maintainer is immediately available and has agreed to
      	      serve the remainder of the period, plus their own
      	      mandatory period (see below).</p></li>
<li><p>When stepping down without a replacement maintainer
      	      taking over the relevant packages have to be flagged as
      	      <b class="const">unmaintained</b>.</p></li>
<li><p>When a replacement mantainer is brought in for a package
      	      it is (kept) marked as <b class="const">maintained</b> (again).</p>
<p>A replacement maintainer is bound by the same rules as
	      the original maintainer, except that the mandatory
	      period of maintenance is shortened to one year.</p></li>
<li><p>For any <b class="const">unmaintained</b> package a contributor
       	      interested in becoming its maintainer can become so by
       	      flagging them as <b class="const">maintained</b> with their name and
       	      contact information, committing themselves to the rules
       	      of a replacement maintainer (see previous point).</p></li>
<li><p>For any already <b class="const">maintained</b> package a contributor
       	      interested in becoming a co-maintainer can become so
       	      with the agreement of the existing maintainer(s),
       	      committing themselves to the rules of a replacement
       	      maintainer (see two points previous).</p></li>
</ol>
<p>The responsibilities as a maintainer include:</p>
<ol class="doctools_enumerated">
       
<li><p>Watching Tcllib's ticket tracker for bugs, bug fixes,
       	      and feature requests related to the new packages.</p></li>
<li><p>Reviewing the aforementioned tickets, rejecting or
       	      applying them</p></li>
<li><p>Coordination and discussion with ticket submitter during
       	      the development and/or application of bug fixes.</p></li>
</ol>
</li>
<li><p>Follow the <span class="sectref"><a href="#section3">Branching and Workflow</a></span> of this guide.</p></li>
</ol>
</div>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">Branching and Workflow</a></h2>
<div id="subsection3" class="doctools_subsection"><h3><a name="subsection3">Package Dependencies</a></h3>
<p>Regarding packages and dependencies between them Tcllib occupies a
middle position between two extremes:</p>
<ol class="doctools_enumerated">
<li><p>On one side a strongly interdependent set of packages, usually
       by a single author, for a single project. Looking at my
       (Andreas Kupries) own work examples of such are
       <a href="https://core.tcl.tk/akupries/marpa/index">Marpa</a>,
       <a href="https://core.tcl.tk/akupries/crimp/index">CRIMP</a>,
       <a href="https://core.tcl.tk/akupries/kinetcl/index">Kinetcl</a>, etc.</p>
<p>For every change the author of the project handles all the
       modifications cascading from any incompatibilities it
       introduced to the system.</p></li>
<li><p>On the other side, the world of semi-independent projects by
       many different authors where authors know what packages their
       own creations depend on, yet usually do not know who else
       depends on them.</p>
<p>The best thing an author making an (incompatible) change to
       their project can do is to for one announce such changes in
       some way, and for two use versioning to distinguish the code
       before and after the change.</p>
<p>The world is then responsible for adapting, be it by updating
       their own projects to the new version, or by sticking to the
       old.</p></li>
</ol>
<p>As mentioned already, Tcllib lives in the middle of that.</p>
<p>While we as maintainers cannot be aware of all users of
       Tcllib's packages, and thus have to rely on the mechanisms
       touched on in point 2 above for that, the dependencies between
       the packages contained in Tcllib are a different matter.</p>
<p>As we are collectively responsible for the usability of Tcllib
       in toto to the outside world, it behooves us to be individually
       mindful even of Tcllib packages we are not directly
       maintaining, when they depend on packages under our
       maintainership.
       This may be as simple as coordinating with the maintainers of
       the affected packages.
       It may also require us to choose how to adapt affected packages
       which do not have maintainers, i.e. modify them to use our
       changed package properly, or modify them to properly depend on
       the unchanged version of our package.</p>
<p>Note that the above is not only a chore but an opportunity as
       well.
       Additional insight can be had by forcing ourselves to look at
       our package and the planned change(s) from an outside
       perspective, to consider the ramifications of our actions on
       others in general, and on dependent packages in particular.</p>
</div>
<div id="subsection4" class="doctools_subsection"><h3><a name="subsection4">Trunk</a></h3>
<p>The management and use of branches is an important part of working
with a <i class="term">Distributed Version Control System</i> (<i class="term">DVCS</i>) like
<a href="https://www.fossil-scm.org/">fossil</a>.</p>
<p>For Tcllib the main branch of the collection is
       <i class="term">trunk</i>. In <i class="term"><a href="../../../index.html#git">git</a></i> this branch would be called
       <i class="term">master</i>, and this is exactly the case in the
       <a href="https://github.com/tcltk/tcllib/">github mirror</a> of
       Tcllib.</p>
<p>To properly support debugging <em>each commit</em> on this
       branch <em>has to pass the entire testsuite</em> of the
       collection. Using bisection to determine when an issue appeared
       is an example of an action made easier by this constraint.</p>
<p>This is part of our collective responsibility for the usability
       of Tcllib in toto to the outside world.
       As <i class="term"><a href="../../../index.html#fossil">fossil</a></i> has no mechanism to enforce this condition
       this is handled on the honor system for developers and maintainers.</p>
<p>To make the task easier Tcllib comes with a tool
       (&quot;<b class="file">sak.tcl</b>&quot;) providing a number of commands in
       support. These commands are explained in the following sections
       of this guide.</p>
<p>While it is possible and allowed to commit directly to trunk
       remember the above constraint regarding the testsuite, and the
       coming notes about other possible issues with a commit.</p>
</div>
<div id="subsection5" class="doctools_subsection"><h3><a name="subsection5">Branches</a></h3>
<p>Given the constraints placed on the <i class="term">trunk</i> branch of the
repository it is (strongly) recommended to perform any development
going beyond trivial changes on a non-trunk branch.</p>
<p>Outside of the trunk developers are allowed to commit
       intermediate broken states of their work.
       Only at the end of a development cycle, when the relevant
       branch is considered ready for merging, will it be necessary to
       perform full the set of validations ensuring that the merge to
       come will create a good commit on trunk.</p>
<p>Note that while a review from a second developer is not a
       required condition for merging a branch it is recommended to
       seek out such an independent opinion as a means of
       cross-checking the work.</p>
<p>It also recommended to give any new branch a name which aids in
       determining additional details about it. Examples of good
       things to stick into a branch name would be</p>
<ul class="doctools_itemized">
<li><p>Developer (nick)name</p></li>
<li><p>Ticket hash/reference</p></li>
<li><p>One or two keywords applicable to the work</p></li>
<li><p>...</p></li>
</ul>
<p>Further, while most development branches are likely quite
       short-lived, no prohibitions exist against making longer-lived
       branches.
       Creators should however be mindful that the longer such a
       branch exists without merges the more divergent they will tend
       to be, with an associated increase in the effort which will
       have to be spent on either merging from and merging to trunk.</p>
</div>
<div id="subsection6" class="doctools_subsection"><h3><a name="subsection6">Working with Branches</a></h3>
<p>In the hope of engendering good work practices now a few example
operations which will come up with branches, and their associated
fossil command (sequences).</p>
<dl class="doctools_definitions">
<dt><em>Awareness</em></dt>
<dd><p>When developing we have to keep ourselves aware of the context of our
work. On what branch are we ? What files have we changed ? What new
files are not yet known to the repository ? What has happened remotely
since we used our checkout ?
The answers to these questions become especially important when using
a long-lived checkout and coming back to it after some time away.</p>
<p>Commands to answer questions like the above are:</p>
<dl class="doctools_definitions">
<dt><b class="cmd">fossil pull</b></dt>
<dd><p>Get all changes done on the remote since the last pull or sync
       from it. This has to be done first, before any of the commands
       below.</p>
<p>Even if the commit in our checkout refers to the branch we want
       right now control operations committed to the remote may have
       changed that from underneath us.</p></dd>
<dt><b class="cmd">fossil info | grep tags</b></dt>
<dd></dd>
<dt><b class="cmd">fossil branch list | grep '\*'</b></dt>
<dd><p>Two different ways of determining the branch our checkout is
       on.</p></dd>
<dt><b class="cmd">fossil timeline</b></dt>
<dd><p>What have we (and others) done recently ?</p>
<p><em>Attention</em>, this information is very likely outdated, the
       more the longer we did not use this checkout.
       Run <b class="cmd">fossil pull</b> first to get latest information from
       the remote repository of the project.</p></dd>
<dt><b class="cmd">fossil timeline current</b></dt>
<dd><p>Place the commit our checkout is based on at the top of the
       timeline.</p></dd>
<dt><b class="cmd">fossil changes</b></dt>
<dd><p>Lists the files we have changed compared to the commit the
       checkout is based on.</p></dd>
<dt><b class="cmd">fossil extra</b></dt>
<dd><p>Lists the files we have in the checkout the repository does not
       know about. This may be leftover chaff from our work, or
       something we have forgotten to <b class="cmd">fossil add</b> to the
       repository yet.</p></dd>
</dl></dd>
<dt><em>Clean checkouts</em></dt>
<dd><p>Be aware of where you are (see first definition).</p>
<p>For pretty much all the operation recipes below a clean
       checkout is at least desired, often required.
       To check that a checkout is clean invoke</p>
<pre class="doctools_example">
    fossil changes
    fossil extra
</pre>
<p>How to clean up when uncommitted changes of all sorts are found is
context-specific and outside of the scope of this guide.</p></dd>
<dt><em>Starting a new branch</em></dt>
<dd><p>Be aware of where you are (see first definition).</p>
<p>Ensure that you have clean checkout (see second definition).
       It is <em>required</em>.</p>
<p>In most situations you want to be on branch <i class="term">trunk</i>, and
       you want to be on the latest commit for it. To get there use</p>
<pre class="doctools_example">
    fossil pull
    fossil update trunk
</pre>
<p>If some other branch is desired as the starting point for the coming
work replace <i class="term">trunk</i> in the commands above with the name of that
branch.</p>
<p>With the base line established we now have two ways of creating
       the new branch, with differing (dis)advantages.
       The simpler way is to</p>
<pre class="doctools_example">
    fossil branch new NAME_OF_NEW_BRANCH
</pre>
<p>and start developing. The advantage here is that you cannot forget to
create the branch. The disadvantages are that we have a branch commit
unchanged from where we branched from, and that we have to use
high-handed techniques like hiding or shunning to get rid of the
commit should we decide to abandon the work before the first actual
commit on the branch.</p>
<p>The other way of creating the branch is to start developing,
and then on the first commit use the option <b class="option">--branch</b> to tell
<b class="syscmd"><a href="../../../index.html#fossil">fossil</a></b> that we are starting a branch now. I.e. run</p>
<pre class="doctools_example">
    fossil commit --branch NAME_OF_NEW_BRANCH ...
</pre>
<p>where <i class="term">...</i> are any other options used to supply the commit
message, files to commit, etc.</p>
<p>The (dis)advantages are now reversed.</p>
<p>We have no superflous commit, only what is actually
       developed. The work is hidden until we commit to make our first
       commit.</p>
<p>We may forget to use <b class="option">--branch NAME_OF_NEW_BRANCH</b> and
       then have to correct that oversight via the fossil web
       interface (I am currently unaware of ways of doing such from
       the command line, although some magic incantantion of
       <b class="cmd">fossil tag create</b> may work).</p>
<p>It helps to keep awareness, like checking before any commit
       that we are on the desired branch.</p></dd>
<dt><em>Merging a branch into trunk</em></dt>
<dd><p>Be aware of where you are (see first definition).</p>
<p>Ensure that you have clean checkout (see second definition).
       In the full-blown sequence (zig-zag) it is <em>required</em>, due
       to the merging from trunk. In the shorter sequence it is only
       desired. That said, keeping the checkout clean before
       any major operations is a good habit to have, in my opinion.</p>
<p>The full-blown sequencing with checks all the way is to</p>
<ol class="doctools_enumerated">
<li><p>Validate the checkout, i.e. last commit on your branch. Run the
       full test suite and other validations, fix all the issues which
       have cropped up.</p></li>
<li><p>Merge the latest state of the <i class="term">trunk</i> (see next definition).</p></li>
<li><p>Validate the checkout again. The incoming trunk changes may
       have broken something now. Do any required fixes.</p></li>
<li><p>Now merge to the trunk using</p>
<pre class="doctools_example">
    fossil update trunk
    fossil merge --integrate YOUR_BRANCH
</pre>
</li>
<li><p>At this point the checkout should be in the same state as at
       the end of point (3) above, because we resolved any issues with
       the trunk already. Thus a simple</p>
<pre class="doctools_example">
    fossil commit ...
</pre>
<p>should be sufficient now to commit the merge back and close the
       branch (due to the <b class="option">--integrate</b> we used on the merge).</p>
<p>The more paranoid may validate the checkout a third time before
       commiting.</p></li>
</ol>
<p>I call this a <i class="term">zig-zag merge</i> because of how the arrows
       look in the timeline, from trunk to feature branch for the
       first merge, and then back for the final merge.</p>
<p>A less paranoid can do what I call a <i class="term">simple merge</i>,
       which moves step (2) after step (4) and skips step (3)
       entirely. The resulting shorter sequence is</p>
<ol class="doctools_enumerated">
<li><p>Validate</p></li>
<li><p>Merge to trunk</p></li>
<li><p>Validate again</p></li>
<li><p>Commit to trunk</p></li>
</ol>
<p>The last step after either zig-zag or plain merge is to</p>
<pre class="doctools_example">
    fossil sync
</pre>
<p>This saves our work to the remote side, and further gives us any other
work done while we were doing our merge. It especially allows us to
check if we raced somebody else, resulting in a split trunk.</p>
<p>When that happens we should coordinate with the other developer
       on who fixes the split, to ensure that we do not race each
       other again.</p></dd>
<dt><em>Merging from trunk</em></dt>
<dd><p>Be aware of where you are (see first definition).</p>
<p>Ensure that you have clean checkout (see second definition).
       It is <em>required</em>.</p>
<p>In most situations you want to import the latest commit of
       branch <i class="term">trunk</i> (or other origin). To get it use</p>
<pre class="doctools_example">
    fossil pull
</pre>
<p>With that done we can now import this commit into our current
       branch with</p>
<pre class="doctools_example">
    fossil merge trunk
</pre>
<p>Even if <b class="syscmd"><a href="../../../index.html#fossil">fossil</a></b> does not report any conflicts it is a
       good idea to check that the operation has not broken the new
       and/or changed functionality we are working on.</p>
<p>With the establishment of a good merge we then save the state
       with</p>
<pre class="doctools_example">
    fossil commit ...
</pre>
<p>before continuing development.</p></dd>
</dl>
</div>
<div id="subsection7" class="doctools_subsection"><h3><a name="subsection7">Version numbers</a></h3>
<p>In Tcllib all changes to a package have to come with an increment of
its version number. What part is incremented (patchlevel, minor, major
version) depends on the kind of change made. With multiple changes in
a commit the highest &quot;wins&quot;.</p>
<p>When working in a development branch the version change can be
       deferred until it is time to merge, and then has to cover all
       the changes in the branch.</p>
<p>Below a list of the kinds of changes and their associated
       version increments:</p>
<dl class="doctools_definitions">
<dt><i class="term">D - documentation</i></dt>
<dd><p>No increment</p></dd>
<dt><i class="term">T - testsuite</i></dt>
<dd><p>No increment</p></dd>
<dt><i class="term">B - bugfix</i></dt>
<dd><p>Patchlevel</p></dd>
<dt><i class="term">I - implementation tweak</i></dt>
<dd><p>Patchlevel</p></dd>
<dt><i class="term">P - performance tweak</i></dt>
<dd><p>Patchlevel</p></dd>
<dt><i class="term">E - backward-compatible extension</i></dt>
<dd><p>Minor</p></dd>
<dt><i class="term">API - incompatible change</i></dt>
<dd><p>Major</p></dd>
</dl>
<p>Note that a commit containing a version increment has to
       mention the new version number in its commit message, as well
       as the kind of change which caused it.</p>
<p>Note further that the version number of a package currently
       exists in three places. An increment has to update all of them:</p>
<ol class="doctools_enumerated">
<li><p>The package implementation.</p></li>
<li><p>The package index (&quot;<b class="file">pkgIndex.tcl</b>&quot;)</p></li>
<li><p>The package documentation.</p></li>
</ol>
<p>The &quot;<b class="file">sak.tcl</b>&quot; command <b class="cmd">validate version</b> helps
       finding discrepancies between the first two.
       All the other <b class="cmd">validate</b> methods are also of interest to
       any developer. Invoke it with</p>
<pre class="doctools_example"> sak.tcl help validate </pre>
<p>to see their documentation.</p>
</div>
</div>
<div id="section4" class="doctools_section"><h2><a name="section4">Structural Overview</a></h2>
<div id="subsection8" class="doctools_subsection"><h3><a name="subsection8">Main Directories</a></h3>
<p>The main directories in the Tcllib toplevel directory and of interest
to a developer are:</p>
<dl class="doctools_definitions">
<dt>&quot;<b class="file">modules</b>&quot;</dt>
<dd><p>Each child directory represents one or more packages.
In the case of the latter the packages are usually related in some
way. Examples are &quot;<b class="file">base64</b>&quot;, &quot;<b class="file">math</b>&quot;, and &quot;<b class="file">struct</b>&quot;, with
loose (base64) to strong (math) relations between the packages in the
directory.</p></dd>
<dt>&quot;<b class="file">apps</b>&quot;</dt>
<dd><p>This directory contains all the installable applications, with their
documentation. Note that this directory is currently <em>not</em> split
into sub-directories.</p></dd>
<dt>&quot;<b class="file">examples</b>&quot;</dt>
<dd><p>Each child directory &quot;<b class="file">foo</b>&quot; contains one or more example
application for the packages in &quot;<b class="file">modules/foo</b>&quot;. These examples are
generally not polished enough to be considered for installation.</p></dd>
</dl>
</div>
<div id="subsection9" class="doctools_subsection"><h3><a name="subsection9">More Directories</a></h3>
<dl class="doctools_definitions">
<dt>&quot;<b class="file">config</b>&quot;</dt>
<dd><p>This directory contains files supporting the Unix build system,
i.e. &quot;<b class="file">configure</b>&quot; and &quot;<b class="file">Makefile.in</b>&quot;.</p></dd>
<dt>&quot;<b class="file">devdoc</b>&quot;</dt>
<dd><p>This directories contains the doctools sources for the global
documentation, like this document and its sibling guides.</p></dd>
<dt>&quot;<b class="file">embedded</b>&quot;</dt>
<dd><p>This directory contains the entire documentation formatted for
<i class="term"><a href="../../../index.html#html">HTML</a></i> and styled to properly mix into the web site generated by
fossil for the repository.</p>
<p>This is the documentation accessible from the Tcllib home
directory, represented in the repository as &quot;<b class="file">embedded/index.md</b>&quot;.</p></dd>
<dt>&quot;<b class="file">idoc</b>&quot;</dt>
<dd><p>This directory contains the entire documentation formatted for
<i class="term"><a href="../../../index.html#nroff">nroff</a></i> and <i class="term"><a href="../../../index.html#html">HTML</a></i>, the latter without any styling.
This is the documentation which will be installed.</p></dd>
<dt>&quot;<b class="file">support</b>&quot;</dt>
<dd><p>This directory contains the sources of internal packages and utilities
used in the implementation of the &quot;<b class="file">installer.tcl</b>&quot; and
&quot;<b class="file">sak.tcl</b>&quot; scripts/tools.</p></dd>
</dl>
</div>
<div id="subsection10" class="doctools_subsection"><h3><a name="subsection10">Top Files</a></h3>
<dl class="doctools_definitions">
<dt>&quot;<b class="file">aclocal.m4</b>&quot;</dt>
<dd></dd>
<dt>&quot;<b class="file">configure</b>&quot;</dt>
<dd></dd>
<dt>&quot;<b class="file">configure.in</b>&quot;</dt>
<dd></dd>
<dt>&quot;<b class="file">Makefile.in</b>&quot;</dt>
<dd><p>These four files comprise the Unix build system layered on top of the
&quot;<b class="file">installer.tcl</b>&quot; script.</p></dd>
<dt>&quot;<b class="file">installer.tcl</b>&quot;</dt>
<dd><p>The Tcl-based installation script/tool.</p></dd>
<dt>&quot;<b class="file">project.shed</b>&quot;</dt>
<dd><p>Configuration file for <i class="term">Sean Wood</i>'s <b class="syscmd"><a href="../modules/practcl/practcl.html">PracTcl</a></b>
buildsystem.</p></dd>
<dt>&quot;<b class="file">sak.tcl</b>&quot;</dt>
<dd><p>This is the main tool for developers and release managers, the
<i class="term">Swiss Army Knife</i> of management operations on the collection.</p></dd>
<dt>&quot;<b class="file">ChangeLog</b>&quot;</dt>
<dd><p>The log of changes to the global support, when the sources were held
in <i class="term"><a href="../../../index.html#cvs">CVS</a></i>. Not relevant any longer with the switch to the
<i class="term"><a href="../../../index.html#fossil">fossil</a></i> SCM.</p></dd>
<dt>&quot;<b class="file">license.terms</b>&quot;</dt>
<dd><p>The license in plain ASCII. See also <i class="term"><a href="tcllib_license.html">Tcllib - License</a></i> for the
nicely formatted form. The text is identical.</p></dd>
<dt>&quot;<b class="file">README.md</b>&quot;</dt>
<dd></dd>
<dt>&quot;<b class="file">.github/CONTRIBUTING.md</b>&quot;</dt>
<dd></dd>
<dt>&quot;<b class="file">.github/ISSUE_TEMPLATE.md</b>&quot;</dt>
<dd></dd>
<dt>&quot;<b class="file">.github/PULL_REQUEST_TEMPLATE.md</b>&quot;</dt>
<dd><p>These markdown-formatted documents are used and shown by the github
mirror of these sources, pointing people back to the official location
and issue trackers.</p></dd>
<dt>&quot;<b class="file">DESCRIPTION.txt</b>&quot;</dt>
<dd></dd>
<dt>&quot;<b class="file">STATUS</b>&quot;</dt>
<dd></dd>
<dt>&quot;<b class="file">tcllib.spec</b>&quot;</dt>
<dd></dd>
<dt>&quot;<b class="file">tcllib.tap</b>&quot;</dt>
<dd></dd>
<dt>&quot;<b class="file">tcllib.yml</b>&quot;</dt>
<dd><p>????</p></dd>
</dl>
</div>
<div id="subsection11" class="doctools_subsection"><h3><a name="subsection11">File Types</a></h3>
<p>The most common file types, by file extension, are:</p>
<dl class="doctools_definitions">
<dt>&quot;<b class="file">.tcl</b>&quot;</dt>
<dd><p>Tcl code for a package, application, or example.</p></dd>
<dt>&quot;<b class="file">.man</b>&quot;</dt>
<dd><p>Doctools-formatted documentation, usually for a package.</p></dd>
<dt>&quot;<b class="file">.test</b>&quot;</dt>
<dd><p>Test suite for a package, or part of.
Based on <b class="package">tcltest</b>.</p></dd>
<dt>&quot;<b class="file">.bench</b>&quot;</dt>
<dd><p>Performance benchmarks for a package, or part of.
Based on &quot;<b class="file">modules/bench</b>&quot;.</p></dd>
<dt>&quot;<b class="file">.pcx</b>&quot;</dt>
<dd><p>Syntax rules for <i class="term">TclDevKit</i>'s <b class="syscmd">tclchecker</b>. Using these
rules allows the checker to validate the use of commands of a Tcllib
package <b class="package">foo</b> without having to scan the &quot;<b class="file">.tcl</b>&quot; files
implementing it.</p></dd>
</dl>
</div>
</div>
<div id="section5" class="doctools_section"><h2><a name="section5">Testsuite Tooling</a></h2>
<p>Testsuites in Tcllib are based on Tcl's standard test package
<b class="package">tcltest</b>, plus utilities found in the directory
&quot;<b class="file">modules/devtools</b>&quot;</p>
<p>Tcllib developers invoke the suites through the
<b class="cmd">test run</b> method of the &quot;<b class="file">sak.tcl</b>&quot; tool, with other methods
of <b class="cmd"><a href="../../../index.html#test">test</a></b> providing management operations, for example setting a
list of standard Tcl shells to use.</p>
<div id="subsection12" class="doctools_subsection"><h3><a name="subsection12">Invoke the testsuites of a specific module</a></h3>
<p>Invoke either</p>
<pre class="doctools_example">  ./sak.tcl test run foo </pre>
<p>or</p>
<pre class="doctools_example">  ./sak.tcl test run modules/foo </pre>
<p>to invoke the testsuites found in a specific module &quot;<b class="file">foo</b>&quot;.</p>
</div>
<div id="subsection13" class="doctools_subsection"><h3><a name="subsection13">Invoke the testsuites of all modules</a></h3>
<p>Invoke the tool without a module name, i.e.</p>
<pre class="doctools_example">  ./sak.tcl test run </pre>
<p>to invoke the testsuites of all modules.</p>
</div>
<div id="subsection14" class="doctools_subsection"><h3><a name="subsection14">Detailed Test Logs</a></h3>
<p>In all the previous examples the test runner will write a combination
of progress display and testsuite log to the standard output, showing
for each module only the tests that passed or failed and how many of
each in a summary at the end.</p>
<p>To get a detailed log, it is necessary to invoke the test
runner with additional options.</p>
<p>For one:</p>
<pre class="doctools_example">
   ./sak.tcl test run --log LOG foo
</pre>
<p>While this shows the same short log on the terminal as before, it also
writes a detailed log to the file &quot;<b class="file">LOG.log</b>&quot;, and excerpts to
other files (&quot;<b class="file">LOG.summary</b>&quot;, &quot;<b class="file">LOG.failures</b>&quot;, etc.).</p>
<p>For two:</p>
<pre class="doctools_example">
  ./sak.tcl test run -v foo
</pre>
<p>This writes the detailed log to the standard output, instead of the
short log.</p>
<p>Regardless of form, the detailed log contains a list of all test
cases executed, which failed, and how they failed (expected versus
actual results).</p>
</div>
<div id="subsection15" class="doctools_subsection"><h3><a name="subsection15">Shell Selection</a></h3>
<p>By default the test runner will use all the Tcl shells specified via
<b class="cmd">test add</b> to invoke the specified testsuites, if any. If no
such are specified it will fall back to the Tcl shell used to run the
tool itself.</p>
<p>Use option <b class="option">--shell</b> to explicitly specify the Tcl shell
to use, like</p>
<pre class="doctools_example">
  ./sak.tcl test run --shell /path/to/tclsh ...
</pre>
</div>
<div id="subsection16" class="doctools_subsection"><h3><a name="subsection16">Help</a></h3>
<p>Invoke the tool as</p>
<pre class="doctools_example">  ./sak.tcl help test </pre>
<p>to see the detailed help for all methods of <b class="cmd"><a href="../../../index.html#test">test</a></b>, and the
associated options.</p>
</div>
</div>
<div id="section6" class="doctools_section"><h2><a name="section6">Documentation Tooling</a></h2>
<p>The standard format used for documentation of packages and other
things in Tcllib is <i class="term"><a href="../../../index.html#doctools">doctools</a></i>.
Its supporting packages are a part of Tcllib, see the directories
&quot;<b class="file">modules/doctools</b>&quot; and &quot;<b class="file">modules/dtplite</b>&quot;. The latter is
an application package, with the actual application
&quot;<b class="file">apps/dtplite</b>&quot; a light wrapper around it.</p>
<p>Tcllib developers gain access to these through the <b class="cmd">doc</b>
method of the &quot;<b class="file">sak.tcl</b>&quot; tool, another (internal) wrapper around
the &quot;<b class="file">modules/dtplite</b>&quot; application package.</p>
<div id="subsection17" class="doctools_subsection"><h3><a name="subsection17">Generate documentation for a specific module</a></h3>
<p>Invoke either</p>
<pre class="doctools_example">  ./sak.tcl doc html foo </pre>
<p>or</p>
<pre class="doctools_example">  ./sak.tcl doc html modules/foo </pre>
<p>to generate HTML for the documentation found in the module &quot;<b class="file">foo</b>&quot;.
Instead of <b class="const">html</b> any other supported format can be used here,
of course.</p>
<p>The generated formatted documentation will be placed into a
directory &quot;<b class="file">doc</b>&quot; in the current working directory.</p>
</div>
<div id="subsection18" class="doctools_subsection"><h3><a name="subsection18">Generate documentation for all modules</a></h3>
<p>Invoke the tool without a module name, i.e.</p>
<pre class="doctools_example">  ./sak.tcl doc html </pre>
<p>to generate HTML for the documentation found in all modules.
Instead of <b class="const">html</b> any other supported format can be used here,
of course.</p>
<p>The generated formatted documentation will be placed into a
directory &quot;<b class="file">doc</b>&quot; in the current working directory.</p>
</div>
<div id="subsection19" class="doctools_subsection"><h3><a name="subsection19">Available output formats, help</a></h3>
<p>Invoke the tool as</p>
<pre class="doctools_example">  ./sak.tcl help doc </pre>
<p>to see the entire set of supported output formats which can be
generated.</p>
</div>
<div id="subsection20" class="doctools_subsection"><h3><a name="subsection20">Validation without output</a></h3>
<p>Note the special format <b class="const">validate</b>.</p>
<p>Using this value as the name of the format to generate forces
the tool to simply check that the documentation is syntactically
correct, without generating actual output.</p>
<p>Invoke it as either</p>
<pre class="doctools_example">  ./sak.tcl doc validate (modules/)foo </pre>
<p>or</p>
<pre class="doctools_example">  ./sak.tcl doc validate </pre>
<p>to either check the packages of a specific module or check all of
them.</p>
</div>
</div>
<div id="section7" class="doctools_section"><h2><a name="section7">Notes On Writing A Testsuite</a></h2>
<p>While previous sections talked about running the testsuites for a
module and the packages therein, this has no meaning if the module in
question has no testsuites at all.</p>
<p>This section gives a very basic overview on possible
methodologies for writing tests and testsuites.</p>
<p>First there are &quot;drudgery&quot; tests. Written to check absolutely
basic assumptions which should never fail.</p>
<p>For example for a command FOO taking two arguments, three tests
calling it with zero, one, and three arguments. The basic checks that
the command fails if it has not enough arguments, or too many.</p>
<p>After that come the tests checking things based on our
knowledge of the command, about its properties and assumptions. Some
examples based on the graph operations added during Google's Summer of
Code 2009 are:</p>
<ul class="doctools_itemized">
<li><p>The BellmanFord command in struct::graph::ops takes a
	<i class="arg">startnode</i> as argument, and this node should be a node of
	the graph. This equals one test case checking the behavior when the
	specified node is not a node of the graph.</p>
<p>This often gives rise to code in the implementation which
	explicitly checks the assumption and throws an understandable error,
	instead of letting the algorithm fail later in some weird
	non-deterministic way.</p>
<p>It is not always possible to do such checks. The graph argument
	for example is just a command in itself, and while we expect
	it to exhibit a certain interface, i.e. a set of sub-commands
	aka methods, we cannot check that it has them, except by
	actually trying to use them. That is done by the algorithm
	anyway, so an explicit check is just overhead we can get by
	without.</p></li>
<li><p>IIRC one of the distinguishing characteristic of either
	BellmanFord and/or Johnson is that they are able to handle
	negative weights. Whereas Dijkstra requires positive weights.</p>
<p>This induces (at least) three testcases ... Graph with all
	positive weights, all negative, and a mix of positive and
	negative weights.
	Thinking further does the algorithm handle the weight
	<b class="const">0</b> as well ? Another test case, or several, if we mix
	zero with positive and negative weights.</p></li>
<li><p>The two algorithms we are currently thinking about are about
	distances between nodes, and distance can be 'Inf'inity,
	i.e. nodes may not be connected. This means that good test
	cases are</p>
<ol class="doctools_enumerated">
	
<li><p>Strongly connected graph</p></li>
<li><p>Connected graph</p></li>
<li><p>Disconnected graph.</p></li>
</ol>
<p>At the extremes of strongly connected and disconnected
	we have the fully connected graphs and graphs without edges,
	only nodes, i.e. completely disconnected.</p></li>
<li><p>IIRC both of the algorithms take weighted arcs, and fill in a
	default if arcs are left unweighted in the input graph.</p>
<p>This also induces three test cases:</p>
<ol class="doctools_enumerated">
	
<li><p>Graph will all arcs with explicit weights.</p></li>
<li><p>Graph without weights at all.</p></li>
<li><p>Graph with mixture of weighted and unweighted graphs.</p></li>
</ol>
</li>
</ul>
<p>What was described above via examples is called
<i class="term">black-box</i> testing. Test cases are designed and written based on
the developer's knowledge of the properties of the algorithm and its
inputs, without referencing a particular implementation.</p>
<p>Going further, a complement to <i class="term">black-box</i> testing is
<i class="term">white-box</i>. For this we know the implementation of the
algorithm, we look at it and design our tests cases so that they force
the code through all possible paths in the implementation. Wherever a
decision is made we have a test case forcing a specific direction of
the decision, for all possible combinations and directions. It is easy
to get a combinatorial explosion in the number of needed test-cases.</p>
<p>In practice I often hope that the black-box tests I have made
are enough to cover all the paths, obviating the need for white-box
tests.</p>
<p>The above should be enough to make it clear that writing tests
for an algorithm takes at least as much time as coding the algorithm,
and often more time. Much more time.
See for example also <a href="http://sqlite.org/testing.html">http://sqlite.org/testing.html</a>, a writeup
on how the Sqlite database engine is tested. Another article of
interest might be <a href="https://www.researchgate.net/publication/298896236">https://www.researchgate.net/publication/298896236</a>.
While geared to a particular numerical algorithm it still shows that
even a simple-looking algorithm can lead to an incredible number of
test cases.</p>
<p>An interesting connection is to documentation. In one
direction, the properties checked with black-box testing are exactly
the properties which should be documented in the algorithm's man
page. And conversely, the documentation of the properties of an
algorithm makes a good reference to base the black-box tests on.</p>
<p>In practice test cases and documentation often get written
together, cross-influencing each other. And the actual writing of test
cases is a mix of black and white box, possibly influencing the
implementation while writing the tests. Like writing a test for a
condition like <i class="term">startnode not in input graph</i> serving as
reminder to put a check for this condition into the code.</p>
</div>
<div id="section8" class="doctools_section"><h2><a name="section8">Installation Tooling</a></h2>
<p>A last thing to consider when adding a new package to the collection
is installation.</p>
<p>How to <em>use</em> the &quot;<b class="file">installer.tcl</b>&quot; script is documented
in <i class="term"><a href="tcllib_installer.html">Tcllib - The Installer's Guide</a></i>.</p>
<p>Here we document how to extend said installer so that it may
install new package(s) and/or application(s).</p>
<p>In most cases only a single file has to be modified, the
&quot;<b class="file">support/installation/modules.tcl</b>&quot; holding one command per module
and application to install.</p>
<p>The relevant commands are:</p>
<dl class="doctools_definitions">
<dt><a name="1"><b class="cmd"><a href="../../../index.html#module">Module</a></b> <i class="arg">name</i> <i class="arg">code-action</i> <i class="arg">doc-action</i> <i class="arg">example-action</i></a></dt>
<dd><p>Install the packages of module <i class="arg">name</i>, found in
&quot;<b class="file">modules/<i class="arg">name</i></b>&quot;.</p>
<p>The <i class="arg">code-action</i> is responsible for installing the
packages and their index. The system currently provides</p>
<dl class="doctools_definitions">
<dt><b class="cmd">_tcl</b></dt>
<dd><p>Copy all &quot;<b class="file">.tcl</b>&quot; files found in
&quot;<b class="file">modules/<i class="arg">name</i></b>&quot; into the installation.</p></dd>
<dt><b class="cmd">_tcr</b></dt>
<dd><p>As <b class="cmd">_tcl</b>, copy the &quot;<b class="file">.tcl</b>&quot; files found in
the subdirectories of &quot;<b class="file">modules/<i class="arg">name</i></b>&quot; as well.</p></dd>
<dt><b class="cmd">_tci</b></dt>
<dd><p>As <b class="cmd">_tcl</b>, and copy the &quot;<b class="file">tclIndex.tcl</b>&quot; file
as well.</p></dd>
<dt><b class="cmd">_msg</b></dt>
<dd><p>As <b class="cmd">_tcl</b>, and copy the subdirectory &quot;<b class="file">msgs</b>&quot;
as well.</p></dd>
<dt><b class="cmd">_doc</b></dt>
<dd><p>As <b class="cmd">_tcl</b>, and copy the subdirectory
&quot;<b class="file">mpformats</b>&quot; as well.</p></dd>
<dt><b class="cmd">_tex</b></dt>
<dd><p>As <b class="cmd">_tcl</b>, and copy &quot;<b class="file">.tex</b>&quot; files as well.</p></dd>
</dl>
<p>The <i class="arg">doc-action</i> is responsible for installing the package
documentation. The system currently provides</p>
<dl class="doctools_definitions">
<dt><b class="cmd">_null</b></dt>
<dd><p>No documentation available, do nothing.</p></dd>
<dt><b class="cmd">_man</b></dt>
<dd><p>Process the &quot;<b class="file">.man</b>&quot; files found in
&quot;<b class="file">modules/<i class="arg">name</i></b>&quot; and install the results (nroff and/or HTML)
in the proper location, as given to the installer.</p>
<p>This is actually a fallback, normally the installer uses the
pre-made formatted documentation found under &quot;<b class="file">idoc</b>&quot;.</p></dd>
</dl>
<p>The <i class="arg">example-action</i> is responsible for installing the
examples. The system currently provides</p>
<dl class="doctools_definitions">
<dt><b class="cmd">_null</b></dt>
<dd><p>No examples available, do nothing.</p></dd>
<dt><b class="cmd">_exa</b></dt>
<dd><p>Copy the the directory &quot;<b class="file">examples/<i class="arg">name</i></b>&quot;
recursively to the install location for examples.</p></dd>
</dl></dd>
<dt><a name="2"><b class="cmd"><a href="../../../index.html#application">Application</a></b> <i class="arg">name</i></a></dt>
<dd><p>Install the application with <i class="arg">name</i>, found in &quot;<b class="file">apps</b>&quot;.</p></dd>
<dt><a name="3"><b class="cmd">Exclude</b> <i class="arg">name</i></a></dt>
<dd><p>This command signals to the installer which of the listed modules to
<em>not</em> install. I.e. they name the deprecated modules of Tcllib.</p></dd>
</dl>
<p>If, and only if the above actions are not suitable for the new
module then a second file has to be modified,
&quot;<b class="file">support/installation/actions.tcl</b>&quot;.</p>
<p>This file contains the implementations of the available
actions, and is the place where any custom action needed to handle the
special circumstances of module has to be added.</p>
</div>
</div></body></html>

Added idoc/www/tcllib/files/devdoc/tcllib_installer.html.

















































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
<!DOCTYPE html><html><head>
<title>tcllib_install_guide - </title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
	color:	 	black;
    }
    DIV.doctools {
	margin-left:	10%;
	margin-right:	10%;
    }
    DIV.doctools H1,DIV.doctools H2 {
	margin-left:	-5%;
    }
    H1, H2, H3, H4 {
	margin-top: 	1em;
	font-family:	sans-serif;
	font-size:	large;
	color:		#005A9C;
	background: 	transparent;
	text-align:		left;
    }
    H1.doctools_title {
	text-align: center;
    }
    UL,OL {
	margin-right: 0em;
	margin-top: 3pt;
	margin-bottom: 3pt;
    }
    UL LI {
	list-style: disc;
    }
    OL LI {
	list-style: decimal;
    }
    DT {
	padding-top: 	1ex;
    }
    UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
	font:		normal 12pt/14pt sans-serif;
	list-style:	none;
    }
    LI.doctools_section, LI.doctools_subsection {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding: 	0em;
    }
    PRE {
	display: 	block;
	font-family:	monospace;
	white-space:	pre;
	margin:		0%;
	padding-top:	0.5ex;
	padding-bottom:	0.5ex;
	padding-left:	1ex;
	padding-right:	1ex;
	width:		100%;
    }
    PRE.doctools_example {
	color: 		black;
	background: 	#f5dcb3;
	border:		1px solid black;
    }
    UL.doctools_requirements LI, UL.doctools_syntax LI {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding:	0em;
    }
    DIV.doctools_synopsis {
	color: 		black;
	background: 	#80ffff;
	border:		1px solid black;
	font-family:	serif;
	margin-top: 	1em;
	margin-bottom: 	1em;
    }
    UL.doctools_syntax {
	margin-top: 	1em;
	border-top:	1px solid black;
    }
    UL.doctools_requirements {
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'tcllib_installer.man' by tcllib/doctools with format 'html'
   -->
<!-- tcllib_install_guide.n
   -->
<body><hr> [
   <a href="../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../toc.html">Table Of Contents</a>
&#124; <a href="../../../index.html">Keyword Index</a>
&#124; <a href="../../../toc0.html">Categories</a>
&#124; <a href="../../../toc1.html">Modules</a>
&#124; <a href="../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">tcllib_install_guide(n) 1 tcllib &quot;&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>tcllib_install_guide - Tcllib - The Installer's Guide</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Requisites</a>
<ul>
<li class="doctools_subsection"><a href="#subsection1">Tcl</a></li>
<li class="doctools_subsection"><a href="#subsection2">Critcl</a></li>
</ul>
</li>
<li class="doctools_section"><a href="#section3">Build &amp; Installation Instructions</a>
<ul>
<li class="doctools_subsection"><a href="#subsection3">Installing on Unix</a></li>
<li class="doctools_subsection"><a href="#subsection4">Installing on Windows</a></li>
<li class="doctools_subsection"><a href="#subsection5">Critcl &amp; Accelerators</a></li>
<li class="doctools_subsection"><a href="#subsection6">Tooling</a></ul>
</li>
</ul>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>Welcome to Tcllib, the Tcl Standard Library. Note that Tcllib is not a
package itself. It is a collection of (semi-independent) <i class="term"><a href="../../../index.html#tcl">Tcl</a></i>
packages that provide utility functions useful to a large collection
of Tcl programmers.</p>
<p>The audience of this document is anyone wishing to build and install
the packages found in Tcllib, for either themselves, or others.</p>
<p>For developers intending to work on the packages themselves we
additionally provide</p>
<ol class="doctools_enumerated">
<li><p><i class="term"><a href="tcllib_devguide.html">Tcllib - The Developer's Guide</a></i>.</p></li>
</ol>
<p>Please read <i class="term"><a href="tcllib_sources.html">Tcllib - How To Get The Sources</a></i> first, if that
was not done already. Here we assume that the sources are already
available in a directory of your choice.</p>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">Requisites</a></h2>
<p>Before Tcllib can be build and used a number of requisites must be installed.
These are:</p>
<ol class="doctools_enumerated">
<li><p>The scripting language Tcl.
       For details see <span class="sectref"><a href="#subsection1">Tcl</a></span>.</p></li>
<li><p>Optionally, the <b class="package">critcl</b> package (C embedding) for <b class="syscmd"><a href="../../../index.html#tcl">Tcl</a></b>.
       For details see <b class="sectref">CriTcl</b>.</p></li>
</ol>
<p>This list assumes that the machine where Tcllib is to be installed is
essentially clean. Of course, if parts of the dependencies listed
below are already installed the associated steps can be skipped. It is
still recommended to read their sections though, to validate that the
dependencies they talk about are indeed installed.</p>
<div id="subsection1" class="doctools_subsection"><h3><a name="subsection1">Tcl</a></h3>
<p>As we are installing a number of Tcl packages and applications it
should be pretty much obvious that a working installation of Tcl
itself is needed, and I will not belabor the point.</p>
<p>Out of the many possibilities use whatever you are comfortable
with, as long as it provides at the very least Tcl 8.2, or higher.
This may be a Tcl installation provided by your operating system
distribution, from a distribution-independent vendor, or built by
yourself.</p>
<p><em>Note</em> that the packages in Tcllib have begun to require
8.4, 8.5, and even 8.6. Older versions of Tcl will not be able to use
such packages. Trying to use them will result in
<em>package not found</em> errors, as their package index files will
not register them in versions of the core unable to use them.</p>
<p>Myself, I used (and still use)
<a href="http://www.activestate.com">ActiveState's</a>
ActiveTcl 8.5 distribution during development, as I am most familiar
with it.</p>
<p><em>(Disclosure: I, Andreas Kupries, worked for ActiveState until 2016, maintaining ActiveTcl and TclDevKit for them).</em>.
I am currently working for SUSE Software Canada ULC, although not in
Tcl-related areas.</p>
<p>This distribution can be found at
<a href="http://www.activestate.com/activetcl">http://www.activestate.com/activetcl</a>. Retrieve the archive of
ActiveTcl 8.5 (or higher) for your platform and install it as directed
by ActiveState.</p>
<p>For those wishing to build and install Tcl on their own, the
relevant sources can be found at</p>
<dl class="doctools_definitions">
<dt>Tcl</dt>
<dd><p><a href="http://core.tcl-lang.org/tcl/">http://core.tcl-lang.org/tcl/</a></p></dd>
</dl>
<p>together with the necessary instructions on how to build it.</p>
<p>If there are problems with building, installing, or using Tcl,
please file a ticket against <i class="term"><a href="../../../index.html#tcl">Tcl</a></i>, or the vendor of your
distribution, and <em>not</em> <i class="term"><a href="../../../index.html#tcllib">Tcllib</a></i>.</p>
</div>
<div id="subsection2" class="doctools_subsection"><h3><a name="subsection2">Critcl</a></h3>
<p>The <b class="syscmd">critcl</b> tool is an <em>optional</em> dependency.</p>
<p>It is only required when trying to build the C-based
<i class="term">accelerators</i> for a number of packages, as explained in
<span class="sectref"><a href="#subsection5">Critcl &amp; Accelerators</a></span></p>
<p>Tcllib's build system looks for it in the ,
using the name <b class="syscmd">critcl</b>. This is for Unix.
On Windows on the other hand the search is more complex. First we look
for a proper application <b class="syscmd">critcl.exe</b>. When that is not found
we look for a combination of interpreter (<b class="syscmd">tclkitsh.exe</b>,
<b class="syscmd">tclsh.exe</b>) and starkit (<b class="syscmd">critcl.kit</b>, <b class="syscmd">critcl</b>)
instead. <em>Note</em> that the choice of starkit can be overriden via
the environment variable .</p>
<p>Tcllib requires Critcl version 2 or higher.</p>
<p>The github repository providing releases of version 2 and
higher, and the associated sources, can be found at
<a href="http://andreas-kupries.github.com/critcl">http://andreas-kupries.github.com/critcl</a>.</p>
<p>Any branch of the repository can be used (if not using the
prebuild starkit or starpack), although the use of the stable branch
<em>master</em> is recommended.</p>
<p>At the above url is also an explanation on how to build and
install Critcl, including a list of its dependencies.</p>
<p>Its instructions will not be repeated here. If there are
problems with these directions please file a ticket against the
<i class="term">Critcl</i> project, and not Tcllib.</p>
</div>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">Build &amp; Installation Instructions</a></h2>
<p>As Tcllib is mainly a bundle of packages written in pure Tcl building
it is the same as installing it. The exceptions to this have their own
subsection, <span class="sectref"><a href="#subsection5">Critcl &amp; Accelerators</a></span>, later on.</p>
<p>Before that however comes the standard case, differentiated by
       the platforms with material differences in the instruction, i.e.
       <i class="term">Unix</i>-like, versus <i class="term">Windows</i>.</p>
<p>Regarding the latter it should also be noted that it is
       possible set up an <i class="term">Unix</i>-like environment using projects
       like <i class="term">MSYS</i>, <i class="term">Cygwin</i>, and others. In that case the
       user has the choice of which instructions to follow.</p>
<p>Regardless of environment or platform, a suitable <i class="term"><a href="../../../index.html#tcl">Tcl</a></i>
       has to be installed, and its <b class="syscmd">tclsh</b> should be placed on
       the  (<i class="term">Unix</i>) or associated with
       &quot;<b class="file">.tcl</b>&quot; files (<i class="term">Windows</i>).</p>
<div id="subsection3" class="doctools_subsection"><h3><a name="subsection3">Installing on Unix</a></h3>
<p>For <i class="term">Unix</i>-like environments Tcllib comes with the standard set
of files to make</p>
<pre class="doctools_example">
  ./configure
  make install
</pre>
<p>a suitable way of installing it.
This is a standard non-interactive install automatically figuring out
where to place everything, i.e. packages, applications, and the
manpages.</p>
<p>To get a graphical installer invoke</p>
<pre class="doctools_example">
  ./installer.tcl
</pre>
<p>instead.</p>
</div>
<div id="subsection4" class="doctools_subsection"><h3><a name="subsection4">Installing on Windows</a></h3>
<p>In a Windows environment we have the <b class="cmd">installer.tcl</b> script to
perform installation.</p>
<p>If the desired <b class="syscmd">tclsh</b> is associated &quot;<b class="file">.tcl</b>&quot; files
       then double-clicking / opening the <b class="cmd">installer.tcl</b> is
       enough to invoke it in graphical mode.
       This assumes that <i class="term"><a href="../../../index.html#tk">Tk</a></i> is installed and available as well.</p>
<p>Without <i class="term"><a href="../../../index.html#tk">Tk</a></i> the only way to invoke the installer are to
       open a DOS window, i.e. <b class="syscmd">cmd.exe</b>, and then to invoke</p>
<pre class="doctools_example">
  ./installer.tcl
</pre>
<p>inside it.</p>
</div>
<div id="subsection5" class="doctools_subsection"><h3><a name="subsection5">Critcl &amp; Accelerators</a></h3>
<p>While the majority of Tcllib consists of packages written in pure Tcl
a number of packages also have <i class="term">accelerators</i> associated with them.
These are <b class="syscmd">critcl</b>-based C packages whose use will boost the
performance of the packages using them.
These accelerators are optional, and they are not installed by
default.</p>
<p>To build the accelerators the normally optional dependency on
       <b class="syscmd">critcl</b> becomes required.</p>
<p>To build and install Tcllib with the accelerators in a
       Unix-like environment invoke:</p>
<pre class="doctools_example">
  ./configure
  make critcl # This builds the shared library holding
              # the accelerators
  make install
</pre>
<p>The underlying tool is &quot;<b class="file">sak.tcl</b>&quot; in the toplevel directory
of Tcllib and the command <b class="cmd">make critcl</b> is just a wrapper around</p>
<pre class="doctools_example">
  ./sak.tcl critcl
</pre>
<p>Therefore in a Windows environment instead invoke</p>
<pre class="doctools_example">
  ./sak.tcl critcl
  ./installer.tcl
</pre>
<p>from within a DOS window, i.e. <b class="syscmd">cmd.exe</b>.</p>
</div>
<div id="subsection6" class="doctools_subsection"><h3><a name="subsection6">Tooling</a></h3>
<p>The core of Tcllib's build system is the script &quot;<b class="file">installer.tcl</b>&quot;
found in the toplevel directory of a checkout or release.</p>
<p>The</p>
<pre class="doctools_example">
         configure ; make install
       </pre>
<p>setup available to
       developers on Unix-like systems is just a wrapper around it.
       To go beyond the standard embodied in the wrapper it is
       necessary to directly invoke this script.</p>
<p>On Windows system using it directly is the only way to invoke
       it.</p>
<p>For basic help invoke it as</p>
<pre class="doctools_example">
         ./installer.tcl -help
       </pre>
<p>This will print a short list of all the available options to
       the standard output channel.</p>
<p>The commands associated with the various <i class="term">install</i> targets
       in the <i class="term">Makefile.in</i> for Unix can be used as additional
       examples on how to use this tool as well.</p>
<p>The installer can operate in GUI and CLI modes.
       By default it chooses the mode automatically, based on if the
       Tcl package <b class="package"><a href="../../../index.html#tk">Tk</a></b> can be used or not.
       The option <b class="option">-no-gui</b> can be used to force CLI mode.</p>
<p>Note that it is possible to specify options on the command line
       even if the installer ultimatively selects GUI mode. In that
       case the hardwired defaults and the options determine the data
       presented to the user for editing.</p>
<p>The installer will select a number of defaults for the
       locations of packages, examples, and documentation, and also
       the format of the documentation. The user can overide these
       defaults in the GUI, or by specifying additional options.
       The defaults depend on the platform detected (Unix/Windows) and
       on the <b class="syscmd">tclsh</b> executable used to run the installer.</p>
<p><em>Options</em></p>
<dl class="doctools_options">
<dt><b class="option">-help</b></dt>
<dd><p>Show the list of options explained here on the standard output channel
and exit.</p></dd>
<dt><b class="option">+excluded</b></dt>
<dd><p>Include deprecated packages in the installation.</p></dd>
<dt><b class="option">-no-gui</b></dt>
<dd><p>Force command line operation of the installer</p></dd>
<dt><b class="option">-no-wait</b></dt>
<dd><p>In CLI mode the installer will by default ask the user to confirm that
the chosen configuration (destination paths, things to install) is
correct before performing any action. Using this option causes the
installer to skip this query and immediately jump to installation.</p></dd>
<dt><b class="option">-app-path</b> <i class="arg">path</i></dt>
<dd></dd>
<dt><b class="option">-example-path</b> <i class="arg">path</i></dt>
<dd></dd>
<dt><b class="option">-html-path</b> <i class="arg">path</i></dt>
<dd></dd>
<dt><b class="option">-nroff-path</b> <i class="arg">path</i></dt>
<dd></dd>
<dt><b class="option">-pkg-path</b> <i class="arg">path</i></dt>
<dd><p>Declare the destination paths for the applications, examples, html
documentation, nroff manpages, and packages. The defaults are derived
from the location of the <b class="syscmd">tclsh</b> used to run the installer.</p></dd>
<dt><b class="option">-dry-run</b></dt>
<dd></dd>
<dt><b class="option">-simulate</b></dt>
<dd><p>Run the installer without modifying the destination directories.</p></dd>
<dt><b class="option">-apps</b></dt>
<dd></dd>
<dt><b class="option">-no-apps</b></dt>
<dd></dd>
<dt><b class="option">-examples</b></dt>
<dd></dd>
<dt><b class="option">-no-examples</b></dt>
<dd></dd>
<dt><b class="option">-pkgs</b></dt>
<dd></dd>
<dt><b class="option">-no-pkgs</b></dt>
<dd></dd>
<dt><b class="option">-html</b></dt>
<dd></dd>
<dt><b class="option">-no-html</b></dt>
<dd></dd>
<dt><b class="option">-nroff</b></dt>
<dd></dd>
<dt><b class="option">-no-nroff</b></dt>
<dd><p>(De)activate the installation of applications, examples, packages,
html documentation, and nroff manpages.</p>
<p>Applications, examples, and packages are installed by default.</p>
<p>On Windows the html documentation is installed by default.</p>
<p>On Unix the nroff manpages are installed by default.</p></dd>
</dl>
</div>
</div>
</div></body></html>

Added idoc/www/tcllib/files/devdoc/tcllib_license.html.





































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
<!DOCTYPE html><html><head>
<title>tcllib_license - </title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
	color:	 	black;
    }
    DIV.doctools {
	margin-left:	10%;
	margin-right:	10%;
    }
    DIV.doctools H1,DIV.doctools H2 {
	margin-left:	-5%;
    }
    H1, H2, H3, H4 {
	margin-top: 	1em;
	font-family:	sans-serif;
	font-size:	large;
	color:		#005A9C;
	background: 	transparent;
	text-align:		left;
    }
    H1.doctools_title {
	text-align: center;
    }
    UL,OL {
	margin-right: 0em;
	margin-top: 3pt;
	margin-bottom: 3pt;
    }
    UL LI {
	list-style: disc;
    }
    OL LI {
	list-style: decimal;
    }
    DT {
	padding-top: 	1ex;
    }
    UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
	font:		normal 12pt/14pt sans-serif;
	list-style:	none;
    }
    LI.doctools_section, LI.doctools_subsection {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding: 	0em;
    }
    PRE {
	display: 	block;
	font-family:	monospace;
	white-space:	pre;
	margin:		0%;
	padding-top:	0.5ex;
	padding-bottom:	0.5ex;
	padding-left:	1ex;
	padding-right:	1ex;
	width:		100%;
    }
    PRE.doctools_example {
	color: 		black;
	background: 	#f5dcb3;
	border:		1px solid black;
    }
    UL.doctools_requirements LI, UL.doctools_syntax LI {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding:	0em;
    }
    DIV.doctools_synopsis {
	color: 		black;
	background: 	#80ffff;
	border:		1px solid black;
	font-family:	serif;
	margin-top: 	1em;
	margin-bottom: 	1em;
    }
    UL.doctools_syntax {
	margin-top: 	1em;
	border-top:	1px solid black;
    }
    UL.doctools_requirements {
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'tcllib_license.man' by tcllib/doctools with format 'html'
   -->
<!-- tcllib_license.n
   -->
<body><hr> [
   <a href="../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../toc.html">Table Of Contents</a>
&#124; <a href="../../../index.html">Keyword Index</a>
&#124; <a href="../../../toc0.html">Categories</a>
&#124; <a href="../../../toc1.html">Modules</a>
&#124; <a href="../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">tcllib_license(n) 1 tcllib &quot;&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>tcllib_license - Tcllib - License</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">License</a></li>
</ul>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>Welcome to Tcllib, the Tcl Standard Library. Note that Tcllib is not a
package itself. It is a collection of (semi-independent) <i class="term"><a href="../../../index.html#tcl">Tcl</a></i>
packages that provide utility functions useful to a large collection
of Tcl programmers.</p>
<p>The collection is under the BSD license.</p>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">License</a></h2>
<p>This software is copyrighted by Ajuba Solutions and other parties.
The following terms apply to all files associated with the software
unless explicitly disclaimed in individual files.</p>
<p>The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose,
provided that existing copyright notices are retained in all copies
and that this notice is included verbatim in any distributions. No
written agreement, license, or royalty fee is required for any of the
authorized uses.  Modifications to this software may be copyrighted by
their authors and need not follow the licensing terms described here,
provided that the new terms are clearly indicated on the first page of
each file where they apply.</p>
<p>IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.</p>
<p>THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN &quot;AS IS&quot; BASIS, AND
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.</p>
<p>GOVERNMENT USE: If you are acquiring this software on behalf of the
U.S. government, the Government shall have only &quot;Restricted Rights&quot; in
the software and related documentation as defined in the Federal
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
are acquiring the software on behalf of the Department of Defense, the
software shall be classified as &quot;Commercial Computer Software&quot; and the
Government shall have only &quot;Restricted Rights&quot; as defined in Clause
252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license.</p>
</div>
</div></body></html>

Added idoc/www/tcllib/files/devdoc/tcllib_releasemgr.html.















































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
<!DOCTYPE html><html><head>
<title>tcllib_releasemgr - </title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
	color:	 	black;
    }
    DIV.doctools {
	margin-left:	10%;
	margin-right:	10%;
    }
    DIV.doctools H1,DIV.doctools H2 {
	margin-left:	-5%;
    }
    H1, H2, H3, H4 {
	margin-top: 	1em;
	font-family:	sans-serif;
	font-size:	large;
	color:		#005A9C;
	background: 	transparent;
	text-align:		left;
    }
    H1.doctools_title {
	text-align: center;
    }
    UL,OL {
	margin-right: 0em;
	margin-top: 3pt;
	margin-bottom: 3pt;
    }
    UL LI {
	list-style: disc;
    }
    OL LI {
	list-style: decimal;
    }
    DT {
	padding-top: 	1ex;
    }
    UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
	font:		normal 12pt/14pt sans-serif;
	list-style:	none;
    }
    LI.doctools_section, LI.doctools_subsection {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding: 	0em;
    }
    PRE {
	display: 	block;
	font-family:	monospace;
	white-space:	pre;
	margin:		0%;
	padding-top:	0.5ex;
	padding-bottom:	0.5ex;
	padding-left:	1ex;
	padding-right:	1ex;
	width:		100%;
    }
    PRE.doctools_example {
	color: 		black;
	background: 	#f5dcb3;
	border:		1px solid black;
    }
    UL.doctools_requirements LI, UL.doctools_syntax LI {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding:	0em;
    }
    DIV.doctools_synopsis {
	color: 		black;
	background: 	#80ffff;
	border:		1px solid black;
	font-family:	serif;
	margin-top: 	1em;
	margin-bottom: 	1em;
    }
    UL.doctools_syntax {
	margin-top: 	1em;
	border-top:	1px solid black;
    }
    UL.doctools_requirements {
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'tcllib_releasemgr.man' by tcllib/doctools with format 'html'
   -->
<!-- tcllib_releasemgr.n
   -->
<body><hr> [
   <a href="../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../toc.html">Table Of Contents</a>
&#124; <a href="../../../index.html">Keyword Index</a>
&#124; <a href="../../../toc0.html">Categories</a>
&#124; <a href="../../../toc1.html">Modules</a>
&#124; <a href="../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">tcllib_releasemgr(n) 1 tcllib &quot;&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>tcllib_releasemgr - Tcllib - The Release Manager's Guide</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Tools</a></li>
<li class="doctools_section"><a href="#section3">Tasks</a>
<ul>
<li class="doctools_subsection"><a href="#subsection1">Start a release candidate</a></li>
<li class="doctools_subsection"><a href="#subsection2">Ready the candidate</a></li>
<li class="doctools_subsection"><a href="#subsection3">Make it official</a></li>
<li class="doctools_subsection"><a href="#subsection4">Distribute the release</a></ul>
</li>
</ul>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>Welcome to Tcllib, the Tcl Standard Library. Note that Tcllib is not a
package itself. It is a collection of (semi-independent) <i class="term"><a href="../../../index.html#tcl">Tcl</a></i>
packages that provide utility functions useful to a large collection
of Tcl programmers.</p>
<p>The audience of this document is the release manager for Tcllib, their
deputies, and anybody else interested in the task of creating
an official release of Tcllib for distribution.</p>
<p>Please read <i class="term"><a href="tcllib_sources.html">Tcllib - How To Get The Sources</a></i> first, if that
was not done already. Here we assume that the sources are already
available in a directory of your choice.</p>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">Tools</a></h2>
<p>The &quot;<b class="file">sak.tcl</b>&quot; script in the toplevel directory of a Tcllib
checkout is the one tool used by the release manager to perform its
<span class="sectref"><a href="#section3">Tasks</a></span>.</p>
<p>The main commands to be used are</p>
<pre class="doctools_example">
    sak.tcl validate
    sak.tcl test run
    sak.tcl review
    sak.tcl readme
    sak.tcl localdoc
    sak.tcl release
</pre>
<p>More detail will be provided in the explanations of the various
<span class="sectref"><a href="#section3">Tasks</a></span>.</p>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">Tasks</a></h2>
<div id="subsection1" class="doctools_subsection"><h3><a name="subsection1">Start a release candidate</a></h3>
<p>todo: open a candidate for release</p>
</div>
<div id="subsection2" class="doctools_subsection"><h3><a name="subsection2">Ready the candidate</a></h3>
<p>todo: test, validate and check that the candidate is worthy of release
fix testsuites, possibly fix packages, documentation
regenerate docs
coordinate with package maintainers wrt fixes
big thing: going over the packages, classify changes since last
release to generate a nice readme.</p>
</div>
<div id="subsection3" class="doctools_subsection"><h3><a name="subsection3">Make it official</a></h3>
<p>todo: finalize release, make candidate official</p>
</div>
<div id="subsection4" class="doctools_subsection"><h3><a name="subsection4">Distribute the release</a></h3>
<p>With the release made it has to be published and the world notified of
its existence.</p>
<ol class="doctools_enumerated">
<li><p>Create a proper fossil event for the release, via
	    <a href="http://core.tcl-lang.org/tcllib/eventedit">http://core.tcl-lang.org/tcllib/eventedit</a>.</p>
<p>An <a href="http://core.tcl-lang.org/tcllib/event/dac0ddcd2e990234143196b4dc438fe01e7b9817">existing event</a> should be used as template.</p></li>
<li><p>Update a number of web locations:</p>
<ol class="doctools_enumerated">
<li><p><a href="http://core.tcl-lang.org/tcllib/doc/trunk/embedded/index.md">Home page</a></p></li>
<li><p><a href="http://core.tcl-lang.org/tcllib/wiki?name=Downloads">Downloads</a></p></li>
<li><p><a href="http://core.tcl-lang.org/tcllib/wiki?name=Past+Releases">Past Releases</a></p></li>
<li><p><a href="http://www.tcl-lang.org/home/release.txt">http://www.tcl-lang.org/home/release.txt</a></p></li>
<li><p><a href="http://www.tcl-lang.org/software/tcllib/*.tml">http://www.tcl-lang.org/software/tcllib/*.tml</a></p></li>
<li><p><a href="http://wiki.tcl-lang.org/page/Tcllib">http://wiki.tcl-lang.org/page/Tcllib</a></p></li>
</ol>
<p>The first location maps to the file &quot;<b class="file">embedded/index.md</b>&quot; in the
repository itself, as such it can edited as part of the release
process. This is where reference to the new fossil event is added, as
the new current release.</p>
<p>The next two locations are in the fossil tcllib wiki and
require admin or wiki write permissions for
<a href="http://core.tcl-lang.org/tcllib">http://core.tcl-lang.org/tcllib</a>.</p>
<p>The last two locations require ssh access to
<a href="http://www.tcl-lang.org">http://www.tcl-lang.org</a> and permission to edit
files in the web area.</p></li>
<li><p>***TODO*** mailing lists and other places to send notes to.</p></li>
</ol>
</div>
</div>
</div></body></html>

Added idoc/www/tcllib/files/devdoc/tcllib_sources.html.



















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
<!DOCTYPE html><html><head>
<title>tcllib_sources - </title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
	color:	 	black;
    }
    DIV.doctools {
	margin-left:	10%;
	margin-right:	10%;
    }
    DIV.doctools H1,DIV.doctools H2 {
	margin-left:	-5%;
    }
    H1, H2, H3, H4 {
	margin-top: 	1em;
	font-family:	sans-serif;
	font-size:	large;
	color:		#005A9C;
	background: 	transparent;
	text-align:		left;
    }
    H1.doctools_title {
	text-align: center;
    }
    UL,OL {
	margin-right: 0em;
	margin-top: 3pt;
	margin-bottom: 3pt;
    }
    UL LI {
	list-style: disc;
    }
    OL LI {
	list-style: decimal;
    }
    DT {
	padding-top: 	1ex;
    }
    UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
	font:		normal 12pt/14pt sans-serif;
	list-style:	none;
    }
    LI.doctools_section, LI.doctools_subsection {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding: 	0em;
    }
    PRE {
	display: 	block;
	font-family:	monospace;
	white-space:	pre;
	margin:		0%;
	padding-top:	0.5ex;
	padding-bottom:	0.5ex;
	padding-left:	1ex;
	padding-right:	1ex;
	width:		100%;
    }
    PRE.doctools_example {
	color: 		black;
	background: 	#f5dcb3;
	border:		1px solid black;
    }
    UL.doctools_requirements LI, UL.doctools_syntax LI {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding:	0em;
    }
    DIV.doctools_synopsis {
	color: 		black;
	background: 	#80ffff;
	border:		1px solid black;
	font-family:	serif;
	margin-top: 	1em;
	margin-bottom: 	1em;
    }
    UL.doctools_syntax {
	margin-top: 	1em;
	border-top:	1px solid black;
    }
    UL.doctools_requirements {
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'tcllib_sources.man' by tcllib/doctools with format 'html'
   -->
<!-- tcllib_sources.n
   -->
<body><hr> [
   <a href="../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../toc.html">Table Of Contents</a>
&#124; <a href="../../../index.html">Keyword Index</a>
&#124; <a href="../../../toc0.html">Categories</a>
&#124; <a href="../../../toc1.html">Modules</a>
&#124; <a href="../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">tcllib_sources(n) 1 tcllib &quot;&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>tcllib_sources - Tcllib - How To Get The Sources</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Source Location</a></li>
<li class="doctools_section"><a href="#section3">Retrieval</a></li>
<li class="doctools_section"><a href="#section4">Source Code Management</a></li>
</ul>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>Welcome to Tcllib, the Tcl Standard Library. Note that Tcllib is not a
package itself. It is a collection of (semi-independent) <i class="term"><a href="../../../index.html#tcl">Tcl</a></i>
packages that provide utility functions useful to a large collection
of Tcl programmers.</p>
<p>The audience of this document is anyone wishing to either have just a
look at Tcllib's source code, or build the packages, or to extend and
modify them.</p>
<p>For builders and developers we additionally provide</p>
<ol class="doctools_enumerated">
<li><p><i class="term"><a href="tcllib_installer.html">Tcllib - The Installer's Guide</a></i>.</p></li>
<li><p><i class="term"><a href="tcllib_devguide.html">Tcllib - The Developer's Guide</a></i>.</p></li>
</ol>
<p>respectively.</p>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">Source Location</a></h2>
<p>The official repository for Tcllib can be found at
<a href="http://core.tcl-lang.org/tcllib">http://core.tcl-lang.org/tcllib</a></p>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">Retrieval</a></h2>
<p>Assuming that you simply wish to look at the sources, or build a
specific revision, the easiest way of retrieving it is to:</p>
<ol class="doctools_enumerated">
<li><p>Log into this site, as &quot;anonymous&quot;, using the semi-random password in the captcha.</p></li>
<li><p>Go to the &quot;Timeline&quot;.</p></li>
<li><p>Choose the revision you wish to have.</p></li>
<li><p>Follow its link to its detailed information page.</p></li>
<li><p>On that page, choose either the &quot;ZIP&quot; or &quot;Tarball&quot; link to get
a copy of this revision in the format of your choice.</p></li>
</ol>
</div>
<div id="section4" class="doctools_section"><h2><a name="section4">Source Code Management</a></h2>
<p>For the curious (or a developer-to-be), the sources are managed by the
<a href="http://www.fossil-scm.org">Fossil SCM</a>.
Binaries for popular platforms can be found directly at its
<a href="http://www.fossil-scm.org/download.html">download page</a>.</p>
<p>With that tool available the full history can be retrieved via:</p>
<pre class="doctools_example">
    fossil clone  http://core.tcl-lang.org/tcllib  tcllib.fossil
</pre>
<p>followed by</p>
<pre class="doctools_example">
    mkdir tcllib
    cd tcllib
    fossil open ../tcllib.fossil
</pre>
<p>to get a checkout of the head of the trunk.</p>
</div>
</div></body></html>

Added idoc/www/tcllib/files/modules/clay/clay.html.































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
<!DOCTYPE html><html><head>
<title>clay - Clay Framework</title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
	color:	 	black;
    }
    DIV.doctools {
	margin-left:	10%;
	margin-right:	10%;
    }
    DIV.doctools H1,DIV.doctools H2 {
	margin-left:	-5%;
    }
    H1, H2, H3, H4 {
	margin-top: 	1em;
	font-family:	sans-serif;
	font-size:	large;
	color:		#005A9C;
	background: 	transparent;
	text-align:		left;
    }
    H1.doctools_title {
	text-align: center;
    }
    UL,OL {
	margin-right: 0em;
	margin-top: 3pt;
	margin-bottom: 3pt;
    }
    UL LI {
	list-style: disc;
    }
    OL LI {
	list-style: decimal;
    }
    DT {
	padding-top: 	1ex;
    }
    UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
	font:		normal 12pt/14pt sans-serif;
	list-style:	none;
    }
    LI.doctools_section, LI.doctools_subsection {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding: 	0em;
    }
    PRE {
	display: 	block;
	font-family:	monospace;
	white-space:	pre;
	margin:		0%;
	padding-top:	0.5ex;
	padding-bottom:	0.5ex;
	padding-left:	1ex;
	padding-right:	1ex;
	width:		100%;
    }
    PRE.doctools_example {
	color: 		black;
	background: 	#f5dcb3;
	border:		1px solid black;
    }
    UL.doctools_requirements LI, UL.doctools_syntax LI {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding:	0em;
    }
    DIV.doctools_synopsis {
	color: 		black;
	background: 	#80ffff;
	border:		1px solid black;
	font-family:	serif;
	margin-top: 	1em;
	margin-bottom: 	1em;
    }
    UL.doctools_syntax {
	margin-top: 	1em;
	border-top:	1px solid black;
    }
    UL.doctools_requirements {
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'clay.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2018 Sean Woods &amp;lt;[email protected]&amp;gt;
   -->
<!-- clay.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">clay(n) 0.8.6 tcllib &quot;Clay Framework&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>clay - A minimalist framework for large scale OO Projects</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a>
<ul>
<li class="doctools_subsection"><a href="#subsection1">Structured Data</a></li>
<li class="doctools_subsection"><a href="#subsection2">Clay Dialect</a></li>
<li class="doctools_subsection"><a href="#subsection3">Method Delegation</a></li>
</ul>
</li>
<li class="doctools_section"><a href="#section2">Commands</a></li>
<li class="doctools_section"><a href="#section3">Classes</a>
<ul>
<li class="doctools_subsection"><a href="#subsection4">Class  clay::class</a></li>
<li class="doctools_subsection"><a href="#subsection5">Class  clay::object</a></li>
</ul>
</li>
<li class="doctools_section"><a href="#section4">AUTHORS</a></li>
<li class="doctools_section"><a href="#section5">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.6</b></li>
<li>package require <b class="pkgname">uuid</b></li>
<li>package require <b class="pkgname">oo::dialect</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1">proc <b class="cmd">clay::PROC</b> <i class="arg">name</i> <i class="arg">arglist</i> <i class="arg">body</i> <span class="opt">?<i class="arg">ninja</i> <b class="const"></b>?</span></a></li>
<li><a href="#2">proc <b class="cmd">clay::_ancestors</b> <i class="arg">resultvar</i> <i class="arg">class</i></a></li>
<li><a href="#3">proc <b class="cmd">clay::ancestors</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#4">proc <b class="cmd">clay::args_to_dict</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#5">proc <b class="cmd">clay::args_to_options</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#6">proc <b class="cmd">clay::dynamic_arguments</b> <i class="arg">ensemble</i> <i class="arg">method</i> <i class="arg">arglist</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#7">proc <b class="cmd">clay::dynamic_wrongargs_message</b> <i class="arg">arglist</i></a></li>
<li><a href="#8">proc <b class="cmd">clay::is_dict</b> <i class="arg">d</i></a></li>
<li><a href="#9">proc <b class="cmd">clay::is_null</b> <i class="arg">value</i></a></li>
<li><a href="#10">proc <b class="cmd">clay::leaf</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#11">proc <b class="cmd">clay::K</b> <i class="arg">a</i> <i class="arg">b</i></a></li>
<li><a href="#12">proc <b class="cmd">clay::noop</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#13">proc <b class="cmd">clay::cleanup</b></a></li>
<li><a href="#14">proc <b class="cmd">clay::object_create</b> <i class="arg">objname</i> <span class="opt">?<i class="arg">class</i> <b class="const"></b>?</span></a></li>
<li><a href="#15">proc <b class="cmd">clay::object_rename</b> <i class="arg">object</i> <i class="arg">newname</i></a></li>
<li><a href="#16">proc <b class="cmd">clay::object_destroy</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#17">proc <b class="cmd">clay::path</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#18">proc <b class="cmd">clay::putb</b> <span class="opt">?<i class="arg">map</i>?</span> <i class="arg">text</i></a></li>
<li><a href="#19">proc <b class="cmd">clay::script_path</b></a></li>
<li><a href="#20">proc <b class="cmd">clay::NSNormalize</b> <i class="arg">qualname</i></a></li>
<li><a href="#21">proc <b class="cmd">clay::uuid_generate</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#22">proc <b class="cmd">clay::uuid::generate_tcl_machinfo</b></a></li>
<li><a href="#23">proc <b class="cmd">clay::uuid::tostring</b> <i class="arg">uuid</i></a></li>
<li><a href="#24">proc <b class="cmd">clay::uuid::fromstring</b> <i class="arg">uuid</i></a></li>
<li><a href="#25">proc <b class="cmd">clay::uuid::equal</b> <i class="arg">left</i> <i class="arg">right</i></a></li>
<li><a href="#26">proc <b class="cmd">clay::uuid</b> <i class="arg">cmd</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#27">proc <b class="cmd">clay::tree::sanitize</b> <i class="arg">dict</i></a></li>
<li><a href="#28">proc <b class="cmd">clay::tree::_sanitizeb</b> <i class="arg">path</i> <i class="arg">varname</i> <i class="arg">dict</i></a></li>
<li><a href="#29">proc <b class="cmd">clay::tree::storage</b> <i class="arg">rawpath</i></a></li>
<li><a href="#30">proc <b class="cmd">clay::tree::dictset</b> <i class="arg">varname</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#31">proc <b class="cmd">clay::tree::dictmerge</b> <i class="arg">varname</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#32">proc <b class="cmd">clay::tree::merge</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#33">proc <b class="cmd">dictargs::proc</b> <i class="arg">name</i> <i class="arg">argspec</i> <i class="arg">body</i></a></li>
<li><a href="#34">proc <b class="cmd">dictargs::method</b> <i class="arg">name</i> <i class="arg">argspec</i> <i class="arg">body</i></a></li>
<li><a href="#35">proc <b class="cmd">clay::dialect::Push</b> <i class="arg">class</i></a></li>
<li><a href="#36">proc <b class="cmd">clay::dialect::Peek</b></a></li>
<li><a href="#37">proc <b class="cmd">clay::dialect::Pop</b></a></li>
<li><a href="#38">proc <b class="cmd">clay::dialect::create</b> <i class="arg">name</i> <span class="opt">?<i class="arg">parent</i> <b class="const"></b>?</span></a></li>
<li><a href="#39">proc <b class="cmd">clay::dialect::NSNormalize</b> <i class="arg">namespace</i> <i class="arg">qualname</i></a></li>
<li><a href="#40">proc <b class="cmd">clay::dialect::DefineThunk</b> <i class="arg">target</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#41">proc <b class="cmd">clay::dialect::Canonical</b> <i class="arg">namespace</i> <i class="arg">NSpace</i> <i class="arg">class</i></a></li>
<li><a href="#42">proc <b class="cmd">clay::dialect::Define</b> <i class="arg">namespace</i> <i class="arg">class</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#43">proc <b class="cmd">clay::dialect::Aliases</b> <i class="arg">namespace</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#44">proc <b class="cmd">clay::dialect::SuperClass</b> <i class="arg">namespace</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#45">proc <b class="cmd">clay::dynamic_methods</b> <i class="arg">class</i></a></li>
<li><a href="#46">proc <b class="cmd">clay::dynamic_methods_class</b> <i class="arg">thisclass</i></a></li>
<li><a href="#47">proc <b class="cmd">clay::define::Array</b> <i class="arg">name</i> <span class="opt">?<i class="arg">values</i> <b class="const"></b>?</span></a></li>
<li><a href="#48">proc <b class="cmd">clay::define::Delegate</b> <i class="arg">name</i> <i class="arg">info</i></a></li>
<li><a href="#49">proc <b class="cmd">clay::define::constructor</b> <i class="arg">arglist</i> <i class="arg">rawbody</i></a></li>
<li><a href="#50">proc <b class="cmd">clay::define::Class_Method</b> <i class="arg">name</i> <i class="arg">arglist</i> <i class="arg">body</i></a></li>
<li><a href="#51">proc <b class="cmd">clay::define::class_method</b> <i class="arg">name</i> <i class="arg">arglist</i> <i class="arg">body</i></a></li>
<li><a href="#52">proc <b class="cmd">clay::define::clay</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#53">proc <b class="cmd">clay::define::destructor</b> <i class="arg">rawbody</i></a></li>
<li><a href="#54">proc <b class="cmd">clay::define::Dict</b> <i class="arg">name</i> <span class="opt">?<i class="arg">values</i> <b class="const"></b>?</span></a></li>
<li><a href="#55">proc <b class="cmd">clay::define::Option</b> <i class="arg">name</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#56">proc <b class="cmd">clay::define::Method</b> <i class="arg">name</i> <i class="arg">argstyle</i> <i class="arg">argspec</i> <i class="arg">body</i></a></li>
<li><a href="#57">proc <b class="cmd">clay::define::Option_Class</b> <i class="arg">name</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#58">proc <b class="cmd">clay::define::Variable</b> <i class="arg">name</i> <span class="opt">?<i class="arg">default</i> <b class="const"></b>?</span></a></li>
<li><a href="#59">proc <b class="cmd">clay::ensemble_methodbody</b> <i class="arg">ensemble</i> <i class="arg">einfo</i></a></li>
<li><a href="#60">proc <b class="cmd">clay::define::Ensemble</b> <i class="arg">rawmethod</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#61">proc <b class="cmd">clay::event::cancel</b> <i class="arg">self</i> <span class="opt">?<i class="arg">task</i> <b class="const">*</b>?</span></a></li>
<li><a href="#62">proc <b class="cmd">clay::event::generate</b> <i class="arg">self</i> <i class="arg">event</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#63">proc <b class="cmd">clay::event::nextid</b></a></li>
<li><a href="#64">proc <b class="cmd">clay::event::Notification_list</b> <i class="arg">self</i> <i class="arg">event</i> <span class="opt">?<i class="arg">stackvar</i> <b class="const"></b>?</span></a></li>
<li><a href="#65">proc <b class="cmd">clay::event::notify</b> <i class="arg">rcpt</i> <i class="arg">sender</i> <i class="arg">event</i> <i class="arg">eventinfo</i></a></li>
<li><a href="#66">proc <b class="cmd">clay::event::process</b> <i class="arg">self</i> <i class="arg">handle</i> <i class="arg">script</i></a></li>
<li><a href="#67">proc <b class="cmd">clay::event::schedule</b> <i class="arg">self</i> <i class="arg">handle</i> <i class="arg">interval</i> <i class="arg">script</i></a></li>
<li><a href="#68">proc <b class="cmd">clay::event::subscribe</b> <i class="arg">self</i> <i class="arg">who</i> <i class="arg">event</i></a></li>
<li><a href="#69">proc <b class="cmd">clay::event::unsubscribe</b> <i class="arg">self</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#70">proc <b class="cmd">clay::singleton</b> <i class="arg">name</i> <i class="arg">script</i></a></li>
<li><a href="#71">method <b class="cmd">clay ancestors</b></a></li>
<li><a href="#72">method <b class="cmd">clay dump</b></a></li>
<li><a href="#73">method <b class="cmd">clay find</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></li>
<li><a href="#74">method <b class="cmd">clay get</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></li>
<li><a href="#75">method <b class="cmd">clay GET</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></li>
<li><a href="#76">method <b class="cmd">clay merge</b> <i class="arg">dict</i> <span class="opt">?<b class="option">dict...</b>?</span></a></li>
<li><a href="#77">method <b class="cmd">clay replace</b> <i class="arg">dictionary</i></a></li>
<li><a href="#78">method <b class="cmd">clay search</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></li>
<li><a href="#79">method <b class="cmd">clay set</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span> <i class="arg">value</i></a></li>
<li><a href="#80">method <b class="cmd">clay ancestors</b></a></li>
<li><a href="#81">method <b class="cmd">clay cache</b> <i class="arg">path</i> <i class="arg">value</i></a></li>
<li><a href="#82">method <b class="cmd">clay cget</b> <i class="arg">field</i></a></li>
<li><a href="#83">method <b class="cmd">clay delegate</b> <span class="opt">?<i class="arg">stub</i>?</span> <span class="opt">?<i class="arg">object</i>?</span></a></li>
<li><a href="#84">method <b class="cmd">clay dump</b></a></li>
<li><a href="#85">method <b class="cmd">clay ensemble_map</b></a></li>
<li><a href="#86">method <b class="cmd">clay eval</b> <i class="arg">script</i></a></li>
<li><a href="#87">method <b class="cmd">clay evolve</b></a></li>
<li><a href="#88">method <b class="cmd">clay exists</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></li>
<li><a href="#89">method <b class="cmd">clay flush</b></a></li>
<li><a href="#90">method <b class="cmd">clay forward</b> <i class="arg">method</i> <i class="arg">object</i></a></li>
<li><a href="#91">method <b class="cmd">clay get</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></li>
<li><a href="#92">method <b class="cmd">clay leaf</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></li>
<li><a href="#93">method <b class="cmd">clay merge</b> <i class="arg">dict</i> <span class="opt">?<b class="option">dict...</b>?</span></a></li>
<li><a href="#94">method <b class="cmd">clay mixin</b> <i class="arg">class</i> <span class="opt">?<b class="option">class...</b>?</span></a></li>
<li><a href="#95">method <b class="cmd">clay mixinmap</b> <span class="opt">?<i class="arg">stub</i>?</span> <span class="opt">?<i class="arg">classes</i>?</span></a></li>
<li><a href="#96">method <b class="cmd">clay provenance</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></li>
<li><a href="#97">method <b class="cmd">clay replace</b> <i class="arg">dictionary</i></a></li>
<li><a href="#98">method <b class="cmd">clay search</b> <i class="arg">path</i> <i class="arg">valuevar</i> <i class="arg">isleafvar</i></a></li>
<li><a href="#99">method <b class="cmd">clay source</b> <i class="arg">filename</i></a></li>
<li><a href="#100">method <b class="cmd">clay set</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span> <i class="arg">value</i></a></li>
<li><a href="#101">method <b class="cmd">InitializePublic</b></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>Clay introduces a method ensemble to both <b class="class">oo::class</b> and <b class="class">oo::object</b> called
clay. This ensemble handles all of the high level interactions within the framework.
Clay stores structured data. Clan manages method delegation. Clay has facilities to
manage the complex interactions that come about with mixins.</p>
<p>The central concept is that inside of every object and class
(which are actually objects too) is a dict called clay. What is stored in that dict is
left to the imagination. But because this dict is exposed via a public method, we can
share structured data between object, classes, and mixins.</p>
<div id="subsection1" class="doctools_subsection"><h3><a name="subsection1">Structured Data</a></h3>
<p>Clay uses a standardized set of method interactions and introspection that TclOO already provides to perform on-the-fly searches. On-the-fly searches mean that the data is never stale, and we avoid many of the sorts of collisions that would arise when objects start mixing in other classes during operation.</p>
<p>The <b class="method">clay</b> methods for both classes and objects have a get and a set method. For objects, get will search through the local clay dict. If the requested leaf is not found, or the query is for a branch, the system will then begin to poll the clay methods of all of the class that implements the object, all of that classes’ ancestors, as well as all of the classes that have been mixed into this object, and all of their ancestors.</p>
<p>Intended branches on a tree end with a directory slash (/). Intended leaves are left unadorned. This is a guide for the tool that builds the search
results to know what parts of a dict are intended to be branches and which are intended to be leaves.
For simple cases, branch marking can be ignored:</p>
<pre class="doctools_example">
::oo::class create ::foo { }
::foo clay set property/ color blue
::foo clay set property/ shape round
set A [::foo new]
$A clay get property/
{color blue shape round}
$A clay set property/ shape square
$A clay get property/
{color blue shape square}
</pre>
<p>But when you start storing blocks of text, guessing what field is a dict and what isn’t gets messy:</p>
<pre class="doctools_example">
::foo clay set description {A generic thing of designated color and shape}
$A clay get description
{A generic thing of designated color and shape}
Without a convention for discerning branches for leaves what should have been a value can be accidentally parsed as a dictionary, and merged with all of the other values that were never intended to be merge. Here is an example of it all going wrong:
::oo::class create ::foo { }
# Add description as a leaf
::foo clay set description  {A generic thing of designated color and shape}
# Add description as a branch
::foo clay set description/  {A generic thing of designated color and shape}
::oo::class create ::bar {
  superclass foo
}
# Add description as a leaf
::bar clay set description  {A drinking establishment of designated color and shape and size}
# Add description as a branch
::bar clay set description/  {A drinking establishment of designated color and shape and size}
set B [::bar new]
# As a leaf we get the value verbatim from he nearest ancestor
$B clay get description
  {A drinking establishment of designated color and shape and size}
# As a branch we get a recursive merge
$B clay get description/
{A drinking establishment of designated color and size thing of}
</pre>
</div>
<div id="subsection2" class="doctools_subsection"><h3><a name="subsection2">Clay Dialect</a></h3>
<p>Clay is built using the oo::dialect module from Tcllib. oo::dialect allows you to either add keywords directly to clay, or to create your own
metaclass and keyword set using Clay as a foundation. For details on the keywords and what they do, consult the functions in the ::clay::define namespace.</p>
</div>
<div id="subsection3" class="doctools_subsection"><h3><a name="subsection3">Method Delegation</a></h3>
<p>Method Delegation
It is sometimes useful to have an external object that can be invoked as if it were a method of the object. Clay provides a delegate ensemble method to perform that delegation, as well as introspect which methods are delegated in that manner. All delegated methods are marked with html-like tag markings (&lt; &gt;) around them.</p>
<pre class="doctools_example">
::clay::define counter {
  Variable counter 0
  method incr {{howmuch 1}} {
    my variable counter
    incr counter $howmuch
  }
  method value {} {
    my variable counter
    return $counter
  }
  method reset {} {
    my variable counter
    set counter 0
  }
}
::clay::define example {
  variable buffer
  constructor {} {
    # Build a counter object
    set obj [namespace current]::counter
    ::counter create $obj
    # Delegate the counter
    my delegate &lt;counter&gt; $obj
  }
  method line {text} {
    my &lt;counter&gt; incr
    append buffer $text
  }
}
set A [example new]
$A line {Who’s line is it anyway?}
$A &lt;counter&gt; value
1
</pre>
</div>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">Commands</a></h2>
<dl class="doctools_definitions">
<dt><a name="1">proc <b class="cmd">clay::PROC</b> <i class="arg">name</i> <i class="arg">arglist</i> <i class="arg">body</i> <span class="opt">?<i class="arg">ninja</i> <b class="const"></b>?</span></a></dt>
<dd><p>Because many features in this package may be added as
 commands to future tcl cores, or be provided in binary
 form by packages, I need a declaritive way of saying
 <em>Create this command if there isn't one already</em>.
 The <em>ninja</em> argument is a script to execute if the
 command is created by this mechanism.</p></dd>
<dt><a name="2">proc <b class="cmd">clay::_ancestors</b> <i class="arg">resultvar</i> <i class="arg">class</i></a></dt>
<dd></dd>
<dt><a name="3">proc <b class="cmd">clay::ancestors</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="4">proc <b class="cmd">clay::args_to_dict</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="5">proc <b class="cmd">clay::args_to_options</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="6">proc <b class="cmd">clay::dynamic_arguments</b> <i class="arg">ensemble</i> <i class="arg">method</i> <i class="arg">arglist</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="7">proc <b class="cmd">clay::dynamic_wrongargs_message</b> <i class="arg">arglist</i></a></dt>
<dd></dd>
<dt><a name="8">proc <b class="cmd">clay::is_dict</b> <i class="arg">d</i></a></dt>
<dd></dd>
<dt><a name="9">proc <b class="cmd">clay::is_null</b> <i class="arg">value</i></a></dt>
<dd></dd>
<dt><a name="10">proc <b class="cmd">clay::leaf</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="11">proc <b class="cmd">clay::K</b> <i class="arg">a</i> <i class="arg">b</i></a></dt>
<dd></dd>
<dt><a name="12">proc <b class="cmd">clay::noop</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Perform a noop. Useful in prototyping for commenting out blocks
 of code without actually having to comment them out. It also makes
 a handy default for method delegation if a delegate has not been
 assigned yet.</p></dd>
<dt><a name="13">proc <b class="cmd">clay::cleanup</b></a></dt>
<dd><p>Process the queue of objects to be destroyed</p></dd>
<dt><a name="14">proc <b class="cmd">clay::object_create</b> <i class="arg">objname</i> <span class="opt">?<i class="arg">class</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
<dt><a name="15">proc <b class="cmd">clay::object_rename</b> <i class="arg">object</i> <i class="arg">newname</i></a></dt>
<dd></dd>
<dt><a name="16">proc <b class="cmd">clay::object_destroy</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Mark an objects for destruction on the next cleanup</p></dd>
<dt><a name="17">proc <b class="cmd">clay::path</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="18">proc <b class="cmd">clay::putb</b> <span class="opt">?<i class="arg">map</i>?</span> <i class="arg">text</i></a></dt>
<dd><p>Append a line of text to a variable. Optionally apply a string mapping.</p></dd>
<dt><a name="19">proc <b class="cmd">clay::script_path</b></a></dt>
<dd></dd>
<dt><a name="20">proc <b class="cmd">clay::NSNormalize</b> <i class="arg">qualname</i></a></dt>
<dd></dd>
<dt><a name="21">proc <b class="cmd">clay::uuid_generate</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="22">proc <b class="cmd">clay::uuid::generate_tcl_machinfo</b></a></dt>
<dd></dd>
<dt><a name="23">proc <b class="cmd">clay::uuid::tostring</b> <i class="arg">uuid</i></a></dt>
<dd></dd>
<dt><a name="24">proc <b class="cmd">clay::uuid::fromstring</b> <i class="arg">uuid</i></a></dt>
<dd><p>Convert a string representation of a uuid into its binary format.</p></dd>
<dt><a name="25">proc <b class="cmd">clay::uuid::equal</b> <i class="arg">left</i> <i class="arg">right</i></a></dt>
<dd><p>Compare two uuids for equality.</p></dd>
<dt><a name="26">proc <b class="cmd">clay::uuid</b> <i class="arg">cmd</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>uuid generate -&gt; string rep of a new uuid
 uuid equal uuid1 uuid2</p></dd>
<dt><a name="27">proc <b class="cmd">clay::tree::sanitize</b> <i class="arg">dict</i></a></dt>
<dd><p>Output a dictionary removing any . entries added by <b class="function">clay::tree::merge</b></p></dd>
<dt><a name="28">proc <b class="cmd">clay::tree::_sanitizeb</b> <i class="arg">path</i> <i class="arg">varname</i> <i class="arg">dict</i></a></dt>
<dd><p>Helper function for ::clay::tree::sanitize
 Formats the string representation for a dictionary element within
 a human readable stream of lines, and determines if it needs to call itself
 with further indentation to express a sub-branch</p></dd>
<dt><a name="29">proc <b class="cmd">clay::tree::storage</b> <i class="arg">rawpath</i></a></dt>
<dd><p>Return the path as a storage path for clay::tree
 with all branch terminators removed.
 This command will also break arguments up if they
 contain /.</p>
<p>Example:</p>
<pre class="doctools_example"> &gt; clay::tree::storage {foo bar baz bang}
 foo bar baz bang
 &gt; clay::tree::storage {foo bar baz bang/}
 foo bar baz bang
 &gt; clay::tree::storage {foo bar baz bang:}
 foo bar baz bang:
 &gt; clay::tree::storage {foo/bar/baz bang:}
 foo bar baz bang:
 &gt; clay::tree::storage {foo/bar/baz/bang}
 foo bar baz bang
</pre>
</dd>
<dt><a name="30">proc <b class="cmd">clay::tree::dictset</b> <i class="arg">varname</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Set an element with a recursive dictionary,
 marking all branches on the way down to the
 final element.
 If the value does not exists in the nested dictionary
 it is added as a leaf. If the value already exists as a branch
 the value given is merged if the value is a valid dict. If the
 incoming value is not a valid dict, the value overrides the value
 stored, and the value is treated as a leaf from then on.</p>
<p>Example:</p>
<pre class="doctools_example"> &gt; set r {}
 &gt; ::clay::tree::dictset r option color default Green
 . {} option {. {} color {. {} default Green}}
 &gt; ::clay::tree::dictset r option {Something not dictlike}
 . {} option {Something not dictlike}
 # Note that if the value is not a dict, and you try to force it to be
 # an error with be thrown on the merge
 &gt; ::clay::tree::dictset r option color default Blue
 missing value to go with key
</pre>
</dd>
<dt><a name="31">proc <b class="cmd">clay::tree::dictmerge</b> <i class="arg">varname</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>A recursive form of dict merge, intended for modifying variables in place.</p>
<p>Example:</p>
<pre class="doctools_example"> &gt; set mydict {sub/ {sub/ {description {a block of text}}}}
 &gt; ::clay::tree::dictmerge mydict {sub/ {sub/ {field {another block of text}}}}]
 &gt; clay::tree::print $mydict
 sub/ {
   sub/ {
     description {a block of text}
     field {another block of text}
   }
 }
</pre>
</dd>
<dt><a name="32">proc <b class="cmd">clay::tree::merge</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>A recursive form of dict merge</p>
<p>A routine to recursively dig through dicts and merge
 adapted from http://stevehavelka.com/tcl-dict-operation-nested-merge/</p>
<p>Example:</p>
<pre class="doctools_example"> &gt; set mydict {sub/ {sub/ {description {a block of text}}}}
 &gt; set odict [clay::tree::merge $mydict {sub/ {sub/ {field {another block of text}}}}]
 &gt; clay::tree::print $odict
 sub/ {
   sub/ {
     description {a block of text}
     field {another block of text}
   }
 }
</pre>
</dd>
<dt><a name="33">proc <b class="cmd">dictargs::proc</b> <i class="arg">name</i> <i class="arg">argspec</i> <i class="arg">body</i></a></dt>
<dd><p>Named Procedures as new command</p></dd>
<dt><a name="34">proc <b class="cmd">dictargs::method</b> <i class="arg">name</i> <i class="arg">argspec</i> <i class="arg">body</i></a></dt>
<dd></dd>
<dt><a name="35">proc <b class="cmd">clay::dialect::Push</b> <i class="arg">class</i></a></dt>
<dd></dd>
<dt><a name="36">proc <b class="cmd">clay::dialect::Peek</b></a></dt>
<dd></dd>
<dt><a name="37">proc <b class="cmd">clay::dialect::Pop</b></a></dt>
<dd></dd>
<dt><a name="38">proc <b class="cmd">clay::dialect::create</b> <i class="arg">name</i> <span class="opt">?<i class="arg">parent</i> <b class="const"></b>?</span></a></dt>
<dd><p>This proc will generate a namespace, a &quot;mother of all classes&quot;, and a
 rudimentary set of policies for this dialect.</p></dd>
<dt><a name="39">proc <b class="cmd">clay::dialect::NSNormalize</b> <i class="arg">namespace</i> <i class="arg">qualname</i></a></dt>
<dd><p>Support commands; not intended to be called directly.</p></dd>
<dt><a name="40">proc <b class="cmd">clay::dialect::DefineThunk</b> <i class="arg">target</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="41">proc <b class="cmd">clay::dialect::Canonical</b> <i class="arg">namespace</i> <i class="arg">NSpace</i> <i class="arg">class</i></a></dt>
<dd></dd>
<dt><a name="42">proc <b class="cmd">clay::dialect::Define</b> <i class="arg">namespace</i> <i class="arg">class</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Implementation of the languages' define command</p></dd>
<dt><a name="43">proc <b class="cmd">clay::dialect::Aliases</b> <i class="arg">namespace</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="44">proc <b class="cmd">clay::dialect::SuperClass</b> <i class="arg">namespace</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="45">proc <b class="cmd">clay::dynamic_methods</b> <i class="arg">class</i></a></dt>
<dd></dd>
<dt><a name="46">proc <b class="cmd">clay::dynamic_methods_class</b> <i class="arg">thisclass</i></a></dt>
<dd></dd>
<dt><a name="47">proc <b class="cmd">clay::define::Array</b> <i class="arg">name</i> <span class="opt">?<i class="arg">values</i> <b class="const"></b>?</span></a></dt>
<dd><p>New OO Keywords for clay</p></dd>
<dt><a name="48">proc <b class="cmd">clay::define::Delegate</b> <i class="arg">name</i> <i class="arg">info</i></a></dt>
<dd><p>An annotation that objects of this class interact with delegated
 methods. The annotation is intended to be a dictionary, and the
 only reserved key is <em>description</em>, a human readable description.</p></dd>
<dt><a name="49">proc <b class="cmd">clay::define::constructor</b> <i class="arg">arglist</i> <i class="arg">rawbody</i></a></dt>
<dd></dd>
<dt><a name="50">proc <b class="cmd">clay::define::Class_Method</b> <i class="arg">name</i> <i class="arg">arglist</i> <i class="arg">body</i></a></dt>
<dd><p>Specify the a method for the class object itself, instead of for objects of the class</p></dd>
<dt><a name="51">proc <b class="cmd">clay::define::class_method</b> <i class="arg">name</i> <i class="arg">arglist</i> <i class="arg">body</i></a></dt>
<dd><p>And alias to the new Class_Method keyword</p></dd>
<dt><a name="52">proc <b class="cmd">clay::define::clay</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="53">proc <b class="cmd">clay::define::destructor</b> <i class="arg">rawbody</i></a></dt>
<dd></dd>
<dt><a name="54">proc <b class="cmd">clay::define::Dict</b> <i class="arg">name</i> <span class="opt">?<i class="arg">values</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
<dt><a name="55">proc <b class="cmd">clay::define::Option</b> <i class="arg">name</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Define an option for the class</p></dd>
<dt><a name="56">proc <b class="cmd">clay::define::Method</b> <i class="arg">name</i> <i class="arg">argstyle</i> <i class="arg">argspec</i> <i class="arg">body</i></a></dt>
<dd></dd>
<dt><a name="57">proc <b class="cmd">clay::define::Option_Class</b> <i class="arg">name</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Define a class of options
 All field / value pairs will be be inherited by an option that
 specify <em>name</em> as it class field.</p></dd>
<dt><a name="58">proc <b class="cmd">clay::define::Variable</b> <i class="arg">name</i> <span class="opt">?<i class="arg">default</i> <b class="const"></b>?</span></a></dt>
<dd><p>This keyword can also be expressed:</p>
<pre class="doctools_example">property variable NAME {default DEFAULT}</pre>
<p>Variables registered in the variable property are also initialized
    (if missing) when the object changes class via the <em>morph</em> method.</p></dd>
<dt><a name="59">proc <b class="cmd">clay::ensemble_methodbody</b> <i class="arg">ensemble</i> <i class="arg">einfo</i></a></dt>
<dd><p>Produce the body of an ensemble's public dispatch method
 ensemble is the name of the the ensemble.
 einfo is a dictionary of methods for the ensemble, and each value is a script
 to execute on dispatch</p>
<p>Example:</p>
<pre class="doctools_example"> ::clay::ensemble_methodbody foo {
   bar {tailcall my Foo_bar {*}$args}
   baz {tailcall my Foo_baz {*}$args}
   clock {return [clock seconds]}
   default {puts &quot;You gave me $method&quot;}
 }
</pre>
</dd>
<dt><a name="60">proc <b class="cmd">clay::define::Ensemble</b> <i class="arg">rawmethod</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="61">proc <b class="cmd">clay::event::cancel</b> <i class="arg">self</i> <span class="opt">?<i class="arg">task</i> <b class="const">*</b>?</span></a></dt>
<dd><p>Cancel a scheduled event</p></dd>
<dt><a name="62">proc <b class="cmd">clay::event::generate</b> <i class="arg">self</i> <i class="arg">event</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Generate an event
    Adds a subscription mechanism for objects
    to see who has recieved this event and prevent
    spamming or infinite recursion</p></dd>
<dt><a name="63">proc <b class="cmd">clay::event::nextid</b></a></dt>
<dd></dd>
<dt><a name="64">proc <b class="cmd">clay::event::Notification_list</b> <i class="arg">self</i> <i class="arg">event</i> <span class="opt">?<i class="arg">stackvar</i> <b class="const"></b>?</span></a></dt>
<dd><p>Called recursively to produce a list of
    who recieves notifications</p></dd>
<dt><a name="65">proc <b class="cmd">clay::event::notify</b> <i class="arg">rcpt</i> <i class="arg">sender</i> <i class="arg">event</i> <i class="arg">eventinfo</i></a></dt>
<dd><p>Final delivery to intended recipient object</p></dd>
<dt><a name="66">proc <b class="cmd">clay::event::process</b> <i class="arg">self</i> <i class="arg">handle</i> <i class="arg">script</i></a></dt>
<dd><p>Evaluate an event script in the global namespace</p></dd>
<dt><a name="67">proc <b class="cmd">clay::event::schedule</b> <i class="arg">self</i> <i class="arg">handle</i> <i class="arg">interval</i> <i class="arg">script</i></a></dt>
<dd><p>Schedule an event to occur later</p></dd>
<dt><a name="68">proc <b class="cmd">clay::event::subscribe</b> <i class="arg">self</i> <i class="arg">who</i> <i class="arg">event</i></a></dt>
<dd><p>Subscribe an object to an event pattern</p></dd>
<dt><a name="69">proc <b class="cmd">clay::event::unsubscribe</b> <i class="arg">self</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Unsubscribe an object from an event pattern</p></dd>
<dt><a name="70">proc <b class="cmd">clay::singleton</b> <i class="arg">name</i> <i class="arg">script</i></a></dt>
<dd><p>An object which is intended to be it's own class.</p></dd>
</dl>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">Classes</a></h2>
<div id="subsection4" class="doctools_subsection"><h3><a name="subsection4">Class  clay::class</a></h3>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="71">method <b class="cmd">clay ancestors</b></a></dt>
<dd><p>Return this class and all ancestors in search order.</p></dd>
<dt><a name="72">method <b class="cmd">clay dump</b></a></dt>
<dd><p>Return a complete dump of this object's clay data, but only this object's clay data.</p></dd>
<dt><a name="73">method <b class="cmd">clay find</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></dt>
<dd><p>Pull a chunk of data from the clay system. If the last element of <em>path</em> is a branch,
     returns a recursive merge of all data from this object and it's constituent classes of the data in that branch.
     If the last element is a leaf, search this object for a matching leaf, or search all  constituent classes for a matching
     leaf and return the first value found.
     If no value is found, returns an empty string.
     If a branch is returned the topmost . entry is omitted.</p></dd>
<dt><a name="74">method <b class="cmd">clay get</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></dt>
<dd><p>Pull a chunk of data from the class's clay system.
     If no value is found, returns an empty string.
     If a branch is returned the topmost . entry is omitted.</p></dd>
<dt><a name="75">method <b class="cmd">clay GET</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></dt>
<dd><p>Pull a chunk of data from the class's clay system.
     If no value is found, returns an empty string.</p></dd>
<dt><a name="76">method <b class="cmd">clay merge</b> <i class="arg">dict</i> <span class="opt">?<b class="option">dict...</b>?</span></a></dt>
<dd><p>Recursively merge the dictionaries given into the object's local clay storage.</p></dd>
<dt><a name="77">method <b class="cmd">clay replace</b> <i class="arg">dictionary</i></a></dt>
<dd><p>Replace the contents of the internal clay storage with the dictionary given.</p></dd>
<dt><a name="78">method <b class="cmd">clay search</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></dt>
<dd><p>Return the first matching value for the path in either this class's clay data or one of its ancestors</p></dd>
<dt><a name="79">method <b class="cmd">clay set</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span> <i class="arg">value</i></a></dt>
<dd><p>Merge the conents of <b class="const">value</b> with the object's clay storage at <b class="const">path</b>.</p></dd>
</dl>
</div>
<div id="subsection5" class="doctools_subsection"><h3><a name="subsection5">Class  clay::object</a></h3>
<p>clay::object
 This class is inherited by all classes that have options.</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="80">method <b class="cmd">clay ancestors</b></a></dt>
<dd><p>Return the class this object belongs to, all classes mixed into this object, and all ancestors of those classes in search order.</p></dd>
<dt><a name="81">method <b class="cmd">clay cache</b> <i class="arg">path</i> <i class="arg">value</i></a></dt>
<dd><p>Store VALUE in such a way that request in SEARCH for PATH will always return it until the cache is flushed</p></dd>
<dt><a name="82">method <b class="cmd">clay cget</b> <i class="arg">field</i></a></dt>
<dd><p>Pull a value from either the object's clay structure or one of its constituent classes that matches the field name.
 The order of search us:</p>
<p>1. The as a value in local dict variable config</p>
<p>2. The as a value in local dict variable clay</p>
<p>3. As a leaf in any ancestor as a root of the clay tree</p>
<p>4. As a leaf in any ancestor as <b class="const">const</b> <em>field</em></p>
<p>5. As a leaf in any ancestor as <b class="const">option</b> <em>field</em> <b class="const">default</b></p></dd>
<dt><a name="83">method <b class="cmd">clay delegate</b> <span class="opt">?<i class="arg">stub</i>?</span> <span class="opt">?<i class="arg">object</i>?</span></a></dt>
<dd><p>Introspect or control method delegation. With no arguments, the method will return a
 key/value list of stubs and objects. With just the <i class="arg">stub</i> argument, the method will
 return the object (if any) attached to the stub. With a <i class="arg">stub</i> and an <i class="arg">object</i>
 this command will forward all calls to the method <i class="arg">stub</i> to the <i class="arg">object</i>.</p></dd>
<dt><a name="84">method <b class="cmd">clay dump</b></a></dt>
<dd><p>Return a complete dump of this object's clay data, as well as the data from all constituent classes recursively blended in.</p></dd>
<dt><a name="85">method <b class="cmd">clay ensemble_map</b></a></dt>
<dd><p>Return a dictionary describing the method ensembles to be assembled for this object</p></dd>
<dt><a name="86">method <b class="cmd">clay eval</b> <i class="arg">script</i></a></dt>
<dd><p>Evaluated a script in the namespace of this object</p></dd>
<dt><a name="87">method <b class="cmd">clay evolve</b></a></dt>
<dd><p>Trigger the <b class="method">InitializePublic</b> private method</p></dd>
<dt><a name="88">method <b class="cmd">clay exists</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></dt>
<dd><p>Returns 1 if <em>path</em> exists in either the object's clay data. Values greater than one indicate the element exists in one of the object's constituent classes. A value of zero indicates the path could not be found.</p></dd>
<dt><a name="89">method <b class="cmd">clay flush</b></a></dt>
<dd><p>Wipe any caches built by the clay implementation</p></dd>
<dt><a name="90">method <b class="cmd">clay forward</b> <i class="arg">method</i> <i class="arg">object</i></a></dt>
<dd><p>A convenience wrapper for</p>
<pre class="doctools_example">oo::objdefine [self] forward {*}$args</pre>
</dd>
<dt><a name="91">method <b class="cmd">clay get</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></dt>
<dd><p>Pull a chunk of data from the clay system. If the last element of <em>path</em> is a branch (ends in a slash /),
   returns a recursive merge of all data from this object and it's constituent classes of the data in that branch.
   If the last element is a leaf, search this object for a matching leaf, or search all  constituent classes for a matching
   leaf and return the first value found.
   If no value is found, returns an empty string.</p></dd>
<dt><a name="92">method <b class="cmd">clay leaf</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></dt>
<dd><p>A modified get which is tailored to pull only leaf elements</p></dd>
<dt><a name="93">method <b class="cmd">clay merge</b> <i class="arg">dict</i> <span class="opt">?<b class="option">dict...</b>?</span></a></dt>
<dd><p>Recursively merge the dictionaries given into the object's local clay storage.</p></dd>
<dt><a name="94">method <b class="cmd">clay mixin</b> <i class="arg">class</i> <span class="opt">?<b class="option">class...</b>?</span></a></dt>
<dd><p>Perform [oo::objdefine [self] mixin] on this object, with a few additional rules:
   Prior to the call, for any class was previously mixed in, but not in the new result, execute the script registered to mixin/ unmap-script (if given.)
   For all new classes, that were not present prior to this call, after the native TclOO mixin is invoked, execute the script registered to mixin/ map-script (if given.)
   Fall all classes that are now present and “mixed in”, execute the script registered to mixin/ react-script (if given.)</p></dd>
<dt><a name="95">method <b class="cmd">clay mixinmap</b> <span class="opt">?<i class="arg">stub</i>?</span> <span class="opt">?<i class="arg">classes</i>?</span></a></dt>
<dd><p>With no arguments returns the map of stubs and classes mixed into the current object. When only stub is given,
  returns the classes mixed in on that stub. When stub and classlist given, replace the classes currently on that stub with the given
  classes and invoke clay mixin on the new matrix of mixed in classes.</p></dd>
<dt><a name="96">method <b class="cmd">clay provenance</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span></a></dt>
<dd><p>Return either <b class="const">self</b> if that path exists in the current object, or return the first class (if any) along the clay search path which contains that element.</p></dd>
<dt><a name="97">method <b class="cmd">clay replace</b> <i class="arg">dictionary</i></a></dt>
<dd><p>Replace the contents of the internal clay storage with the dictionary given.</p></dd>
<dt><a name="98">method <b class="cmd">clay search</b> <i class="arg">path</i> <i class="arg">valuevar</i> <i class="arg">isleafvar</i></a></dt>
<dd><p>Return true, and set valuevar to the value and isleafar to true for false if PATH was found in the cache.</p></dd>
<dt><a name="99">method <b class="cmd">clay source</b> <i class="arg">filename</i></a></dt>
<dd><p>Source the given filename within the object's namespace</p></dd>
<dt><a name="100">method <b class="cmd">clay set</b> <i class="arg">path</i> <span class="opt">?<b class="option">path...</b>?</span> <i class="arg">value</i></a></dt>
<dd><p>Merge the conents of <b class="const">value</b> with the object's clay storage at <b class="const">path</b>.</p></dd>
<dt><a name="101">method <b class="cmd">InitializePublic</b></a></dt>
<dd><p>Instantiate variables. Called on object creation and during clay mixin.</p></dd>
</dl>
</div>
</div>
<div id="section4" class="doctools_section"><h2><a name="section4">AUTHORS</a></h2>
<p>Sean Woods <a href="mailto:<[email protected]>">mailto:&lt;[email protected]&gt;</a></p>
</div>
<div id="section5" class="doctools_section"><h2><a name="section5">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>oo</em> of the
<a href="http://core.tcl.tk/tcllib/reportlist">Tcllib Trackers</a>.
Please also report any ideas for enhancements you may have for either
package and/or documentation.</p>
<p>When proposing code changes, please provide <em>unified diffs</em>,
i.e the output of <b class="const">diff -u</b>.</p>
<p>Note further that <em>attachments</em> are strongly preferred over
inlined patches. Attachments can be made by going to the <b class="const">Edit</b>
form of the ticket immediately after its creation, and then using the
left-most button in the secondary navigation bar.</p>
</div>
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#tcloo">TclOO</a>, <a href="../../../../index.html#oo">oo</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Programming tools</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2018 Sean Woods &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/debug/debug_heartbeat.html.

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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">debug::heartbeat(n) 1 tcllib &quot;debug narrative&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>debug::heartbeat - debug narrative - heartbeat</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">API</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">debug::heartbeat <span class="opt">?1?</span></b></li>
<li>package require <b class="pkgname">debug <span class="opt">?1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd"><a href="debug.html">debug</a></b> <b class="method">heartbeat</b> <span class="opt">?<i class="arg">delta</i>?</span></a></li>
</ul>
</div>
</div>







|



















|







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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">debug::heartbeat(n) 1.0.1 tcllib &quot;debug narrative&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>debug::heartbeat - debug narrative - heartbeat</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">API</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">debug::heartbeat <span class="opt">?1.0.1?</span></b></li>
<li>package require <b class="pkgname">debug <span class="opt">?1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd"><a href="debug.html">debug</a></b> <b class="method">heartbeat</b> <span class="opt">?<i class="arg">delta</i>?</span></a></li>
</ul>
</div>
</div>

Changes to idoc/www/tcllib/files/modules/dicttool/dicttool.html.

122
123
124
125
126
127
128

129
130
131
132
133
134
135
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>

</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">ladd</b> <i class="arg">varname</i> <i class="arg">args</i></a></li>
<li><a href="#2"><b class="cmd">ldelete</b> <i class="arg">varname</i> <i class="arg">args</i></a></li>
<li><a href="#3"><b class="cmd">dict getnull</b> <i class="arg">args</i></a></li>
<li><a href="#4"><b class="cmd">dict print</b> <i class="arg">dict</i></a></li>
<li><a href="#5"><b class="cmd">dict is_dict</b> <i class="arg">value</i></a></li>







>







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">dicttool <span class="opt">?1.0?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">ladd</b> <i class="arg">varname</i> <i class="arg">args</i></a></li>
<li><a href="#2"><b class="cmd">ldelete</b> <i class="arg">varname</i> <i class="arg">args</i></a></li>
<li><a href="#3"><b class="cmd">dict getnull</b> <i class="arg">args</i></a></li>
<li><a href="#4"><b class="cmd">dict print</b> <i class="arg">dict</i></a></li>
<li><a href="#5"><b class="cmd">dict is_dict</b> <i class="arg">value</i></a></li>
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
Each command checks to see if a command already exists of the same name before adding itself,
just in case any of these slip into the core.</p>
<dl class="doctools_definitions">
<dt><a name="1"><b class="cmd">ladd</b> <i class="arg">varname</i> <i class="arg">args</i></a></dt>
<dd><p>This command will add a new instance of each element in <i class="arg">args</i> to <i class="arg">varname</i>, but only if that element
is not already present.</p></dd>
<dt><a name="2"><b class="cmd">ldelete</b> <i class="arg">varname</i> <i class="arg">args</i></a></dt>
<dd><p>This command will add a delete all instances of each element in <i class="arg">args</i> from <i class="arg">varname</i>.</p></dd>
<dt><a name="3"><b class="cmd">dict getnull</b> <i class="arg">args</i></a></dt>
<dd><p>Operates like <b class="cmd">dict get</b>, however if the key <i class="arg">args</i> does not exist, it returns an empty
list instead of throwing an error.</p></dd>
<dt><a name="4"><b class="cmd">dict print</b> <i class="arg">dict</i></a></dt>
<dd><p>This command will produce a string representation of <i class="arg">dict</i>, with each nested branch on
a newline, and indented with two spaces for every level.</p></dd>
<dt><a name="5"><b class="cmd">dict is_dict</b> <i class="arg">value</i></a></dt>







|







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
Each command checks to see if a command already exists of the same name before adding itself,
just in case any of these slip into the core.</p>
<dl class="doctools_definitions">
<dt><a name="1"><b class="cmd">ladd</b> <i class="arg">varname</i> <i class="arg">args</i></a></dt>
<dd><p>This command will add a new instance of each element in <i class="arg">args</i> to <i class="arg">varname</i>, but only if that element
is not already present.</p></dd>
<dt><a name="2"><b class="cmd">ldelete</b> <i class="arg">varname</i> <i class="arg">args</i></a></dt>
<dd><p>This command will delete all instances of each element in <i class="arg">args</i> from <i class="arg">varname</i>.</p></dd>
<dt><a name="3"><b class="cmd">dict getnull</b> <i class="arg">args</i></a></dt>
<dd><p>Operates like <b class="cmd">dict get</b>, however if the key <i class="arg">args</i> does not exist, it returns an empty
list instead of throwing an error.</p></dd>
<dt><a name="4"><b class="cmd">dict print</b> <i class="arg">dict</i></a></dt>
<dd><p>This command will produce a string representation of <i class="arg">dict</i>, with each nested branch on
a newline, and indented with two spaces for every level.</p></dd>
<dt><a name="5"><b class="cmd">dict is_dict</b> <i class="arg">value</i></a></dt>

Changes to idoc/www/tcllib/files/modules/dns/tcllib_dns.html.

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">dns(n) 1.4.0 tcllib &quot;Domain Name Service&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>dns - Tcl Domain Name Service Client</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>







|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">dns(n) 1.4.1 tcllib &quot;Domain Name Service&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>dns - Tcl Domain Name Service Client</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">dns <span class="opt">?1.4.0?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::dns::resolve</b> <i class="arg">query</i> <span class="opt">?<i class="arg">options</i>?</span></a></li>
<li><a href="#2"><b class="cmd">::dns::configure</b> <span class="opt">?<i class="arg">options</i>?</span></a></li>
<li><a href="#3"><b class="cmd">::dns::name</b> <i class="arg">token</i></a></li>
<li><a href="#4"><b class="cmd">::dns::address</b> <i class="arg">token</i></a></li>
<li><a href="#5"><b class="cmd">::dns::cname</b> <i class="arg">token</i></a></li>







|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">dns <span class="opt">?1.4.1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::dns::resolve</b> <i class="arg">query</i> <span class="opt">?<i class="arg">options</i>?</span></a></li>
<li><a href="#2"><b class="cmd">::dns::configure</b> <span class="opt">?<i class="arg">options</i>?</span></a></li>
<li><a href="#3"><b class="cmd">::dns::name</b> <i class="arg">token</i></a></li>
<li><a href="#4"><b class="cmd">::dns::address</b> <i class="arg">token</i></a></li>
<li><a href="#5"><b class="cmd">::dns::cname</b> <i class="arg">token</i></a></li>

Changes to idoc/www/tcllib/files/modules/doctools/docidx_lang_intro.html.

146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
<b class="const">[</b> and <b class="const">]</b>. Inside of these delimiters the usual
rules for a Tcl command apply with regard to word quotation, nested
commands, continuation lines, etc. I.e.</p>
<pre class="doctools_example">
    ... [key {markup language}] ...
</pre>
<pre class="doctools_example">
  ... [manpage thefile \\
          {file description}] ...
</pre>
</div>
<div id="subsection2" class="doctools_subsection"><h3><a name="subsection2">Basic structure</a></h3>
<p>The most simple document which can be written in docidx is</p>
<pre class="doctools_example">
    [index_begin GROUPTITLE TITLE]







|







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
<b class="const">[</b> and <b class="const">]</b>. Inside of these delimiters the usual
rules for a Tcl command apply with regard to word quotation, nested
commands, continuation lines, etc. I.e.</p>
<pre class="doctools_example">
    ... [key {markup language}] ...
</pre>
<pre class="doctools_example">
  ... [manpage thefile \
          {file description}] ...
</pre>
</div>
<div id="subsection2" class="doctools_subsection"><h3><a name="subsection2">Basic structure</a></h3>
<p>The most simple document which can be written in docidx is</p>
<pre class="doctools_example">
    [index_begin GROUPTITLE TITLE]

Changes to idoc/www/tcllib/files/modules/doctools/doctoc_lang_intro.html.

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<b class="const">[</b> and <b class="const">]</b>. Inside of these delimiters the usual
rules for a Tcl command apply with regard to word quotation, nested
commands, continuation lines, etc. I.e.</p>
<pre class="doctools_example">
    ... [division_start {Appendix 1}] ...
</pre>
<pre class="doctools_example">
  ... [item thefile \\
          label {file description}] ...
</pre>
</div>
<div id="subsection2" class="doctools_subsection"><h3><a name="subsection2">Basic structure</a></h3>
<p>The most simple document which can be written in doctoc is</p>
<pre class="doctools_example">
    [toc_begin GROUPTITLE TITLE]







|







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<b class="const">[</b> and <b class="const">]</b>. Inside of these delimiters the usual
rules for a Tcl command apply with regard to word quotation, nested
commands, continuation lines, etc. I.e.</p>
<pre class="doctools_example">
    ... [division_start {Appendix 1}] ...
</pre>
<pre class="doctools_example">
  ... [item thefile \
          label {file description}] ...
</pre>
</div>
<div id="subsection2" class="doctools_subsection"><h3><a name="subsection2">Basic structure</a></h3>
<p>The most simple document which can be written in doctoc is</p>
<pre class="doctools_example">
    [toc_begin GROUPTITLE TITLE]

Changes to idoc/www/tcllib/files/modules/doctools/doctools.html.

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools(n) 1.5.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools - doctools - Processing documents</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>







|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools(n) 1.5.6 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools - doctools - Processing documents</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">doctools <span class="opt">?1.5.1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::doctools::new</b> <i class="arg">objectName</i> <span class="opt">?<i class="arg">option value</i>...?</span></a></li>
<li><a href="#2"><b class="cmd">::doctools::help</b></a></li>
<li><a href="#3"><b class="cmd">::doctools::search</b> <i class="arg">path</i></a></li>
<li><a href="#4"><b class="cmd">objectName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
<li><a href="#5"><i class="arg">objectName</i> <b class="method">configure</b></a></li>







|







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">doctools <span class="opt">?1.5.6?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::doctools::new</b> <i class="arg">objectName</i> <span class="opt">?<i class="arg">option value</i>...?</span></a></li>
<li><a href="#2"><b class="cmd">::doctools::help</b></a></li>
<li><a href="#3"><b class="cmd">::doctools::search</b> <i class="arg">path</i></a></li>
<li><a href="#4"><b class="cmd">objectName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
<li><a href="#5"><i class="arg">objectName</i> <b class="method">configure</b></a></li>

Changes to idoc/www/tcllib/files/modules/doctools/doctools_lang_intro.html.

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<b class="const">[</b> and <b class="const">]</b>. Inside of these delimiters the usual
rules for a Tcl command apply with regard to word quotation, nested
commands, continuation lines, etc. I.e.</p>
<pre class="doctools_example">
  ... [list_begin enumerated] ...
</pre>
<pre class="doctools_example">
  ... [call [cmd foo] \\
          [arg bar]] ...
</pre>
<pre class="doctools_example">
  ... [term {complex concept}] ...
</pre>
<pre class="doctools_example">
  ... [opt &quot;[arg key] [arg value]&quot;] ...







|







150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<b class="const">[</b> and <b class="const">]</b>. Inside of these delimiters the usual
rules for a Tcl command apply with regard to word quotation, nested
commands, continuation lines, etc. I.e.</p>
<pre class="doctools_example">
  ... [list_begin enumerated] ...
</pre>
<pre class="doctools_example">
  ... [call [cmd foo] \
          [arg bar]] ...
</pre>
<pre class="doctools_example">
  ... [term {complex concept}] ...
</pre>
<pre class="doctools_example">
  ... [opt &quot;[arg key] [arg value]&quot;] ...
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
[keywords {doctools language}]
[keywords {doctools markup}]
[keywords {doctools syntax}]
[keywords markup]
[keywords {semantic markup}]
    [description]
    [vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]
</pre>
<p>This also shows us that all doctools documents are split into two
parts, the <i class="term">header</i> and the <i class="term">body</i>. Everything coming before
[<b class="cmd">description</b>] belongs to the header, and everything coming
after belongs to the body, with the whole document bracketed by the
two <b class="cmd">manpage_*</b> commands. Before and after these opening and







|







176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
[keywords {doctools language}]
[keywords {doctools markup}]
[keywords {doctools syntax}]
[keywords markup]
[keywords {semantic markup}]
    [description]
    [vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]
</pre>
<p>This also shows us that all doctools documents are split into two
parts, the <i class="term">header</i> and the <i class="term">body</i>. Everything coming before
[<b class="cmd">description</b>] belongs to the header, and everything coming
after belongs to the body, with the whole document bracketed by the
two <b class="cmd">manpage_*</b> commands. Before and after these opening and
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
</pre>
<p>Remember that the whitespace is optional. The document</p>
<pre class="doctools_example">
    [manpage_begin NAME SECTION VERSION]
    [copyright {YEAR AUTHOR}][titledesc TITLE][moddesc MODULE_TITLE]
    [require PACKAGE VERSION][require PACKAGE][description]
    [vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]
</pre>
<p>has the same meaning as the example before.</p>
<p>On the other hand, if <i class="term">whitespace</i> is present it consists not
only of any sequence of characters containing the space character,
horizontal and vertical tabs, carriage return, and newline, but it may
contain comment markup as well, in the form of the <b class="cmd"><a href="../../../../index.html#comment">comment</a></b>







|







227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
</pre>
<p>Remember that the whitespace is optional. The document</p>
<pre class="doctools_example">
    [manpage_begin NAME SECTION VERSION]
    [copyright {YEAR AUTHOR}][titledesc TITLE][moddesc MODULE_TITLE]
    [require PACKAGE VERSION][require PACKAGE][description]
    [vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]
</pre>
<p>has the same meaning as the example before.</p>
<p>On the other hand, if <i class="term">whitespace</i> is present it consists not
only of any sequence of characters containing the space character,
horizontal and vertical tabs, carriage return, and newline, but it may
contain comment markup as well, in the form of the <b class="cmd"><a href="../../../../index.html#comment">comment</a></b>

Changes to idoc/www/tcllib/files/modules/doctools2idx/export_docidx.html.

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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::export::docidx.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::idx::export::docidx(n) 0.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::idx::export::docidx - docidx export plugin</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>







|













|







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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::export::docidx.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::idx::export::docidx(n) 0.2.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::idx::export::docidx - docidx export plugin</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">doctools::idx::export::docidx <span class="opt">?0.1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd"><a href="../../../../index.html#export">export</a></b> <i class="arg">serial</i> <i class="arg">configuration</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>







|







126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">doctools::idx::export::docidx <span class="opt">?0.2.1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd"><a href="../../../../index.html#export">export</a></b> <i class="arg">serial</i> <i class="arg">configuration</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
300
301
302
303
304
305
306
307
308
309
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#docidx">docidx</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#serialization">serialization</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


300
301
302
303
304
305
306
307
308
309
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#docidx">docidx</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#serialization">serialization</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2idx/idx_export.html.

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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'idx_export.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2018 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::export.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::idx::export(n) 0.2 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::idx::export - Exporting keyword indices</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>







|













|







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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'idx_export.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::export.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::idx::export(n) 0.2.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::idx::export - Exporting keyword indices</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">doctools::idx::export <span class="opt">?0.2?</span></b></li>
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">doctools::config</b></li>
<li>package require <b class="pkgname">doctools::idx::structure</b></li>
<li>package require <b class="pkgname">snit</b></li>
<li>package require <b class="pkgname">pluginmgr</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::doctools::idx::export</b> <i class="arg">objectName</i></a></li>
<li><a href="#2"><b class="cmd">objectName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>







|

|







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">doctools::idx::export <span class="opt">?0.2.1?</span></b></li>
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">struct::map</b></li>
<li>package require <b class="pkgname">doctools::idx::structure</b></li>
<li>package require <b class="pkgname">snit</b></li>
<li>package require <b class="pkgname">pluginmgr</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::doctools::idx::export</b> <i class="arg">objectName</i></a></li>
<li><a href="#2"><b class="cmd">objectName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
458
459
460
461
462
463
464
465
466
467
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#html">HTML</a>, <a href="../../../../index.html#conversion">conversion</a>, <a href="../../../../index.html#docidx">docidx</a>, <a href="../../../../index.html#documentation">documentation</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#formatting">formatting</a>, <a href="../../../../index.html#generation">generation</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#json">json</a>, <a href="../../../../index.html#keyword_index">keyword index</a>, <a href="../../../../index.html#manpage">manpage</a>, <a href="../../../../index.html#markup">markup</a>, <a href="../../../../index.html#nroff">nroff</a>, <a href="../../../../index.html#plugin">plugin</a>, <a href="../../../../index.html#reference">reference</a>, <a href="../../../../index.html#tcler_s_wiki">tcler's wiki</a>, <a href="../../../../index.html#text">text</a>, <a href="../../../../index.html#url">url</a>, <a href="../../../../index.html#wiki">wiki</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Documentation tools</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2018 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


458
459
460
461
462
463
464
465
466
467
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#html">HTML</a>, <a href="../../../../index.html#conversion">conversion</a>, <a href="../../../../index.html#docidx">docidx</a>, <a href="../../../../index.html#documentation">documentation</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#formatting">formatting</a>, <a href="../../../../index.html#generation">generation</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#json">json</a>, <a href="../../../../index.html#keyword_index">keyword index</a>, <a href="../../../../index.html#manpage">manpage</a>, <a href="../../../../index.html#markup">markup</a>, <a href="../../../../index.html#nroff">nroff</a>, <a href="../../../../index.html#plugin">plugin</a>, <a href="../../../../index.html#reference">reference</a>, <a href="../../../../index.html#tcler_s_wiki">tcler's wiki</a>, <a href="../../../../index.html#text">text</a>, <a href="../../../../index.html#url">url</a>, <a href="../../../../index.html#wiki">wiki</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Documentation tools</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2idx/idx_export_html.html.

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::export::html.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::export::html.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
362
363
364
365
366
367
368
369
370
371
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#html">HTML</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#serialization">serialization</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


362
363
364
365
366
367
368
369
370
371
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#html">HTML</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#serialization">serialization</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2idx/idx_export_json.html.

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::export::json.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::export::json.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
315
316
317
318
319
320
321
322
323
324
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#json">JSON</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#serialization">serialization</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


315
316
317
318
319
320
321
322
323
324
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#json">JSON</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#serialization">serialization</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2idx/idx_export_nroff.html.

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::export::nroff.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::export::nroff.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
269
270
271
272
273
274
275
276
277
278
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#nroff">nroff</a>, <a href="../../../../index.html#serialization">serialization</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


269
270
271
272
273
274
275
276
277
278
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#nroff">nroff</a>, <a href="../../../../index.html#serialization">serialization</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2idx/idx_export_text.html.

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::export::text.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::export::text.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
256
257
258
259
260
261
262
263
264
265
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#plain_text">plain text</a>, <a href="../../../../index.html#serialization">serialization</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


256
257
258
259
260
261
262
263
264
265
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#plain_text">plain text</a>, <a href="../../../../index.html#serialization">serialization</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2idx/idx_export_wiki.html.

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::export::wiki.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::export::wiki.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
269
270
271
272
273
274
275
276
277
278
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#wiki">wiki</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


269
270
271
272
273
274
275
276
277
278
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#wiki">wiki</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2idx/idx_import.html.

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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'idx_import.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2018 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::import.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::idx::import(n) 0.2 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::idx::import - Importing keyword indices</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>







|













|







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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'idx_import.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::import.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::idx::import(n) 0.2.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::idx::import - Importing keyword indices</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">doctools::idx::import <span class="opt">?0.2?</span></b></li>
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">doctools::config</b></li>
<li>package require <b class="pkgname">doctools::idx::structure</b></li>
<li>package require <b class="pkgname">snit</b></li>
<li>package require <b class="pkgname">pluginmgr</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::doctools::idx::import</b> <i class="arg">objectName</i></a></li>
<li><a href="#2"><b class="cmd">objectName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>







|

|







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">doctools::idx::import <span class="opt">?0.2.1?</span></b></li>
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">struct::map</b></li>
<li>package require <b class="pkgname">doctools::idx::structure</b></li>
<li>package require <b class="pkgname">snit</b></li>
<li>package require <b class="pkgname">pluginmgr</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::doctools::idx::import</b> <i class="arg">objectName</i></a></li>
<li><a href="#2"><b class="cmd">objectName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
517
518
519
520
521
522
523
524
525
526
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#conversion">conversion</a>, <a href="../../../../index.html#docidx">docidx</a>, <a href="../../../../index.html#documentation">documentation</a>, <a href="../../../../index.html#import">import</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#json">json</a>, <a href="../../../../index.html#keyword_index">keyword index</a>, <a href="../../../../index.html#manpage">manpage</a>, <a href="../../../../index.html#markup">markup</a>, <a href="../../../../index.html#parsing">parsing</a>, <a href="../../../../index.html#plugin">plugin</a>, <a href="../../../../index.html#reference">reference</a>, <a href="../../../../index.html#url">url</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Documentation tools</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2018 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


517
518
519
520
521
522
523
524
525
526
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#conversion">conversion</a>, <a href="../../../../index.html#docidx">docidx</a>, <a href="../../../../index.html#documentation">documentation</a>, <a href="../../../../index.html#import">import</a>, <a href="../../../../index.html#index">index</a>, <a href="../../../../index.html#json">json</a>, <a href="../../../../index.html#keyword_index">keyword index</a>, <a href="../../../../index.html#manpage">manpage</a>, <a href="../../../../index.html#markup">markup</a>, <a href="../../../../index.html#parsing">parsing</a>, <a href="../../../../index.html#plugin">plugin</a>, <a href="../../../../index.html#reference">reference</a>, <a href="../../../../index.html#url">url</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Documentation tools</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2idx/idx_import_json.html.

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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::import::json.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::idx::import::json(n) 0.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::idx::import::json - JSON import plugin</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">API</a></li>
<li class="doctools_section"><a href="#section3">JSON notation of keyword indices</a></li>
<li class="doctools_section"><a href="#section4">Keyword index serialization format</a></li>
<li class="doctools_section"><a href="#section5">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">doctools::idx::import::json <span class="opt">?0.1?</span></b></li>
<li>package require <b class="pkgname">doctools::idx::structure</b></li>
<li>package require <b class="pkgname">json</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd"><a href="../../../../index.html#import">import</a></b> <i class="arg">string</i> <i class="arg">configuration</i></a></li>
</ul>
</div>







|













|




















|
|







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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::import::json.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::idx::import::json(n) 0.2.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::idx::import::json - JSON import plugin</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">API</a></li>
<li class="doctools_section"><a href="#section3">JSON notation of keyword indices</a></li>
<li class="doctools_section"><a href="#section4">Keyword index serialization format</a></li>
<li class="doctools_section"><a href="#section5">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">doctools::idx::import::json <span class="opt">?0.2.1?</span></b></li>
<li>package require <b class="pkgname">doctools::idx::structure</b></li>
<li>package require <b class="pkgname">json</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd"><a href="../../../../index.html#import">import</a></b> <i class="arg">string</i> <i class="arg">configuration</i></a></li>
</ul>
</div>
292
293
294
295
296
297
298
299
300
301
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#json">JSON</a>, <a href="../../../../index.html#deserialization">deserialization</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#import">import</a>, <a href="../../../../index.html#index">index</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


292
293
294
295
296
297
298
299
300
301
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#json">JSON</a>, <a href="../../../../index.html#deserialization">deserialization</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#import">import</a>, <a href="../../../../index.html#index">index</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2idx/idx_introduction.html.

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
<pre class="doctools_example">
                                    ~~~~~~~~~~~ doctools::idx ~~~~~~~~~~~
                                   ~~                   |               ~~
                doctools::idx::export ~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ doctools::idx::import
                        |                               |                       |
        +---------------+-------------------------+     |    +------------------+---------------+-----------------------+---------------+
        |               |                         |     |    |                  |               |                       |               |
doctools::config        =                         |     |    |                  =       doctools::include       doctools::config doctools::paths
                        |                         |     |    |                  |
                doctools::idx::export::&lt;*&gt;        |     |    |          doctools::idx::import::&lt;*&gt;
                        docidx                    |     |    |                  docidx, json
                        json                      |     |    |                  |           \\
                        html                      |     |    |          doctools::idx::parse \\
                        nroff                     |     |    |                  |             \\
                        wiki                      |     |    |  +---------------+              json
                        text                      |     |    |  |               |
                                                doctools::idx::structure        |
                                                                                |
                                                                        +-------+---------------+
                                                                        |                       |
          doctools::html  doctools::html::cssdefaults           doctools::tcl::parse    doctools::msgcat        







|



|
|
|







206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
<pre class="doctools_example">
                                    ~~~~~~~~~~~ doctools::idx ~~~~~~~~~~~
                                   ~~                   |               ~~
                doctools::idx::export ~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ doctools::idx::import
                        |                               |                       |
        +---------------+-------------------------+     |    +------------------+---------------+-----------------------+---------------+
        |               |                         |     |    |                  |               |                       |               |
struct::map             =                         |     |    |                  =       doctools::include       struct::map      fileutil::paths
                        |                         |     |    |                  |
                doctools::idx::export::&lt;*&gt;        |     |    |          doctools::idx::import::&lt;*&gt;
                        docidx                    |     |    |                  docidx, json
                        json                      |     |    |                  |           \
                        html                      |     |    |          doctools::idx::parse \
                        nroff                     |     |    |                  |             \
                        wiki                      |     |    |  +---------------+              json
                        text                      |     |    |  |               |
                                                doctools::idx::structure        |
                                                                                |
                                                                        +-------+---------------+
                                                                        |                       |
          doctools::html  doctools::html::cssdefaults           doctools::tcl::parse    doctools::msgcat        

Changes to idoc/www/tcllib/files/modules/doctools2idx/import_docidx.html.

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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::import::docidx.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::idx::import::docidx(n) 0.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::idx::import::docidx - docidx import plugin</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">API</a></li>
<li class="doctools_section"><a href="#section3">[docidx] notation of keyword indices</a></li>
<li class="doctools_section"><a href="#section4">Keyword index serialization format</a></li>
<li class="doctools_section"><a href="#section5">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">doctools::idx::import::docidx <span class="opt">?0.1?</span></b></li>
<li>package require <b class="pkgname">doctools::idx::parse</b></li>
<li>package require <b class="pkgname">doctools::idx::structure</b></li>
<li>package require <b class="pkgname">doctools::msgcat</b></li>
<li>package require <b class="pkgname">doctools::tcl::parse</b></li>
<li>package require <b class="pkgname">fileutil</b></li>
<li>package require <b class="pkgname">logger</b></li>
<li>package require <b class="pkgname">snit</b></li>







|













|




















|
|







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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::idx::import::docidx.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::idx::import::docidx(n) 0.2.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::idx::import::docidx - docidx import plugin</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">API</a></li>
<li class="doctools_section"><a href="#section3">[docidx] notation of keyword indices</a></li>
<li class="doctools_section"><a href="#section4">Keyword index serialization format</a></li>
<li class="doctools_section"><a href="#section5">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">doctools::idx::import::docidx <span class="opt">?0.2.1?</span></b></li>
<li>package require <b class="pkgname">doctools::idx::parse</b></li>
<li>package require <b class="pkgname">doctools::idx::structure</b></li>
<li>package require <b class="pkgname">doctools::msgcat</b></li>
<li>package require <b class="pkgname">doctools::tcl::parse</b></li>
<li>package require <b class="pkgname">fileutil</b></li>
<li>package require <b class="pkgname">logger</b></li>
<li>package require <b class="pkgname">snit</b></li>
269
270
271
272
273
274
275
276
277
278
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#deserialization">deserialization</a>, <a href="../../../../index.html#docidx">docidx</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#import">import</a>, <a href="../../../../index.html#index">index</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


269
270
271
272
273
274
275
276
277
278
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#deserialization">deserialization</a>, <a href="../../../../index.html#docidx">docidx</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#import">import</a>, <a href="../../../../index.html#index">index</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2toc/export_doctoc.html.

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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::export::doctoc.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::toc::export::doctoc(n) 0.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::toc::export::doctoc - doctoc export plugin</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>







|













|







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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::export::doctoc.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::toc::export::doctoc(n) 0.2.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::toc::export::doctoc - doctoc export plugin</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">doctools::toc::export::doctoc <span class="opt">?0.1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd"><a href="../../../../index.html#export">export</a></b> <i class="arg">serial</i> <i class="arg">configuration</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>







|







126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">doctools::toc::export::doctoc <span class="opt">?0.2.1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd"><a href="../../../../index.html#export">export</a></b> <i class="arg">serial</i> <i class="arg">configuration</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
323
324
325
326
327
328
329
330
331
332
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#doctoc">doctoc</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


323
324
325
326
327
328
329
330
331
332
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#doctoc">doctoc</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2toc/import_doctoc.html.

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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::import::doctoc.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::toc::import::doctoc(n) 0.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::toc::import::doctoc - doctoc import plugin</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">API</a></li>
<li class="doctools_section"><a href="#section3">[doctoc] notation of tables of contents</a></li>
<li class="doctools_section"><a href="#section4">ToC serialization format</a></li>
<li class="doctools_section"><a href="#section5">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">doctools::toc::import::doctoc <span class="opt">?0.1?</span></b></li>
<li>package require <b class="pkgname">doctools::toc::parse</b></li>
<li>package require <b class="pkgname">doctools::toc::structure</b></li>
<li>package require <b class="pkgname">doctools::msgcat</b></li>
<li>package require <b class="pkgname">doctools::tcl::parse</b></li>
<li>package require <b class="pkgname">fileutil</b></li>
<li>package require <b class="pkgname">logger</b></li>
<li>package require <b class="pkgname">snit</b></li>







|













|




















|
|







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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::import::doctoc.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::toc::import::doctoc(n) 0.2.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::toc::import::doctoc - doctoc import plugin</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">API</a></li>
<li class="doctools_section"><a href="#section3">[doctoc] notation of tables of contents</a></li>
<li class="doctools_section"><a href="#section4">ToC serialization format</a></li>
<li class="doctools_section"><a href="#section5">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">doctools::toc::import::doctoc <span class="opt">?0.2.1?</span></b></li>
<li>package require <b class="pkgname">doctools::toc::parse</b></li>
<li>package require <b class="pkgname">doctools::toc::structure</b></li>
<li>package require <b class="pkgname">doctools::msgcat</b></li>
<li>package require <b class="pkgname">doctools::tcl::parse</b></li>
<li>package require <b class="pkgname">fileutil</b></li>
<li>package require <b class="pkgname">logger</b></li>
<li>package require <b class="pkgname">snit</b></li>
293
294
295
296
297
298
299
300
301
302
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#deserialization">deserialization</a>, <a href="../../../../index.html#doctoc">doctoc</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#import">import</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


293
294
295
296
297
298
299
300
301
302
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#deserialization">deserialization</a>, <a href="../../../../index.html#doctoc">doctoc</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#import">import</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2toc/toc_export.html.

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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'toc_export.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2018 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::export.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::toc::export(n) 0.2 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::toc::export - Exporting tables of contents</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>







|













|







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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'toc_export.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::export.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::toc::export(n) 0.2.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::toc::export - Exporting tables of contents</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">doctools::toc::export <span class="opt">?0.2?</span></b></li>
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">doctools::config</b></li>
<li>package require <b class="pkgname">doctools::toc::structure</b></li>
<li>package require <b class="pkgname">snit</b></li>
<li>package require <b class="pkgname">pluginmgr</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::doctools::toc::export</b> <i class="arg">objectName</i></a></li>
<li><a href="#2"><b class="cmd">objectName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>







|

|







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">doctools::toc::export <span class="opt">?0.2.1?</span></b></li>
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">struct::map</b></li>
<li>package require <b class="pkgname">doctools::toc::structure</b></li>
<li>package require <b class="pkgname">snit</b></li>
<li>package require <b class="pkgname">pluginmgr</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::doctools::toc::export</b> <i class="arg">objectName</i></a></li>
<li><a href="#2"><b class="cmd">objectName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
474
475
476
477
478
479
480
481
482
483
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#html">HTML</a>, <a href="../../../../index.html#conversion">conversion</a>, <a href="../../../../index.html#doctoc">doctoc</a>, <a href="../../../../index.html#documentation">documentation</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#formatting">formatting</a>, <a href="../../../../index.html#generation">generation</a>, <a href="../../../../index.html#json">json</a>, <a href="../../../../index.html#manpage">manpage</a>, <a href="../../../../index.html#markup">markup</a>, <a href="../../../../index.html#nroff">nroff</a>, <a href="../../../../index.html#plugin">plugin</a>, <a href="../../../../index.html#reference">reference</a>, <a href="../../../../index.html#table">table</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#tcler_s_wiki">tcler's wiki</a>, <a href="../../../../index.html#text">text</a>, <a href="../../../../index.html#url">url</a>, <a href="../../../../index.html#wiki">wiki</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Documentation tools</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2018 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


474
475
476
477
478
479
480
481
482
483
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#html">HTML</a>, <a href="../../../../index.html#conversion">conversion</a>, <a href="../../../../index.html#doctoc">doctoc</a>, <a href="../../../../index.html#documentation">documentation</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#formatting">formatting</a>, <a href="../../../../index.html#generation">generation</a>, <a href="../../../../index.html#json">json</a>, <a href="../../../../index.html#manpage">manpage</a>, <a href="../../../../index.html#markup">markup</a>, <a href="../../../../index.html#nroff">nroff</a>, <a href="../../../../index.html#plugin">plugin</a>, <a href="../../../../index.html#reference">reference</a>, <a href="../../../../index.html#table">table</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#tcler_s_wiki">tcler's wiki</a>, <a href="../../../../index.html#text">text</a>, <a href="../../../../index.html#url">url</a>, <a href="../../../../index.html#wiki">wiki</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Documentation tools</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2toc/toc_export_html.html.

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::export::html.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::export::html.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
356
357
358
359
360
361
362
363
364
365
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#html">HTML</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


356
357
358
359
360
361
362
363
364
365
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#html">HTML</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2toc/toc_export_json.html.

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::export::json.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::export::json.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
359
360
361
362
363
364
365
366
367
368
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#json">JSON</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


359
360
361
362
363
364
365
366
367
368
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#json">JSON</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2toc/toc_export_nroff.html.

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::export::nroff.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::export::nroff.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
293
294
295
296
297
298
299
300
301
302
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#nroff">nroff</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


293
294
295
296
297
298
299
300
301
302
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#nroff">nroff</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2toc/toc_export_text.html.

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::export::text.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::export::text.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
279
280
281
282
283
284
285
286
287
288
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#plain_text">plain text</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


279
280
281
282
283
284
285
286
287
288
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#plain_text">plain text</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2toc/toc_export_wiki.html.

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::export::wiki.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::export::wiki.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
286
287
288
289
290
291
292
293
294
295
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a>, <a href="../../../../index.html#wiki">wiki</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


286
287
288
289
290
291
292
293
294
295
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#export">export</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a>, <a href="../../../../index.html#wiki">wiki</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2toc/toc_import.html.

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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'toc_import.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2018 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::import.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::toc::import(n) 0.2 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::toc::import - Importing keyword indices</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>







|













|







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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'toc_import.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::import.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::toc::import(n) 0.2.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::toc::import - Importing keyword indices</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">doctools::toc::import <span class="opt">?0.2?</span></b></li>
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">doctools::config</b></li>
<li>package require <b class="pkgname">doctools::toc::structure</b></li>
<li>package require <b class="pkgname">snit</b></li>
<li>package require <b class="pkgname">pluginmgr</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::doctools::toc::import</b> <i class="arg">objectName</i></a></li>
<li><a href="#2"><b class="cmd">objectName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>







|

|







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">doctools::toc::import <span class="opt">?0.2.1?</span></b></li>
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">struct::map</b></li>
<li>package require <b class="pkgname">doctools::toc::structure</b></li>
<li>package require <b class="pkgname">snit</b></li>
<li>package require <b class="pkgname">pluginmgr</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::doctools::toc::import</b> <i class="arg">objectName</i></a></li>
<li><a href="#2"><b class="cmd">objectName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
535
536
537
538
539
540
541
542
543
544
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#conversion">conversion</a>, <a href="../../../../index.html#doctoc">doctoc</a>, <a href="../../../../index.html#documentation">documentation</a>, <a href="../../../../index.html#import">import</a>, <a href="../../../../index.html#json">json</a>, <a href="../../../../index.html#manpage">manpage</a>, <a href="../../../../index.html#markup">markup</a>, <a href="../../../../index.html#parsing">parsing</a>, <a href="../../../../index.html#plugin">plugin</a>, <a href="../../../../index.html#reference">reference</a>, <a href="../../../../index.html#table">table</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#url">url</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Documentation tools</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2018 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


535
536
537
538
539
540
541
542
543
544
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#conversion">conversion</a>, <a href="../../../../index.html#doctoc">doctoc</a>, <a href="../../../../index.html#documentation">documentation</a>, <a href="../../../../index.html#import">import</a>, <a href="../../../../index.html#json">json</a>, <a href="../../../../index.html#manpage">manpage</a>, <a href="../../../../index.html#markup">markup</a>, <a href="../../../../index.html#parsing">parsing</a>, <a href="../../../../index.html#plugin">plugin</a>, <a href="../../../../index.html#reference">reference</a>, <a href="../../../../index.html#table">table</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#url">url</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Documentation tools</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2toc/toc_import_json.html.

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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::import::json.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::toc::import::json(n) 0.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::toc::import::json - JSON import plugin</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">API</a></li>
<li class="doctools_section"><a href="#section3">JSON notation of tables of contents</a></li>
<li class="doctools_section"><a href="#section4">ToC serialization format</a></li>
<li class="doctools_section"><a href="#section5">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">doctools::toc::import::json <span class="opt">?0.1?</span></b></li>
<li>package require <b class="pkgname">doctools::toc::structure</b></li>
<li>package require <b class="pkgname">json</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd"><a href="../../../../index.html#import">import</a></b> <i class="arg">string</i> <i class="arg">configuration</i></a></li>
</ul>
</div>







|













|




















|
|







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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'plugin.inc' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009-2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- doctools::toc::import::json.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">doctools::toc::import::json(n) 0.2.1 tcllib &quot;Documentation tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>doctools::toc::import::json - JSON import plugin</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">API</a></li>
<li class="doctools_section"><a href="#section3">JSON notation of tables of contents</a></li>
<li class="doctools_section"><a href="#section4">ToC serialization format</a></li>
<li class="doctools_section"><a href="#section5">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">doctools::toc::import::json <span class="opt">?0.2.1?</span></b></li>
<li>package require <b class="pkgname">doctools::toc::structure</b></li>
<li>package require <b class="pkgname">json</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd"><a href="../../../../index.html#import">import</a></b> <i class="arg">string</i> <i class="arg">configuration</i></a></li>
</ul>
</div>
336
337
338
339
340
341
342
343
344
345
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#json">JSON</a>, <a href="../../../../index.html#deserialization">deserialization</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#import">import</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


336
337
338
339
340
341
342
343
344
345
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#json">JSON</a>, <a href="../../../../index.html#deserialization">deserialization</a>, <a href="../../../../index.html#doctools">doctools</a>, <a href="../../../../index.html#import">import</a>, <a href="../../../../index.html#table_of_contents">table of contents</a>, <a href="../../../../index.html#toc">toc</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text formatter plugin</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009-2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/doctools2toc/toc_introduction.html.

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
<pre class="doctools_example">
                                    ~~~~~~~~~~~ doctools::toc ~~~~~~~~~~~
                                   ~~                   |               ~~
                doctools::toc::export ~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ doctools::toc::import
                        |                               |                       |
        +---------------+-------------------------+     |    +------------------+---------------+-----------------------+---------------+
        |               |                         |     |    |                  |               |                       |               |
doctools::config        =                         |     |    |                  =       doctools::include       doctools::config doctools::paths
                        |                         |     |    |                  |
                doctools::toc::export::&lt;*&gt;        |     |    |          doctools::toc::import::&lt;*&gt;
                        doctoc                    |     |    |                  doctoc, json
                        json                      |     |    |                  |           \\
                        html                      |     |    |          doctools::toc::parse \\
                        nroff                     |     |    |                  |             \\
                        wiki                      |     |    |  +---------------+              json
                        text                      |     |    |  |               |
                                                doctools::toc::structure        |
                                                                                |
                                                                        +-------+---------------+
                                                                        |                       |
          doctools::html  doctools::html::cssdefaults           doctools::tcl::parse    doctools::msgcat        







|



|
|
|







206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
<pre class="doctools_example">
                                    ~~~~~~~~~~~ doctools::toc ~~~~~~~~~~~
                                   ~~                   |               ~~
                doctools::toc::export ~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ doctools::toc::import
                        |                               |                       |
        +---------------+-------------------------+     |    +------------------+---------------+-----------------------+---------------+
        |               |                         |     |    |                  |               |                       |               |
struct:map              =                         |     |    |                  =       doctools::include       struct::map      fileutil::paths
                        |                         |     |    |                  |
                doctools::toc::export::&lt;*&gt;        |     |    |          doctools::toc::import::&lt;*&gt;
                        doctoc                    |     |    |                  doctoc, json
                        json                      |     |    |                  |           \
                        html                      |     |    |          doctools::toc::parse \
                        nroff                     |     |    |                  |             \
                        wiki                      |     |    |  +---------------+              json
                        text                      |     |    |  |               |
                                                doctools::toc::structure        |
                                                                                |
                                                                        +-------+---------------+
                                                                        |                       |
          doctools::html  doctools::html::cssdefaults           doctools::tcl::parse    doctools::msgcat        

Changes to idoc/www/tcllib/files/modules/fileutil/multiop.html.

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
<dd><p>Returns the current path type limiter.</p></dd>
</dl>
</div>
<div id="section5" class="doctools_section"><h2><a name="section5">EXAMPLES</a></h2>
<p>The following examples assume that the variable <b class="variable">F</b> contains a
reference to a multi-file operation object.</p>
<pre class="doctools_example">
    $F do copy                       \\
	the  *.dll                    \\
	from c:/TDK/PrivateOpenSSL/bin \\
	to   [installdir_of tls]
</pre>
<pre class="doctools_example">
    $F do move      \\
	the  *       \\
	from /sources \\
	into /scratch  \\
	but not *.html
    # Alternatively use 'except for *.html'.
</pre>
<pre class="doctools_example">
    $F do           \\
	move         \\
	the  index    \\
	from /sources  \\
	into /scratch   \\
	as   pkgIndex.tcl
</pre>
<pre class="doctools_example">
    $F do         \\
	remove     \\
	the *.txt  \\
	in /scratch
</pre>
<p>Note that the fact that most commands just modify the object state
allows us to use more off forms as specifications instead of just
nearly-natural language sentences.
For example the second example in this section can re-arranged into:</p>
<pre class="doctools_example">
    $F do            \\
	from /sources \\
	into /scratch  \\
	but not *.html \\
	move           \\
	the  *
</pre>
<p>and the result is not only still a valid specification, but even stays
relatively readable.</p>
<p>Further note that the information collected by the commands <b class="cmd">but</b>,
<b class="cmd">except</b>, and <b class="cmd">as</b> is automatically reset after the associated
<b class="cmd">the</b> was executed. However no other state is reset in that
manner, allowing the user to avoid repetitions of unchanging
information. For example the second and third examples of this section
can be merged and rewritten into the equivalent:</p>
<pre class="doctools_example">
$F do                   \\
    move                 \\
    the  *                \\
    from /sources          \\
    into /scratch           \\
    but not *.html not index \\
    the  index               \\
    as   pkgIndex.tcl
</pre>
</div>
<div id="section6" class="doctools_section"><h2><a name="section6">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>fileutil</em> of the







|
|
|



|
|
|
|




|
|
|
|
|



|
|
|







|
|
|
|
|











|
|
|
|
|
|
|







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
<dd><p>Returns the current path type limiter.</p></dd>
</dl>
</div>
<div id="section5" class="doctools_section"><h2><a name="section5">EXAMPLES</a></h2>
<p>The following examples assume that the variable <b class="variable">F</b> contains a
reference to a multi-file operation object.</p>
<pre class="doctools_example">
    $F do copy                       \
	the  *.dll                    \
	from c:/TDK/PrivateOpenSSL/bin \
	to   [installdir_of tls]
</pre>
<pre class="doctools_example">
    $F do move      \
	the  *       \
	from /sources \
	into /scratch  \
	but not *.html
    # Alternatively use 'except for *.html'.
</pre>
<pre class="doctools_example">
    $F do           \
	move         \
	the  index    \
	from /sources  \
	into /scratch   \
	as   pkgIndex.tcl
</pre>
<pre class="doctools_example">
    $F do         \
	remove     \
	the *.txt  \
	in /scratch
</pre>
<p>Note that the fact that most commands just modify the object state
allows us to use more off forms as specifications instead of just
nearly-natural language sentences.
For example the second example in this section can re-arranged into:</p>
<pre class="doctools_example">
    $F do            \
	from /sources \
	into /scratch  \
	but not *.html \
	move           \
	the  *
</pre>
<p>and the result is not only still a valid specification, but even stays
relatively readable.</p>
<p>Further note that the information collected by the commands <b class="cmd">but</b>,
<b class="cmd">except</b>, and <b class="cmd">as</b> is automatically reset after the associated
<b class="cmd">the</b> was executed. However no other state is reset in that
manner, allowing the user to avoid repetitions of unchanging
information. For example the second and third examples of this section
can be merged and rewritten into the equivalent:</p>
<pre class="doctools_example">
$F do                   \
    move                 \
    the  *                \
    from /sources          \
    into /scratch           \
    but not *.html not index \
    the  index               \
    as   pkgIndex.tcl
</pre>
</div>
<div id="section6" class="doctools_section"><h2><a name="section6">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>fileutil</em> of the

Added idoc/www/tcllib/files/modules/fileutil/paths.html.





























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
<!DOCTYPE html><html><head>
<title>fileutil::paths - </title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
	color:	 	black;
    }
    DIV.doctools {
	margin-left:	10%;
	margin-right:	10%;
    }
    DIV.doctools H1,DIV.doctools H2 {
	margin-left:	-5%;
    }
    H1, H2, H3, H4 {
	margin-top: 	1em;
	font-family:	sans-serif;
	font-size:	large;
	color:		#005A9C;
	background: 	transparent;
	text-align:		left;
    }
    H1.doctools_title {
	text-align: center;
    }
    UL,OL {
	margin-right: 0em;
	margin-top: 3pt;
	margin-bottom: 3pt;
    }
    UL LI {
	list-style: disc;
    }
    OL LI {
	list-style: decimal;
    }
    DT {
	padding-top: 	1ex;
    }
    UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
	font:		normal 12pt/14pt sans-serif;
	list-style:	none;
    }
    LI.doctools_section, LI.doctools_subsection {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding: 	0em;
    }
    PRE {
	display: 	block;
	font-family:	monospace;
	white-space:	pre;
	margin:		0%;
	padding-top:	0.5ex;
	padding-bottom:	0.5ex;
	padding-left:	1ex;
	padding-right:	1ex;
	width:		100%;
    }
    PRE.doctools_example {
	color: 		black;
	background: 	#f5dcb3;
	border:		1px solid black;
    }
    UL.doctools_requirements LI, UL.doctools_syntax LI {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding:	0em;
    }
    DIV.doctools_synopsis {
	color: 		black;
	background: 	#80ffff;
	border:		1px solid black;
	font-family:	serif;
	margin-top: 	1em;
	margin-bottom: 	1em;
    }
    UL.doctools_syntax {
	margin-top: 	1em;
	border-top:	1px solid black;
    }
    UL.doctools_requirements {
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'paths.man' by tcllib/doctools with format 'html'
   -->
<!-- fileutil::paths.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">fileutil::paths(n) 1 tcllib &quot;&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>fileutil::paths - Manage search path pools</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">API</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">fileutil::paths <span class="opt">?1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::fileutil::paths</b> <i class="arg">poolName</i></a></li>
<li><a href="#2"><b class="cmd">poolName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
<li><a href="#3"><i class="arg">poolName</i> <b class="method">add</b> <i class="arg">path</i></a></li>
<li><a href="#4"><i class="arg">poolName</i> <b class="method">clear</b></a></li>
<li><a href="#5"><i class="arg">poolName</i> <b class="method">paths</b></a></li>
<li><a href="#6"><i class="arg">poolName</i> <b class="method">remove</b> <i class="arg">path</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>Provides a snit class whose instances manage a pool of (search) paths.</p>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">API</a></h2>
<p>The main command provides construction of search path pools:</p>
<dl class="doctools_definitions">
<dt><a name="1"><b class="cmd">::fileutil::paths</b> <i class="arg">poolName</i></a></dt>
<dd><p>Creates a new, empty pool of search paths with an associated global
Tcl command whose name is <i class="arg">poolName</i>.
It may be used to invoke various operations on the pool.
It has the following general form:</p>
<dl class="doctools_definitions">
<dt><a name="2"><b class="cmd">poolName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></dt>
<dd><p><b class="method">method</b> and <i class="arg">arg</i>uments determine the exact behavior of
the command.</p></dd>
</dl>
<p>If <i class="arg">poolName</i> is specified as <b class="const">%AUTO%</b> a unique name will be
generated by the package itself.
The result of the command is the fully-qualified name of the instance
command.</p></dd>
</dl>
<p>The following commands are possible for pool objects:</p>
<dl class="doctools_definitions">
<dt><a name="3"><i class="arg">poolName</i> <b class="method">add</b> <i class="arg">path</i></a></dt>
<dd><p>Adds the <i class="arg">path</i> to the pool.
Nothing is done if the <i class="arg">path</i> is already known to the pool.
The result of the command is the empty string.</p></dd>
<dt><a name="4"><i class="arg">poolName</i> <b class="method">clear</b></a></dt>
<dd><p>Clears the entire pool. In other words, removes all paths from it.
The result of the command is the empty string.</p></dd>
<dt><a name="5"><i class="arg">poolName</i> <b class="method">paths</b></a></dt>
<dd><p>Returns the list of all paths known to the pool, in the order they
were added.</p></dd>
<dt><a name="6"><i class="arg">poolName</i> <b class="method">remove</b> <i class="arg">path</i></a></dt>
<dd><p>Removes the <i class="arg">path</i> from the pool, if it is known to the pool.
Unknown paths are ignored without error.
The result of the command is the empty string.</p></dd>
</dl>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>fileutil</em> of the
<a href="http://core.tcl.tk/tcllib/reportlist">Tcllib Trackers</a>.
Please also report any ideas for enhancements you may have for either
package and/or documentation.</p>
<p>When proposing code changes, please provide <em>unified diffs</em>,
i.e the output of <b class="const">diff -u</b>.</p>
<p>Note further that <em>attachments</em> are strongly preferred over
inlined patches. Attachments can be made by going to the <b class="const">Edit</b>
form of the ticket immediately after its creation, and then using the
left-most button in the secondary navigation bar.</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/grammar_fa/fa.html.

309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
in a very simple way :)</p>
<pre class="doctools_example">
    Drive -- yellow --&gt; Brake -- red --&gt; (Stop) -- red/yellow --&gt; Attention -- green --&gt; Drive
    (...) is the start state.
</pre>
<p>a possible serialization is</p>
<pre class="doctools_example">
    grammar::fa \\
    {yellow red green red/yellow} \\
    {Drive     {0 0 {yellow     Brake}} \\
     Brake     {0 0 {red        Stop}} \\
     Stop      {1 0 {red/yellow Attention}} \\
     Attention {0 0 {green      Drive}}}
</pre>
<p>A possible one, because I did not care about creation order here</p></dd>
<dt><a name="8"><i class="arg">faName</i> <b class="method">deserialize</b> <i class="arg">serialization</i></a></dt>
<dd><p>This is the complement to <b class="method">serialize</b>. It replaces the
automaton definition in <i class="arg">faName</i> with the automaton described by
the <i class="arg">serialization</i> value. The old contents of <i class="arg">faName</i> are







|
|
|
|
|







309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
in a very simple way :)</p>
<pre class="doctools_example">
    Drive -- yellow --&gt; Brake -- red --&gt; (Stop) -- red/yellow --&gt; Attention -- green --&gt; Drive
    (...) is the start state.
</pre>
<p>a possible serialization is</p>
<pre class="doctools_example">
    grammar::fa \
    {yellow red green red/yellow} \
    {Drive     {0 0 {yellow     Brake}} \
     Brake     {0 0 {red        Stop}} \
     Stop      {1 0 {red/yellow Attention}} \
     Attention {0 0 {green      Drive}}}
</pre>
<p>A possible one, because I did not care about creation order here</p></dd>
<dt><a name="8"><i class="arg">faName</i> <b class="method">deserialize</b> <i class="arg">serialization</i></a></dt>
<dd><p>This is the complement to <b class="method">serialize</b>. It replaces the
automaton definition in <i class="arg">faName</i> with the automaton described by
the <i class="arg">serialization</i> value. The old contents of <i class="arg">faName</i> are

Changes to idoc/www/tcllib/files/modules/grammar_peg/peg.html.

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
    MulOp      &lt;- '*' / '/'
    Factor     &lt;- Term (AddOp Term)*
    AddOp      &lt;- '+'/'-'
    Term       &lt;- Number
</pre>
<p>a possible serialization is</p>
<pre class="doctools_example">
    grammar::peg \\
    {Expression {/ {x ( Expression )} {x Factor {* {x MulOp Factor}}}} \\
     Factor     {x Term {* {x AddOp Term}}} \\
     Term       Number \\
     MulOp      {/ * /} \\
     AddOp      {/ + -} \\
     Number     {x {? Sign} {+ Digit}} \\
     Sign       {/ + -} \\
     Digit      {/ 0 1 2 3 4 5 6 7 8 9} \\
    } \\
    {Expression value     Factor     value \\
     Term       value     MulOp      value \\
     AddOp      value     Number     value \\
     Sign       value     Digit      value \\
    }
    Expression
</pre>
<p>A possible one, because the order of the nonterminals in the
dictionary is not relevant.</p></dd>
<dt><a name="7"><i class="arg">pegName</i> <b class="method">deserialize</b> <i class="arg">serialization</i></a></dt>
<dd><p>This is the complement to <b class="method">serialize</b>. It replaces the grammar







|
|
|
|
|
|
|
|
|
|
|
|
|
|







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
    MulOp      &lt;- '*' / '/'
    Factor     &lt;- Term (AddOp Term)*
    AddOp      &lt;- '+'/'-'
    Term       &lt;- Number
</pre>
<p>a possible serialization is</p>
<pre class="doctools_example">
    grammar::peg \
    {Expression {/ {x ( Expression )} {x Factor {* {x MulOp Factor}}}} \
     Factor     {x Term {* {x AddOp Term}}} \
     Term       Number \
     MulOp      {/ * /} \
     AddOp      {/ + -} \
     Number     {x {? Sign} {+ Digit}} \
     Sign       {/ + -} \
     Digit      {/ 0 1 2 3 4 5 6 7 8 9} \
    } \
    {Expression value     Factor     value \
     Term       value     MulOp      value \
     AddOp      value     Number     value \
     Sign       value     Digit      value \
    }
    Expression
</pre>
<p>A possible one, because the order of the nonterminals in the
dictionary is not relevant.</p></dd>
<dt><a name="7"><i class="arg">pegName</i> <b class="method">deserialize</b> <i class="arg">serialization</i></a></dt>
<dd><p>This is the complement to <b class="method">serialize</b>. It replaces the grammar

Changes to idoc/www/tcllib/files/modules/html/html.html.

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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">html(n) 1.4.4 tcllib &quot;HTML Generation&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>html - Procedures to generate HTML structures</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#see-also">See Also</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">html <span class="opt">?1.4.4?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::html::author</b> <i class="arg">author</i></a></li>
<li><a href="#2"><b class="cmd">::html::bodyTag</b> <i class="arg">args</i></a></li>
<li><a href="#3"><b class="cmd">::html::cell</b> <i class="arg">param value</i> <span class="opt">?<i class="arg">tag</i>?</span></a></li>
<li><a href="#4"><b class="cmd">::html::checkbox</b> <i class="arg">name value</i></a></li>
<li><a href="#5"><b class="cmd">::html::checkSet</b> <i class="arg">key sep list</i></a></li>







|


















|







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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">html(n) 1.5 tcllib &quot;HTML Generation&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>html - Procedures to generate HTML structures</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#see-also">See Also</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">html <span class="opt">?1.5?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::html::author</b> <i class="arg">author</i></a></li>
<li><a href="#2"><b class="cmd">::html::bodyTag</b> <i class="arg">args</i></a></li>
<li><a href="#3"><b class="cmd">::html::cell</b> <i class="arg">param value</i> <span class="opt">?<i class="arg">tag</i>?</span></a></li>
<li><a href="#4"><b class="cmd">::html::checkbox</b> <i class="arg">name value</i></a></li>
<li><a href="#5"><b class="cmd">::html::checkSet</b> <i class="arg">key sep list</i></a></li>
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
<li><a href="#28"><b class="cmd">::html::headTag</b> <i class="arg">string</i></a></li>
<li><a href="#29"><b class="cmd">::html::html_entities</b> <i class="arg">string</i></a></li>
<li><a href="#30"><b class="cmd">::html::if</b> <i class="arg">expr1 body1</i> <span class="opt">?<b class="const">elseif</b> <i class="arg">expr2 body2 ...</i>?</span> <span class="opt">?<b class="const">else</b> <i class="arg">bodyN</i>?</span></a></li>
<li><a href="#31"><b class="cmd">::html::init</b> <span class="opt">?<i class="arg">list</i>?</span></a></li>
<li><a href="#32"><b class="cmd">::html::keywords</b> <i class="arg">args</i></a></li>
<li><a href="#33"><b class="cmd">::html::mailto</b> <i class="arg">email</i> <span class="opt">?<i class="arg">subject</i>?</span></a></li>
<li><a href="#34"><b class="cmd">::html::meta</b> <i class="arg">args</i></a></li>
<li><a href="#35"><b class="cmd">::html::css</b> <i class="arg">href</i></a></li>
<li><a href="#36"><b class="cmd">::html::css-clear</b></a></li>
<li><a href="#37"><b class="cmd">::html::js</b> <i class="arg">href</i></a></li>
<li><a href="#38"><b class="cmd">::html::js-clear</b></a></li>



<li><a href="#39"><b class="cmd">::html::minorList</b> <i class="arg">list</i> <span class="opt">?<i class="arg">ordered</i>?</span></a></li>
<li><a href="#40"><b class="cmd">::html::minorMenu</b> <i class="arg">list</i> <span class="opt">?<i class="arg">sep</i>?</span></a></li>
<li><a href="#41"><b class="cmd">::html::nl2br</b> <i class="arg">string</i></a></li>
<li><a href="#42"><b class="cmd">::html::openTag</b> <i class="arg">tag</i> <span class="opt">?<i class="arg">param</i>?</span></a></li>
<li><a href="#43"><b class="cmd">::html::paramRow</b> <i class="arg">list</i> <span class="opt">?<i class="arg">rparam</i>?</span> <span class="opt">?<i class="arg">cparam</i>?</span></a></li>
<li><a href="#44"><b class="cmd">::html::passwordInput</b> <span class="opt">?<i class="arg">name</i>?</span></a></li>
<li><a href="#45"><b class="cmd">::html::passwordInputRow</b> <i class="arg">label</i> <span class="opt">?<i class="arg">name</i>?</span></a></li>
<li><a href="#46"><b class="cmd">::html::quoteFormValue</b> <i class="arg">value</i></a></li>
<li><a href="#47"><b class="cmd">::html::radioSet</b> <i class="arg">key sep list</i></a></li>
<li><a href="#48"><b class="cmd">::html::radioValue</b> <i class="arg">name value</i></a></li>
<li><a href="#49"><b class="cmd">::html::refresh</b> <i class="arg">seconds url</i></a></li>
<li><a href="#50"><b class="cmd">::html::row</b> <i class="arg">args</i></a></li>
<li><a href="#51"><b class="cmd">::html::select</b> <i class="arg">name param choices</i> <span class="opt">?<i class="arg">current</i>?</span></a></li>
<li><a href="#52"><b class="cmd">::html::selectPlain</b> <i class="arg">name param choices</i> <span class="opt">?<i class="arg">current</i>?</span></a></li>
<li><a href="#53"><b class="cmd">::html::set</b> <i class="arg">var val</i></a></li>
<li><a href="#54"><b class="cmd">::html::submit</b> <i class="arg">label</i> <span class="opt">?<i class="arg">name</i>?</span></a></li>
<li><a href="#55"><b class="cmd">::html::tableFromArray</b> <i class="arg">arrname</i> <span class="opt">?<i class="arg">param</i>?</span> <span class="opt">?<i class="arg">pat</i>?</span></a></li>
<li><a href="#56"><b class="cmd">::html::tableFromList</b> <i class="arg">querylist</i> <span class="opt">?<i class="arg">param</i>?</span></a></li>
<li><a href="#57"><b class="cmd">::html::textarea</b> <i class="arg">name</i> <span class="opt">?<i class="arg">param</i>?</span> <span class="opt">?<i class="arg">current</i>?</span></a></li>
<li><a href="#58"><b class="cmd">::html::textInput</b> <i class="arg">name value args</i></a></li>
<li><a href="#59"><b class="cmd">::html::textInputRow</b> <i class="arg">label name value args</i></a></li>
<li><a href="#60"><b class="cmd">::html::varEmpty</b> <i class="arg">name</i></a></li>
<li><a href="#61"><b class="cmd">::html::while</b> <i class="arg">test body</i></a></li>
<li><a href="#62"><b class="cmd">::html::doctype</b> <i class="arg">id</i></a></li>

</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>The package <b class="package">html</b> provides commands that generate HTML.
These commands typically return an HTML string as their result. In
particular, they do not output their result to <b class="const">stdout</b>.</p>







|
|
|
|
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>







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
<li><a href="#28"><b class="cmd">::html::headTag</b> <i class="arg">string</i></a></li>
<li><a href="#29"><b class="cmd">::html::html_entities</b> <i class="arg">string</i></a></li>
<li><a href="#30"><b class="cmd">::html::if</b> <i class="arg">expr1 body1</i> <span class="opt">?<b class="const">elseif</b> <i class="arg">expr2 body2 ...</i>?</span> <span class="opt">?<b class="const">else</b> <i class="arg">bodyN</i>?</span></a></li>
<li><a href="#31"><b class="cmd">::html::init</b> <span class="opt">?<i class="arg">list</i>?</span></a></li>
<li><a href="#32"><b class="cmd">::html::keywords</b> <i class="arg">args</i></a></li>
<li><a href="#33"><b class="cmd">::html::mailto</b> <i class="arg">email</i> <span class="opt">?<i class="arg">subject</i>?</span></a></li>
<li><a href="#34"><b class="cmd">::html::meta</b> <i class="arg">args</i></a></li>
<li><a href="#35"><b class="cmd">::html::meta_name</b> <i class="arg">args</i></a></li>
<li><a href="#36"><b class="cmd">::html::meta_equiv</b> <i class="arg">args</i></a></li>
<li><a href="#37"><b class="cmd">::html::meta_charset</b> <i class="arg">charset</i></a></li>
<li><a href="#38"><b class="cmd">::html::css</b> <i class="arg">href</i></a></li>
<li><a href="#39"><b class="cmd">::html::css-clear</b></a></li>
<li><a href="#40"><b class="cmd">::html::js</b> <i class="arg">href</i></a></li>
<li><a href="#41"><b class="cmd">::html::js-clear</b></a></li>
<li><a href="#42"><b class="cmd">::html::minorList</b> <i class="arg">list</i> <span class="opt">?<i class="arg">ordered</i>?</span></a></li>
<li><a href="#43"><b class="cmd">::html::minorMenu</b> <i class="arg">list</i> <span class="opt">?<i class="arg">sep</i>?</span></a></li>
<li><a href="#44"><b class="cmd">::html::nl2br</b> <i class="arg">string</i></a></li>
<li><a href="#45"><b class="cmd">::html::openTag</b> <i class="arg">tag</i> <span class="opt">?<i class="arg">param</i>?</span></a></li>
<li><a href="#46"><b class="cmd">::html::paramRow</b> <i class="arg">list</i> <span class="opt">?<i class="arg">rparam</i>?</span> <span class="opt">?<i class="arg">cparam</i>?</span></a></li>
<li><a href="#47"><b class="cmd">::html::passwordInput</b> <span class="opt">?<i class="arg">name</i>?</span></a></li>
<li><a href="#48"><b class="cmd">::html::passwordInputRow</b> <i class="arg">label</i> <span class="opt">?<i class="arg">name</i>?</span></a></li>
<li><a href="#49"><b class="cmd">::html::quoteFormValue</b> <i class="arg">value</i></a></li>
<li><a href="#50"><b class="cmd">::html::radioSet</b> <i class="arg">key sep list</i></a></li>
<li><a href="#51"><b class="cmd">::html::radioValue</b> <i class="arg">name value</i></a></li>
<li><a href="#52"><b class="cmd">::html::refresh</b> <i class="arg">seconds url</i></a></li>
<li><a href="#53"><b class="cmd">::html::row</b> <i class="arg">args</i></a></li>
<li><a href="#54"><b class="cmd">::html::select</b> <i class="arg">name param choices</i> <span class="opt">?<i class="arg">current</i>?</span></a></li>
<li><a href="#55"><b class="cmd">::html::selectPlain</b> <i class="arg">name param choices</i> <span class="opt">?<i class="arg">current</i>?</span></a></li>
<li><a href="#56"><b class="cmd">::html::set</b> <i class="arg">var val</i></a></li>
<li><a href="#57"><b class="cmd">::html::submit</b> <i class="arg">label</i> <span class="opt">?<i class="arg">name</i>?</span> <span class="opt">?<i class="arg">title</i>?</span></a></li>
<li><a href="#58"><b class="cmd">::html::tableFromArray</b> <i class="arg">arrname</i> <span class="opt">?<i class="arg">param</i>?</span> <span class="opt">?<i class="arg">pat</i>?</span></a></li>
<li><a href="#59"><b class="cmd">::html::tableFromList</b> <i class="arg">querylist</i> <span class="opt">?<i class="arg">param</i>?</span></a></li>
<li><a href="#60"><b class="cmd">::html::textarea</b> <i class="arg">name</i> <span class="opt">?<i class="arg">param</i>?</span> <span class="opt">?<i class="arg">current</i>?</span></a></li>
<li><a href="#61"><b class="cmd">::html::textInput</b> <i class="arg">name value args</i></a></li>
<li><a href="#62"><b class="cmd">::html::textInputRow</b> <i class="arg">label name value args</i></a></li>
<li><a href="#63"><b class="cmd">::html::varEmpty</b> <i class="arg">name</i></a></li>
<li><a href="#64"><b class="cmd">::html::while</b> <i class="arg">test body</i></a></li>
<li><a href="#65"><b class="cmd">::html::doctype</b> <i class="arg">id</i></a></li>
<li><a href="#66"><b class="cmd">::html::wrapTag</b> <i class="arg">tag</i> <span class="opt">?<i class="arg">text</i>?</span> <span class="opt">?<i class="arg">args</i>?</span></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>The package <b class="package">html</b> provides commands that generate HTML.
These commands typically return an HTML string as their result. In
particular, they do not output their result to <b class="const">stdout</b>.</p>
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
<dt><a name="32"><b class="cmd">::html::keywords</b> <i class="arg">args</i></a></dt>
<dd><p><em>Side effect only</em>.  Call this before <b class="cmd">::html::head</b> to
define a keyword <i class="term">meta</i> tag for the page.  The <i class="term">meta</i> tag
is included in the result of <b class="cmd">::html::head</b>.</p></dd>
<dt><a name="33"><b class="cmd">::html::mailto</b> <i class="arg">email</i> <span class="opt">?<i class="arg">subject</i>?</span></a></dt>
<dd><p>Generate a hypertext link to a mailto: URL.</p></dd>
<dt><a name="34"><b class="cmd">::html::meta</b> <i class="arg">args</i></a></dt>


<dd><p><em>Side effect only</em>.  Call this before <b class="cmd">::html::head</b> to

















define a <i class="term">meta</i> tag for the page.  The <i class="arg">args</i> is a Tcl-style name,
value list that is used for the name= and value= parameters for the

<i class="term">meta</i> tag.  The <i class="term">meta</i> tag is included in the result of
<b class="cmd">::html::head</b>.</p></dd>
<dt><a name="35"><b class="cmd">::html::css</b> <i class="arg">href</i></a></dt>
<dd><p><em>Side effect only</em>.  Call this before <b class="cmd">::html::head</b> to
define a <i class="term">link</i> tag for a linked CSS document.  The <i class="arg">href</i> 
value is a HTTP URL to a CSS document. The <i class="term">link</i> tag is included 
in the result of <b class="cmd">::html::head</b>.</p>
<p>Multiple calls of this command are allowed, enabling the use of
multiple CSS document references. In other words, the arguments
of multiple calls are accumulated, and do not overwrite each other.</p></dd>
<dt><a name="36"><b class="cmd">::html::css-clear</b></a></dt>
<dd><p><em>Side effect only</em>.  Call this before <b class="cmd">::html::head</b> to
clear all links to CSS documents.</p>
<p>Multiple calls of this command are allowed, doing nothing after the
first of a sequence with no intervening <b class="cmd">::html::css</b>.</p></dd>
<dt><a name="37"><b class="cmd">::html::js</b> <i class="arg">href</i></a></dt>
<dd><p><em>Side effect only</em>.  Call this before <b class="cmd">::html::head</b> to
define a <i class="term">script</i> tag for a linked JavaScript document.  The 
<i class="arg">href</i> is a HTTP URL to a JavaScript document. The <i class="term">script</i>
tag is included in the result of <b class="cmd">::html::head</b>.</p>
<p>Multiple calls of this command are allowed, enabling the use of
multiple JavaScript document references. In other words, the arguments
of multiple calls are accumulated, and do not overwrite each other.</p></dd>
<dt><a name="38"><b class="cmd">::html::js-clear</b></a></dt>
<dd><p><em>Side effect only</em>.  Call this before <b class="cmd">::html::head</b> to
clear all links to JavaScript documents.</p>
<p>Multiple calls of this command are allowed, doing nothing after the
first of a sequence with no intervening <b class="cmd">::html::js</b>.</p></dd>
<dt><a name="39"><b class="cmd">::html::minorList</b> <i class="arg">list</i> <span class="opt">?<i class="arg">ordered</i>?</span></a></dt>
<dd><p>Generate an ordered or unordered list of links.  The <i class="arg">list</i> is a
Tcl-style name, value list of labels and urls for the links.
<i class="arg">ordered</i> is a boolean used to choose between an ordered or
unordered list. It defaults to <b class="const">false</b>.</p></dd>
<dt><a name="40"><b class="cmd">::html::minorMenu</b> <i class="arg">list</i> <span class="opt">?<i class="arg">sep</i>?</span></a></dt>
<dd><p>Generate a series of hypertext links.  The <i class="arg">list</i> is a Tcl-style
name, value list of labels and urls for the links.  The <i class="arg">sep</i> is
the text to put between each link. It defaults to &quot; | &quot;.</p></dd>
<dt><a name="41"><b class="cmd">::html::nl2br</b> <i class="arg">string</i></a></dt>
<dd><p>This command replaces all line-endings in the <i class="arg">string</i> with a
<i class="term">br</i> tag and returns the modified text.</p></dd>
<dt><a name="42"><b class="cmd">::html::openTag</b> <i class="arg">tag</i> <span class="opt">?<i class="arg">param</i>?</span></a></dt>
<dd><p>Push <i class="arg">tag</i> onto a stack and generate the opening tag for
<i class="arg">tag</i>. Use <b class="cmd">::html::closeTag</b> to pop the tag from the
stack. The second argument provides any tag arguments, as a
list whose elements are formatted to be in the form
&quot;<b class="variable">key</b>=<b class="const">value</b>&quot;.</p></dd>
<dt><a name="43"><b class="cmd">::html::paramRow</b> <i class="arg">list</i> <span class="opt">?<i class="arg">rparam</i>?</span> <span class="opt">?<i class="arg">cparam</i>?</span></a></dt>
<dd><p>Generate a table row, including <i class="term">tr</i> and <i class="term">td</i> tags. Each value in
<i class="arg">list</i> is placed into its own table cell. This uses
<b class="cmd">::html::cell</b>. The value of <i class="arg">rparam</i> is used as parameter for
the <i class="term">tr</i> tag. The value of <i class="arg">cparam</i> is passed to <b class="cmd">::html::cell</b>
as parameter for the <i class="term">td</i> tags.</p></dd>
<dt><a name="44"><b class="cmd">::html::passwordInput</b> <span class="opt">?<i class="arg">name</i>?</span></a></dt>
<dd><p>Generate an <i class="term">input</i> tag of type <i class="term"><a href="../../../../index.html#password">password</a></i>. The <i class="arg">name</i> defaults to
&quot;password&quot;.</p></dd>
<dt><a name="45"><b class="cmd">::html::passwordInputRow</b> <i class="arg">label</i> <span class="opt">?<i class="arg">name</i>?</span></a></dt>
<dd><p>Format a table row containing a label and an <i class="term">input</i> tag of type
<i class="term"><a href="../../../../index.html#password">password</a></i>. The <i class="arg">name</i> defaults to &quot;password&quot;.</p></dd>
<dt><a name="46"><b class="cmd">::html::quoteFormValue</b> <i class="arg">value</i></a></dt>
<dd><p>Quote special characters in <i class="arg">value</i> by replacing them with HTML
entities for quotes, ampersand, and angle brackets.</p></dd>
<dt><a name="47"><b class="cmd">::html::radioSet</b> <i class="arg">key sep list</i></a></dt>
<dd><p>Generate a set of <i class="term">input</i> tags of type <i class="term">radio</i> and an associated text
label.  All the radio buttons share the same <i class="arg">key</i> for their name.
The <i class="arg">sep</i> is text used to separate the elements.  The <i class="arg">list</i>
is a Tcl-style label, value list.</p></dd>
<dt><a name="48"><b class="cmd">::html::radioValue</b> <i class="arg">name value</i></a></dt>
<dd><p>Generate the &quot;name=<i class="arg">name</i> value=<i class="arg">value</i>&quot; for a <i class="term">radio</i> form
element.  If the CGI variable <i class="arg">name</i> has the value <i class="arg">value</i>,
then SELECTED is added to the return value.</p></dd>
<dt><a name="49"><b class="cmd">::html::refresh</b> <i class="arg">seconds url</i></a></dt>
<dd><p>Set up a refresh <i class="term">meta</i> tag. Call this before <b class="cmd">::html::head</b> and the
HEAD section will contain a <i class="term">meta</i> tag that causes the document to
refresh in <i class="arg">seconds</i> seconds.  The <i class="arg">url</i> is optional.  If
specified, it specifies a new page to load after the refresh interval.</p></dd>
<dt><a name="50"><b class="cmd">::html::row</b> <i class="arg">args</i></a></dt>
<dd><p>Generate a table row, including <i class="term">tr</i> and <i class="term">td</i> tags.  Each value in
<i class="arg">args</i> is place into its own table cell. This uses
<b class="cmd">::html::cell</b>. Ignores any default information set up via
<b class="cmd">::html::init</b>.</p></dd>
<dt><a name="51"><b class="cmd">::html::select</b> <i class="arg">name param choices</i> <span class="opt">?<i class="arg">current</i>?</span></a></dt>
<dd><p>Generate a <i class="term">select</i> form element and nested <i class="term">option</i> tags. The <i class="arg">name</i>
and <i class="arg">param</i> are used to generate the <i class="term">select</i> tag. The <i class="arg">choices</i>
list is a Tcl-style name, value list.</p></dd>
<dt><a name="52"><b class="cmd">::html::selectPlain</b> <i class="arg">name param choices</i> <span class="opt">?<i class="arg">current</i>?</span></a></dt>
<dd><p>Like <b class="cmd">::html::select</b> except that <i class="arg">choices</i> is a Tcl list of
values used for the <i class="term">option</i> tags.  The label and the value for each
<i class="term">option</i> are the same.</p></dd>
<dt><a name="53"><b class="cmd">::html::set</b> <i class="arg">var val</i></a></dt>
<dd><p>This procedure is similar to the built-in Tcl <b class="cmd"><a href="../../../../index.html#set">set</a></b> command.  The
main difference is that it returns &quot;&quot; so it can be called from an HTML
template file without appending unwanted results.  The other
difference is that it must take two arguments.</p></dd>
<dt><a name="54"><b class="cmd">::html::submit</b> <i class="arg">label</i> <span class="opt">?<i class="arg">name</i>?</span></a></dt>
<dd><p>Generate an <i class="term">input</i> tag of type <i class="term">submit</i>. <i class="arg">name</i> defaults to &quot;submit&quot;.</p></dd>



<dt><a name="55"><b class="cmd">::html::tableFromArray</b> <i class="arg">arrname</i> <span class="opt">?<i class="arg">param</i>?</span> <span class="opt">?<i class="arg">pat</i>?</span></a></dt>
<dd><p>Generate a two-column <i class="term"><a href="../../../../index.html#table">table</a></i> and nested rows to display a Tcl array. The
table gets a heading that matches the array name, and each generated row
contains a name, value pair. The array names are sorted (<b class="cmd">lsort</b> without
special options). The argument <i class="arg">param</i> is for the <i class="term"><a href="../../../../index.html#table">table</a></i> tag and has
to contain a pre-formatted string. The <i class="arg">pat</i> is a <b class="cmd">string match</b>
pattern used to select the array elements to show in the table. It defaults to
<b class="const">*</b>, i.e. the whole array is shown.</p></dd>
<dt><a name="56"><b class="cmd">::html::tableFromList</b> <i class="arg">querylist</i> <span class="opt">?<i class="arg">param</i>?</span></a></dt>
<dd><p>Generate a two-column <i class="term"><a href="../../../../index.html#table">table</a></i> and nested rows to display <i class="arg">querylist</i>,
which is a Tcl dictionary. Each generated row contains a name, value pair. The
information is shown in the same order as specified in the dictionary. The
argument <i class="arg">param</i> is for the <i class="term"><a href="../../../../index.html#table">table</a></i> tag  and has to contain a
pre-formatted string.</p></dd>
<dt><a name="57"><b class="cmd">::html::textarea</b> <i class="arg">name</i> <span class="opt">?<i class="arg">param</i>?</span> <span class="opt">?<i class="arg">current</i>?</span></a></dt>
<dd><p>Generate a <i class="term">textarea</i> tag wrapped around its current values.</p></dd>
<dt><a name="58"><b class="cmd">::html::textInput</b> <i class="arg">name value args</i></a></dt>
<dd><p>Generate an <i class="term">input</i> form tag with type <i class="term"><a href="../../../../index.html#text">text</a></i>.  This uses
<b class="cmd">::html::formValue</b>.  The args is any additional tag attributes
you want to put into the <i class="term">input</i> tag.</p></dd>
<dt><a name="59"><b class="cmd">::html::textInputRow</b> <i class="arg">label name value args</i></a></dt>
<dd><p>Generate an <i class="term">input</i> form tag with type <i class="term"><a href="../../../../index.html#text">text</a></i> formatted into a table row
with an associated label.  The args is any additional tag attributes
you want to put into the <i class="term">input</i> tag.</p></dd>
<dt><a name="60"><b class="cmd">::html::varEmpty</b> <i class="arg">name</i></a></dt>
<dd><p>This returns 1 if the named variable either does not exist or has the
empty string for its value.</p></dd>
<dt><a name="61"><b class="cmd">::html::while</b> <i class="arg">test body</i></a></dt>
<dd><p>This procedure is similar to the built-in Tcl <b class="cmd">while</b> control
structure.  Rather than evaluating the body, it returns the subst'ed
<i class="arg">body</i>.  Each iteration of the loop causes another string to be
concatenated to the result value.</p></dd>
<dt><a name="62"><b class="cmd">::html::doctype</b> <i class="arg">id</i></a></dt>
<dd><p>This procedure can be used to build the standard DOCTYPE
declaration string. It will return the standard declaration
string for the id, or throw an error if the id is not known.
The following id's are defined:</p>
<ol class="doctools_enumerated">
<li><p>HTML32</p></li>
<li><p>HTML40</p></li>
<li><p>HTML40T</p></li>
<li><p>HTML40F</p></li>
<li><p>HTML401</p></li>
<li><p>HTML401T</p></li>
<li><p>HTML401F</p></li>
<li><p>XHTML10S</p></li>
<li><p>XHTML10T</p></li>
<li><p>XHTML10F</p></li>
<li><p>XHTML11</p></li>
<li><p>XHTMLB</p></li>
</ol></dd>






</dl>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>html</em> of the
<a href="http://core.tcl.tk/tcllib/reportlist">Tcllib Trackers</a>.







>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
>


|







|




|







|




|




|



|


|





|





|


|


|


|




|



|




|




|



|



|




|
|
>
>
>
|







|





|

|



|



|


|




|


















>
>
>
>
>
>







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
<dt><a name="32"><b class="cmd">::html::keywords</b> <i class="arg">args</i></a></dt>
<dd><p><em>Side effect only</em>.  Call this before <b class="cmd">::html::head</b> to
define a keyword <i class="term">meta</i> tag for the page.  The <i class="term">meta</i> tag
is included in the result of <b class="cmd">::html::head</b>.</p></dd>
<dt><a name="33"><b class="cmd">::html::mailto</b> <i class="arg">email</i> <span class="opt">?<i class="arg">subject</i>?</span></a></dt>
<dd><p>Generate a hypertext link to a mailto: URL.</p></dd>
<dt><a name="34"><b class="cmd">::html::meta</b> <i class="arg">args</i></a></dt>
<dd><p>Compatibility name for <b class="cmd">html::meta_name</b>.</p></dd>
<dt><a name="35"><b class="cmd">::html::meta_name</b> <i class="arg">args</i></a></dt>
<dd><p><em>Side effect only</em>.
Call this before <b class="cmd">::html::head</b> to define a <i class="term">meta</i> tag for
the page.
The arguments (<i class="arg">args</i>) are a Tcl-style name, value list that is
used for the <b class="const">name=</b> and <b class="const">content=</b> attributes of the
<i class="term">meta</i> tag.  The <i class="term">meta</i> tag is included in the result of
<b class="cmd">::html::head</b>.</p></dd>
<dt><a name="36"><b class="cmd">::html::meta_equiv</b> <i class="arg">args</i></a></dt>
<dd><p><em>Side effect only</em>.
Call this before <b class="cmd">::html::head</b> to define a <i class="term">meta</i> tag for
the page.
The arguments (<i class="arg">args</i>) are a Tcl-style name, value list that is
used for the <b class="const">http-equiv=</b> and <b class="const">content=</b> attributes of
the <i class="term">meta</i> tag.  The <i class="term">meta</i> tag is included in the result of
<b class="cmd">::html::head</b>.</p></dd>
<dt><a name="37"><b class="cmd">::html::meta_charset</b> <i class="arg">charset</i></a></dt>
<dd><p><em>Side effect only</em>.
Call this before <b class="cmd">::html::head</b> to
define a <i class="term">meta</i> tag for the page.

The <i class="arg">charset</i> is used with the <b class="const">charset=</b> attribute of the
<i class="term">meta</i> tag.  The <i class="term">meta</i> tag is included in the result of
<b class="cmd">::html::head</b>.</p></dd>
<dt><a name="38"><b class="cmd">::html::css</b> <i class="arg">href</i></a></dt>
<dd><p><em>Side effect only</em>.  Call this before <b class="cmd">::html::head</b> to
define a <i class="term">link</i> tag for a linked CSS document.  The <i class="arg">href</i> 
value is a HTTP URL to a CSS document. The <i class="term">link</i> tag is included 
in the result of <b class="cmd">::html::head</b>.</p>
<p>Multiple calls of this command are allowed, enabling the use of
multiple CSS document references. In other words, the arguments
of multiple calls are accumulated, and do not overwrite each other.</p></dd>
<dt><a name="39"><b class="cmd">::html::css-clear</b></a></dt>
<dd><p><em>Side effect only</em>.  Call this before <b class="cmd">::html::head</b> to
clear all links to CSS documents.</p>
<p>Multiple calls of this command are allowed, doing nothing after the
first of a sequence with no intervening <b class="cmd">::html::css</b>.</p></dd>
<dt><a name="40"><b class="cmd">::html::js</b> <i class="arg">href</i></a></dt>
<dd><p><em>Side effect only</em>.  Call this before <b class="cmd">::html::head</b> to
define a <i class="term">script</i> tag for a linked JavaScript document.  The 
<i class="arg">href</i> is a HTTP URL to a JavaScript document. The <i class="term">script</i>
tag is included in the result of <b class="cmd">::html::head</b>.</p>
<p>Multiple calls of this command are allowed, enabling the use of
multiple JavaScript document references. In other words, the arguments
of multiple calls are accumulated, and do not overwrite each other.</p></dd>
<dt><a name="41"><b class="cmd">::html::js-clear</b></a></dt>
<dd><p><em>Side effect only</em>.  Call this before <b class="cmd">::html::head</b> to
clear all links to JavaScript documents.</p>
<p>Multiple calls of this command are allowed, doing nothing after the
first of a sequence with no intervening <b class="cmd">::html::js</b>.</p></dd>
<dt><a name="42"><b class="cmd">::html::minorList</b> <i class="arg">list</i> <span class="opt">?<i class="arg">ordered</i>?</span></a></dt>
<dd><p>Generate an ordered or unordered list of links.  The <i class="arg">list</i> is a
Tcl-style name, value list of labels and urls for the links.
<i class="arg">ordered</i> is a boolean used to choose between an ordered or
unordered list. It defaults to <b class="const">false</b>.</p></dd>
<dt><a name="43"><b class="cmd">::html::minorMenu</b> <i class="arg">list</i> <span class="opt">?<i class="arg">sep</i>?</span></a></dt>
<dd><p>Generate a series of hypertext links.  The <i class="arg">list</i> is a Tcl-style
name, value list of labels and urls for the links.  The <i class="arg">sep</i> is
the text to put between each link. It defaults to &quot; | &quot;.</p></dd>
<dt><a name="44"><b class="cmd">::html::nl2br</b> <i class="arg">string</i></a></dt>
<dd><p>This command replaces all line-endings in the <i class="arg">string</i> with a
<i class="term">br</i> tag and returns the modified text.</p></dd>
<dt><a name="45"><b class="cmd">::html::openTag</b> <i class="arg">tag</i> <span class="opt">?<i class="arg">param</i>?</span></a></dt>
<dd><p>Push <i class="arg">tag</i> onto a stack and generate the opening tag for
<i class="arg">tag</i>. Use <b class="cmd">::html::closeTag</b> to pop the tag from the
stack. The second argument provides any tag arguments, as a
list whose elements are formatted to be in the form
&quot;<b class="variable">key</b>=<b class="const">value</b>&quot;.</p></dd>
<dt><a name="46"><b class="cmd">::html::paramRow</b> <i class="arg">list</i> <span class="opt">?<i class="arg">rparam</i>?</span> <span class="opt">?<i class="arg">cparam</i>?</span></a></dt>
<dd><p>Generate a table row, including <i class="term">tr</i> and <i class="term">td</i> tags. Each value in
<i class="arg">list</i> is placed into its own table cell. This uses
<b class="cmd">::html::cell</b>. The value of <i class="arg">rparam</i> is used as parameter for
the <i class="term">tr</i> tag. The value of <i class="arg">cparam</i> is passed to <b class="cmd">::html::cell</b>
as parameter for the <i class="term">td</i> tags.</p></dd>
<dt><a name="47"><b class="cmd">::html::passwordInput</b> <span class="opt">?<i class="arg">name</i>?</span></a></dt>
<dd><p>Generate an <i class="term">input</i> tag of type <i class="term"><a href="../../../../index.html#password">password</a></i>. The <i class="arg">name</i> defaults to
&quot;password&quot;.</p></dd>
<dt><a name="48"><b class="cmd">::html::passwordInputRow</b> <i class="arg">label</i> <span class="opt">?<i class="arg">name</i>?</span></a></dt>
<dd><p>Format a table row containing a label and an <i class="term">input</i> tag of type
<i class="term"><a href="../../../../index.html#password">password</a></i>. The <i class="arg">name</i> defaults to &quot;password&quot;.</p></dd>
<dt><a name="49"><b class="cmd">::html::quoteFormValue</b> <i class="arg">value</i></a></dt>
<dd><p>Quote special characters in <i class="arg">value</i> by replacing them with HTML
entities for quotes, ampersand, and angle brackets.</p></dd>
<dt><a name="50"><b class="cmd">::html::radioSet</b> <i class="arg">key sep list</i></a></dt>
<dd><p>Generate a set of <i class="term">input</i> tags of type <i class="term">radio</i> and an associated text
label.  All the radio buttons share the same <i class="arg">key</i> for their name.
The <i class="arg">sep</i> is text used to separate the elements.  The <i class="arg">list</i>
is a Tcl-style label, value list.</p></dd>
<dt><a name="51"><b class="cmd">::html::radioValue</b> <i class="arg">name value</i></a></dt>
<dd><p>Generate the &quot;name=<i class="arg">name</i> value=<i class="arg">value</i>&quot; for a <i class="term">radio</i> form
element.  If the CGI variable <i class="arg">name</i> has the value <i class="arg">value</i>,
then SELECTED is added to the return value.</p></dd>
<dt><a name="52"><b class="cmd">::html::refresh</b> <i class="arg">seconds url</i></a></dt>
<dd><p>Set up a refresh <i class="term">meta</i> tag. Call this before <b class="cmd">::html::head</b> and the
HEAD section will contain a <i class="term">meta</i> tag that causes the document to
refresh in <i class="arg">seconds</i> seconds.  The <i class="arg">url</i> is optional.  If
specified, it specifies a new page to load after the refresh interval.</p></dd>
<dt><a name="53"><b class="cmd">::html::row</b> <i class="arg">args</i></a></dt>
<dd><p>Generate a table row, including <i class="term">tr</i> and <i class="term">td</i> tags.  Each value in
<i class="arg">args</i> is place into its own table cell. This uses
<b class="cmd">::html::cell</b>. Ignores any default information set up via
<b class="cmd">::html::init</b>.</p></dd>
<dt><a name="54"><b class="cmd">::html::select</b> <i class="arg">name param choices</i> <span class="opt">?<i class="arg">current</i>?</span></a></dt>
<dd><p>Generate a <i class="term">select</i> form element and nested <i class="term">option</i> tags. The <i class="arg">name</i>
and <i class="arg">param</i> are used to generate the <i class="term">select</i> tag. The <i class="arg">choices</i>
list is a Tcl-style name, value list.</p></dd>
<dt><a name="55"><b class="cmd">::html::selectPlain</b> <i class="arg">name param choices</i> <span class="opt">?<i class="arg">current</i>?</span></a></dt>
<dd><p>Like <b class="cmd">::html::select</b> except that <i class="arg">choices</i> is a Tcl list of
values used for the <i class="term">option</i> tags.  The label and the value for each
<i class="term">option</i> are the same.</p></dd>
<dt><a name="56"><b class="cmd">::html::set</b> <i class="arg">var val</i></a></dt>
<dd><p>This procedure is similar to the built-in Tcl <b class="cmd"><a href="../../../../index.html#set">set</a></b> command.  The
main difference is that it returns &quot;&quot; so it can be called from an HTML
template file without appending unwanted results.  The other
difference is that it must take two arguments.</p></dd>
<dt><a name="57"><b class="cmd">::html::submit</b> <i class="arg">label</i> <span class="opt">?<i class="arg">name</i>?</span> <span class="opt">?<i class="arg">title</i>?</span></a></dt>
<dd><p>Generate an <i class="term">input</i> tag of type <i class="term">submit</i>.
The <i class="arg">name</i> defaults to &quot;submit&quot;.
When a non-empty <i class="arg">title</i> string is specified the button gains a
<b class="const">title=</b> attribute with that value.</p></dd>
<dt><a name="58"><b class="cmd">::html::tableFromArray</b> <i class="arg">arrname</i> <span class="opt">?<i class="arg">param</i>?</span> <span class="opt">?<i class="arg">pat</i>?</span></a></dt>
<dd><p>Generate a two-column <i class="term"><a href="../../../../index.html#table">table</a></i> and nested rows to display a Tcl array. The
table gets a heading that matches the array name, and each generated row
contains a name, value pair. The array names are sorted (<b class="cmd">lsort</b> without
special options). The argument <i class="arg">param</i> is for the <i class="term"><a href="../../../../index.html#table">table</a></i> tag and has
to contain a pre-formatted string. The <i class="arg">pat</i> is a <b class="cmd">string match</b>
pattern used to select the array elements to show in the table. It defaults to
<b class="const">*</b>, i.e. the whole array is shown.</p></dd>
<dt><a name="59"><b class="cmd">::html::tableFromList</b> <i class="arg">querylist</i> <span class="opt">?<i class="arg">param</i>?</span></a></dt>
<dd><p>Generate a two-column <i class="term"><a href="../../../../index.html#table">table</a></i> and nested rows to display <i class="arg">querylist</i>,
which is a Tcl dictionary. Each generated row contains a name, value pair. The
information is shown in the same order as specified in the dictionary. The
argument <i class="arg">param</i> is for the <i class="term"><a href="../../../../index.html#table">table</a></i> tag  and has to contain a
pre-formatted string.</p></dd>
<dt><a name="60"><b class="cmd">::html::textarea</b> <i class="arg">name</i> <span class="opt">?<i class="arg">param</i>?</span> <span class="opt">?<i class="arg">current</i>?</span></a></dt>
<dd><p>Generate a <i class="term">textarea</i> tag wrapped around its current values.</p></dd>
<dt><a name="61"><b class="cmd">::html::textInput</b> <i class="arg">name value args</i></a></dt>
<dd><p>Generate an <i class="term">input</i> form tag with type <i class="term"><a href="../../../../index.html#text">text</a></i>.  This uses
<b class="cmd">::html::formValue</b>.  The args is any additional tag attributes
you want to put into the <i class="term">input</i> tag.</p></dd>
<dt><a name="62"><b class="cmd">::html::textInputRow</b> <i class="arg">label name value args</i></a></dt>
<dd><p>Generate an <i class="term">input</i> form tag with type <i class="term"><a href="../../../../index.html#text">text</a></i> formatted into a table row
with an associated label.  The args is any additional tag attributes
you want to put into the <i class="term">input</i> tag.</p></dd>
<dt><a name="63"><b class="cmd">::html::varEmpty</b> <i class="arg">name</i></a></dt>
<dd><p>This returns 1 if the named variable either does not exist or has the
empty string for its value.</p></dd>
<dt><a name="64"><b class="cmd">::html::while</b> <i class="arg">test body</i></a></dt>
<dd><p>This procedure is similar to the built-in Tcl <b class="cmd">while</b> control
structure.  Rather than evaluating the body, it returns the subst'ed
<i class="arg">body</i>.  Each iteration of the loop causes another string to be
concatenated to the result value.</p></dd>
<dt><a name="65"><b class="cmd">::html::doctype</b> <i class="arg">id</i></a></dt>
<dd><p>This procedure can be used to build the standard DOCTYPE
declaration string. It will return the standard declaration
string for the id, or throw an error if the id is not known.
The following id's are defined:</p>
<ol class="doctools_enumerated">
<li><p>HTML32</p></li>
<li><p>HTML40</p></li>
<li><p>HTML40T</p></li>
<li><p>HTML40F</p></li>
<li><p>HTML401</p></li>
<li><p>HTML401T</p></li>
<li><p>HTML401F</p></li>
<li><p>XHTML10S</p></li>
<li><p>XHTML10T</p></li>
<li><p>XHTML10F</p></li>
<li><p>XHTML11</p></li>
<li><p>XHTMLB</p></li>
</ol></dd>
<dt><a name="66"><b class="cmd">::html::wrapTag</b> <i class="arg">tag</i> <span class="opt">?<i class="arg">text</i>?</span> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>A helper to wrap a <i class="arg">text</i> in a pair of open/close <i class="arg">tag</i>s.
The arguments (<i class="arg">args</i>) are a Tcl-style name, value list that is
used to provide attributes and associated values to the opening tag.
The result is a string with the open <i class="arg">tag</i> along with the optional
attributes, the optional text, and the closed tag.</p></dd>
</dl>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>html</em> of the
<a href="http://core.tcl.tk/tcllib/reportlist">Tcllib Trackers</a>.

Changes to idoc/www/tcllib/files/modules/httpd/httpd.html.

1
2
3
4
5
6
7
8
9
<!DOCTYPE html><html><head>
<title>tool - Tcl Web Server</title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;

|







1
2
3
4
5
6
7
8
9
<!DOCTYPE html><html><head>
<title>httpd - Tcl Web Server</title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
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
    }
--></style>
</head>
<!-- Generated from file 'httpd.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2018 Sean Woods &amp;lt;[email protected]&amp;gt;
   -->
<!-- tool.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">tool(n) 4.1.1 tcllib &quot;Tcl Web Server&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>tool - A TclOO and coroutine based web server</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Minimal Example</a></li>
<li class="doctools_section"><a href="#section3">Class ::httpd::server</a></li>

<li class="doctools_section"><a href="#section4">Class ::httpd::reply</a></li>
<li class="doctools_section"><a href="#section5">Reply Method Ensembles</a></li>
<li class="doctools_section"><a href="#section6">Reply Method Ensemble: http_info</a></li>
<li class="doctools_section"><a href="#section7">Reply Method Ensemble: request</a></li>
<li class="doctools_section"><a href="#section8">Reply Method Ensemble: reply</a></li>
<li class="doctools_section"><a href="#section9">Reply Methods</a></li>
<li class="doctools_section"><a href="#section10">Class ::httpd::content</a></li>
<li class="doctools_section"><a href="#section11">Class ::httpd::content.cgi</a></li>
<li class="doctools_section"><a href="#section12">Class ::httpd::content.file</a></li>
<li class="doctools_section"><a href="#section13">Class ::httpd::content.proxy</a></li>


<li class="doctools_section"><a href="#section14">Class ::httpd::content.scgi</a></li>

<li class="doctools_section"><a href="#section15">Class ::httpd::content.websocket</a></li>
<li class="doctools_section"><a href="#section16">SCGI Server Functions</a></li>
<li class="doctools_section"><a href="#section17">Class ::httpd::reply.scgi</a></li>
<li class="doctools_section"><a href="#section18">Class ::httpd::server.scgi</a></li>



<li class="doctools_section"><a href="#section19">AUTHORS</a></li>
<li class="doctools_section"><a href="#section20">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.6</b></li>
<li>package require <b class="pkgname">httpd <span class="opt">?4.1.1?</span></b></li>
<li>package require <b class="pkgname">sha1</b></li>
<li>package require <b class="pkgname">dicttool</b></li>
<li>package require <b class="pkgname">oo::meta</b></li>
<li>package require <b class="pkgname">oo::dialect</b></li>
<li>package require <b class="pkgname">tool</b></li>
<li>package require <b class="pkgname">coroutine</b></li>
<li>package require <b class="pkgname">fileutil</b></li>
<li>package require <b class="pkgname">fileutil::magic::filetype</b></li>
<li>package require <b class="pkgname">websocket</b></li>
<li>package require <b class="pkgname">mime</b></li>
<li>package require <b class="pkgname">cron</b></li>
<li>package require <b class="pkgname">uri</b></li>
<li>package require <b class="pkgname">Markdown</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1">constructor ?port <span class="opt">?port?</span>? ?myaddr <span class="opt">?ipaddr?</span>|all? ?server_string <span class="opt">?string?</span>? ?server_name <span class="opt">?string?</span>?</a></li>
<li><a href="#2">method <b class="cmd">add_uri</b> <i class="arg">pattern</i> <i class="arg">dict</i></a></li>
<li><a href="#3">method <b class="cmd">connect</b> <i class="arg">sock</i> <i class="arg">ip</i> <i class="arg">port</i></a></li>
<li><a href="#4">method <b class="cmd">Connect</b> <i class="arg">uuid</i> <i class="arg">sock</i> <i class="arg">ip</i></a></li>
<li><a href="#5">method <b class="cmd"><a href="../counter/counter.html">counter</a></b> <i class="arg">which</i></a></li>
<li><a href="#6">method <b class="cmd">CheckTimeout</b></a></li>
<li><a href="#7">method <b class="cmd">dispatch</b> <i class="arg">header_dict</i></a></li>
<li><a href="#8">method <b class="cmd"><a href="../log/log.html">log</a></b> <i class="arg">args</i></a></li>
<li><a href="#9">method <b class="cmd">port_listening</b></a></li>
<li><a href="#10">method <b class="cmd">PrefixNormalize</b> <i class="arg">prefix</i></a></li>
<li><a href="#11">method <b class="cmd">start</b></a></li>
<li><a href="#12">method <b class="cmd">stop</b></a></li>
<li><a href="#13">method <b class="cmd">template</b> <i class="arg">page</i></a></li>
<li><a href="#14">method <b class="cmd">TemplateSearch</b> <i class="arg">page</i></a></li>
<li><a href="#15">method <b class="cmd">Validate_Connection</b> <i class="arg">sock</i> <i class="arg">ip</i></a></li>
<li><a href="#16">method <b class="cmd">ENSEMBLE::add</b> <i class="arg">field</i> <i class="arg">element</i></a></li>
<li><a href="#17">method <b class="cmd">ENSEMBLE::dump</b></a></li>
<li><a href="#18">method <b class="cmd">ENSEMBLE::get</b> <i class="arg">field</i></a></li>
<li><a href="#19">method <b class="cmd">ENSEMBLE::reset</b></a></li>
<li><a href="#20">method <b class="cmd">ENSEMBLE::remove</b> <i class="arg">field</i> <i class="arg">element</i></a></li>
<li><a href="#21">method <b class="cmd">ENSEMBLE::replace</b> <i class="arg">keyvaluelist</i></a></li>
<li><a href="#22">method <b class="cmd">ENSEMBLE::reset</b></a></li>
<li><a href="#23">method <b class="cmd">ENSEMBLE::set</b> <i class="arg">field</i> <i class="arg">value</i></a></li>
<li><a href="#24">method <b class="cmd">http_info::netstring</b></a></li>
<li><a href="#25">method <b class="cmd">request::parse</b> <i class="arg">string</i></a></li>
<li><a href="#26">method <b class="cmd">reply::output</b></a></li>
<li><a href="#27">method <b class="cmd">close</b></a></li>
<li><a href="#28">method <b class="cmd">HttpHeaders</b> <i class="arg">sock</i> <i class="arg">?debug?</i></a></li>
<li><a href="#29">method <b class="cmd">dispatch</b> <i class="arg">newsock</i> <i class="arg">datastate</i></a></li>
<li><a href="#30">method <b class="cmd"><a href="../../../../index.html#error">error</a></b> <i class="arg">code</i> <i class="arg">?message?</i> <i class="arg">?errorInfo?</i></a></li>
<li><a href="#31">method <b class="cmd">content</b></a></li>
<li><a href="#32">method <b class="cmd">EncodeStatus</b> <i class="arg">status</i></a></li>
<li><a href="#33">method FormData</a></li>
<li><a href="#34">method MimeParse <i class="arg">mimetext</i></a></li>
<li><a href="#35">method <b class="cmd">DoOutput</b></a></li>
<li><a href="#36">method PostData <i class="arg">length</i></a></li>
<li><a href="#37">method <b class="cmd">puts</b> <i class="arg">string</i></a></li>
<li><a href="#38">method <b class="cmd">reset</b></a></li>
<li><a href="#39">method <b class="cmd">timeOutCheck</b></a></li>
<li><a href="#40">method <b class="cmd"><a href="../../../../index.html#timestamp">timestamp</a></b></a></li>








<li><a href="#41">method <b class="cmd">TransferComplete</b> <i class="arg">args</i></a></li>


<li><a href="#42">method <b class="cmd">Url_Decode</b> <i class="arg">string</i></a></li>
<li><a href="#43">method cgi_info</a></li>





<li><a href="#44">option <b class="cmd">path</b></a></li>

<li><a href="#45">option <b class="cmd"><a href="../../../../index.html#prefix">prefix</a></b></a></li>
<li><a href="#46">method proxy_info</a></li>
<li><a href="#47">method scgi_info</a></li>











































</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>This module implements a web server, suitable for embedding in an
application. The server is object oriented, and contains all of the
fundamentals needed for a full service website.</p>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">Minimal Example</a></h2>
<p>Starting a web service requires starting a class of type
<b class="cmd">httpd::server</b>, and providing that server with one or more URIs
to service, and <b class="cmd">httpd::reply</b> derived classes to generate them.</p>
<pre class="doctools_example">
tool::define ::reply.hello {
  method content {} {
    my puts &quot;&lt;HTML&gt;&lt;HEAD&gt;&lt;TITLE&gt;IRM Dispatch Server&lt;/TITLE&gt;&lt;/HEAD&gt;&lt;BODY&gt;&quot;
    my puts &quot;&lt;h1&gt;Hello World!&lt;/h1&gt;&quot;
    my puts &lt;/BODY&gt;&lt;/HTML&gt;
  }
}
::docserver::server create HTTPD port 8015 myaddr 127.0.0.1

HTTPD add_uri /* [list mixin reply.hello]
</pre>














</div>
<div id="section3" class="doctools_section"><h2><a name="section3">Class ::httpd::server</a></h2>


<p>This class is the root object of the webserver. It is responsible
for opening the socket and providing the initial connection negotiation.</p>
<dl class="doctools_definitions">
<dt><a name="1">constructor ?port <span class="opt">?port?</span>? ?myaddr <span class="opt">?ipaddr?</span>|all? ?server_string <span class="opt">?string?</span>? ?server_name <span class="opt">?string?</span>?</a></dt>
<dd><p>Build a new server object. <span class="opt">?port?</span> is the port to listen on</p></dd>
<dt><a name="2">method <b class="cmd">add_uri</b> <i class="arg">pattern</i> <i class="arg">dict</i></a></dt>
<dd><p>Set the hander for a URI pattern. Information given in the <i class="arg">dict</i> is stored
in the data structure the <b class="cmd">dispatch</b> method uses. If a field called
<i class="arg">mixin</i> is given, that class will be mixed into the reply object immediately
after construction.</p></dd>
<dt><a name="3">method <b class="cmd">connect</b> <i class="arg">sock</i> <i class="arg">ip</i> <i class="arg">port</i></a></dt>
<dd><p>Reply to an open socket. This method builds a coroutine to manage the remainder
of the connection. The coroutine's operations are driven by the <b class="cmd">Connect</b> method.</p></dd>
<dt><a name="4">method <b class="cmd">Connect</b> <i class="arg">uuid</i> <i class="arg">sock</i> <i class="arg">ip</i></a></dt>
<dd><p>This method reads HTTP headers, and then consults the <b class="cmd">dispatch</b> method to
determine if the request is valid, and/or what kind of reply to generate. Under
normal cases, an object of class <b class="cmd">::http::reply</b> is created.
Fields the server are looking for in particular are:
class: A class to use instead of the server's own <i class="arg">reply_class</i>
mixin: A class to be mixed into the new object after construction.
All other fields are passed along to the <b class="cmd">http_info</b> structure of the
reply object.
After the class is created and the mixin is mixed in, the server invokes the
reply objects <b class="cmd">dispatch</b> method. This action passes control of the socket to
the reply object. The reply object manages the rest of the transaction, including
closing the socket.</p></dd>
<dt><a name="5">method <b class="cmd"><a href="../counter/counter.html">counter</a></b> <i class="arg">which</i></a></dt>
<dd><p>Increment an internal counter.</p></dd>
<dt><a name="6">method <b class="cmd">CheckTimeout</b></a></dt>
<dd><p>Check open connections for a time out event.</p></dd>
<dt><a name="7">method <b class="cmd">dispatch</b> <i class="arg">header_dict</i></a></dt>
<dd><p>Given a key/value list of information, return a data structure describing how

the server should reply.</p></dd>
<dt><a name="8">method <b class="cmd"><a href="../log/log.html">log</a></b> <i class="arg">args</i></a></dt>
<dd><p>Log an event. The input for args is free form. This method is intended


to be replaced by the user, and is a noop for a stock http::server object.</p></dd>
<dt><a name="9">method <b class="cmd">port_listening</b></a></dt>
<dd><p>Return the actual port that httpd is listening on.</p></dd>
<dt><a name="10">method <b class="cmd">PrefixNormalize</b> <i class="arg">prefix</i></a></dt>
<dd><p>For the stock version, trim trailing /'s and *'s from a prefix. This
method can be replaced by the end user to perform any other transformations
needed for the application.</p></dd>
<dt><a name="11">method <b class="cmd">start</b></a></dt>
<dd><p>Open the socket listener.</p></dd>
<dt><a name="12">method <b class="cmd">stop</b></a></dt>
<dd><p>Shut off the socket listener, and destroy any pending replies.</p></dd>
<dt><a name="13">method <b class="cmd">template</b> <i class="arg">page</i></a></dt>
<dd><p>Return a template for the string <i class="arg">page</i></p></dd>
<dt><a name="14">method <b class="cmd">TemplateSearch</b> <i class="arg">page</i></a></dt>
<dd><p>Perform a search for the template that best matches <i class="arg">page</i>. This
can include local file searches, in-memory structures, or even
database lookups. The stock implementation simply looks for files
with a .tml or .html extension in the <span class="opt">?doc_root?</span> directory.</p></dd>
<dt><a name="15">method <b class="cmd">Validate_Connection</b> <i class="arg">sock</i> <i class="arg">ip</i></a></dt>
<dd><p>Given a socket and an ip address, return true if this connection should
be terminated, or false if it should be allowed to continue. The stock
implementation always returns 0. This is intended for applications to
be able to implement black lists and/or provide security based on IP
address.</p></dd>
</dl>
</div>
<div id="section4" class="doctools_section"><h2><a name="section4">Class ::httpd::reply</a></h2>

<p>A class which shephards a request through the process of generating a
reply.
The socket associated with the reply is available at all times as the <i class="arg">chan</i>
variable.
The process of generating a reply begins with an <b class="cmd">httpd::server</b> generating a
<b class="cmd">http::class</b> object, mixing in a set of behaviors and then invoking the reply
object's <b class="cmd">dispatch</b> method.
In normal operations the <b class="cmd">dispatch</b> method:</p>
<ol class="doctools_enumerated">

<li><p>Invokes the <b class="cmd">reset</b> method for the object to populate default headers.</p></li>
<li><p>Invokes the <b class="cmd">HttpHeaders</b> method to stream the MIME headers out of the socket</p></li>
<li><p>Invokes the <b class="cmd">request parse</b> method to convert the stream of MIME headers into a
dict that can be read via the <b class="cmd">request</b> method.</p></li>
<li><p>Stores the raw stream of MIME headers in the <i class="arg">rawrequest</i> variable of the object.</p></li>
<li><p>Invokes the <b class="cmd">content</b> method for the object, generating an call to the <b class="cmd"><a href="../../../../index.html#error">error</a></b>
method if an exception is raised.</p></li>
<li><p>Invokes the <b class="cmd">output</b> method for the object</p></li>
</ol>
</div>
<div id="section5" class="doctools_section"><h2><a name="section5">Reply Method Ensembles</a></h2>
<p>The <b class="cmd">http::reply</b> class and its derivatives maintain several variables as dictionaries
internally. Access to these dictionaries is managed through a dedicated ensemble. The
ensemble implements most of the same behaviors as the <b class="cmd"><a href="../../../../index.html#dict">dict</a></b> command.
Each ensemble implements the following methods above, beyond, or modifying standard dicts:</p>
<dl class="doctools_definitions">
<dt><a name="16">method <b class="cmd">ENSEMBLE::add</b> <i class="arg">field</i> <i class="arg">element</i></a></dt>
<dd><p>Add <i class="arg">element</i> to a list stored in <i class="arg">field</i>, but only if it is not already present om the list.</p></dd>
<dt><a name="17">method <b class="cmd">ENSEMBLE::dump</b></a></dt>
<dd><p>Return the current contents of the data structure as a key/value list.</p></dd>
<dt><a name="18">method <b class="cmd">ENSEMBLE::get</b> <i class="arg">field</i></a></dt>
<dd><p>Return the value of the field <i class="arg">field</i>, or an empty string if it does not exist.</p></dd>
<dt><a name="19">method <b class="cmd">ENSEMBLE::reset</b></a></dt>
<dd><p>Return a key/value list of the default contents for this data structure.</p></dd>
<dt><a name="20">method <b class="cmd">ENSEMBLE::remove</b> <i class="arg">field</i> <i class="arg">element</i></a></dt>
<dd><p>Remove all instances of <i class="arg">element</i> from the list stored in <i class="arg">field</i>.</p></dd>
<dt><a name="21">method <b class="cmd">ENSEMBLE::replace</b> <i class="arg">keyvaluelist</i></a></dt>
<dd><p>Replace the internal dict with the contents of <i class="arg">keyvaluelist</i></p></dd>
<dt><a name="22">method <b class="cmd">ENSEMBLE::reset</b></a></dt>
<dd><p>Replace the internal dict with the default state.</p></dd>
<dt><a name="23">method <b class="cmd">ENSEMBLE::set</b> <i class="arg">field</i> <i class="arg">value</i></a></dt>
<dd><p>Set the value of <i class="arg">field</i> to <i class="arg">value</i>.</p></dd>
</dl>
</div>
<div id="section6" class="doctools_section"><h2><a name="section6">Reply Method Ensemble: http_info</a></h2>
<p>Manages HTTP headers passed in by the server.
Ensemble Methods:</p>
<dl class="doctools_definitions">
<dt><a name="24">method <b class="cmd">http_info::netstring</b></a></dt>
<dd><p>Return the contents of this data structure as a netstring encoded block.</p></dd>
</dl>
</div>
<div id="section7" class="doctools_section"><h2><a name="section7">Reply Method Ensemble: request</a></h2>
<p>Managed data from MIME headers of the request.</p>
<dl class="doctools_definitions">
<dt><a name="25">method <b class="cmd">request::parse</b> <i class="arg">string</i></a></dt>
<dd><p>Replace the contents of the data structure with information encoded in a MIME
formatted block of text (<i class="arg">string</i>).</p></dd>
</dl>
</div>
<div id="section8" class="doctools_section"><h2><a name="section8">Reply Method Ensemble: reply</a></h2>
<p>Manage the headers sent in the reply.</p>
<dl class="doctools_definitions">
<dt><a name="26">method <b class="cmd">reply::output</b></a></dt>
<dd><p>Return the contents of this data structure as a MIME encoded block appropriate
for an HTTP response.</p></dd>
</dl>
</div>
<div id="section9" class="doctools_section"><h2><a name="section9">Reply Methods</a></h2>
<dl class="doctools_definitions">
<dt><a name="27">method <b class="cmd">close</b></a></dt>
<dd><p>Terminate the transaction, and close the socket.</p></dd>
<dt><a name="28">method <b class="cmd">HttpHeaders</b> <i class="arg">sock</i> <i class="arg">?debug?</i></a></dt>
<dd><p>Stream MIME headers from the socket <i class="arg">sock</i>, stopping at an empty line. Returns
the stream as a block of text.</p></dd>
<dt><a name="29">method <b class="cmd">dispatch</b> <i class="arg">newsock</i> <i class="arg">datastate</i></a></dt>
<dd><p>Take over control of the socket <i class="arg">newsock</i>, and store that as the <i class="arg">chan</i> variable
for the object. This method runs through all of the steps of reading HTTP headers, generating
content, and closing the connection. (See class writetup).</p></dd>
<dt><a name="30">method <b class="cmd"><a href="../../../../index.html#error">error</a></b> <i class="arg">code</i> <i class="arg">?message?</i> <i class="arg">?errorInfo?</i></a></dt>
<dd><p>Generate an error message of the specified <i class="arg">code</i>, and display the <i class="arg">message</i> as the
reason for the exception. <i class="arg">errorInfo</i> is passed in from calls, but how or if it should be
displayed is a prerogative of the developer.</p></dd>
<dt><a name="31">method <b class="cmd">content</b></a></dt>
<dd><p>Generate the content for the reply. This method is intended to be replaced by the mixin.
Developers have the option of streaming output to a buffer via the <b class="cmd">puts</b> method of the
reply, or simply populating the <i class="arg">reply_body</i> variable of the object.
The information returned by the <b class="cmd">content</b> method is not interpreted in any way.
If an exception is thrown (via the <b class="cmd"><a href="../../../../index.html#error">error</a></b> command in Tcl, for example) the caller will
auto-generate a 500 {Internal Error} message.
A typical implementation of <b class="cmd">content</b> look like:</p>
<pre class="doctools_example">
tool::define ::test::content.file {
	superclass ::httpd::content.file
	# Return a file
	# Note: this is using the content.file mixin which looks for the reply_file variable
	# and will auto-compute the Content-Type
	method content {} {
	  my reset
    set doc_root [my http_info get doc_root]
    my variable reply_file
    set reply_file [file join $doc_root index.html]
	}
}
tool::define ::test::content.time {
  # return the current system time
	method content {} {
		my variable reply_body
    my reply set Content-Type text/plain
		set reply_body [clock seconds]
	}
}
tool::define ::test::content.echo {
	method content {} {
		my variable reply_body
    my reply set Content-Type [my request get CONTENT_TYPE]
		set reply_body [my PostData [my request get CONTENT_LENGTH]]
	}
}
tool::define ::test::content.form_handler {
	method content {} {
	  set form [my FormData]
	  my reply set Content-Type {text/html; charset=UTF-8}
    my puts [my html header {My Dynamic Page}]
    my puts &quot;&lt;BODY&gt;&quot;
    my puts &quot;You Sent&lt;p&gt;&quot;
    my puts &quot;&lt;TABLE&gt;&quot;
    foreach {f v} $form {
      my puts &quot;&lt;TR&gt;&lt;TH&gt;$f&lt;/TH&gt;&lt;TD&gt;&lt;verbatim&gt;$v&lt;/verbatim&gt;&lt;/TD&gt;&quot;
    }
    my puts &quot;&lt;/TABLE&gt;&lt;p&gt;&quot;
    my puts &quot;Send some info:&lt;p&gt;&quot;
    my puts &quot;&lt;FORM action=/[my http_info get REQUEST_PATH] method POST&gt;&quot;
    my puts &quot;&lt;TABLE&gt;&quot;
    foreach field {name rank serial_number} {
      set line &quot;&lt;TR&gt;&lt;TH&gt;$field&lt;/TH&gt;&lt;TD&gt;&lt;input name=\&quot;$field\&quot; &quot;
      if {[dict exists $form $field]} {
        append line &quot; value=\&quot;[dict get $form $field]\&quot;&quot;&quot;
      }
      append line &quot; /&gt;&lt;/TD&gt;&lt;/TR&gt;&quot;
      my puts $line
    }
    my puts &quot;&lt;/TABLE&gt;&quot;
    my puts [my html footer]
	}
}
</pre>



</dd>












































<dt><a name="32">method <b class="cmd">EncodeStatus</b> <i class="arg">status</i></a></dt>
<dd><p>Formulate a standard HTTP status header from he string provided.</p></dd>




<dt><a name="33">method FormData</a></dt>



<dd><p>For GET requests, converts the QUERY_DATA header into a key/value list.
For POST requests, reads the Post data and converts that information to
a key/value list for application/x-www-form-urlencoded posts. For multipart
posts, it composites all of the MIME headers of the post to a singular key/value
list, and provides MIME_* information as computed by the <b class="cmd"><a href="../mime/mime.html">mime</a></b> package, including
the MIME_TOKEN, which can be fed back into the mime package to read out the contents.</p></dd>
<dt><a name="34">method MimeParse <i class="arg">mimetext</i></a></dt>
<dd><p>Converts a block of mime encoded text to a key/value list. If an exception is encountered,
the method will generate its own call to the <b class="cmd"><a href="../../../../index.html#error">error</a></b> method, and immediately invoke
the <b class="cmd">output</b> method to produce an error code and close the connection.</p></dd>
<dt><a name="35">method <b class="cmd">DoOutput</b></a></dt>
<dd><p>Generates the the HTTP reply, and streams that reply back across <i class="arg">chan</i>.</p></dd>
<dt><a name="36">method PostData <i class="arg">length</i></a></dt>
<dd><p>Stream <i class="arg">length</i> bytes from the <i class="arg">chan</i> socket, but only of the request is a
POST or PUSH. Returns an empty string otherwise.</p></dd>


<dt><a name="37">method <b class="cmd">puts</b> <i class="arg">string</i></a></dt>
<dd><p>Appends the value of <i class="arg">string</i> to the end of <i class="arg">reply_body</i>, as well as a trailing newline
character.</p></dd>






<dt><a name="38">method <b class="cmd">reset</b></a></dt>
<dd><p>Clear the contents of the <i class="arg">reply_body</i> variable, and reset all headers in the <b class="cmd">reply</b>
structure back to the defaults for this object.</p></dd>
<dt><a name="39">method <b class="cmd">timeOutCheck</b></a></dt>
<dd><p>Called from the <b class="cmd">http::server</b> object which spawned this reply. Checks to see
if too much time has elapsed while waiting for data or generating a reply, and issues
a timeout error to the request if it has, as well as destroy the object and close the
<i class="arg">chan</i> socket.</p></dd>
<dt><a name="40">method <b class="cmd"><a href="../../../../index.html#timestamp">timestamp</a></b></a></dt>
<dd><p>Return the current system time in the format:</p>
<pre class="doctools_example">%a, %d %b %Y %T %Z</pre>
</dd>



<dt><a name="41">method <b class="cmd">TransferComplete</b> <i class="arg">args</i></a></dt>
<dd><p>Intended to be invoked from <b class="cmd">chan copy</b> as a callback. This closes every channel
fed to it on the command line, and then destroys the object.</p>
<pre class="doctools_example">
    ###
    # Output the body
    ###
    chan configure $sock -translation binary -blocking 0 -buffering full -buffersize 4096


    chan configure $chan -translation binary -blocking 0 -buffering full -buffersize 4096

    if {$length} {
      ###
      # Send any POST/PUT/etc content
      ###






      chan copy $sock $chan -size $SIZE -command [info coroutine]


      yield
    }




    catch {close $sock}
    chan flush $chan


</pre>





</dd>










































<dt><a name="42">method <b class="cmd">Url_Decode</b> <i class="arg">string</i></a></dt>
<dd><p>De-httpizes a string.</p></dd>



</dl>

</div>
<div id="section10" class="doctools_section"><h2><a name="section10">Class ::httpd::content</a></h2>




<p>The httpd module includes several ready to use implementations of content mixins

for common use cases. Options are passed in to the <b class="cmd">add_uri</b> method of the server.</p>

</div>
<div id="section11" class="doctools_section"><h2><a name="section11">Class ::httpd::content.cgi</a></h2>

<p>An implementation to relay requests to process which will accept post data
streamed in vie stdin, and sent a reply streamed to stdout.</p>
<dl class="doctools_definitions">



<dt><a name="43">method cgi_info</a></dt>

<dd><p>Mandatory method to be replaced by the end user. If needed, activates the
process to proxy, and then returns a list of three values:

<i class="arg">exec</i> - The arguments to send to exec to fire off the responding process, minus the stdin/stdout redirection.</p></dd>
</dl>
</div>






<div id="section12" class="doctools_section"><h2><a name="section12">Class ::httpd::content.file</a></h2>
<p>An implementation to deliver files from the local file system.</p>








<dl class="doctools_definitions">
<dt><a name="44">option <b class="cmd">path</b></a></dt>
<dd><p>The root directory on the local file system to be exposed via http.</p></dd>





<dt><a name="45">option <b class="cmd"><a href="../../../../index.html#prefix">prefix</a></b></a></dt>
<dd><p>The prefix of the URI portion to ignore when calculating relative file paths.</p></dd>
</dl>
















</div>


<div id="section13" class="doctools_section"><h2><a name="section13">Class ::httpd::content.proxy</a></h2>
<p>An implementation to relay requests to another HTTP server, and relay
the results back across the request channel.</p>




<dl class="doctools_definitions">


<dt><a name="46">method proxy_info</a></dt>
<dd><p>Mandatory method to be replaced by the end user. If needed, activates the




process to proxy, and then returns a list of three values:
<i class="arg">proxyhost</i> - The hostname where the proxy is located
<i class="arg">proxyport</i> - The port to connect to

<i class="arg">proxyscript</i> - A pre-amble block of text to send prior to the mirrored request</p></dd>








</dl>
</div>

<div id="section14" class="doctools_section"><h2><a name="section14">Class ::httpd::content.scgi</a></h2>
<p>An implementation to relay requests to a server listening on a socket
expecting SCGI encoded requests, and relay
the results back across the request channel.</p>

<dl class="doctools_definitions">
<dt><a name="47">method scgi_info</a></dt>
<dd><p>Mandatory method to be replaced by the end user. If needed, activates the











process to proxy, and then returns a list of three values:


<i class="arg">scgihost</i> - The hostname where the scgi listener is located






<i class="arg">scgiport</i> - The port to connect to




<i class="arg">scgiscript</i> - The contents of the <i class="arg">SCRIPT_NAME</i> header to be sent</p></dd>



</dl>
</div>











<div id="section15" class="doctools_section"><h2><a name="section15">Class ::httpd::content.websocket</a></h2>
<p>A placeholder for a future implementation to manage requests that can expect to be
promoted to a Websocket. Currently it is an empty class.</p>
</div>
<div id="section16" class="doctools_section"><h2><a name="section16">SCGI Server Functions</a></h2>
<p>The HTTP module also provides an SCGI server implementation, as well as an HTTP








implementation. To use the SCGI functions, create an object of the <b class="cmd">http::server.scgi</b>
class instead of the <b class="cmd">http::server</b> class.</p>




</div>



<div id="section17" class="doctools_section"><h2><a name="section17">Class ::httpd::reply.scgi</a></h2>
<p>An modified <b class="cmd">http::reply</b> implementation that understands how to deal with





netstring encoded headers.</p>
</div>


<div id="section18" class="doctools_section"><h2><a name="section18">Class ::httpd::server.scgi</a></h2>



<p>A modified <b class="cmd">http::server</b> which is tailored to replying to request according to


the SCGI standard instead of the HTTP standard.</p>

</div>

<div id="section19" class="doctools_section"><h2><a name="section19">AUTHORS</a></h2>
<p>Sean Woods</p>
</div>
<div id="section20" class="doctools_section"><h2><a name="section20">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>network</em> of the
<a href="http://core.tcl.tk/tcllib/reportlist">Tcllib Trackers</a>.
Please also report any ideas for enhancements you may have for either
package and/or documentation.</p>
<p>When proposing code changes, please provide <em>unified diffs</em>,







|











|

|







|
>
|
|
|
|
|
|
|
|
|
|
>
>
|
>
|
|
|
|
>
>
>
|
|









<
|
|
<
<
<










|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|



>
>
>
>
>
>
>
>
|
>
>
|
|
>
>
>
>
>
|
>
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













|






|
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
>
|
<

|
|
|
<
<
<
|
|
|
<
|
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
<
<
|
>
|
|
<
>
>
|
|
|
|
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|


|
>

|
|
|
|
|
|
|

>



|


|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
|
>
>
>

|
|
|
|
|
<
<
<
<
<
<
|

|
>
>
|

|
>
>
>
>
>
>


|


|
|
|




>
>
>
|
|
<
|
<
<
<
<
>
>
|
>
|
<
|
<
>
>
>
>
>
>
|
>
>
|
<
>
>
>
>
|
<
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
|
>
|
|
>
>
>
>
|
>
|
>
|
|
>
|
<
|
>
>
>
|
>
|
|
>
|


>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>

|
|
>
>
>
>
>
|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
<
<
>
>
>
>

>
>
|
|
>
>
>
>
|
|
|
>
|
>
>
>
>
>
>
>
>


>
|
<
<
<
>

|
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>


>
>
>
>
>
>
>
>
>
>
>
|
<
|

|
<
>
>
>
>
>
>
>
>
|
|
>
>
>
>

>
>
>
|
|
>
>
>
>
>
|

>
>
|
>
>
>
|
>
>
|
>

>
|


|







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
    }
--></style>
</head>
<!-- Generated from file 'httpd.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2018 Sean Woods &amp;lt;[email protected]&amp;gt;
   -->
<!-- httpd.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">httpd(n) 4.3.4 tcllib &quot;Tcl Web Server&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>httpd - A TclOO and coroutine based web server</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Minimal Example</a></li>
<li class="doctools_section"><a href="#section3">Classes</a>
<ul>
<li class="doctools_subsection"><a href="#subsection1">Class  httpd::mime</a></li>
<li class="doctools_subsection"><a href="#subsection2">Class  httpd::reply</a></li>
<li class="doctools_subsection"><a href="#subsection3">Class  httpd::server</a></li>
<li class="doctools_subsection"><a href="#subsection4">Class  httpd::server::dispatch</a></li>
<li class="doctools_subsection"><a href="#subsection5">Class  httpd::content.redirect</a></li>
<li class="doctools_subsection"><a href="#subsection6">Class  httpd::content.cache</a></li>
<li class="doctools_subsection"><a href="#subsection7">Class  httpd::content.template</a></li>
<li class="doctools_subsection"><a href="#subsection8">Class  httpd::content.file</a></li>
<li class="doctools_subsection"><a href="#subsection9">Class  httpd::content.exec</a></li>
<li class="doctools_subsection"><a href="#subsection10">Class  httpd::content.proxy</a></li>
<li class="doctools_subsection"><a href="#subsection11">Class  httpd::content.cgi</a></li>
<li class="doctools_subsection"><a href="#subsection12">Class  httpd::protocol.scgi</a></li>
<li class="doctools_subsection"><a href="#subsection13">Class  httpd::content.scgi</a></li>
<li class="doctools_subsection"><a href="#subsection14">Class  httpd::server.scgi</a></li>
<li class="doctools_subsection"><a href="#subsection15">Class  httpd::content.websocket</a></li>
<li class="doctools_subsection"><a href="#subsection16">Class  httpd::plugin</a></li>
<li class="doctools_subsection"><a href="#subsection17">Class  httpd::plugin.dict_dispatch</a></li>
<li class="doctools_subsection"><a href="#subsection18">Class  httpd::reply.memchan</a></li>
<li class="doctools_subsection"><a href="#subsection19">Class  httpd::plugin.local_memchan</a></li>
</ul>
</li>
<li class="doctools_section"><a href="#section4">AUTHORS</a></li>
<li class="doctools_section"><a href="#section5">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.6</b></li>

<li>package require <b class="pkgname">uuid</b></li>
<li>package require <b class="pkgname">clay</b></li>



<li>package require <b class="pkgname">coroutine</b></li>
<li>package require <b class="pkgname">fileutil</b></li>
<li>package require <b class="pkgname">fileutil::magic::filetype</b></li>
<li>package require <b class="pkgname">websocket</b></li>
<li>package require <b class="pkgname">mime</b></li>
<li>package require <b class="pkgname">cron</b></li>
<li>package require <b class="pkgname">uri</b></li>
<li>package require <b class="pkgname">Markdown</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1">method <b class="cmd">ChannelCopy</b> <i class="arg">in</i> <i class="arg">out</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#2">method <b class="cmd">html_header</b> <span class="opt">?<i class="arg">title</i> <b class="const"></b>?</span> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#3">method <b class="cmd">html_footer</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#4">method <b class="cmd">http_code_string</b> <i class="arg">code</i></a></li>
<li><a href="#5">method <b class="cmd">HttpHeaders</b> <i class="arg">sock</i> <span class="opt">?<i class="arg">debug</i> <b class="const"></b>?</span></a></li>
<li><a href="#6">method <b class="cmd">HttpHeaders_Default</b></a></li>
<li><a href="#7">method <b class="cmd">HttpServerHeaders</b></a></li>
<li><a href="#8">method <b class="cmd">MimeParse</b> <i class="arg">mimetext</i></a></li>
<li><a href="#9">method <b class="cmd">Url_Decode</b> <i class="arg">data</i></a></li>
<li><a href="#10">method <b class="cmd">Url_PathCheck</b> <i class="arg">urlsuffix</i></a></li>
<li><a href="#11">method <b class="cmd">wait</b> <i class="arg">mode</i> <i class="arg">sock</i></a></li>
<li><a href="#12">variable <b class="cmd">ChannelRegister</b></a></li>
<li><a href="#13">variable <b class="cmd">reply</b></a></li>
<li><a href="#14">variable <b class="cmd">request</b></a></li>
<li><a href="#15">delegate <b class="cmd">&lt;server&gt;</b></a></li>
<li><a href="#16">method <b class="cmd">constructor</b> <i class="arg">ServerObj</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#17">method <b class="cmd">destructor</b> <span class="opt">?<i class="arg">dictargs</i>?</span></a></li>
<li><a href="#18">method <b class="cmd">ChannelRegister</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#19">method <b class="cmd">close</b></a></li>
<li><a href="#20">method <b class="cmd">Log_Dispatched</b></a></li>
<li><a href="#21">method <b class="cmd">dispatch</b> <i class="arg">newsock</i> <i class="arg">datastate</i></a></li>
<li><a href="#22">method <b class="cmd">Dispatch</b></a></li>
<li><a href="#23">method <b class="cmd">html_header</b> <i class="arg">title</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#24">method <b class="cmd">html_footer</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#25">method <b class="cmd"><a href="../../../../index.html#error">error</a></b> <i class="arg">code</i> <span class="opt">?<i class="arg">msg</i> <b class="const"></b>?</span> <span class="opt">?<i class="arg">errorInfo</i> <b class="const"></b>?</span></a></li>
<li><a href="#26">method <b class="cmd">content</b></a></li>
<li><a href="#27">method <b class="cmd">EncodeStatus</b> <i class="arg">status</i></a></li>
<li><a href="#28">method <b class="cmd"><a href="../log/log.html">log</a></b> <i class="arg">type</i> <span class="opt">?<i class="arg">info</i> <b class="const"></b>?</span></a></li>
<li><a href="#29">method <b class="cmd">CoroName</b></a></li>
<li><a href="#30">method <b class="cmd">DoOutput</b></a></li>
<li><a href="#31">method <b class="cmd">FormData</b></a></li>
<li><a href="#32">method <b class="cmd">PostData</b> <i class="arg">length</i></a></li>
<li><a href="#33">method <b class="cmd">Session_Load</b></a></li>
<li><a href="#34">method <b class="cmd">puts</b> <i class="arg">line</i></a></li>
<li><a href="#35">method <b class="cmd">RequestFind</b> <i class="arg">field</i></a></li>
<li><a href="#36">method <b class="cmd">request</b> <i class="arg">subcommand</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#37">method <b class="cmd">reply</b> <i class="arg">subcommand</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#38">method <b class="cmd">reset</b></a></li>
<li><a href="#39">method <b class="cmd">timeOutCheck</b></a></li>
<li><a href="#40">method <b class="cmd"><a href="../../../../index.html#timestamp">timestamp</a></b></a></li>
<li><a href="#41">variable <b class="cmd">template</b></a></li>
<li><a href="#42">variable <b class="cmd">url_patterns</b></a></li>
<li><a href="#43">method <b class="cmd">constructor</b> <i class="arg">args</i> <span class="opt">?<i class="arg">port</i> <b class="const">auto</b>?</span> <span class="opt">?<i class="arg">myaddr</i> <b class="const">127.0.0.1</b>?</span> <span class="opt">?<i class="arg">string</i> <b class="const">auto</b>?</span> <span class="opt">?<i class="arg">name</i> <b class="const">auto</b>?</span> <span class="opt">?<i class="arg">doc_root</i> <b class="const"></b>?</span> <span class="opt">?<i class="arg">reverse_dns</i> <b class="const">0</b>?</span> <span class="opt">?<i class="arg">configuration_file</i> <b class="const"></b>?</span> <span class="opt">?<i class="arg">protocol</i> <b class="const">HTTP/1.1</b>?</span></a></li>
<li><a href="#44">method <b class="cmd">destructor</b> <span class="opt">?<i class="arg">dictargs</i>?</span></a></li>
<li><a href="#45">method <b class="cmd">connect</b> <i class="arg">sock</i> <i class="arg">ip</i> <i class="arg">port</i></a></li>
<li><a href="#46">method <b class="cmd">ServerHeaders</b> <i class="arg">ip</i> <i class="arg">http_request</i> <i class="arg">mimetxt</i></a></li>
<li><a href="#47">method <b class="cmd">Connect</b> <i class="arg">uuid</i> <i class="arg">sock</i> <i class="arg">ip</i></a></li>
<li><a href="#48">method <b class="cmd"><a href="../counter/counter.html">counter</a></b> <i class="arg">which</i></a></li>
<li><a href="#49">method <b class="cmd">CheckTimeout</b></a></li>
<li><a href="#50">method <b class="cmd"><a href="../debug/debug.html">debug</a></b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#51">method <b class="cmd">dispatch</b> <i class="arg">data</i></a></li>
<li><a href="#52">method <b class="cmd">Dispatch_Default</b> <i class="arg">reply</i></a></li>
<li><a href="#53">method <b class="cmd">Dispatch_Local</b> <i class="arg">data</i></a></li>
<li><a href="#54">method <b class="cmd">Headers_Local</b> <i class="arg">varname</i></a></li>
<li><a href="#55">method <b class="cmd">Headers_Process</b> <i class="arg">varname</i></a></li>
<li><a href="#56">method <b class="cmd">HostName</b> <i class="arg">ipaddr</i></a></li>
<li><a href="#57">method <b class="cmd"><a href="../log/log.html">log</a></b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#58">method <b class="cmd"><a href="../../../../index.html#plugin">plugin</a></b> <i class="arg">slot</i> <span class="opt">?<i class="arg">class</i> <b class="const"></b>?</span></a></li>
<li><a href="#59">method <b class="cmd">port_listening</b></a></li>
<li><a href="#60">method <b class="cmd">PrefixNormalize</b> <i class="arg">prefix</i></a></li>
<li><a href="#61">method <b class="cmd"><a href="../../../../index.html#source">source</a></b> <i class="arg">filename</i></a></li>
<li><a href="#62">method <b class="cmd">start</b></a></li>
<li><a href="#63">method <b class="cmd">stop</b></a></li>
<li><a href="#64">method <b class="cmd">SubObject {} db</b></a></li>
<li><a href="#65">method <b class="cmd">SubObject {} default</b></a></li>
<li><a href="#66">method <b class="cmd">template</b> <i class="arg">page</i></a></li>
<li><a href="#67">method <b class="cmd">TemplateSearch</b> <i class="arg">page</i></a></li>
<li><a href="#68">method <b class="cmd">Thread_start</b></a></li>
<li><a href="#69">method <b class="cmd">Uuid_Generate</b></a></li>
<li><a href="#70">method <b class="cmd">Validate_Connection</b> <i class="arg">sock</i> <i class="arg">ip</i></a></li>
<li><a href="#71">method <b class="cmd">reset</b></a></li>
<li><a href="#72">method <b class="cmd">content</b></a></li>
<li><a href="#73">method <b class="cmd">Dispatch</b></a></li>
<li><a href="#74">method <b class="cmd">content</b></a></li>
<li><a href="#75">method <b class="cmd">FileName</b></a></li>
<li><a href="#76">method <b class="cmd">DirectoryListing</b> <i class="arg">local_file</i></a></li>
<li><a href="#77">method <b class="cmd">content</b></a></li>
<li><a href="#78">method <b class="cmd">Dispatch</b></a></li>
<li><a href="#79">variable <b class="cmd">exename</b></a></li>
<li><a href="#80">method <b class="cmd">CgiExec</b> <i class="arg">execname</i> <i class="arg">script</i> <i class="arg">arglist</i></a></li>
<li><a href="#81">method <b class="cmd">Cgi_Executable</b> <i class="arg">script</i></a></li>
<li><a href="#82">method <b class="cmd">proxy_channel</b></a></li>
<li><a href="#83">method <b class="cmd">proxy_path</b></a></li>
<li><a href="#84">method <b class="cmd">ProxyRequest</b> <i class="arg">chana</i> <i class="arg">chanb</i></a></li>
<li><a href="#85">method <b class="cmd">ProxyReply</b> <i class="arg">chana</i> <i class="arg">chanb</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#86">method <b class="cmd">Dispatch</b></a></li>
<li><a href="#87">method <b class="cmd">FileName</b></a></li>
<li><a href="#88">method <b class="cmd">proxy_channel</b></a></li>
<li><a href="#89">method <b class="cmd">ProxyRequest</b> <i class="arg">chana</i> <i class="arg">chanb</i></a></li>
<li><a href="#90">method <b class="cmd">ProxyReply</b> <i class="arg">chana</i> <i class="arg">chanb</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#91">method <b class="cmd">DirectoryListing</b> <i class="arg">local_file</i></a></li>
<li><a href="#92">method <b class="cmd">EncodeStatus</b> <i class="arg">status</i></a></li>
<li><a href="#93">method <b class="cmd">scgi_info</b></a></li>
<li><a href="#94">method <b class="cmd">proxy_channel</b></a></li>
<li><a href="#95">method <b class="cmd">ProxyRequest</b> <i class="arg">chana</i> <i class="arg">chanb</i></a></li>
<li><a href="#96">method <b class="cmd">ProxyReply</b> <i class="arg">chana</i> <i class="arg">chanb</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#97">method <b class="cmd"><a href="../debug/debug.html">debug</a></b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#98">method <b class="cmd">Connect</b> <i class="arg">uuid</i> <i class="arg">sock</i> <i class="arg">ip</i></a></li>
<li><a href="#99">method <b class="cmd">Dispatch_Dict</b> <i class="arg">data</i></a></li>
<li><a href="#100">method <b class="cmd">uri {} add</b> <i class="arg">vhosts</i> <i class="arg">patterns</i> <i class="arg">info</i></a></li>
<li><a href="#101">method <b class="cmd">uri {} direct</b> <i class="arg">vhosts</i> <i class="arg">patterns</i> <i class="arg">info</i> <i class="arg">body</i></a></li>
<li><a href="#102">method <b class="cmd">output</b></a></li>
<li><a href="#103">method <b class="cmd">DoOutput</b></a></li>
<li><a href="#104">method <b class="cmd">close</b></a></li>
<li><a href="#105">method <b class="cmd">local_memchan</b> <i class="arg">command</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#106">method <b class="cmd">Connect_Local</b> <i class="arg">uuid</i> <i class="arg">sock</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>This module implements a web server, suitable for embedding in an
application. The server is object oriented, and contains all of the
fundamentals needed for a full service website.</p>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">Minimal Example</a></h2>
<p>Starting a web service requires starting a class of type
<b class="cmd">httpd::server</b>, and providing that server with one or more URIs
to service, and <b class="cmd">httpd::reply</b> derived classes to generate them.</p>
<pre class="doctools_example">
oo::class create ::reply.hello {
  method content {} {
    my puts &quot;&lt;HTML&gt;&lt;HEAD&gt;&lt;TITLE&gt;IRM Dispatch Server&lt;/TITLE&gt;&lt;/HEAD&gt;&lt;BODY&gt;&quot;
    my puts &quot;&lt;h1&gt;Hello World!&lt;/h1&gt;&quot;
    my puts &lt;/BODY&gt;&lt;/HTML&gt;
  }
}
::httpd::server create HTTPD port 8015 myaddr 127.0.0.1 doc_root ~/htdocs
HTTPD plugin dispatch httpd::server::dispatch
HTTPD uri add * /hello [list mixin reply.hello]
</pre>
<p>The bare module does have facilities to hose a files from a file system. Files that end in a .tml will be substituted in the style of Tclhttpd:</p>
<pre class="doctools_example">
&lt;!-- hello.tml --&gt;
[my html_header {Hello World!}]
Your Server is running.
&lt;p&gt;
The time is now [clock format [clock seconds]]
[my html_footer]
</pre>
<p>A complete example of an httpd server is in the /examples directory of Tcllib. It also show how to dispatch URIs to other processes via SCGI and HTTP proxies.</p>
<pre class="doctools_example">
cd ~/tcl/sandbox/tcllib
tclsh examples/httpd.tcl
</pre>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">Classes</a></h2>
<div id="subsection1" class="doctools_subsection"><h3><a name="subsection1">Class  httpd::mime</a></h3>
<p>A metaclass for MIME handling behavior across a live socket</p>
<p><b class="class">Methods</b></p>

<dl class="doctools_definitions">
<dt><a name="1">method <b class="cmd">ChannelCopy</b> <i class="arg">in</i> <i class="arg">out</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="2">method <b class="cmd">html_header</b> <span class="opt">?<i class="arg">title</i> <b class="const"></b>?</span> <span class="opt">?<i class="arg">args</i>?</span></a></dt>



<dd><p>Returns a block of HTML</p></dd>
<dt><a name="3">method <b class="cmd">html_footer</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>

<dt><a name="4">method <b class="cmd">http_code_string</b> <i class="arg">code</i></a></dt>











<dd></dd>
<dt><a name="5">method <b class="cmd">HttpHeaders</b> <i class="arg">sock</i> <span class="opt">?<i class="arg">debug</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
<dt><a name="6">method <b class="cmd">HttpHeaders_Default</b></a></dt>


<dd></dd>
<dt><a name="7">method <b class="cmd">HttpServerHeaders</b></a></dt>
<dd></dd>
<dt><a name="8">method <b class="cmd">MimeParse</b> <i class="arg">mimetext</i></a></dt>

<dd><p>Converts a block of mime encoded text to a key/value list. If an exception is encountered,
 the method will generate its own call to the <b class="cmd"><a href="../../../../index.html#error">error</a></b> method, and immediately invoke
 the <b class="cmd">output</b> method to produce an error code and close the connection.</p></dd>
<dt><a name="9">method <b class="cmd">Url_Decode</b> <i class="arg">data</i></a></dt>
<dd><p>De-httpizes a string.</p></dd>
<dt><a name="10">method <b class="cmd">Url_PathCheck</b> <i class="arg">urlsuffix</i></a></dt>


<dd></dd>
<dt><a name="11">method <b class="cmd">wait</b> <i class="arg">mode</i> <i class="arg">sock</i></a></dt>















<dd></dd>
</dl>
</div>
<div id="subsection2" class="doctools_subsection"><h3><a name="subsection2">Class  httpd::reply</a></h3>
<p><em>ancestors</em>: <b class="class">httpd::mime</b></p>
<p>A class which shephards a request through the process of generating a
 reply.
 The socket associated with the reply is available at all times as the <i class="arg">chan</i>
 variable.
 The process of generating a reply begins with an <b class="cmd">httpd::server</b> generating a
 <b class="cmd">http::class</b> object, mixing in a set of behaviors and then invoking the reply
 object's <b class="cmd">dispatch</b> method.
 In normal operations the <b class="cmd">dispatch</b> method:</p>
<ol class="doctools_enumerated">
 
<li><p>Invokes the <b class="cmd">reset</b> method for the object to populate default headers.</p></li>
<li><p>Invokes the <b class="cmd">HttpHeaders</b> method to stream the MIME headers out of the socket</p></li>
<li><p>Invokes the <b class="cmd">request parse</b> method to convert the stream of MIME headers into a
 dict that can be read via the <b class="cmd">request</b> method.</p></li>
<li><p>Stores the raw stream of MIME headers in the <i class="arg">rawrequest</i> variable of the object.</p></li>
<li><p>Invokes the <b class="cmd">content</b> method for the object, generating an call to the <b class="cmd"><a href="../../../../index.html#error">error</a></b>
 method if an exception is raised.</p></li>
<li><p>Invokes the <b class="cmd">output</b> method for the object</p></li>
</ol>


































































<p>Developers have the option of streaming output to a buffer via the <b class="cmd">puts</b> method of the
 reply, or simply populating the <i class="arg">reply_body</i> variable of the object.
 The information returned by the <b class="cmd">content</b> method is not interpreted in any way.
 If an exception is thrown (via the <b class="cmd"><a href="../../../../index.html#error">error</a></b> command in Tcl, for example) the caller will
 auto-generate a 500 {Internal Error} message.
 A typical implementation of <b class="cmd">content</b> look like:</p>
<pre class="doctools_example">
 clay::define ::test::content.file {
 	superclass ::httpd::content.file
 	# Return a file
 	# Note: this is using the content.file mixin which looks for the reply_file variable
 	# and will auto-compute the Content-Type
 	method content {} {
 	  my reset
     set doc_root [my request get DOCUMENT_ROOT]
     my variable reply_file
     set reply_file [file join $doc_root index.html]
 	}
 }
 clay::define ::test::content.time {
   # return the current system time
 	method content {} {
 		my variable reply_body
     my reply set Content-Type text/plain
 		set reply_body [clock seconds]
 	}
 }
 clay::define ::test::content.echo {
 	method content {} {
 		my variable reply_body
     my reply set Content-Type [my request get CONTENT_TYPE]
 		set reply_body [my PostData [my request get CONTENT_LENGTH]]
 	}
 }
 clay::define ::test::content.form_handler {
 	method content {} {
 	  set form [my FormData]
 	  my reply set Content-Type {text/html; charset=UTF-8}
     my puts [my html_header {My Dynamic Page}]
     my puts &quot;&lt;BODY&gt;&quot;
     my puts &quot;You Sent&lt;p&gt;&quot;
     my puts &quot;&lt;TABLE&gt;&quot;
     foreach {f v} $form {
       my puts &quot;&lt;TR&gt;&lt;TH&gt;$f&lt;/TH&gt;&lt;TD&gt;&lt;verbatim&gt;$v&lt;/verbatim&gt;&lt;/TD&gt;&quot;
     }
     my puts &quot;&lt;/TABLE&gt;&lt;p&gt;&quot;
     my puts &quot;Send some info:&lt;p&gt;&quot;
     my puts &quot;&lt;FORM action=/[my request get REQUEST_PATH] method POST&gt;&quot;
     my puts &quot;&lt;TABLE&gt;&quot;
     foreach field {name rank serial_number} {
       set line &quot;&lt;TR&gt;&lt;TH&gt;$field&lt;/TH&gt;&lt;TD&gt;&lt;input name=\&quot;$field\&quot; &quot;
       if {[dict exists $form $field]} {
         append line &quot; value=\&quot;[dict get $form $field]\&quot;&quot;&quot;
       }
       append line &quot; /&gt;&lt;/TD&gt;&lt;/TR&gt;&quot;
       my puts $line
     }
     my puts &quot;&lt;/TABLE&gt;&quot;
     my puts [my html footer]
 	}
 }
 </pre>
<p><b class="class">Variable</b></p>
<dl class="doctools_definitions">
<dt><a name="12">variable <b class="cmd">ChannelRegister</b></a></dt>
<dd></dd>
<dt><a name="13">variable <b class="cmd">reply</b></a></dt>
<dd><p>A dictionary which will converted into the MIME headers of the reply</p></dd>
<dt><a name="14">variable <b class="cmd">request</b></a></dt>
<dd><p>A dictionary containing the SCGI transformed HTTP headers for the request</p></dd>
</dl>
<p><b class="class">Delegate</b></p>
<dl class="doctools_definitions">
<dt><a name="15">delegate <b class="cmd">&lt;server&gt;</b></a></dt>
<dd><p>The server object which spawned this reply</p></dd>
</dl>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="16">method <b class="cmd">constructor</b> <i class="arg">ServerObj</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="17">method <b class="cmd">destructor</b> <span class="opt">?<i class="arg">dictargs</i>?</span></a></dt>
<dd><p>clean up on exit</p></dd>
<dt><a name="18">method <b class="cmd">ChannelRegister</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Registers a channel to be closed by the close method</p></dd>
<dt><a name="19">method <b class="cmd">close</b></a></dt>
<dd><p>Close channels opened by this object</p></dd>
<dt><a name="20">method <b class="cmd">Log_Dispatched</b></a></dt>
<dd><p>Record a dispatch event</p></dd>
<dt><a name="21">method <b class="cmd">dispatch</b> <i class="arg">newsock</i> <i class="arg">datastate</i></a></dt>
<dd><p>Accept the handoff from the server object of the socket
 <em>newsock</em> and feed it the state <em>datastate</em>.
 Fields the <em>datastate</em> are looking for in particular are:</p>
<p>* <b class="const">mixin</b> - A key/value list of slots and classes to be mixed into the
 object prior to invoking <b class="cmd">Dispatch</b>.</p>
<p>* <b class="const">http</b> - A key/value list of values to populate the object's <em>request</em>
 ensemble</p>
<p>All other fields are passed along to the <b class="method">clay</b> structure of the object.</p></dd>
<dt><a name="22">method <b class="cmd">Dispatch</b></a></dt>
<dd></dd>
<dt><a name="23">method <b class="cmd">html_header</b> <i class="arg">title</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="24">method <b class="cmd">html_footer</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="25">method <b class="cmd"><a href="../../../../index.html#error">error</a></b> <i class="arg">code</i> <span class="opt">?<i class="arg">msg</i> <b class="const"></b>?</span> <span class="opt">?<i class="arg">errorInfo</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
<dt><a name="26">method <b class="cmd">content</b></a></dt>
<dd><p>REPLACE ME:
 This method is the &quot;meat&quot; of your application.
 It writes to the result buffer via the &quot;puts&quot; method
 and can tweak the headers via &quot;clay put header_reply&quot;</p></dd>
<dt><a name="27">method <b class="cmd">EncodeStatus</b> <i class="arg">status</i></a></dt>
<dd><p>Formulate a standard HTTP status header from he string provided.</p></dd>
<dt><a name="28">method <b class="cmd"><a href="../log/log.html">log</a></b> <i class="arg">type</i> <span class="opt">?<i class="arg">info</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
<dt><a name="29">method <b class="cmd">CoroName</b></a></dt>
<dd></dd>
<dt><a name="30">method <b class="cmd">DoOutput</b></a></dt>
<dd><p>Generates the the HTTP reply, streams that reply back across <i class="arg">chan</i>,
 and destroys the object.</p></dd>
<dt><a name="31">method <b class="cmd">FormData</b></a></dt>
<dd><p>For GET requests, converts the QUERY_DATA header into a key/value list.
 For POST requests, reads the Post data and converts that information to
 a key/value list for application/x-www-form-urlencoded posts. For multipart
 posts, it composites all of the MIME headers of the post to a singular key/value
 list, and provides MIME_* information as computed by the <b class="cmd"><a href="../mime/mime.html">mime</a></b> package, including
 the MIME_TOKEN, which can be fed back into the mime package to read out the contents.</p></dd>






<dt><a name="32">method <b class="cmd">PostData</b> <i class="arg">length</i></a></dt>
<dd><p>Stream <i class="arg">length</i> bytes from the <i class="arg">chan</i> socket, but only of the request is a
 POST or PUSH. Returns an empty string otherwise.</p></dd>
<dt><a name="33">method <b class="cmd">Session_Load</b></a></dt>
<dd><p>Manage session data</p></dd>
<dt><a name="34">method <b class="cmd">puts</b> <i class="arg">line</i></a></dt>
<dd><p>Appends the value of <i class="arg">string</i> to the end of <i class="arg">reply_body</i>, as well as a trailing newline
 character.</p></dd>
<dt><a name="35">method <b class="cmd">RequestFind</b> <i class="arg">field</i></a></dt>
<dd></dd>
<dt><a name="36">method <b class="cmd">request</b> <i class="arg">subcommand</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="37">method <b class="cmd">reply</b> <i class="arg">subcommand</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="38">method <b class="cmd">reset</b></a></dt>
<dd><p>Clear the contents of the <i class="arg">reply_body</i> variable, and reset all headers in the <b class="cmd">reply</b>
 structure back to the defaults for this object.</p></dd>
<dt><a name="39">method <b class="cmd">timeOutCheck</b></a></dt>
<dd><p>Called from the <b class="cmd">http::server</b> object which spawned this reply. Checks to see
 if too much time has elapsed while waiting for data or generating a reply, and issues
 a timeout error to the request if it has, as well as destroy the object and close the
 <i class="arg">chan</i> socket.</p></dd>
<dt><a name="40">method <b class="cmd"><a href="../../../../index.html#timestamp">timestamp</a></b></a></dt>
<dd><p>Return the current system time in the format:</p>
<pre class="doctools_example">%a, %d %b %Y %T %Z</pre>
</dd>
</dl>
</div>
<div id="subsection3" class="doctools_subsection"><h3><a name="subsection3">Class  httpd::server</a></h3>
<p><em>ancestors</em>: <b class="class">httpd::mime</b></p>
<p><b class="class">Variable</b></p>

<dl class="doctools_definitions">




<dt><a name="41">variable <b class="cmd">template</b></a></dt>
<dd></dd>
<dt><a name="42">variable <b class="cmd">url_patterns</b></a></dt>
<dd></dd>
</dl>

<p><b class="class">Methods</b></p>

<dl class="doctools_definitions">
<dt><a name="43">method <b class="cmd">constructor</b> <i class="arg">args</i> <span class="opt">?<i class="arg">port</i> <b class="const">auto</b>?</span> <span class="opt">?<i class="arg">myaddr</i> <b class="const">127.0.0.1</b>?</span> <span class="opt">?<i class="arg">string</i> <b class="const">auto</b>?</span> <span class="opt">?<i class="arg">name</i> <b class="const">auto</b>?</span> <span class="opt">?<i class="arg">doc_root</i> <b class="const"></b>?</span> <span class="opt">?<i class="arg">reverse_dns</i> <b class="const">0</b>?</span> <span class="opt">?<i class="arg">configuration_file</i> <b class="const"></b>?</span> <span class="opt">?<i class="arg">protocol</i> <b class="const">HTTP/1.1</b>?</span></a></dt>
<dd></dd>
<dt><a name="44">method <b class="cmd">destructor</b> <span class="opt">?<i class="arg">dictargs</i>?</span></a></dt>
<dd></dd>
<dt><a name="45">method <b class="cmd">connect</b> <i class="arg">sock</i> <i class="arg">ip</i> <i class="arg">port</i></a></dt>
<dd><p>Reply to an open socket. This method builds a coroutine to manage the remainder
 of the connection. The coroutine's operations are driven by the <b class="cmd">Connect</b> method.</p></dd>
<dt><a name="46">method <b class="cmd">ServerHeaders</b> <i class="arg">ip</i> <i class="arg">http_request</i> <i class="arg">mimetxt</i></a></dt>
<dd></dd>

<dt><a name="47">method <b class="cmd">Connect</b> <i class="arg">uuid</i> <i class="arg">sock</i> <i class="arg">ip</i></a></dt>
<dd><p>This method reads HTTP headers, and then consults the <b class="cmd">dispatch</b> method to
 determine if the request is valid, and/or what kind of reply to generate. Under
 normal cases, an object of class <b class="cmd">::http::reply</b> is created, and that class's
 <b class="cmd">dispatch</b> method.

 This action passes control of the socket to
 the reply object. The reply object manages the rest of the transaction, including
 closing the socket.</p></dd>
<dt><a name="48">method <b class="cmd"><a href="../counter/counter.html">counter</a></b> <i class="arg">which</i></a></dt>
<dd><p>Increment an internal counter.</p></dd>
<dt><a name="49">method <b class="cmd">CheckTimeout</b></a></dt>
<dd><p>Check open connections for a time out event.</p></dd>
<dt><a name="50">method <b class="cmd"><a href="../debug/debug.html">debug</a></b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="51">method <b class="cmd">dispatch</b> <i class="arg">data</i></a></dt>
<dd><p>Given a key/value list of information, return a data structure describing how
 the server should reply.</p></dd>
<dt><a name="52">method <b class="cmd">Dispatch_Default</b> <i class="arg">reply</i></a></dt>
<dd><p>Method dispatch method of last resort before returning a 404 NOT FOUND error.
 The default behavior is to look for a file in <em>DOCUMENT_ROOT</em> which
 matches the query.</p></dd>
<dt><a name="53">method <b class="cmd">Dispatch_Local</b> <i class="arg">data</i></a></dt>
<dd><p>Method dispatch method invoked prior to invoking methods implemented by plugins.
 If this method returns a non-empty dictionary, that structure will be passed to
 the reply. The default is an empty implementation.</p></dd>
<dt><a name="54">method <b class="cmd">Headers_Local</b> <i class="arg">varname</i></a></dt>
<dd><p>Introspect and possibly modify a data structure destined for a reply. This
 method is invoked before invoking Header methods implemented by plugins.
 The default implementation is empty.</p></dd>
<dt><a name="55">method <b class="cmd">Headers_Process</b> <i class="arg">varname</i></a></dt>
<dd><p>Introspect and possibly modify a data structure destined for a reply. This
 method is built dynamically by the <b class="cmd"><a href="../../../../index.html#plugin">plugin</a></b> method.</p></dd>
<dt><a name="56">method <b class="cmd">HostName</b> <i class="arg">ipaddr</i></a></dt>
<dd><p>Convert an ip address to a host name. If the server/ reverse_dns flag
 is false, this method simply returns the IP address back.
 Internally, this method uses the <em>dns</em> module from tcllib.</p></dd>
<dt><a name="57">method <b class="cmd"><a href="../log/log.html">log</a></b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Log an event. The input for args is free form. This method is intended
 to be replaced by the user, and is a noop for a stock http::server object.</p></dd>
<dt><a name="58">method <b class="cmd"><a href="../../../../index.html#plugin">plugin</a></b> <i class="arg">slot</i> <span class="opt">?<i class="arg">class</i> <b class="const"></b>?</span></a></dt>
<dd><p>Incorporate behaviors from a plugin.
 This method dynamically rebuilds the <b class="cmd">Dispatch</b> and <b class="cmd">Headers</b>
 method. For every plugin, the server looks for the following entries in
 <em>clay plugin/</em>:</p>
<p><em>load</em> - A script to invoke in the server's namespace during the <b class="cmd"><a href="../../../../index.html#plugin">plugin</a></b> method invokation.</p>
<p><em>dispatch</em> - A script to stitch into the server's <b class="cmd">Dispatch</b> method.</p>
<p><em>headers</em> - A script to stitch into the server's <b class="cmd">Headers</b> method.</p>
<p><em>thread</em> - A script to stitch into the server's <b class="cmd">Thread_start</b> method.</p></dd>
<dt><a name="59">method <b class="cmd">port_listening</b></a></dt>
<dd><p>Return the actual port that httpd is listening on.</p></dd>
<dt><a name="60">method <b class="cmd">PrefixNormalize</b> <i class="arg">prefix</i></a></dt>
<dd><p>For the stock version, trim trailing /'s and *'s from a prefix. This
 method can be replaced by the end user to perform any other transformations
 needed for the application.</p></dd>
<dt><a name="61">method <b class="cmd"><a href="../../../../index.html#source">source</a></b> <i class="arg">filename</i></a></dt>
<dd></dd>
<dt><a name="62">method <b class="cmd">start</b></a></dt>
<dd><p>Open the socket listener.</p></dd>
<dt><a name="63">method <b class="cmd">stop</b></a></dt>
<dd><p>Shut off the socket listener, and destroy any pending replies.</p></dd>
<dt><a name="64">method <b class="cmd">SubObject {} db</b></a></dt>
<dd></dd>
<dt><a name="65">method <b class="cmd">SubObject {} default</b></a></dt>
<dd></dd>
<dt><a name="66">method <b class="cmd">template</b> <i class="arg">page</i></a></dt>
<dd><p>Return a template for the string <i class="arg">page</i></p></dd>
<dt><a name="67">method <b class="cmd">TemplateSearch</b> <i class="arg">page</i></a></dt>
<dd><p>Perform a search for the template that best matches <i class="arg">page</i>. This
 can include local file searches, in-memory structures, or even
 database lookups. The stock implementation simply looks for files
 with a .tml or .html extension in the <span class="opt">?doc_root?</span> directory.</p></dd>
<dt><a name="68">method <b class="cmd">Thread_start</b></a></dt>
<dd><p>Built by the <b class="cmd"><a href="../../../../index.html#plugin">plugin</a></b> method. Called by the <b class="cmd">start</b> method. Intended
 to allow plugins to spawn worker threads.</p></dd>
<dt><a name="69">method <b class="cmd">Uuid_Generate</b></a></dt>
<dd><p>Generate a GUUID. Used to ensure every request has a unique ID.
 The default implementation is:</p>

<pre class="doctools_example">
   return [::clay::uuid generate]
 </pre>
</dd>
<dt><a name="70">method <b class="cmd">Validate_Connection</b> <i class="arg">sock</i> <i class="arg">ip</i></a></dt>
<dd><p>Given a socket and an ip address, return true if this connection should
 be terminated, or false if it should be allowed to continue. The stock
 implementation always returns 0. This is intended for applications to
 be able to implement black lists and/or provide security based on IP
 address.</p></dd>
</dl>
</div>
<div id="subsection4" class="doctools_subsection"><h3><a name="subsection4">Class  httpd::server::dispatch</a></h3>
<p><em>ancestors</em>: <b class="class">httpd::server</b></p>
<p>Provide a backward compadible alias</p>
</div>
<div id="subsection5" class="doctools_subsection"><h3><a name="subsection5">Class  httpd::content.redirect</a></h3>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">

<dt><a name="71">method <b class="cmd">reset</b></a></dt>
<dd></dd>
<dt><a name="72">method <b class="cmd">content</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection6" class="doctools_subsection"><h3><a name="subsection6">Class  httpd::content.cache</a></h3>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="73">method <b class="cmd">Dispatch</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection7" class="doctools_subsection"><h3><a name="subsection7">Class  httpd::content.template</a></h3>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="74">method <b class="cmd">content</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection8" class="doctools_subsection"><h3><a name="subsection8">Class  httpd::content.file</a></h3>
<p>Class to deliver Static content
 When utilized, this class is fed a local filename
 by the dispatcher</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="75">method <b class="cmd">FileName</b></a></dt>
<dd></dd>
<dt><a name="76">method <b class="cmd">DirectoryListing</b> <i class="arg">local_file</i></a></dt>
<dd></dd>
<dt><a name="77">method <b class="cmd">content</b></a></dt>
<dd></dd>
<dt><a name="78">method <b class="cmd">Dispatch</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection9" class="doctools_subsection"><h3><a name="subsection9">Class  httpd::content.exec</a></h3>
<p><b class="class">Variable</b></p>
<dl class="doctools_definitions">


<dt><a name="79">variable <b class="cmd">exename</b></a></dt>
<dd></dd>
</dl>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="80">method <b class="cmd">CgiExec</b> <i class="arg">execname</i> <i class="arg">script</i> <i class="arg">arglist</i></a></dt>
<dd></dd>
<dt><a name="81">method <b class="cmd">Cgi_Executable</b> <i class="arg">script</i></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection10" class="doctools_subsection"><h3><a name="subsection10">Class  httpd::content.proxy</a></h3>
<p><em>ancestors</em>: <b class="class">httpd::content.exec</b></p>
<p>Return data from an proxy process</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="82">method <b class="cmd">proxy_channel</b></a></dt>
<dd></dd>
<dt><a name="83">method <b class="cmd">proxy_path</b></a></dt>
<dd></dd>
<dt><a name="84">method <b class="cmd">ProxyRequest</b> <i class="arg">chana</i> <i class="arg">chanb</i></a></dt>
<dd></dd>
<dt><a name="85">method <b class="cmd">ProxyReply</b> <i class="arg">chana</i> <i class="arg">chanb</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="86">method <b class="cmd">Dispatch</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection11" class="doctools_subsection"><h3><a name="subsection11">Class  httpd::content.cgi</a></h3>
<p><em>ancestors</em>: <b class="class">httpd::content.proxy</b></p>



<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="87">method <b class="cmd">FileName</b></a></dt>
<dd></dd>
<dt><a name="88">method <b class="cmd">proxy_channel</b></a></dt>
<dd></dd>
<dt><a name="89">method <b class="cmd">ProxyRequest</b> <i class="arg">chana</i> <i class="arg">chanb</i></a></dt>
<dd></dd>
<dt><a name="90">method <b class="cmd">ProxyReply</b> <i class="arg">chana</i> <i class="arg">chanb</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="91">method <b class="cmd">DirectoryListing</b> <i class="arg">local_file</i></a></dt>
<dd><p>For most CGI applications a directory list is vorboten</p></dd>
</dl>
</div>
<div id="subsection12" class="doctools_subsection"><h3><a name="subsection12">Class  httpd::protocol.scgi</a></h3>
<p>Return data from an SCGI process</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="92">method <b class="cmd">EncodeStatus</b> <i class="arg">status</i></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection13" class="doctools_subsection"><h3><a name="subsection13">Class  httpd::content.scgi</a></h3>
<p><em>ancestors</em>: <b class="class">httpd::content.proxy</b></p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="93">method <b class="cmd">scgi_info</b></a></dt>
<dd></dd>
<dt><a name="94">method <b class="cmd">proxy_channel</b></a></dt>
<dd></dd>
<dt><a name="95">method <b class="cmd">ProxyRequest</b> <i class="arg">chana</i> <i class="arg">chanb</i></a></dt>
<dd></dd>
<dt><a name="96">method <b class="cmd">ProxyReply</b> <i class="arg">chana</i> <i class="arg">chanb</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection14" class="doctools_subsection"><h3><a name="subsection14">Class  httpd::server.scgi</a></h3>
<p><em>ancestors</em>: <b class="class">httpd::server</b></p>
<p>Act as an  SCGI Server</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="97">method <b class="cmd"><a href="../debug/debug.html">debug</a></b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="98">method <b class="cmd">Connect</b> <i class="arg">uuid</i> <i class="arg">sock</i> <i class="arg">ip</i></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection15" class="doctools_subsection"><h3><a name="subsection15">Class  httpd::content.websocket</a></h3>

<p>Upgrade a connection to a websocket</p>
</div>
<div id="subsection16" class="doctools_subsection"><h3><a name="subsection16">Class  httpd::plugin</a></h3>

<p>httpd plugin template</p>
</div>
<div id="subsection17" class="doctools_subsection"><h3><a name="subsection17">Class  httpd::plugin.dict_dispatch</a></h3>
<p>A rudimentary plugin that dispatches URLs from a dict
 data structure</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="99">method <b class="cmd">Dispatch_Dict</b> <i class="arg">data</i></a></dt>
<dd><p>Implementation of the dispatcher</p></dd>
<dt><a name="100">method <b class="cmd">uri {} add</b> <i class="arg">vhosts</i> <i class="arg">patterns</i> <i class="arg">info</i></a></dt>
<dd></dd>
<dt><a name="101">method <b class="cmd">uri {} direct</b> <i class="arg">vhosts</i> <i class="arg">patterns</i> <i class="arg">info</i> <i class="arg">body</i></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection18" class="doctools_subsection"><h3><a name="subsection18">Class  httpd::reply.memchan</a></h3>
<p><em>ancestors</em>: <b class="class">httpd::reply</b></p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="102">method <b class="cmd">output</b></a></dt>
<dd></dd>
<dt><a name="103">method <b class="cmd">DoOutput</b></a></dt>
<dd></dd>
<dt><a name="104">method <b class="cmd">close</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection19" class="doctools_subsection"><h3><a name="subsection19">Class  httpd::plugin.local_memchan</a></h3>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="105">method <b class="cmd">local_memchan</b> <i class="arg">command</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="106">method <b class="cmd">Connect_Local</b> <i class="arg">uuid</i> <i class="arg">sock</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>A modified connection method that passes simple GET request to an object
 and pulls data directly from the reply_body data variable in the object
 Needed because memchan is bidirectional, and we can't seem to communicate that
 the server is one side of the link and the reply is another</p></dd>
</dl>
</div>
</div>
<div id="section4" class="doctools_section"><h2><a name="section4">AUTHORS</a></h2>
<p>Sean Woods</p>
</div>
<div id="section5" class="doctools_section"><h2><a name="section5">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>network</em> of the
<a href="http://core.tcl.tk/tcllib/reportlist">Tcllib Trackers</a>.
Please also report any ideas for enhancements you may have for either
package and/or documentation.</p>
<p>When proposing code changes, please provide <em>unified diffs</em>,

Changes to idoc/www/tcllib/files/modules/imap4/imap4.html.

117
118
119
120
121
122
123

124
125
126
127
128
129
130
131
132
133
134
135
136
137
<li class="doctools_section"><a href="#section2">PROCEDURES</a></li>
<li class="doctools_section"><a href="#section3">EXAMPLES</a></li>
<li class="doctools_section"><a href="#section4">TLS Security Considerations</a></li>
<li class="doctools_section"><a href="#section5">REFERENCES</a></li>
<li class="doctools_section"><a href="#section6">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#see-also">See Also</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>

</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">imap4 <span class="opt">?0.5.2?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::imap4::open</b> <i class="arg">hostname</i> <span class="opt">?<i class="arg">port</i>?</span></a></li>
<li><a href="#2"><b class="cmd">::imap4::starttls</b> <i class="arg">chan</i></a></li>
<li><a href="#3"><b class="cmd">::imap4::login</b> <i class="arg">chan</i> <i class="arg">user</i> <i class="arg">pass</i></a></li>
<li><a href="#4"><b class="cmd">::imap4::folders</b> <i class="arg">chan</i> <span class="opt">?<i class="arg">-inline</i>?</span> <span class="opt">?<i class="arg">mboxref</i>?</span> <span class="opt">?<i class="arg">mboxname</i>?</span></a></li>
<li><a href="#5"><b class="cmd">::imap4::select</b> <i class="arg">chan</i> <span class="opt">?<i class="arg">mailbox</i>?</span></a></li>







>






|







117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<li class="doctools_section"><a href="#section2">PROCEDURES</a></li>
<li class="doctools_section"><a href="#section3">EXAMPLES</a></li>
<li class="doctools_section"><a href="#section4">TLS Security Considerations</a></li>
<li class="doctools_section"><a href="#section5">REFERENCES</a></li>
<li class="doctools_section"><a href="#section6">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#see-also">See Also</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">imap4 <span class="opt">?0.5.3?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::imap4::open</b> <i class="arg">hostname</i> <span class="opt">?<i class="arg">port</i>?</span></a></li>
<li><a href="#2"><b class="cmd">::imap4::starttls</b> <i class="arg">chan</i></a></li>
<li><a href="#3"><b class="cmd">::imap4::login</b> <i class="arg">chan</i> <i class="arg">user</i> <i class="arg">pass</i></a></li>
<li><a href="#4"><b class="cmd">::imap4::folders</b> <i class="arg">chan</i> <span class="opt">?<i class="arg">-inline</i>?</span> <span class="opt">?<i class="arg">mboxref</i>?</span> <span class="opt">?<i class="arg">mboxname</i>?</span></a></li>
<li><a href="#5"><b class="cmd">::imap4::select</b> <i class="arg">chan</i> <span class="opt">?<i class="arg">mailbox</i>?</span></a></li>
486
487
488
489
490
491
492
493



494
Only a small part of rfc3501 implemented.</p>
</div>
<div id="see-also" class="doctools_section"><h2><a name="see-also">See Also</a></h2>
<p><a href="../ftp/ftp.html">ftp</a>, <a href="../../../../index.html#http">http</a>, <a href="../../../../index.html#imap">imap</a>, <a href="../mime/mime.html">mime</a>, <a href="../pop3/pop3.html">pop3</a>, <a href="../../../../index.html#tls">tls</a></p>
</div>
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#email">email</a>, <a href="../../../../index.html#imap">imap</a>, <a href="../../../../index.html#internet">internet</a>, <a href="../../../../index.html#mail">mail</a>, <a href="../../../../index.html#net">net</a>, <a href="../../../../index.html#rfc3501">rfc3501</a>, <a href="../../../../index.html#ssl">ssl</a>, <a href="../../../../index.html#tls">tls</a></p>
</div>



</div></body></html>








>
>
>

487
488
489
490
491
492
493
494
495
496
497
498
Only a small part of rfc3501 implemented.</p>
</div>
<div id="see-also" class="doctools_section"><h2><a name="see-also">See Also</a></h2>
<p><a href="../ftp/ftp.html">ftp</a>, <a href="../../../../index.html#http">http</a>, <a href="../../../../index.html#imap">imap</a>, <a href="../mime/mime.html">mime</a>, <a href="../pop3/pop3.html">pop3</a>, <a href="../../../../index.html#tls">tls</a></p>
</div>
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#email">email</a>, <a href="../../../../index.html#imap">imap</a>, <a href="../../../../index.html#internet">internet</a>, <a href="../../../../index.html#mail">mail</a>, <a href="../../../../index.html#net">net</a>, <a href="../../../../index.html#rfc3501">rfc3501</a>, <a href="../../../../index.html#ssl">ssl</a>, <a href="../../../../index.html#tls">tls</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Networking</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/log/loggerUtils.html.

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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">logger::utils(n) 1.3 tcllib &quot;Object Oriented logging facility&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>logger::utils - Utilities for logger</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">logger::utils <span class="opt">?1.3?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::logger::utils::createFormatCmd</b> <i class="arg">formatString</i></a></li>
<li><a href="#2"><b class="cmd">::logger::utils::createLogProc</b> <b class="option">-procName</b> <i class="arg">procName</i> <span class="opt">?<i class="arg">options</i>...?</span></a></li>
<li><a href="#3"><b class="cmd">::logger::utils::applyAppender</b> <b class="option">-appender</b> <i class="arg">appenderType</i> <span class="opt">?<i class="arg">options</i>...?</span></a></li>
<li><a href="#4"><b class="cmd">::logger::utils::autoApplyAppender</b> <i class="arg">command</i> <i class="arg">command-string</i> <i class="arg">log</i> <i class="arg">op</i> <i class="arg">args</i>...</a></li>
</ul>







|


















|







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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">logger::utils(n) 1.3.1 tcllib &quot;Object Oriented logging facility&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>logger::utils - Utilities for logger</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">logger::utils <span class="opt">?1.3.1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::logger::utils::createFormatCmd</b> <i class="arg">formatString</i></a></li>
<li><a href="#2"><b class="cmd">::logger::utils::createLogProc</b> <b class="option">-procName</b> <i class="arg">procName</i> <span class="opt">?<i class="arg">options</i>...?</span></a></li>
<li><a href="#3"><b class="cmd">::logger::utils::applyAppender</b> <b class="option">-appender</b> <i class="arg">appenderType</i> <span class="opt">?<i class="arg">options</i>...?</span></a></li>
<li><a href="#4"><b class="cmd">::logger::utils::autoApplyAppender</b> <i class="arg">command</i> <i class="arg">command-string</i> <i class="arg">log</i> <i class="arg">op</i> <i class="arg">args</i>...</a></li>
</ul>

Changes to idoc/www/tcllib/files/modules/markdown/markdown.html.

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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">markdown(n) 1.1 tcllib &quot;Markdown to HTML Converter&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>markdown - Converts Markdown text to HTML</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">Markdown 1.1</b></li>
<li>package require <b class="pkgname">textutil <span class="opt">?0.8?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::Markdown::convert</b> <i class="arg">markdown</i></a></li>
<li><a href="#2"><b class="cmd">::Markdown::register</b> <i class="arg">langspec</i> <i class="arg">converter</i></a></li>
<li><a href="#3"><b class="cmd">::Markdown::get_lang_counter</b></a></li>
<li><a href="#4"><b class="cmd">::Markdown::reset_lang_counter</b></a></li>







|
















|







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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">markdown(n) 1.1.1 tcllib &quot;Markdown to HTML Converter&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>markdown - Converts Markdown text to HTML</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">Markdown 1.1.1</b></li>
<li>package require <b class="pkgname">textutil <span class="opt">?0.8?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::Markdown::convert</b> <i class="arg">markdown</i></a></li>
<li><a href="#2"><b class="cmd">::Markdown::register</b> <i class="arg">langspec</i> <i class="arg">converter</i></a></li>
<li><a href="#3"><b class="cmd">::Markdown::get_lang_counter</b></a></li>
<li><a href="#4"><b class="cmd">::Markdown::reset_lang_counter</b></a></li>

Changes to idoc/www/tcllib/files/modules/math/math_geometry.html.

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
<li><a href="#8"><b class="cmd">::math::geometry::h</b> <i class="arg">length</i></a></li>
<li><a href="#9"><b class="cmd">::math::geometry::v</b> <i class="arg">length</i></a></li>
<li><a href="#10"><b class="cmd">::math::geometry::between</b> <i class="arg">point1</i> <i class="arg">point2</i> <i class="arg">s</i></a></li>
<li><a href="#11"><b class="cmd">::math::geometry::octant</b> <i class="arg">point</i></a></li>
<li><a href="#12"><b class="cmd">::math::geometry::rect</b> <i class="arg">nw</i> <i class="arg">se</i></a></li>
<li><a href="#13"><b class="cmd">::math::geometry::nwse</b> <i class="arg">rect</i></a></li>
<li><a href="#14"><b class="cmd">::math::geometry::angle</b> <i class="arg">line</i></a></li>



<li><a href="#15"><b class="cmd">::math::geometry::calculateDistanceToLine</b> <i class="arg">P</i> <i class="arg">line</i></a></li>
<li><a href="#16"><b class="cmd">::math::geometry::calculateDistanceToLineSegment</b> <i class="arg">P</i> <i class="arg">linesegment</i></a></li>
<li><a href="#17"><b class="cmd">::math::geometry::calculateDistanceToPolyline</b> <i class="arg">P</i> <i class="arg">polyline</i></a></li>
<li><a href="#18"><b class="cmd">::math::geometry::calculateDistanceToPolygon</b> <i class="arg">P</i> <i class="arg">polygon</i></a></li>
<li><a href="#19"><b class="cmd">::math::geometry::findClosestPointOnLine</b> <i class="arg">P</i> <i class="arg">line</i></a></li>
<li><a href="#20"><b class="cmd">::math::geometry::findClosestPointOnLineSegment</b> <i class="arg">P</i> <i class="arg">linesegment</i></a></li>
<li><a href="#21"><b class="cmd">::math::geometry::findClosestPointOnPolyline</b> <i class="arg">P</i> <i class="arg">polyline</i></a></li>
<li><a href="#22"><b class="cmd">::math::geometry::lengthOfPolyline</b> <i class="arg">polyline</i></a></li>
<li><a href="#23"><b class="cmd">::math::geometry::movePointInDirection</b> <i class="arg">P</i> <i class="arg">direction</i> <i class="arg">dist</i></a></li>
<li><a href="#24"><b class="cmd">::math::geometry::lineSegmentsIntersect</b> <i class="arg">linesegment1</i> <i class="arg">linesegment2</i></a></li>
<li><a href="#25"><b class="cmd">::math::geometry::findLineSegmentIntersection</b> <i class="arg">linesegment1</i> <i class="arg">linesegment2</i></a></li>
<li><a href="#26"><b class="cmd">::math::geometry::findLineIntersection</b> <i class="arg">line1</i> <i class="arg">line2</i></a></li>
<li><a href="#27"><b class="cmd">::math::geometry::polylinesIntersect</b> <i class="arg">polyline1</i> <i class="arg">polyline2</i></a></li>
<li><a href="#28"><b class="cmd">::math::geometry::polylinesBoundingIntersect</b> <i class="arg">polyline1</i> <i class="arg">polyline2</i> <i class="arg">granularity</i></a></li>
<li><a href="#29"><b class="cmd">::math::geometry::intervalsOverlap</b> <i class="arg">y1</i> <i class="arg">y2</i> <i class="arg">y3</i> <i class="arg">y4</i> <i class="arg">strict</i></a></li>
<li><a href="#30"><b class="cmd">::math::geometry::rectanglesOverlap</b> <i class="arg">P1</i> <i class="arg">P2</i> <i class="arg">Q1</i> <i class="arg">Q2</i> <i class="arg">strict</i></a></li>
<li><a href="#31"><b class="cmd">::math::geometry::bbox</b> <i class="arg">polyline</i></a></li>
<li><a href="#32"><b class="cmd">::math::geometry::pointInsidePolygon</b> <i class="arg">P</i> <i class="arg">polyline</i></a></li>
<li><a href="#33"><b class="cmd">::math::geometry::pointInsidePolygonAlt</b> <i class="arg">P</i> <i class="arg">polyline</i></a></li>
<li><a href="#34"><b class="cmd">::math::geometry::rectangleInsidePolygon</b> <i class="arg">P1</i> <i class="arg">P2</i> <i class="arg">polyline</i></a></li>
<li><a href="#35"><b class="cmd">::math::geometry::areaPolygon</b> <i class="arg">polygon</i></a></li>
<li><a href="#36"><b class="cmd">::math::geometry::translate</b> <i class="arg">vector</i> <i class="arg">polyline</i></a></li>
<li><a href="#37"><b class="cmd">::math::geometry::rotate</b> <i class="arg">angle</i> <i class="arg">polyline</i></a></li>
<li><a href="#38"><b class="cmd">::math::geometry::reflect</b> <i class="arg">angle</i> <i class="arg">polyline</i></a></li>
<li><a href="#39"><b class="cmd">::math::geometry::degToRad</b> <i class="arg">angle</i></a></li>
<li><a href="#40"><b class="cmd">::math::geometry::radToDeg</b> <i class="arg">angle</i></a></li>
<li><a href="#41"><b class="cmd">::math::geometry::circle</b> <i class="arg">centre</i> <i class="arg">radius</i></a></li>
<li><a href="#42"><b class="cmd">::math::geometry::circleTwoPoints</b> <i class="arg">point1</i> <i class="arg">point2</i></a></li>
<li><a href="#43"><b class="cmd">::math::geometry::pointInsideCircle</b> <i class="arg">point</i> <i class="arg">circle</i></a></li>
<li><a href="#44"><b class="cmd">::math::geometry::lineIntersectsCircle</b> <i class="arg">line</i> <i class="arg">circle</i></a></li>
<li><a href="#45"><b class="cmd">::math::geometry::lineSegmentIntersectsCircle</b> <i class="arg">segment</i> <i class="arg">circle</i></a></li>
<li><a href="#46"><b class="cmd">::math::geometry::intersectionLineWithCircle</b> <i class="arg">line</i> <i class="arg">circle</i></a></li>
<li><a href="#47"><b class="cmd">::math::geometry::intersectionCircleWithCircle</b> <i class="arg">circle1</i> <i class="arg">circle2</i></a></li>
<li><a href="#48"><b class="cmd">::math::geometry::tangentLinesToCircle</b> <i class="arg">point</i> <i class="arg">circle</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>The <b class="package">math::geometry</b> package is a collection of functions for
computations and manipulations on two-dimensional geometrical objects,
such as points, lines and polygons.</p>







>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







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
<li><a href="#8"><b class="cmd">::math::geometry::h</b> <i class="arg">length</i></a></li>
<li><a href="#9"><b class="cmd">::math::geometry::v</b> <i class="arg">length</i></a></li>
<li><a href="#10"><b class="cmd">::math::geometry::between</b> <i class="arg">point1</i> <i class="arg">point2</i> <i class="arg">s</i></a></li>
<li><a href="#11"><b class="cmd">::math::geometry::octant</b> <i class="arg">point</i></a></li>
<li><a href="#12"><b class="cmd">::math::geometry::rect</b> <i class="arg">nw</i> <i class="arg">se</i></a></li>
<li><a href="#13"><b class="cmd">::math::geometry::nwse</b> <i class="arg">rect</i></a></li>
<li><a href="#14"><b class="cmd">::math::geometry::angle</b> <i class="arg">line</i></a></li>
<li><a href="#15"><b class="cmd">::math::geometry::angleBetween</b> <i class="arg">vector1</i> <i class="arg">vector2</i></a></li>
<li><a href="#16"><b class="cmd">::math::geometry::inproduct</b> <i class="arg">vector1</i> <i class="arg">vector2</i></a></li>
<li><a href="#17"><b class="cmd">::math::geometry::areaParallellogram</b> <i class="arg">vector1</i> <i class="arg">vector2</i></a></li>
<li><a href="#18"><b class="cmd">::math::geometry::calculateDistanceToLine</b> <i class="arg">P</i> <i class="arg">line</i></a></li>
<li><a href="#19"><b class="cmd">::math::geometry::calculateDistanceToLineSegment</b> <i class="arg">P</i> <i class="arg">linesegment</i></a></li>
<li><a href="#20"><b class="cmd">::math::geometry::calculateDistanceToPolyline</b> <i class="arg">P</i> <i class="arg">polyline</i></a></li>
<li><a href="#21"><b class="cmd">::math::geometry::calculateDistanceToPolygon</b> <i class="arg">P</i> <i class="arg">polygon</i></a></li>
<li><a href="#22"><b class="cmd">::math::geometry::findClosestPointOnLine</b> <i class="arg">P</i> <i class="arg">line</i></a></li>
<li><a href="#23"><b class="cmd">::math::geometry::findClosestPointOnLineSegment</b> <i class="arg">P</i> <i class="arg">linesegment</i></a></li>
<li><a href="#24"><b class="cmd">::math::geometry::findClosestPointOnPolyline</b> <i class="arg">P</i> <i class="arg">polyline</i></a></li>
<li><a href="#25"><b class="cmd">::math::geometry::lengthOfPolyline</b> <i class="arg">polyline</i></a></li>
<li><a href="#26"><b class="cmd">::math::geometry::movePointInDirection</b> <i class="arg">P</i> <i class="arg">direction</i> <i class="arg">dist</i></a></li>
<li><a href="#27"><b class="cmd">::math::geometry::lineSegmentsIntersect</b> <i class="arg">linesegment1</i> <i class="arg">linesegment2</i></a></li>
<li><a href="#28"><b class="cmd">::math::geometry::findLineSegmentIntersection</b> <i class="arg">linesegment1</i> <i class="arg">linesegment2</i></a></li>
<li><a href="#29"><b class="cmd">::math::geometry::findLineIntersection</b> <i class="arg">line1</i> <i class="arg">line2</i></a></li>
<li><a href="#30"><b class="cmd">::math::geometry::polylinesIntersect</b> <i class="arg">polyline1</i> <i class="arg">polyline2</i></a></li>
<li><a href="#31"><b class="cmd">::math::geometry::polylinesBoundingIntersect</b> <i class="arg">polyline1</i> <i class="arg">polyline2</i> <i class="arg">granularity</i></a></li>
<li><a href="#32"><b class="cmd">::math::geometry::intervalsOverlap</b> <i class="arg">y1</i> <i class="arg">y2</i> <i class="arg">y3</i> <i class="arg">y4</i> <i class="arg">strict</i></a></li>
<li><a href="#33"><b class="cmd">::math::geometry::rectanglesOverlap</b> <i class="arg">P1</i> <i class="arg">P2</i> <i class="arg">Q1</i> <i class="arg">Q2</i> <i class="arg">strict</i></a></li>
<li><a href="#34"><b class="cmd">::math::geometry::bbox</b> <i class="arg">polyline</i></a></li>
<li><a href="#35"><b class="cmd">::math::geometry::pointInsidePolygon</b> <i class="arg">P</i> <i class="arg">polyline</i></a></li>
<li><a href="#36"><b class="cmd">::math::geometry::pointInsidePolygonAlt</b> <i class="arg">P</i> <i class="arg">polyline</i></a></li>
<li><a href="#37"><b class="cmd">::math::geometry::rectangleInsidePolygon</b> <i class="arg">P1</i> <i class="arg">P2</i> <i class="arg">polyline</i></a></li>
<li><a href="#38"><b class="cmd">::math::geometry::areaPolygon</b> <i class="arg">polygon</i></a></li>
<li><a href="#39"><b class="cmd">::math::geometry::translate</b> <i class="arg">vector</i> <i class="arg">polyline</i></a></li>
<li><a href="#40"><b class="cmd">::math::geometry::rotate</b> <i class="arg">angle</i> <i class="arg">polyline</i></a></li>
<li><a href="#41"><b class="cmd">::math::geometry::reflect</b> <i class="arg">angle</i> <i class="arg">polyline</i></a></li>
<li><a href="#42"><b class="cmd">::math::geometry::degToRad</b> <i class="arg">angle</i></a></li>
<li><a href="#43"><b class="cmd">::math::geometry::radToDeg</b> <i class="arg">angle</i></a></li>
<li><a href="#44"><b class="cmd">::math::geometry::circle</b> <i class="arg">centre</i> <i class="arg">radius</i></a></li>
<li><a href="#45"><b class="cmd">::math::geometry::circleTwoPoints</b> <i class="arg">point1</i> <i class="arg">point2</i></a></li>
<li><a href="#46"><b class="cmd">::math::geometry::pointInsideCircle</b> <i class="arg">point</i> <i class="arg">circle</i></a></li>
<li><a href="#47"><b class="cmd">::math::geometry::lineIntersectsCircle</b> <i class="arg">line</i> <i class="arg">circle</i></a></li>
<li><a href="#48"><b class="cmd">::math::geometry::lineSegmentIntersectsCircle</b> <i class="arg">segment</i> <i class="arg">circle</i></a></li>
<li><a href="#49"><b class="cmd">::math::geometry::intersectionLineWithCircle</b> <i class="arg">line</i> <i class="arg">circle</i></a></li>
<li><a href="#50"><b class="cmd">::math::geometry::intersectionCircleWithCircle</b> <i class="arg">circle1</i> <i class="arg">circle2</i></a></li>
<li><a href="#51"><b class="cmd">::math::geometry::tangentLinesToCircle</b> <i class="arg">point</i> <i class="arg">circle</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>The <b class="package">math::geometry</b> package is a collection of functions for
computations and manipulations on two-dimensional geometrical objects,
such as points, lines and polygons.</p>
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
<dt><a name="14"><b class="cmd">::math::geometry::angle</b> <i class="arg">line</i></a></dt>
<dd><p>Calculate the angle from the positive x-axis to a given line
(in two dimensions only).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">line</i></dt>
<dd><p>Coordinates of the line</p></dd>
</dl></dd>
























<dt><a name="15"><b class="cmd">::math::geometry::calculateDistanceToLine</b> <i class="arg">P</i> <i class="arg">line</i></a></dt>
<dd><p>Calculate the distance of point P to the (infinite) line and return the
result</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>List of two numbers, the coordinates of the point</p></dd>
<dt>list <i class="arg">line</i></dt>
<dd><p>List of four numbers, the coordinates of two points
on the line</p></dd>
</dl></dd>
<dt><a name="16"><b class="cmd">::math::geometry::calculateDistanceToLineSegment</b> <i class="arg">P</i> <i class="arg">linesegment</i></a></dt>
<dd><p>Calculate the distance of point P to the (finite) line segment and
return the result.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>List of two numbers, the coordinates of the point</p></dd>
<dt>list <i class="arg">linesegment</i></dt>
<dd><p>List of four numbers, the coordinates of the
first and last points of the line segment</p></dd>
</dl></dd>
<dt><a name="17"><b class="cmd">::math::geometry::calculateDistanceToPolyline</b> <i class="arg">P</i> <i class="arg">polyline</i></a></dt>
<dd><p>Calculate the distance of point P to the polyline and
return the result. Note that a polyline needs not to be closed.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>List of two numbers, the coordinates of the point</p></dd>
<dt>list <i class="arg">polyline</i></dt>
<dd><p>List of numbers, the coordinates of the
vertices of the polyline</p></dd>
</dl></dd>
<dt><a name="18"><b class="cmd">::math::geometry::calculateDistanceToPolygon</b> <i class="arg">P</i> <i class="arg">polygon</i></a></dt>
<dd><p>Calculate the distance of point P to the polygon and
return the result. If the list of coordinates is not closed (first and last
points differ), it is automatically closed.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>List of two numbers, the coordinates of the point</p></dd>
<dt>list <i class="arg">polygon</i></dt>
<dd><p>List of numbers, the coordinates of the
vertices of the polygon</p></dd>
</dl></dd>
<dt><a name="19"><b class="cmd">::math::geometry::findClosestPointOnLine</b> <i class="arg">P</i> <i class="arg">line</i></a></dt>
<dd><p>Return the point on a line which is closest to a given point.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>List of two numbers, the coordinates of the point</p></dd>
<dt>list <i class="arg">line</i></dt>
<dd><p>List of four numbers, the coordinates of two points
on the line</p></dd>
</dl></dd>
<dt><a name="20"><b class="cmd">::math::geometry::findClosestPointOnLineSegment</b> <i class="arg">P</i> <i class="arg">linesegment</i></a></dt>
<dd><p>Return the point on a <em>line segment</em> which is closest to a given
point.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>List of two numbers, the coordinates of the point</p></dd>
<dt>list <i class="arg">linesegment</i></dt>
<dd><p>List of four numbers, the first and last
points on the line segment</p></dd>
</dl></dd>
<dt><a name="21"><b class="cmd">::math::geometry::findClosestPointOnPolyline</b> <i class="arg">P</i> <i class="arg">polyline</i></a></dt>
<dd><p>Return the point on a <em>polyline</em> which is closest to a given
point.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>List of two numbers, the coordinates of the point</p></dd>
<dt>list <i class="arg">polyline</i></dt>
<dd><p>List of numbers, the vertices of the polyline</p></dd>
</dl></dd>
<dt><a name="22"><b class="cmd">::math::geometry::lengthOfPolyline</b> <i class="arg">polyline</i></a></dt>
<dd><p>Return the length of the <em>polyline</em> (note: it not regarded as a
polygon)</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">polyline</i></dt>
<dd><p>List of numbers, the vertices of the polyline</p></dd>
</dl></dd>
<dt><a name="23"><b class="cmd">::math::geometry::movePointInDirection</b> <i class="arg">P</i> <i class="arg">direction</i> <i class="arg">dist</i></a></dt>
<dd><p>Move a point over a given distance in a given direction and return the
new coordinates (in two dimensions only).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>Coordinates of the point to be moved</p></dd>
<dt>double <i class="arg">direction</i></dt>
<dd><p>Direction (in degrees; 0 is to the right, 90
upwards)</p></dd>
<dt>list <i class="arg">dist</i></dt>
<dd><p>Distance over which to move the point</p></dd>
</dl></dd>
<dt><a name="24"><b class="cmd">::math::geometry::lineSegmentsIntersect</b> <i class="arg">linesegment1</i> <i class="arg">linesegment2</i></a></dt>
<dd><p>Check if two line segments intersect or coincide. Returns 1 if that is
the case, 0 otherwise (in two dimensions only). If an endpoint of one segment lies on
the other segment (or is very close to the segment), they are considered to intersect</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">linesegment1</i></dt>
<dd><p>First line segment</p></dd>
<dt>list <i class="arg">linesegment2</i></dt>
<dd><p>Second line segment</p></dd>
</dl></dd>
<dt><a name="25"><b class="cmd">::math::geometry::findLineSegmentIntersection</b> <i class="arg">linesegment1</i> <i class="arg">linesegment2</i></a></dt>
<dd><p>Find the intersection point of two line segments. Return the coordinates
or the keywords &quot;coincident&quot; or &quot;none&quot; if the line segments coincide or
have no points in common (in two dimensions only).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">linesegment1</i></dt>
<dd><p>First line segment</p></dd>
<dt>list <i class="arg">linesegment2</i></dt>
<dd><p>Second line segment</p></dd>
</dl></dd>
<dt><a name="26"><b class="cmd">::math::geometry::findLineIntersection</b> <i class="arg">line1</i> <i class="arg">line2</i></a></dt>
<dd><p>Find the intersection point of two (infinite) lines. Return the coordinates
or the keywords &quot;coincident&quot; or &quot;none&quot; if the lines coincide or
have no points in common (in two dimensions only).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">line1</i></dt>
<dd><p>First line</p></dd>
<dt>list <i class="arg">line2</i></dt>
<dd><p>Second line</p></dd>
</dl>
<p>See section <span class="sectref"><a href="#section3">References</a></span> for details on the algorithm and math behind it.</p></dd>
<dt><a name="27"><b class="cmd">::math::geometry::polylinesIntersect</b> <i class="arg">polyline1</i> <i class="arg">polyline2</i></a></dt>
<dd><p>Check if two polylines intersect or not (in two dimensions only).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">polyline1</i></dt>
<dd><p>First polyline</p></dd>
<dt>list <i class="arg">polyline2</i></dt>
<dd><p>Second polyline</p></dd>
</dl></dd>
<dt><a name="28"><b class="cmd">::math::geometry::polylinesBoundingIntersect</b> <i class="arg">polyline1</i> <i class="arg">polyline2</i> <i class="arg">granularity</i></a></dt>
<dd><p>Check whether two polylines intersect, but reduce
the correctness of the result to the given granularity.
Use this for faster, but weaker, intersection checking.</p>
<p>How it works:</p>
<p>Each polyline is split into a number of smaller polylines,
consisting of granularity points each. If a pair of those smaller
lines' bounding boxes intersect, then this procedure returns 1,
otherwise it returns 0.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">polyline1</i></dt>
<dd><p>First polyline</p></dd>
<dt>list <i class="arg">polyline2</i></dt>
<dd><p>Second polyline</p></dd>
<dt>int <i class="arg">granularity</i></dt>
<dd><p>Number of points in each part (&lt;=1 means check
every edge)</p></dd>
</dl></dd>
<dt><a name="29"><b class="cmd">::math::geometry::intervalsOverlap</b> <i class="arg">y1</i> <i class="arg">y2</i> <i class="arg">y3</i> <i class="arg">y4</i> <i class="arg">strict</i></a></dt>
<dd><p>Check if two intervals overlap.</p>
<dl class="doctools_arguments">
<dt>double <i class="arg">y1,y2</i></dt>
<dd><p>Begin and end of first interval</p></dd>
<dt>double <i class="arg">y3,y4</i></dt>
<dd><p>Begin and end of second interval</p></dd>
<dt>logical <i class="arg">strict</i></dt>
<dd><p>Check for strict or non-strict overlap</p></dd>
</dl></dd>
<dt><a name="30"><b class="cmd">::math::geometry::rectanglesOverlap</b> <i class="arg">P1</i> <i class="arg">P2</i> <i class="arg">Q1</i> <i class="arg">Q2</i> <i class="arg">strict</i></a></dt>
<dd><p>Check if two rectangles overlap.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P1</i></dt>
<dd><p>upper-left corner of the first rectangle</p></dd>
<dt>list <i class="arg">P2</i></dt>
<dd><p>lower-right corner of the first rectangle</p></dd>
<dt>list <i class="arg">Q1</i></dt>
<dd><p>upper-left corner of the second rectangle</p></dd>
<dt>list <i class="arg">Q2</i></dt>
<dd><p>lower-right corner of the second rectangle</p></dd>
<dt>list <i class="arg">strict</i></dt>
<dd><p>choosing strict or non-strict interpretation</p></dd>
</dl></dd>
<dt><a name="31"><b class="cmd">::math::geometry::bbox</b> <i class="arg">polyline</i></a></dt>
<dd><p>Calculate the bounding box of a polyline. Returns a list of four
coordinates: the upper-left and the lower-right corner of the box.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">polyline</i></dt>
<dd><p>The polyline to be examined</p></dd>
</dl></dd>
<dt><a name="32"><b class="cmd">::math::geometry::pointInsidePolygon</b> <i class="arg">P</i> <i class="arg">polyline</i></a></dt>
<dd><p>Determine if a point is completely inside a polygon. If the point
touches the polygon, then the point is not completely inside the
polygon.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>Coordinates of the point</p></dd>
<dt>list <i class="arg">polyline</i></dt>
<dd><p>The polyline to be examined</p></dd>
</dl></dd>
<dt><a name="33"><b class="cmd">::math::geometry::pointInsidePolygonAlt</b> <i class="arg">P</i> <i class="arg">polyline</i></a></dt>
<dd><p>Determine if a point is completely inside a polygon. If the point
touches the polygon, then the point is not completely inside the
polygon. <em>Note:</em> this alternative procedure uses the so-called
winding number to determine this. It handles self-intersecting polygons
in a &quot;natural&quot; way.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>Coordinates of the point</p></dd>
<dt>list <i class="arg">polyline</i></dt>
<dd><p>The polyline to be examined</p></dd>
</dl></dd>
<dt><a name="34"><b class="cmd">::math::geometry::rectangleInsidePolygon</b> <i class="arg">P1</i> <i class="arg">P2</i> <i class="arg">polyline</i></a></dt>
<dd><p>Determine if a rectangle is completely inside a polygon. If polygon
touches the rectangle, then the rectangle is not complete inside the
polygon.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P1</i></dt>
<dd><p>Upper-left corner of the rectangle</p></dd>
<dt>list <i class="arg">P2</i></dt>
<dd><p>Lower-right corner of the rectangle</p></dd>
<dt>list <i class="arg">polygon</i></dt>
<dd><p>The polygon in question</p></dd>
</dl></dd>
<dt><a name="35"><b class="cmd">::math::geometry::areaPolygon</b> <i class="arg">polygon</i></a></dt>
<dd><p>Calculate the area of a polygon.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">polygon</i></dt>
<dd><p>The polygon in question</p></dd>
</dl></dd>
<dt><a name="36"><b class="cmd">::math::geometry::translate</b> <i class="arg">vector</i> <i class="arg">polyline</i></a></dt>
<dd><p>Translate a polyline over a given vector</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">vector</i></dt>
<dd><p>Translation vector</p></dd>
<dt>list <i class="arg">polyline</i></dt>
<dd><p>The polyline to be rotated</p></dd>
</dl></dd>
<dt><a name="37"><b class="cmd">::math::geometry::rotate</b> <i class="arg">angle</i> <i class="arg">polyline</i></a></dt>
<dd><p>Rotate a polyline over a given angle (degrees) around the origin</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">angle</i></dt>
<dd><p>Angle over which to rotate the polyline (degrees)</p></dd>
<dt>list <i class="arg">polyline</i></dt>
<dd><p>The polyline to be translated</p></dd>
</dl></dd>
<dt><a name="38"><b class="cmd">::math::geometry::reflect</b> <i class="arg">angle</i> <i class="arg">polyline</i></a></dt>
<dd><p>Reflect a polyline in a line through the origin at a given angle (degrees) to the x-axis</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">angle</i></dt>
<dd><p>Angle of the line of reflection (degrees)</p></dd>
<dt>list <i class="arg">polyline</i></dt>
<dd><p>The polyline to be reflected</p></dd>
</dl></dd>
<dt><a name="39"><b class="cmd">::math::geometry::degToRad</b> <i class="arg">angle</i></a></dt>
<dd><p>Convert from degrees to radians</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">angle</i></dt>
<dd><p>Angle in degrees</p></dd>
</dl></dd>
<dt><a name="40"><b class="cmd">::math::geometry::radToDeg</b> <i class="arg">angle</i></a></dt>
<dd><p>Convert from radians to degrees</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">angle</i></dt>
<dd><p>Angle in radians</p></dd>
</dl></dd>
<dt><a name="41"><b class="cmd">::math::geometry::circle</b> <i class="arg">centre</i> <i class="arg">radius</i></a></dt>
<dd><p>Convenience procedure to create a circle from a point and a radius.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">centre</i></dt>
<dd><p>Coordinates of the circle centre</p></dd>
<dt>list <i class="arg">radius</i></dt>
<dd><p>Radius of the circle</p></dd>
</dl></dd>
<dt><a name="42"><b class="cmd">::math::geometry::circleTwoPoints</b> <i class="arg">point1</i> <i class="arg">point2</i></a></dt>
<dd><p>Convenience procedure to create a circle from two points on its circumference
The centre is the point between the two given points, the radius is half the
distance between them.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">point1</i></dt>
<dd><p>First point</p></dd>
<dt>list <i class="arg">point2</i></dt>
<dd><p>Second point</p></dd>
</dl></dd>
<dt><a name="43"><b class="cmd">::math::geometry::pointInsideCircle</b> <i class="arg">point</i> <i class="arg">circle</i></a></dt>
<dd><p>Determine if the given point is inside the circle or on the circumference (1)
or outside (0).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">point</i></dt>
<dd><p>Point to be checked</p></dd>
<dt>list <i class="arg">circle</i></dt>
<dd><p>Circle that may or may not contain the point</p></dd>
</dl></dd>
<dt><a name="44"><b class="cmd">::math::geometry::lineIntersectsCircle</b> <i class="arg">line</i> <i class="arg">circle</i></a></dt>
<dd><p>Determine if the given line intersects the circle or touches it (1)
or does not (0).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">line</i></dt>
<dd><p>Line to be checked</p></dd>
<dt>list <i class="arg">circle</i></dt>
<dd><p>Circle that may or may not be intersected</p></dd>
</dl></dd>
<dt><a name="45"><b class="cmd">::math::geometry::lineSegmentIntersectsCircle</b> <i class="arg">segment</i> <i class="arg">circle</i></a></dt>
<dd><p>Determine if the given line segment intersects the circle or touches it (1)
or does not (0).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">segment</i></dt>
<dd><p>Line segment to be checked</p></dd>
<dt>list <i class="arg">circle</i></dt>
<dd><p>Circle that may or may not be intersected</p></dd>
</dl></dd>
<dt><a name="46"><b class="cmd">::math::geometry::intersectionLineWithCircle</b> <i class="arg">line</i> <i class="arg">circle</i></a></dt>
<dd><p>Determine the points at which the given line intersects the circle. There can
be zero, one or two points. (If the line touches the circle or is close to it,
then one point is returned. An arbitrary margin of 1.0e-10 times the radius
is used to determine this situation.)</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">line</i></dt>
<dd><p>Line to be checked</p></dd>
<dt>list <i class="arg">circle</i></dt>
<dd><p>Circle that may or may not be intersected</p></dd>
</dl></dd>
<dt><a name="47"><b class="cmd">::math::geometry::intersectionCircleWithCircle</b> <i class="arg">circle1</i> <i class="arg">circle2</i></a></dt>
<dd><p>Determine the points at which the given two circles intersect. There can
be zero, one or two points. (If the two circles touch the circle or are very close,
then one point is returned. An arbitrary margin of 1.0e-10 times the mean of the radii of
the two circles is used to determine this situation.)</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">circle1</i></dt>
<dd><p>First circle</p></dd>
<dt>list <i class="arg">circle2</i></dt>
<dd><p>Second circle</p></dd>
</dl></dd>
<dt><a name="48"><b class="cmd">::math::geometry::tangentLinesToCircle</b> <i class="arg">point</i> <i class="arg">circle</i></a></dt>
<dd><p>Determine the tangent lines from the given point to the circle. There can
be zero, one or two lines. (If the point is on the cirucmference or very close to
the circle, then one line is returned. An arbitrary margin of 1.0e-10 times the
radius of the circle is used to determine this situation.)</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">point</i></dt>
<dd><p>Point in question</p></dd>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|









|









|









|










|








|









|








|






|











|









|









|










|







|

















|









|













|






|









|











|











|





|





|

|





|

|







|





|





|







|









|








|








|








|










|










|







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
<dt><a name="14"><b class="cmd">::math::geometry::angle</b> <i class="arg">line</i></a></dt>
<dd><p>Calculate the angle from the positive x-axis to a given line
(in two dimensions only).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">line</i></dt>
<dd><p>Coordinates of the line</p></dd>
</dl></dd>
<dt><a name="15"><b class="cmd">::math::geometry::angleBetween</b> <i class="arg">vector1</i> <i class="arg">vector2</i></a></dt>
<dd><p>Calculate the angle between two vectors (in degrees)</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">vector1</i></dt>
<dd><p>First vector</p></dd>
<dt>list <i class="arg">vector2</i></dt>
<dd><p>Second vector</p></dd>
</dl></dd>
<dt><a name="16"><b class="cmd">::math::geometry::inproduct</b> <i class="arg">vector1</i> <i class="arg">vector2</i></a></dt>
<dd><p>Calculate the inner product of two vectors</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">vector1</i></dt>
<dd><p>First vector</p></dd>
<dt>list <i class="arg">vector2</i></dt>
<dd><p>Second vector</p></dd>
</dl></dd>
<dt><a name="17"><b class="cmd">::math::geometry::areaParallellogram</b> <i class="arg">vector1</i> <i class="arg">vector2</i></a></dt>
<dd><p>Calculate the area of the parallellogram with the two vectors as its sides</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">vector1</i></dt>
<dd><p>First vector</p></dd>
<dt>list <i class="arg">vector2</i></dt>
<dd><p>Second vector</p></dd>
</dl></dd>
<dt><a name="18"><b class="cmd">::math::geometry::calculateDistanceToLine</b> <i class="arg">P</i> <i class="arg">line</i></a></dt>
<dd><p>Calculate the distance of point P to the (infinite) line and return the
result</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>List of two numbers, the coordinates of the point</p></dd>
<dt>list <i class="arg">line</i></dt>
<dd><p>List of four numbers, the coordinates of two points
on the line</p></dd>
</dl></dd>
<dt><a name="19"><b class="cmd">::math::geometry::calculateDistanceToLineSegment</b> <i class="arg">P</i> <i class="arg">linesegment</i></a></dt>
<dd><p>Calculate the distance of point P to the (finite) line segment and
return the result.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>List of two numbers, the coordinates of the point</p></dd>
<dt>list <i class="arg">linesegment</i></dt>
<dd><p>List of four numbers, the coordinates of the
first and last points of the line segment</p></dd>
</dl></dd>
<dt><a name="20"><b class="cmd">::math::geometry::calculateDistanceToPolyline</b> <i class="arg">P</i> <i class="arg">polyline</i></a></dt>
<dd><p>Calculate the distance of point P to the polyline and
return the result. Note that a polyline needs not to be closed.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>List of two numbers, the coordinates of the point</p></dd>
<dt>list <i class="arg">polyline</i></dt>
<dd><p>List of numbers, the coordinates of the
vertices of the polyline</p></dd>
</dl></dd>
<dt><a name="21"><b class="cmd">::math::geometry::calculateDistanceToPolygon</b> <i class="arg">P</i> <i class="arg">polygon</i></a></dt>
<dd><p>Calculate the distance of point P to the polygon and
return the result. If the list of coordinates is not closed (first and last
points differ), it is automatically closed.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>List of two numbers, the coordinates of the point</p></dd>
<dt>list <i class="arg">polygon</i></dt>
<dd><p>List of numbers, the coordinates of the
vertices of the polygon</p></dd>
</dl></dd>
<dt><a name="22"><b class="cmd">::math::geometry::findClosestPointOnLine</b> <i class="arg">P</i> <i class="arg">line</i></a></dt>
<dd><p>Return the point on a line which is closest to a given point.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>List of two numbers, the coordinates of the point</p></dd>
<dt>list <i class="arg">line</i></dt>
<dd><p>List of four numbers, the coordinates of two points
on the line</p></dd>
</dl></dd>
<dt><a name="23"><b class="cmd">::math::geometry::findClosestPointOnLineSegment</b> <i class="arg">P</i> <i class="arg">linesegment</i></a></dt>
<dd><p>Return the point on a <em>line segment</em> which is closest to a given
point.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>List of two numbers, the coordinates of the point</p></dd>
<dt>list <i class="arg">linesegment</i></dt>
<dd><p>List of four numbers, the first and last
points on the line segment</p></dd>
</dl></dd>
<dt><a name="24"><b class="cmd">::math::geometry::findClosestPointOnPolyline</b> <i class="arg">P</i> <i class="arg">polyline</i></a></dt>
<dd><p>Return the point on a <em>polyline</em> which is closest to a given
point.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>List of two numbers, the coordinates of the point</p></dd>
<dt>list <i class="arg">polyline</i></dt>
<dd><p>List of numbers, the vertices of the polyline</p></dd>
</dl></dd>
<dt><a name="25"><b class="cmd">::math::geometry::lengthOfPolyline</b> <i class="arg">polyline</i></a></dt>
<dd><p>Return the length of the <em>polyline</em> (note: it not regarded as a
polygon)</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">polyline</i></dt>
<dd><p>List of numbers, the vertices of the polyline</p></dd>
</dl></dd>
<dt><a name="26"><b class="cmd">::math::geometry::movePointInDirection</b> <i class="arg">P</i> <i class="arg">direction</i> <i class="arg">dist</i></a></dt>
<dd><p>Move a point over a given distance in a given direction and return the
new coordinates (in two dimensions only).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>Coordinates of the point to be moved</p></dd>
<dt>double <i class="arg">direction</i></dt>
<dd><p>Direction (in degrees; 0 is to the right, 90
upwards)</p></dd>
<dt>list <i class="arg">dist</i></dt>
<dd><p>Distance over which to move the point</p></dd>
</dl></dd>
<dt><a name="27"><b class="cmd">::math::geometry::lineSegmentsIntersect</b> <i class="arg">linesegment1</i> <i class="arg">linesegment2</i></a></dt>
<dd><p>Check if two line segments intersect or coincide. Returns 1 if that is
the case, 0 otherwise (in two dimensions only). If an endpoint of one segment lies on
the other segment (or is very close to the segment), they are considered to intersect</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">linesegment1</i></dt>
<dd><p>First line segment</p></dd>
<dt>list <i class="arg">linesegment2</i></dt>
<dd><p>Second line segment</p></dd>
</dl></dd>
<dt><a name="28"><b class="cmd">::math::geometry::findLineSegmentIntersection</b> <i class="arg">linesegment1</i> <i class="arg">linesegment2</i></a></dt>
<dd><p>Find the intersection point of two line segments. Return the coordinates
or the keywords &quot;coincident&quot; or &quot;none&quot; if the line segments coincide or
have no points in common (in two dimensions only).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">linesegment1</i></dt>
<dd><p>First line segment</p></dd>
<dt>list <i class="arg">linesegment2</i></dt>
<dd><p>Second line segment</p></dd>
</dl></dd>
<dt><a name="29"><b class="cmd">::math::geometry::findLineIntersection</b> <i class="arg">line1</i> <i class="arg">line2</i></a></dt>
<dd><p>Find the intersection point of two (infinite) lines. Return the coordinates
or the keywords &quot;coincident&quot; or &quot;none&quot; if the lines coincide or
have no points in common (in two dimensions only).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">line1</i></dt>
<dd><p>First line</p></dd>
<dt>list <i class="arg">line2</i></dt>
<dd><p>Second line</p></dd>
</dl>
<p>See section <span class="sectref"><a href="#section3">References</a></span> for details on the algorithm and math behind it.</p></dd>
<dt><a name="30"><b class="cmd">::math::geometry::polylinesIntersect</b> <i class="arg">polyline1</i> <i class="arg">polyline2</i></a></dt>
<dd><p>Check if two polylines intersect or not (in two dimensions only).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">polyline1</i></dt>
<dd><p>First polyline</p></dd>
<dt>list <i class="arg">polyline2</i></dt>
<dd><p>Second polyline</p></dd>
</dl></dd>
<dt><a name="31"><b class="cmd">::math::geometry::polylinesBoundingIntersect</b> <i class="arg">polyline1</i> <i class="arg">polyline2</i> <i class="arg">granularity</i></a></dt>
<dd><p>Check whether two polylines intersect, but reduce
the correctness of the result to the given granularity.
Use this for faster, but weaker, intersection checking.</p>
<p>How it works:</p>
<p>Each polyline is split into a number of smaller polylines,
consisting of granularity points each. If a pair of those smaller
lines' bounding boxes intersect, then this procedure returns 1,
otherwise it returns 0.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">polyline1</i></dt>
<dd><p>First polyline</p></dd>
<dt>list <i class="arg">polyline2</i></dt>
<dd><p>Second polyline</p></dd>
<dt>int <i class="arg">granularity</i></dt>
<dd><p>Number of points in each part (&lt;=1 means check
every edge)</p></dd>
</dl></dd>
<dt><a name="32"><b class="cmd">::math::geometry::intervalsOverlap</b> <i class="arg">y1</i> <i class="arg">y2</i> <i class="arg">y3</i> <i class="arg">y4</i> <i class="arg">strict</i></a></dt>
<dd><p>Check if two intervals overlap.</p>
<dl class="doctools_arguments">
<dt>double <i class="arg">y1,y2</i></dt>
<dd><p>Begin and end of first interval</p></dd>
<dt>double <i class="arg">y3,y4</i></dt>
<dd><p>Begin and end of second interval</p></dd>
<dt>logical <i class="arg">strict</i></dt>
<dd><p>Check for strict or non-strict overlap</p></dd>
</dl></dd>
<dt><a name="33"><b class="cmd">::math::geometry::rectanglesOverlap</b> <i class="arg">P1</i> <i class="arg">P2</i> <i class="arg">Q1</i> <i class="arg">Q2</i> <i class="arg">strict</i></a></dt>
<dd><p>Check if two rectangles overlap.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P1</i></dt>
<dd><p>upper-left corner of the first rectangle</p></dd>
<dt>list <i class="arg">P2</i></dt>
<dd><p>lower-right corner of the first rectangle</p></dd>
<dt>list <i class="arg">Q1</i></dt>
<dd><p>upper-left corner of the second rectangle</p></dd>
<dt>list <i class="arg">Q2</i></dt>
<dd><p>lower-right corner of the second rectangle</p></dd>
<dt>list <i class="arg">strict</i></dt>
<dd><p>choosing strict or non-strict interpretation</p></dd>
</dl></dd>
<dt><a name="34"><b class="cmd">::math::geometry::bbox</b> <i class="arg">polyline</i></a></dt>
<dd><p>Calculate the bounding box of a polyline. Returns a list of four
coordinates: the upper-left and the lower-right corner of the box.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">polyline</i></dt>
<dd><p>The polyline to be examined</p></dd>
</dl></dd>
<dt><a name="35"><b class="cmd">::math::geometry::pointInsidePolygon</b> <i class="arg">P</i> <i class="arg">polyline</i></a></dt>
<dd><p>Determine if a point is completely inside a polygon. If the point
touches the polygon, then the point is not completely inside the
polygon.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>Coordinates of the point</p></dd>
<dt>list <i class="arg">polyline</i></dt>
<dd><p>The polyline to be examined</p></dd>
</dl></dd>
<dt><a name="36"><b class="cmd">::math::geometry::pointInsidePolygonAlt</b> <i class="arg">P</i> <i class="arg">polyline</i></a></dt>
<dd><p>Determine if a point is completely inside a polygon. If the point
touches the polygon, then the point is not completely inside the
polygon. <em>Note:</em> this alternative procedure uses the so-called
winding number to determine this. It handles self-intersecting polygons
in a &quot;natural&quot; way.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P</i></dt>
<dd><p>Coordinates of the point</p></dd>
<dt>list <i class="arg">polyline</i></dt>
<dd><p>The polyline to be examined</p></dd>
</dl></dd>
<dt><a name="37"><b class="cmd">::math::geometry::rectangleInsidePolygon</b> <i class="arg">P1</i> <i class="arg">P2</i> <i class="arg">polyline</i></a></dt>
<dd><p>Determine if a rectangle is completely inside a polygon. If polygon
touches the rectangle, then the rectangle is not complete inside the
polygon.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">P1</i></dt>
<dd><p>Upper-left corner of the rectangle</p></dd>
<dt>list <i class="arg">P2</i></dt>
<dd><p>Lower-right corner of the rectangle</p></dd>
<dt>list <i class="arg">polygon</i></dt>
<dd><p>The polygon in question</p></dd>
</dl></dd>
<dt><a name="38"><b class="cmd">::math::geometry::areaPolygon</b> <i class="arg">polygon</i></a></dt>
<dd><p>Calculate the area of a polygon.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">polygon</i></dt>
<dd><p>The polygon in question</p></dd>
</dl></dd>
<dt><a name="39"><b class="cmd">::math::geometry::translate</b> <i class="arg">vector</i> <i class="arg">polyline</i></a></dt>
<dd><p>Translate a polyline over a given vector</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">vector</i></dt>
<dd><p>Translation vector</p></dd>
<dt>list <i class="arg">polyline</i></dt>
<dd><p>The polyline to be translated</p></dd>
</dl></dd>
<dt><a name="40"><b class="cmd">::math::geometry::rotate</b> <i class="arg">angle</i> <i class="arg">polyline</i></a></dt>
<dd><p>Rotate a polyline over a given angle (degrees) around the origin</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">angle</i></dt>
<dd><p>Angle over which to rotate the polyline (degrees)</p></dd>
<dt>list <i class="arg">polyline</i></dt>
<dd><p>The polyline to be rotated</p></dd>
</dl></dd>
<dt><a name="41"><b class="cmd">::math::geometry::reflect</b> <i class="arg">angle</i> <i class="arg">polyline</i></a></dt>
<dd><p>Reflect a polyline in a line through the origin at a given angle (degrees) to the x-axis</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">angle</i></dt>
<dd><p>Angle of the line of reflection (degrees)</p></dd>
<dt>list <i class="arg">polyline</i></dt>
<dd><p>The polyline to be reflected</p></dd>
</dl></dd>
<dt><a name="42"><b class="cmd">::math::geometry::degToRad</b> <i class="arg">angle</i></a></dt>
<dd><p>Convert from degrees to radians</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">angle</i></dt>
<dd><p>Angle in degrees</p></dd>
</dl></dd>
<dt><a name="43"><b class="cmd">::math::geometry::radToDeg</b> <i class="arg">angle</i></a></dt>
<dd><p>Convert from radians to degrees</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">angle</i></dt>
<dd><p>Angle in radians</p></dd>
</dl></dd>
<dt><a name="44"><b class="cmd">::math::geometry::circle</b> <i class="arg">centre</i> <i class="arg">radius</i></a></dt>
<dd><p>Convenience procedure to create a circle from a point and a radius.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">centre</i></dt>
<dd><p>Coordinates of the circle centre</p></dd>
<dt>list <i class="arg">radius</i></dt>
<dd><p>Radius of the circle</p></dd>
</dl></dd>
<dt><a name="45"><b class="cmd">::math::geometry::circleTwoPoints</b> <i class="arg">point1</i> <i class="arg">point2</i></a></dt>
<dd><p>Convenience procedure to create a circle from two points on its circumference
The centre is the point between the two given points, the radius is half the
distance between them.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">point1</i></dt>
<dd><p>First point</p></dd>
<dt>list <i class="arg">point2</i></dt>
<dd><p>Second point</p></dd>
</dl></dd>
<dt><a name="46"><b class="cmd">::math::geometry::pointInsideCircle</b> <i class="arg">point</i> <i class="arg">circle</i></a></dt>
<dd><p>Determine if the given point is inside the circle or on the circumference (1)
or outside (0).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">point</i></dt>
<dd><p>Point to be checked</p></dd>
<dt>list <i class="arg">circle</i></dt>
<dd><p>Circle that may or may not contain the point</p></dd>
</dl></dd>
<dt><a name="47"><b class="cmd">::math::geometry::lineIntersectsCircle</b> <i class="arg">line</i> <i class="arg">circle</i></a></dt>
<dd><p>Determine if the given line intersects the circle or touches it (1)
or does not (0).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">line</i></dt>
<dd><p>Line to be checked</p></dd>
<dt>list <i class="arg">circle</i></dt>
<dd><p>Circle that may or may not be intersected</p></dd>
</dl></dd>
<dt><a name="48"><b class="cmd">::math::geometry::lineSegmentIntersectsCircle</b> <i class="arg">segment</i> <i class="arg">circle</i></a></dt>
<dd><p>Determine if the given line segment intersects the circle or touches it (1)
or does not (0).</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">segment</i></dt>
<dd><p>Line segment to be checked</p></dd>
<dt>list <i class="arg">circle</i></dt>
<dd><p>Circle that may or may not be intersected</p></dd>
</dl></dd>
<dt><a name="49"><b class="cmd">::math::geometry::intersectionLineWithCircle</b> <i class="arg">line</i> <i class="arg">circle</i></a></dt>
<dd><p>Determine the points at which the given line intersects the circle. There can
be zero, one or two points. (If the line touches the circle or is close to it,
then one point is returned. An arbitrary margin of 1.0e-10 times the radius
is used to determine this situation.)</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">line</i></dt>
<dd><p>Line to be checked</p></dd>
<dt>list <i class="arg">circle</i></dt>
<dd><p>Circle that may or may not be intersected</p></dd>
</dl></dd>
<dt><a name="50"><b class="cmd">::math::geometry::intersectionCircleWithCircle</b> <i class="arg">circle1</i> <i class="arg">circle2</i></a></dt>
<dd><p>Determine the points at which the given two circles intersect. There can
be zero, one or two points. (If the two circles touch the circle or are very close,
then one point is returned. An arbitrary margin of 1.0e-10 times the mean of the radii of
the two circles is used to determine this situation.)</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">circle1</i></dt>
<dd><p>First circle</p></dd>
<dt>list <i class="arg">circle2</i></dt>
<dd><p>Second circle</p></dd>
</dl></dd>
<dt><a name="51"><b class="cmd">::math::geometry::tangentLinesToCircle</b> <i class="arg">point</i> <i class="arg">circle</i></a></dt>
<dd><p>Determine the tangent lines from the given point to the circle. There can
be zero, one or two lines. (If the point is on the cirucmference or very close to
the circle, then one line is returned. An arbitrary margin of 1.0e-10 times the
radius of the circle is used to determine this situation.)</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">point</i></dt>
<dd><p>Point in question</p></dd>

Changes to idoc/www/tcllib/files/modules/math/numtheory.html.

142
143
144
145
146
147
148

149
150
151
152
153
154
155
<li><a href="#11"><b class="cmd">math::numtheory::legendre</b> <i class="arg">a</i> <i class="arg">p</i></a></li>
<li><a href="#12"><b class="cmd">math::numtheory::jacobi</b> <i class="arg">a</i> <i class="arg">b</i></a></li>
<li><a href="#13"><b class="cmd">math::numtheory::gcd</b> <i class="arg">m</i> <i class="arg">n</i></a></li>
<li><a href="#14"><b class="cmd">math::numtheory::lcm</b> <i class="arg">m</i> <i class="arg">n</i></a></li>
<li><a href="#15"><b class="cmd">math::numtheory::numberPrimesGauss</b> <i class="arg">N</i></a></li>
<li><a href="#16"><b class="cmd">math::numtheory::numberPrimesLegendre</b> <i class="arg">N</i></a></li>
<li><a href="#17"><b class="cmd">math::numtheory::numberPrimesLegendreModified</b> <i class="arg">N</i></a></li>

</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>This package is for collecting various number-theoretic operations, with
a slight bias to prime numbers.</p>
<dl class="doctools_definitions">







>







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<li><a href="#11"><b class="cmd">math::numtheory::legendre</b> <i class="arg">a</i> <i class="arg">p</i></a></li>
<li><a href="#12"><b class="cmd">math::numtheory::jacobi</b> <i class="arg">a</i> <i class="arg">b</i></a></li>
<li><a href="#13"><b class="cmd">math::numtheory::gcd</b> <i class="arg">m</i> <i class="arg">n</i></a></li>
<li><a href="#14"><b class="cmd">math::numtheory::lcm</b> <i class="arg">m</i> <i class="arg">n</i></a></li>
<li><a href="#15"><b class="cmd">math::numtheory::numberPrimesGauss</b> <i class="arg">N</i></a></li>
<li><a href="#16"><b class="cmd">math::numtheory::numberPrimesLegendre</b> <i class="arg">N</i></a></li>
<li><a href="#17"><b class="cmd">math::numtheory::numberPrimesLegendreModified</b> <i class="arg">N</i></a></li>
<li><a href="#18"><b class="cmd">math::numtheory::differenceNumberPrimesLegendreModified</b> <i class="arg">lower</i> <i class="arg">upper</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>This package is for collecting various number-theoretic operations, with
a slight bias to prime numbers.</p>
<dl class="doctools_definitions">
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
<dt>integer <i class="arg">n</i> (in)</dt>
<dd><p>Second number</p></dd>
</dl></dd>
<dt><a name="15"><b class="cmd">math::numtheory::numberPrimesGauss</b> <i class="arg">N</i></a></dt>
<dd><p>Estimate the number of primes according the formula by Gauss.</p>
<dl class="doctools_arguments">
<dt>integer <i class="arg">N</i> (in)</dt>
<dd><p>Number in question</p></dd>
</dl></dd>
<dt><a name="16"><b class="cmd">math::numtheory::numberPrimesLegendre</b> <i class="arg">N</i></a></dt>
<dd><p>Estimate the number of primes according the formula by Legendre.</p>
<dl class="doctools_arguments">
<dt>integer <i class="arg">N</i> (in)</dt>
<dd><p>Number in question</p></dd>
</dl></dd>
<dt><a name="17"><b class="cmd">math::numtheory::numberPrimesLegendreModified</b> <i class="arg">N</i></a></dt>
<dd><p>Estimate the number of primes according the modified formula by Legendre.</p>
<dl class="doctools_arguments">
<dt>integer <i class="arg">N</i> (in)</dt>
<dd><p>Number in question</p></dd>








</dl></dd>
</dl>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>math :: numtheory</em> of the







|





|





|
>
>
>
>
>
>
>
>







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
<dt>integer <i class="arg">n</i> (in)</dt>
<dd><p>Second number</p></dd>
</dl></dd>
<dt><a name="15"><b class="cmd">math::numtheory::numberPrimesGauss</b> <i class="arg">N</i></a></dt>
<dd><p>Estimate the number of primes according the formula by Gauss.</p>
<dl class="doctools_arguments">
<dt>integer <i class="arg">N</i> (in)</dt>
<dd><p>Number in question, should be larger than 0</p></dd>
</dl></dd>
<dt><a name="16"><b class="cmd">math::numtheory::numberPrimesLegendre</b> <i class="arg">N</i></a></dt>
<dd><p>Estimate the number of primes according the formula by Legendre.</p>
<dl class="doctools_arguments">
<dt>integer <i class="arg">N</i> (in)</dt>
<dd><p>Number in question, should be larger than 0</p></dd>
</dl></dd>
<dt><a name="17"><b class="cmd">math::numtheory::numberPrimesLegendreModified</b> <i class="arg">N</i></a></dt>
<dd><p>Estimate the number of primes according the modified formula by Legendre.</p>
<dl class="doctools_arguments">
<dt>integer <i class="arg">N</i> (in)</dt>
<dd><p>Number in question, should be larger than 0</p></dd>
</dl></dd>
<dt><a name="18"><b class="cmd">math::numtheory::differenceNumberPrimesLegendreModified</b> <i class="arg">lower</i> <i class="arg">upper</i></a></dt>
<dd><p>Estimate the number of primes between tow limits according the modified formula by Legendre.</p>
<dl class="doctools_arguments">
<dt>integer <i class="arg">lower</i> (in)</dt>
<dd><p>Lower limit for the primes, should be larger than 0</p></dd>
<dt>integer <i class="arg">upper</i> (in)</dt>
<dd><p>Upper limit for the primes, should be larger than 0</p></dd>
</dl></dd>
</dl>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>math :: numtheory</em> of the

Added idoc/www/tcllib/files/modules/math/quasirandom.html.



































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
<!DOCTYPE html><html><head>
<title>math::quasirandom - Tcl Math Library</title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
	color:	 	black;
    }
    DIV.doctools {
	margin-left:	10%;
	margin-right:	10%;
    }
    DIV.doctools H1,DIV.doctools H2 {
	margin-left:	-5%;
    }
    H1, H2, H3, H4 {
	margin-top: 	1em;
	font-family:	sans-serif;
	font-size:	large;
	color:		#005A9C;
	background: 	transparent;
	text-align:		left;
    }
    H1.doctools_title {
	text-align: center;
    }
    UL,OL {
	margin-right: 0em;
	margin-top: 3pt;
	margin-bottom: 3pt;
    }
    UL LI {
	list-style: disc;
    }
    OL LI {
	list-style: decimal;
    }
    DT {
	padding-top: 	1ex;
    }
    UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
	font:		normal 12pt/14pt sans-serif;
	list-style:	none;
    }
    LI.doctools_section, LI.doctools_subsection {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding: 	0em;
    }
    PRE {
	display: 	block;
	font-family:	monospace;
	white-space:	pre;
	margin:		0%;
	padding-top:	0.5ex;
	padding-bottom:	0.5ex;
	padding-left:	1ex;
	padding-right:	1ex;
	width:		100%;
    }
    PRE.doctools_example {
	color: 		black;
	background: 	#f5dcb3;
	border:		1px solid black;
    }
    UL.doctools_requirements LI, UL.doctools_syntax LI {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding:	0em;
    }
    DIV.doctools_synopsis {
	color: 		black;
	background: 	#80ffff;
	border:		1px solid black;
	font-family:	serif;
	margin-top: 	1em;
	margin-bottom: 	1em;
    }
    UL.doctools_syntax {
	margin-top: 	1em;
	border-top:	1px solid black;
    }
    UL.doctools_requirements {
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'quasirandom.man' by tcllib/doctools with format 'html'
   -->
<!-- math::quasirandom.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">math::quasirandom(n) 1 tcllib &quot;Tcl Math Library&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>math::quasirandom - Quasi-random points for integration and Monte Carlo type methods</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">COMMANDS</a></li>
<li class="doctools_section"><a href="#section3">TODO</a></li>
<li class="doctools_section"><a href="#section4">References</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">TclOO</b></li>
<li>package require <b class="pkgname">math::quasirandom 1</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::math::quasirandom::qrpoint create</b> <i class="arg">NAME</i> <i class="arg">DIM</i> <span class="opt">?ARGS?</span></a></li>
<li><a href="#2"><b class="cmd">gen next</b></a></li>
<li><a href="#3"><b class="cmd">gen set-start</b> <i class="arg">index</i></a></li>
<li><a href="#4"><b class="cmd">gen set-evaluations</b> <i class="arg">number</i></a></li>
<li><a href="#5"><b class="cmd">gen integral</b> <i class="arg">func</i> <i class="arg">minmax</i> <i class="arg">args</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>In many applications pseudo-random numbers and pseudo-random points in a (limited)
sample space play an important role. For instance in any type of Monte Carlo simulation.
Pseudo-random numbers, however, may be too random and as a consequence a large
number of data points is required to reduce the error or fluctuation in the results
to the desired value.</p>
<p>Quasi-random numbers can be used as an alternative: instead of &quot;completely&quot; arbitrary
points, points are generated that are diverse enough to cover the entire sample space
in a more or less uniform way. As a consequence convergence to the limit can be
much faster, when such quasi-random numbers are well-chosen.</p>
<p>The package defines a <i class="term"><a href="../../../../index.html#class">class</a></i> &quot;qrpoint&quot; that creates a command to generate
quasi-random points in 1, 2 or more dimensions. The command can either generate
separate points, so that they can be used in a user-defined algorithm or use these
points to calculate integrals of functions defined over 1, 2 or more dimensions.
It also holds several other common algorithms. (NOTE: these are not implemented yet)</p>
<p>One particular characteristic of the generators is that there are no tuning parameters
involved, which makes the use particularly simple.</p>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">COMMANDS</a></h2>
<p>A quasi-random point generator is created using the <i class="term">qrpoint</i> class:</p>
<dl class="doctools_definitions">
<dt><a name="1"><b class="cmd">::math::quasirandom::qrpoint create</b> <i class="arg">NAME</i> <i class="arg">DIM</i> <span class="opt">?ARGS?</span></a></dt>
<dd><p>This command takes the following arguments:</p>
<dl class="doctools_arguments">
<dt>string <i class="arg">NAME</i></dt>
<dd><p>The name of the command to be created (alternatively: the <i class="term">new</i> subcommand
will generate a unique name)</p></dd>
<dt>integer/string <i class="arg">DIM</i></dt>
<dd><p>The number of dimensions or one of: &quot;circle&quot;, &quot;disk&quot;, &quot;sphere&quot; or &quot;ball&quot;</p></dd>
<dt>strings <i class="arg">ARGS</i></dt>
<dd><p>Zero or more key-value pairs. The supported options are:</p>
<ul class="doctools_itemized">
<li><p><i class="term">-start index</i>: The index for the next point to be generated (default: 1)</p></li>
<li><p><i class="term">-evaluations number</i>: The number of evaluations to be used by default (default: 100)</p></li>
</ul></dd>
</dl></dd>
</dl>
<p>The points that are returned lie in the hyperblock [0,1[^n (n the number of dimensions)
or on the unit circle, within the unit disk, on the unit sphere or within the unit ball.</p>
<p>Each generator supports the following subcommands:</p>
<dl class="doctools_definitions">
<dt><a name="2"><b class="cmd">gen next</b></a></dt>
<dd><p>Return the coordinates of the next quasi-random point</p></dd>
<dt><a name="3"><b class="cmd">gen set-start</b> <i class="arg">index</i></a></dt>
<dd><p>Reset the index for the next quasi-random point. This is useful to control which list of points is returned.
Returns the new or the current value, if no value is given.</p></dd>
<dt><a name="4"><b class="cmd">gen set-evaluations</b> <i class="arg">number</i></a></dt>
<dd><p>Reset the default number of evaluations in compound algorithms. Note that the actual number is the
smallest 4-fold larger or equal to the given number. (The 4-fold plays a role in the detailed integration
routine.)</p></dd>
<dt><a name="5"><b class="cmd">gen integral</b> <i class="arg">func</i> <i class="arg">minmax</i> <i class="arg">args</i></a></dt>
<dd><p>Calculate the integral of the given function over the block (or the circle, sphere etc.)</p>
<dl class="doctools_arguments">
<dt>string <i class="arg">func</i></dt>
<dd><p>The name of the function to be integrated</p></dd>
<dt>list <i class="arg">minmax</i></dt>
<dd><p>List of pairs of minimum and maximum coordinates. This can be used to
map the quasi-random coordinates to the desired hyper-block.</p>
<p>If the space is a circle, disk etc. then this argument should be a single value, the radius.
The circle, disk, etc. is centred at the origin. If this is not what is required, then a coordinate
transformation should be made within the function.</p></dd>
<dt>strings <i class="arg">args</i></dt>
<dd><p>Zero or more key-value pairs. The following options are supported:</p>
<ul class="doctools_itemized">
<li><p><i class="term">-evaluations number</i>: The number of evaluations to be used. If not specified use the
default of the generator object.</p></li>
</ul></dd>
</dl></dd>
</dl>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">TODO</a></h2>
<p>Implement other algorithms and variants</p>
<p>Implement more unit tests.</p>
<p>Comparison to pseudo-random numbers for integration.</p>
</div>
<div id="section4" class="doctools_section"><h2><a name="section4">References</a></h2>
<p>Various algorithms exist for generating quasi-random numbers. The generators created in this package are based on:
<a href="http://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/">http://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/</a></p>
</div>
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#mathematics">mathematics</a>, <a href="../../../../index.html#quasi_random">quasi-random</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Mathematics</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/math/special.html.

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">math::special(n) 0.3 tcllib &quot;Tcl Math Library&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>math::special - Special mathematical functions</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>







|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">math::special(n) 0.4 tcllib &quot;Tcl Math Library&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>math::special - Special mathematical functions</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
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
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl <span class="opt">?8.3?</span></b></li>
<li>package require <b class="pkgname">math::special <span class="opt">?0.3?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::math::special::Beta</b> <i class="arg">x</i> <i class="arg">y</i></a></li>
<li><a href="#2"><b class="cmd">::math::special::Gamma</b> <i class="arg">x</i></a></li>
<li><a href="#3"><b class="cmd">::math::special::erf</b> <i class="arg">x</i></a></li>
<li><a href="#4"><b class="cmd">::math::special::erfc</b> <i class="arg">x</i></a></li>
<li><a href="#5"><b class="cmd">::math::special::invnorm</b> <i class="arg">p</i></a></li>
<li><a href="#6"><b class="cmd">::math::special::J0</b> <i class="arg">x</i></a></li>
<li><a href="#7"><b class="cmd">::math::special::J1</b> <i class="arg">x</i></a></li>
<li><a href="#8"><b class="cmd">::math::special::Jn</b> <i class="arg">n</i> <i class="arg">x</i></a></li>
<li><a href="#9"><b class="cmd">::math::special::J1/2</b> <i class="arg">x</i></a></li>
<li><a href="#10"><b class="cmd">::math::special::J-1/2</b> <i class="arg">x</i></a></li>
<li><a href="#11"><b class="cmd">::math::special::I_n</b> <i class="arg">x</i></a></li>
<li><a href="#12"><b class="cmd">::math::special::cn</b> <i class="arg">u</i> <i class="arg">k</i></a></li>
<li><a href="#13"><b class="cmd">::math::special::dn</b> <i class="arg">u</i> <i class="arg">k</i></a></li>
<li><a href="#14"><b class="cmd">::math::special::sn</b> <i class="arg">u</i> <i class="arg">k</i></a></li>
<li><a href="#15"><b class="cmd">::math::special::elliptic_K</b> <i class="arg">k</i></a></li>
<li><a href="#16"><b class="cmd">::math::special::elliptic_E</b> <i class="arg">k</i></a></li>
<li><a href="#17"><b class="cmd">::math::special::exponential_Ei</b> <i class="arg">x</i></a></li>
<li><a href="#18"><b class="cmd">::math::special::exponential_En</b> <i class="arg">n</i> <i class="arg">x</i></a></li>
<li><a href="#19"><b class="cmd">::math::special::exponential_li</b> <i class="arg">x</i></a></li>
<li><a href="#20"><b class="cmd">::math::special::exponential_Ci</b> <i class="arg">x</i></a></li>
<li><a href="#21"><b class="cmd">::math::special::exponential_Si</b> <i class="arg">x</i></a></li>
<li><a href="#22"><b class="cmd">::math::special::exponential_Chi</b> <i class="arg">x</i></a></li>
<li><a href="#23"><b class="cmd">::math::special::exponential_Shi</b> <i class="arg">x</i></a></li>
<li><a href="#24"><b class="cmd">::math::special::fresnel_C</b> <i class="arg">x</i></a></li>
<li><a href="#25"><b class="cmd">::math::special::fresnel_S</b> <i class="arg">x</i></a></li>
<li><a href="#26"><b class="cmd">::math::special::sinc</b> <i class="arg">x</i></a></li>
<li><a href="#27"><b class="cmd">::math::special::legendre</b> <i class="arg">n</i></a></li>
<li><a href="#28"><b class="cmd">::math::special::chebyshev</b> <i class="arg">n</i></a></li>



<li><a href="#29"><b class="cmd">::math::special::laguerre</b> <i class="arg">alpha</i> <i class="arg">n</i></a></li>
<li><a href="#30"><b class="cmd">::math::special::hermite</b> <i class="arg">n</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>This package implements several so-called special functions, like
the Gamma function, the Bessel functions and such.</p>
<p>Each function is implemented by a procedure that bears its name (well,







|
|



|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
|
|







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
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl <span class="opt">?8.5?</span></b></li>
<li>package require <b class="pkgname">math::special <span class="opt">?0.4?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::math::special::Beta</b> <i class="arg">x</i> <i class="arg">y</i></a></li>
<li><a href="#2"><b class="cmd">::math::special::incBeta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">x</i></a></li>
<li><a href="#3"><b class="cmd">::math::special::regIncBeta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">x</i></a></li>
<li><a href="#4"><b class="cmd">::math::special::Gamma</b> <i class="arg">x</i></a></li>
<li><a href="#5"><b class="cmd">::math::special::digamma</b> <i class="arg">x</i></a></li>
<li><a href="#6"><b class="cmd">::math::special::erf</b> <i class="arg">x</i></a></li>
<li><a href="#7"><b class="cmd">::math::special::erfc</b> <i class="arg">x</i></a></li>
<li><a href="#8"><b class="cmd">::math::special::invnorm</b> <i class="arg">p</i></a></li>
<li><a href="#9"><b class="cmd">::math::special::J0</b> <i class="arg">x</i></a></li>
<li><a href="#10"><b class="cmd">::math::special::J1</b> <i class="arg">x</i></a></li>
<li><a href="#11"><b class="cmd">::math::special::Jn</b> <i class="arg">n</i> <i class="arg">x</i></a></li>
<li><a href="#12"><b class="cmd">::math::special::J1/2</b> <i class="arg">x</i></a></li>
<li><a href="#13"><b class="cmd">::math::special::J-1/2</b> <i class="arg">x</i></a></li>
<li><a href="#14"><b class="cmd">::math::special::I_n</b> <i class="arg">x</i></a></li>
<li><a href="#15"><b class="cmd">::math::special::cn</b> <i class="arg">u</i> <i class="arg">k</i></a></li>
<li><a href="#16"><b class="cmd">::math::special::dn</b> <i class="arg">u</i> <i class="arg">k</i></a></li>
<li><a href="#17"><b class="cmd">::math::special::sn</b> <i class="arg">u</i> <i class="arg">k</i></a></li>
<li><a href="#18"><b class="cmd">::math::special::elliptic_K</b> <i class="arg">k</i></a></li>
<li><a href="#19"><b class="cmd">::math::special::elliptic_E</b> <i class="arg">k</i></a></li>
<li><a href="#20"><b class="cmd">::math::special::exponential_Ei</b> <i class="arg">x</i></a></li>
<li><a href="#21"><b class="cmd">::math::special::exponential_En</b> <i class="arg">n</i> <i class="arg">x</i></a></li>
<li><a href="#22"><b class="cmd">::math::special::exponential_li</b> <i class="arg">x</i></a></li>
<li><a href="#23"><b class="cmd">::math::special::exponential_Ci</b> <i class="arg">x</i></a></li>
<li><a href="#24"><b class="cmd">::math::special::exponential_Si</b> <i class="arg">x</i></a></li>
<li><a href="#25"><b class="cmd">::math::special::exponential_Chi</b> <i class="arg">x</i></a></li>
<li><a href="#26"><b class="cmd">::math::special::exponential_Shi</b> <i class="arg">x</i></a></li>
<li><a href="#27"><b class="cmd">::math::special::fresnel_C</b> <i class="arg">x</i></a></li>
<li><a href="#28"><b class="cmd">::math::special::fresnel_S</b> <i class="arg">x</i></a></li>
<li><a href="#29"><b class="cmd">::math::special::sinc</b> <i class="arg">x</i></a></li>
<li><a href="#30"><b class="cmd">::math::special::legendre</b> <i class="arg">n</i></a></li>
<li><a href="#31"><b class="cmd">::math::special::chebyshev</b> <i class="arg">n</i></a></li>
<li><a href="#32"><b class="cmd">::math::special::laguerre</b> <i class="arg">alpha</i> <i class="arg">n</i></a></li>
<li><a href="#33"><b class="cmd">::math::special::hermite</b> <i class="arg">n</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>This package implements several so-called special functions, like
the Gamma function, the Bessel functions and such.</p>
<p>Each function is implemented by a procedure that bears its name (well,
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
             |             |             |             |
Fresnel      | C           |  all of R   |     --      |   &lt; 2.0e-3
integrals    | S           |  all of R   |     --      |   &lt; 2.0e-3
             |             |             |             |
general      | Beta        | (see Gamma) |     --      |   &lt; 1.0e-9
             | Gamma       |  x != 0,-1, |     --      |   &lt; 1.0e-9
             |             |  -2, ...    |             |





             | sinc        |  all of R   |     --      |   exact
             |             |             |             |
orthogonal   | Legendre    |  all of R   | n = 0,1,... |   exact
polynomials  | Chebyshev   |  all of R   | n = 0,1,... |   exact
             | Laguerre    |  all of R   | n = 0,1,... |   exact
             |             |             | alpha el. R |
             | Hermite     |  all of R   | n = 0,1,... |   exact
</pre>
<p><em>Note:</em> Some of the error bounds are estimated, as no
&quot;formal&quot; bounds were available with the implemented approximation
method, others hold for the auxiliary functions used for estimating
the primary functions.</p>
<p>The following well-known functions are currently missing from the package:</p>
<ul class="doctools_itemized">
<li><p>Bessel functions of the second kind (Y_n, K_n)</p></li>
<li><p>Bessel functions of arbitrary order (and hence the Airy functions)</p></li>
<li><p>Chebyshev polynomials of the second kind (U_n)</p></li>
<li><p>The digamma function (psi)</p></li>
<li><p>The incomplete gamma and beta functions</p></li>
</ul>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">PROCEDURES</a></h2>
<p>The package defines the following public procedures:</p>
<dl class="doctools_definitions">
<dt><a name="1"><b class="cmd">::math::special::Beta</b> <i class="arg">x</i> <i class="arg">y</i></a></dt>
<dd><p>Compute the Beta function for arguments &quot;x&quot; and &quot;y&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>First argument for the Beta function</p></dd>
<dt>float <i class="arg">y</i></dt>
<dd><p>Second argument for the Beta function</p></dd>
</dl></dd>




















<dt><a name="2"><b class="cmd">::math::special::Gamma</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the Gamma function for argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the Gamma function</p></dd>
</dl></dd>






<dt><a name="3"><b class="cmd">::math::special::erf</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the error function for argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the error function</p></dd>
</dl></dd>
<dt><a name="4"><b class="cmd">::math::special::erfc</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the complementary error function for argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the complementary error function</p></dd>
</dl></dd>
<dt><a name="5"><b class="cmd">::math::special::invnorm</b> <i class="arg">p</i></a></dt>
<dd><p>Compute the inverse of the normal distribution function for argument &quot;p&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">p</i></dt>
<dd><p>Argument for the inverse normal distribution function
(p must be greater than 0 and lower than 1)</p></dd>
</dl></dd>
<dt><a name="6"><b class="cmd">::math::special::J0</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the zeroth-order Bessel function of the first kind for the
argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the Bessel function</p></dd>
</dl></dd>
<dt><a name="7"><b class="cmd">::math::special::J1</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the first-order Bessel function of the first kind for the
argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the Bessel function</p></dd>
</dl></dd>
<dt><a name="8"><b class="cmd">::math::special::Jn</b> <i class="arg">n</i> <i class="arg">x</i></a></dt>
<dd><p>Compute the nth-order Bessel function of the first kind for the
argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>integer <i class="arg">n</i></dt>
<dd><p>Order of the Bessel function</p></dd>
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the Bessel function</p></dd>
</dl></dd>
<dt><a name="9"><b class="cmd">::math::special::J1/2</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the half-order Bessel function of the first kind for the
argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the Bessel function</p></dd>
</dl></dd>
<dt><a name="10"><b class="cmd">::math::special::J-1/2</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the minus-half-order Bessel function of the first kind for the
argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the Bessel function</p></dd>
</dl></dd>
<dt><a name="11"><b class="cmd">::math::special::I_n</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the modified Bessel function of the first kind of order n for
the argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">x</i></dt>
<dd><p>Positive integer order of the function</p></dd>
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function</p></dd>
</dl></dd>
<dt><a name="12"><b class="cmd">::math::special::cn</b> <i class="arg">u</i> <i class="arg">k</i></a></dt>
<dd><p>Compute the elliptic function <em>cn</em> for the argument &quot;u&quot; and
parameter &quot;k&quot;.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">u</i></dt>
<dd><p>Argument for the function</p></dd>
<dt>float <i class="arg">k</i></dt>
<dd><p>Parameter</p></dd>
</dl></dd>
<dt><a name="13"><b class="cmd">::math::special::dn</b> <i class="arg">u</i> <i class="arg">k</i></a></dt>
<dd><p>Compute the elliptic function <em>dn</em> for the argument &quot;u&quot; and
parameter &quot;k&quot;.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">u</i></dt>
<dd><p>Argument for the function</p></dd>
<dt>float <i class="arg">k</i></dt>
<dd><p>Parameter</p></dd>
</dl></dd>
<dt><a name="14"><b class="cmd">::math::special::sn</b> <i class="arg">u</i> <i class="arg">k</i></a></dt>
<dd><p>Compute the elliptic function <em>sn</em> for the argument &quot;u&quot; and
parameter &quot;k&quot;.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">u</i></dt>
<dd><p>Argument for the function</p></dd>
<dt>float <i class="arg">k</i></dt>
<dd><p>Parameter</p></dd>
</dl></dd>
<dt><a name="15"><b class="cmd">::math::special::elliptic_K</b> <i class="arg">k</i></a></dt>
<dd><p>Compute the complete elliptic integral of the first kind
for the argument &quot;k&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">k</i></dt>
<dd><p>Argument for the function</p></dd>
</dl></dd>
<dt><a name="16"><b class="cmd">::math::special::elliptic_E</b> <i class="arg">k</i></a></dt>
<dd><p>Compute the complete elliptic integral of the second kind
for the argument &quot;k&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">k</i></dt>
<dd><p>Argument for the function</p></dd>
</dl></dd>
<dt><a name="17"><b class="cmd">::math::special::exponential_Ei</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the exponential integral of the second kind
for the argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function (x != 0)</p></dd>
</dl></dd>
<dt><a name="18"><b class="cmd">::math::special::exponential_En</b> <i class="arg">n</i> <i class="arg">x</i></a></dt>
<dd><p>Compute the exponential integral of the first kind
for the argument &quot;x&quot; and order n</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">n</i></dt>
<dd><p>Order of the integral (n &gt;= 0)</p></dd>
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function (x &gt;= 0)</p></dd>
</dl></dd>
<dt><a name="19"><b class="cmd">::math::special::exponential_li</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the logarithmic integral for the argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function (x &gt; 0)</p></dd>
</dl></dd>
<dt><a name="20"><b class="cmd">::math::special::exponential_Ci</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the cosine integral for the argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function (x &gt; 0)</p></dd>
</dl></dd>
<dt><a name="21"><b class="cmd">::math::special::exponential_Si</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the sine integral for the argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function (x &gt; 0)</p></dd>
</dl></dd>
<dt><a name="22"><b class="cmd">::math::special::exponential_Chi</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the hyperbolic cosine integral for the argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function (x &gt; 0)</p></dd>
</dl></dd>
<dt><a name="23"><b class="cmd">::math::special::exponential_Shi</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the hyperbolic sine integral for the argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function (x &gt; 0)</p></dd>
</dl></dd>
<dt><a name="24"><b class="cmd">::math::special::fresnel_C</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the Fresnel cosine integral for real argument x</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function</p></dd>
</dl></dd>
<dt><a name="25"><b class="cmd">::math::special::fresnel_S</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the Fresnel sine integral for real argument x</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function</p></dd>
</dl></dd>
<dt><a name="26"><b class="cmd">::math::special::sinc</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the sinc function for real argument x</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function</p></dd>
</dl></dd>
<dt><a name="27"><b class="cmd">::math::special::legendre</b> <i class="arg">n</i></a></dt>
<dd><p>Return the Legendre polynomial of degree n
(see <span class="sectref"><a href="#section4">THE ORTHOGONAL POLYNOMIALS</a></span>)</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">n</i></dt>
<dd><p>Degree of the polynomial</p></dd>
</dl></dd>
<dt><a name="28"><b class="cmd">::math::special::chebyshev</b> <i class="arg">n</i></a></dt>
<dd><p>Return the Chebyshev polynomial of degree n (of the first kind)</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">n</i></dt>
<dd><p>Degree of the polynomial</p></dd>
</dl></dd>
<dt><a name="29"><b class="cmd">::math::special::laguerre</b> <i class="arg">alpha</i> <i class="arg">n</i></a></dt>
<dd><p>Return the Laguerre polynomial of degree n with parameter alpha</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">alpha</i></dt>
<dd><p>Parameter of the Laguerre polynomial</p></dd>
<dt>int <i class="arg">n</i></dt>
<dd><p>Degree of the polynomial</p></dd>
</dl></dd>
<dt><a name="30"><b class="cmd">::math::special::hermite</b> <i class="arg">n</i></a></dt>
<dd><p>Return the Hermite polynomial of degree n</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">n</i></dt>
<dd><p>Degree of the polynomial</p></dd>
</dl></dd>
</dl>
</div>







>
>
>
>
>

















<
|













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|





>
>
>
>
>
>
|





|





|






|






|






|








|






|






|








|








|








|








|






|






|






|








|





|





|





|





|





|





|





|





|






|





|







|







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
             |             |             |             |
Fresnel      | C           |  all of R   |     --      |   &lt; 2.0e-3
integrals    | S           |  all of R   |     --      |   &lt; 2.0e-3
             |             |             |             |
general      | Beta        | (see Gamma) |     --      |   &lt; 1.0e-9
             | Gamma       |  x != 0,-1, |     --      |   &lt; 1.0e-9
             |             |  -2, ...    |             |
             | incBeta     |             |  a, b &gt; 0   |   &lt; 1.0e-9
             | regIncBeta  |             |  a, b &gt; 0   |   &lt; 1.0e-9
             | digamma     |  x != 0,-1  |             |   &lt; 1.0e-9
             |             |  -2, ...    |             |
             |             |             |             |
             | sinc        |  all of R   |     --      |   exact
             |             |             |             |
orthogonal   | Legendre    |  all of R   | n = 0,1,... |   exact
polynomials  | Chebyshev   |  all of R   | n = 0,1,... |   exact
             | Laguerre    |  all of R   | n = 0,1,... |   exact
             |             |             | alpha el. R |
             | Hermite     |  all of R   | n = 0,1,... |   exact
</pre>
<p><em>Note:</em> Some of the error bounds are estimated, as no
&quot;formal&quot; bounds were available with the implemented approximation
method, others hold for the auxiliary functions used for estimating
the primary functions.</p>
<p>The following well-known functions are currently missing from the package:</p>
<ul class="doctools_itemized">
<li><p>Bessel functions of the second kind (Y_n, K_n)</p></li>
<li><p>Bessel functions of arbitrary order (and hence the Airy functions)</p></li>
<li><p>Chebyshev polynomials of the second kind (U_n)</p></li>

<li><p>The incomplete gamma function</p></li>
</ul>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">PROCEDURES</a></h2>
<p>The package defines the following public procedures:</p>
<dl class="doctools_definitions">
<dt><a name="1"><b class="cmd">::math::special::Beta</b> <i class="arg">x</i> <i class="arg">y</i></a></dt>
<dd><p>Compute the Beta function for arguments &quot;x&quot; and &quot;y&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>First argument for the Beta function</p></dd>
<dt>float <i class="arg">y</i></dt>
<dd><p>Second argument for the Beta function</p></dd>
</dl></dd>
<dt><a name="2"><b class="cmd">::math::special::incBeta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">x</i></a></dt>
<dd><p>Compute the incomplete Beta function for argument &quot;x&quot; with parameters &quot;a&quot; and &quot;b&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">a</i></dt>
<dd><p>First parameter for the incomplete Beta function, a &gt; 0</p></dd>
<dt>float <i class="arg">b</i></dt>
<dd><p>Second parameter for the incomplete Beta function, b &gt; 0</p></dd>
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the incomplete Beta function</p></dd>
</dl></dd>
<dt><a name="3"><b class="cmd">::math::special::regIncBeta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">x</i></a></dt>
<dd><p>Compute the regularized incomplete Beta function for argument &quot;x&quot; with parameters &quot;a&quot; and &quot;b&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">a</i></dt>
<dd><p>First parameter for the incomplete Beta function, a &gt; 0</p></dd>
<dt>float <i class="arg">b</i></dt>
<dd><p>Second parameter for the incomplete Beta function, b &gt; 0</p></dd>
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the regularized incomplete Beta function</p></dd>
</dl></dd>
<dt><a name="4"><b class="cmd">::math::special::Gamma</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the Gamma function for argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the Gamma function</p></dd>
</dl></dd>
<dt><a name="5"><b class="cmd">::math::special::digamma</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the digamma function (psi) for argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the digamma function</p></dd>
</dl></dd>
<dt><a name="6"><b class="cmd">::math::special::erf</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the error function for argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the error function</p></dd>
</dl></dd>
<dt><a name="7"><b class="cmd">::math::special::erfc</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the complementary error function for argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the complementary error function</p></dd>
</dl></dd>
<dt><a name="8"><b class="cmd">::math::special::invnorm</b> <i class="arg">p</i></a></dt>
<dd><p>Compute the inverse of the normal distribution function for argument &quot;p&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">p</i></dt>
<dd><p>Argument for the inverse normal distribution function
(p must be greater than 0 and lower than 1)</p></dd>
</dl></dd>
<dt><a name="9"><b class="cmd">::math::special::J0</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the zeroth-order Bessel function of the first kind for the
argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the Bessel function</p></dd>
</dl></dd>
<dt><a name="10"><b class="cmd">::math::special::J1</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the first-order Bessel function of the first kind for the
argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the Bessel function</p></dd>
</dl></dd>
<dt><a name="11"><b class="cmd">::math::special::Jn</b> <i class="arg">n</i> <i class="arg">x</i></a></dt>
<dd><p>Compute the nth-order Bessel function of the first kind for the
argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>integer <i class="arg">n</i></dt>
<dd><p>Order of the Bessel function</p></dd>
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the Bessel function</p></dd>
</dl></dd>
<dt><a name="12"><b class="cmd">::math::special::J1/2</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the half-order Bessel function of the first kind for the
argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the Bessel function</p></dd>
</dl></dd>
<dt><a name="13"><b class="cmd">::math::special::J-1/2</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the minus-half-order Bessel function of the first kind for the
argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the Bessel function</p></dd>
</dl></dd>
<dt><a name="14"><b class="cmd">::math::special::I_n</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the modified Bessel function of the first kind of order n for
the argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">x</i></dt>
<dd><p>Positive integer order of the function</p></dd>
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function</p></dd>
</dl></dd>
<dt><a name="15"><b class="cmd">::math::special::cn</b> <i class="arg">u</i> <i class="arg">k</i></a></dt>
<dd><p>Compute the elliptic function <em>cn</em> for the argument &quot;u&quot; and
parameter &quot;k&quot;.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">u</i></dt>
<dd><p>Argument for the function</p></dd>
<dt>float <i class="arg">k</i></dt>
<dd><p>Parameter</p></dd>
</dl></dd>
<dt><a name="16"><b class="cmd">::math::special::dn</b> <i class="arg">u</i> <i class="arg">k</i></a></dt>
<dd><p>Compute the elliptic function <em>dn</em> for the argument &quot;u&quot; and
parameter &quot;k&quot;.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">u</i></dt>
<dd><p>Argument for the function</p></dd>
<dt>float <i class="arg">k</i></dt>
<dd><p>Parameter</p></dd>
</dl></dd>
<dt><a name="17"><b class="cmd">::math::special::sn</b> <i class="arg">u</i> <i class="arg">k</i></a></dt>
<dd><p>Compute the elliptic function <em>sn</em> for the argument &quot;u&quot; and
parameter &quot;k&quot;.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">u</i></dt>
<dd><p>Argument for the function</p></dd>
<dt>float <i class="arg">k</i></dt>
<dd><p>Parameter</p></dd>
</dl></dd>
<dt><a name="18"><b class="cmd">::math::special::elliptic_K</b> <i class="arg">k</i></a></dt>
<dd><p>Compute the complete elliptic integral of the first kind
for the argument &quot;k&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">k</i></dt>
<dd><p>Argument for the function</p></dd>
</dl></dd>
<dt><a name="19"><b class="cmd">::math::special::elliptic_E</b> <i class="arg">k</i></a></dt>
<dd><p>Compute the complete elliptic integral of the second kind
for the argument &quot;k&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">k</i></dt>
<dd><p>Argument for the function</p></dd>
</dl></dd>
<dt><a name="20"><b class="cmd">::math::special::exponential_Ei</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the exponential integral of the second kind
for the argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function (x != 0)</p></dd>
</dl></dd>
<dt><a name="21"><b class="cmd">::math::special::exponential_En</b> <i class="arg">n</i> <i class="arg">x</i></a></dt>
<dd><p>Compute the exponential integral of the first kind
for the argument &quot;x&quot; and order n</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">n</i></dt>
<dd><p>Order of the integral (n &gt;= 0)</p></dd>
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function (x &gt;= 0)</p></dd>
</dl></dd>
<dt><a name="22"><b class="cmd">::math::special::exponential_li</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the logarithmic integral for the argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function (x &gt; 0)</p></dd>
</dl></dd>
<dt><a name="23"><b class="cmd">::math::special::exponential_Ci</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the cosine integral for the argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function (x &gt; 0)</p></dd>
</dl></dd>
<dt><a name="24"><b class="cmd">::math::special::exponential_Si</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the sine integral for the argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function (x &gt; 0)</p></dd>
</dl></dd>
<dt><a name="25"><b class="cmd">::math::special::exponential_Chi</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the hyperbolic cosine integral for the argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function (x &gt; 0)</p></dd>
</dl></dd>
<dt><a name="26"><b class="cmd">::math::special::exponential_Shi</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the hyperbolic sine integral for the argument &quot;x&quot;</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function (x &gt; 0)</p></dd>
</dl></dd>
<dt><a name="27"><b class="cmd">::math::special::fresnel_C</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the Fresnel cosine integral for real argument x</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function</p></dd>
</dl></dd>
<dt><a name="28"><b class="cmd">::math::special::fresnel_S</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the Fresnel sine integral for real argument x</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function</p></dd>
</dl></dd>
<dt><a name="29"><b class="cmd">::math::special::sinc</b> <i class="arg">x</i></a></dt>
<dd><p>Compute the sinc function for real argument x</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>Argument for the function</p></dd>
</dl></dd>
<dt><a name="30"><b class="cmd">::math::special::legendre</b> <i class="arg">n</i></a></dt>
<dd><p>Return the Legendre polynomial of degree n
(see <span class="sectref"><a href="#section4">THE ORTHOGONAL POLYNOMIALS</a></span>)</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">n</i></dt>
<dd><p>Degree of the polynomial</p></dd>
</dl></dd>
<dt><a name="31"><b class="cmd">::math::special::chebyshev</b> <i class="arg">n</i></a></dt>
<dd><p>Return the Chebyshev polynomial of degree n (of the first kind)</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">n</i></dt>
<dd><p>Degree of the polynomial</p></dd>
</dl></dd>
<dt><a name="32"><b class="cmd">::math::special::laguerre</b> <i class="arg">alpha</i> <i class="arg">n</i></a></dt>
<dd><p>Return the Laguerre polynomial of degree n with parameter alpha</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">alpha</i></dt>
<dd><p>Parameter of the Laguerre polynomial</p></dd>
<dt>int <i class="arg">n</i></dt>
<dd><p>Degree of the polynomial</p></dd>
</dl></dd>
<dt><a name="33"><b class="cmd">::math::special::hermite</b> <i class="arg">n</i></a></dt>
<dd><p>Return the Hermite polynomial of degree n</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">n</i></dt>
<dd><p>Degree of the polynomial</p></dd>
</dl></dd>
</dl>
</div>

Changes to idoc/www/tcllib/files/modules/math/statistics.html.

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
<li><a href="#31"><b class="cmd">::math::statistics::print-2x2</b> <i class="arg">n11</i> <i class="arg">n21</i> <i class="arg">n12</i> <i class="arg">n22</i></a></li>
<li><a href="#32"><b class="cmd">::math::statistics::control-xbar</b> <i class="arg">data</i> <span class="opt">?nsamples?</span></a></li>
<li><a href="#33"><b class="cmd">::math::statistics::control-Rchart</b> <i class="arg">data</i> <span class="opt">?nsamples?</span></a></li>
<li><a href="#34"><b class="cmd">::math::statistics::test-xbar</b> <i class="arg">control</i> <i class="arg">data</i></a></li>
<li><a href="#35"><b class="cmd">::math::statistics::test-Rchart</b> <i class="arg">control</i> <i class="arg">data</i></a></li>
<li><a href="#36"><b class="cmd">::math::statistics::test-Kruskal-Wallis</b> <i class="arg">confidence</i> <i class="arg">args</i></a></li>
<li><a href="#37"><b class="cmd">::math::statistics::analyse-Kruskal-Wallis</b> <i class="arg">args</i></a></li>


<li><a href="#38"><b class="cmd">::math::statistics::group-rank</b> <i class="arg">args</i></a></li>
<li><a href="#39"><b class="cmd">::math::statistics::test-Wilcoxon</b> <i class="arg">sample_a</i> <i class="arg">sample_b</i></a></li>
<li><a href="#40"><b class="cmd">::math::statistics::spearman-rank</b> <i class="arg">sample_a</i> <i class="arg">sample_b</i></a></li>
<li><a href="#41"><b class="cmd">::math::statistics::spearman-rank-extended</b> <i class="arg">sample_a</i> <i class="arg">sample_b</i></a></li>
<li><a href="#42"><b class="cmd">::math::statistics::kernel-density</b> <i class="arg">data</i> opt <i class="arg">-option value</i> ...</a></li>
<li><a href="#43"><b class="cmd">::math::statistics::bootstrap</b> <i class="arg">data</i> <i class="arg">sampleSize</i> <span class="opt">?numberSamples?</span></a></li>
<li><a href="#44"><b class="cmd">::math::statistics::wasserstein-distance</b> <i class="arg">prob1</i> <i class="arg">prob2</i></a></li>
<li><a href="#45"><b class="cmd">::math::statistics::kl-divergence</b> <i class="arg">prob1</i> <i class="arg">prob2</i></a></li>
<li><a href="#46"><b class="cmd">::math::statistics::logistic-model</b> <i class="arg">xdata</i> <i class="arg">ydata</i></a></li>
<li><a href="#47"><b class="cmd">::math::statistics::logistic-probability</b> <i class="arg">coeffs</i> <i class="arg">x</i></a></li>
<li><a href="#48"><b class="cmd">::math::statistics::tstat</b> <i class="arg">dof</i> <span class="opt">?alpha?</span></a></li>
<li><a href="#49"><b class="cmd">::math::statistics::mv-wls</b> <i class="arg">wt1</i> <i class="arg">weights_and_values</i></a></li>
<li><a href="#50"><b class="cmd">::math::statistics::mv-ols</b> <i class="arg">values</i></a></li>
<li><a href="#51"><b class="cmd">::math::statistics::pdf-normal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></li>
<li><a href="#52"><b class="cmd">::math::statistics::pdf-lognormal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></li>
<li><a href="#53"><b class="cmd">::math::statistics::pdf-exponential</b> <i class="arg">mean</i> <i class="arg">value</i></a></li>
<li><a href="#54"><b class="cmd">::math::statistics::pdf-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></li>


<li><a href="#55"><b class="cmd">::math::statistics::pdf-gamma</b> <i class="arg">alpha</i> <i class="arg">beta</i> <i class="arg">value</i></a></li>
<li><a href="#56"><b class="cmd">::math::statistics::pdf-poisson</b> <i class="arg">mu</i> <i class="arg">k</i></a></li>
<li><a href="#57"><b class="cmd">::math::statistics::pdf-chisquare</b> <i class="arg">df</i> <i class="arg">value</i></a></li>
<li><a href="#58"><b class="cmd">::math::statistics::pdf-student-t</b> <i class="arg">df</i> <i class="arg">value</i></a></li>
<li><a href="#59"><b class="cmd">::math::statistics::pdf-gamma</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></li>
<li><a href="#60"><b class="cmd">::math::statistics::pdf-beta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></li>
<li><a href="#61"><b class="cmd">::math::statistics::pdf-weibull</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></li>
<li><a href="#62"><b class="cmd">::math::statistics::pdf-gumbel</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></li>
<li><a href="#63"><b class="cmd">::math::statistics::pdf-pareto</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></li>
<li><a href="#64"><b class="cmd">::math::statistics::pdf-cauchy</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></li>



<li><a href="#65"><b class="cmd">::math::statistics::cdf-normal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></li>
<li><a href="#66"><b class="cmd">::math::statistics::cdf-lognormal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></li>
<li><a href="#67"><b class="cmd">::math::statistics::cdf-exponential</b> <i class="arg">mean</i> <i class="arg">value</i></a></li>
<li><a href="#68"><b class="cmd">::math::statistics::cdf-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></li>


<li><a href="#69"><b class="cmd">::math::statistics::cdf-students-t</b> <i class="arg">degrees</i> <i class="arg">value</i></a></li>
<li><a href="#70"><b class="cmd">::math::statistics::cdf-gamma</b> <i class="arg">alpha</i> <i class="arg">beta</i> <i class="arg">value</i></a></li>
<li><a href="#71"><b class="cmd">::math::statistics::cdf-poisson</b> <i class="arg">mu</i> <i class="arg">k</i></a></li>
<li><a href="#72"><b class="cmd">::math::statistics::cdf-beta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></li>
<li><a href="#73"><b class="cmd">::math::statistics::cdf-weibull</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></li>
<li><a href="#74"><b class="cmd">::math::statistics::cdf-gumbel</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></li>
<li><a href="#75"><b class="cmd">::math::statistics::cdf-pareto</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></li>
<li><a href="#76"><b class="cmd">::math::statistics::cdf-cauchy</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></li>
<li><a href="#77"><b class="cmd">::math::statistics::cdf-F</b> <i class="arg">nf1</i> <i class="arg">nf2</i> <i class="arg">value</i></a></li>



<li><a href="#78"><b class="cmd">::math::statistics::empirical-distribution</b> <i class="arg">values</i></a></li>
<li><a href="#79"><b class="cmd">::math::statistics::random-normal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">number</i></a></li>
<li><a href="#80"><b class="cmd">::math::statistics::random-lognormal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">number</i></a></li>
<li><a href="#81"><b class="cmd">::math::statistics::random-exponential</b> <i class="arg">mean</i> <i class="arg">number</i></a></li>
<li><a href="#82"><b class="cmd">::math::statistics::random-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">number</i></a></li>


<li><a href="#83"><b class="cmd">::math::statistics::random-gamma</b> <i class="arg">alpha</i> <i class="arg">beta</i> <i class="arg">number</i></a></li>
<li><a href="#84"><b class="cmd">::math::statistics::random-poisson</b> <i class="arg">mu</i> <i class="arg">number</i></a></li>
<li><a href="#85"><b class="cmd">::math::statistics::random-chisquare</b> <i class="arg">df</i> <i class="arg">number</i></a></li>
<li><a href="#86"><b class="cmd">::math::statistics::random-student-t</b> <i class="arg">df</i> <i class="arg">number</i></a></li>
<li><a href="#87"><b class="cmd">::math::statistics::random-beta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">number</i></a></li>
<li><a href="#88"><b class="cmd">::math::statistics::random-weibull</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">number</i></a></li>
<li><a href="#89"><b class="cmd">::math::statistics::random-gumbel</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">number</i></a></li>
<li><a href="#90"><b class="cmd">::math::statistics::random-pareto</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">number</i></a></li>
<li><a href="#91"><b class="cmd">::math::statistics::random-cauchy</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">number</i></a></li>



<li><a href="#92"><b class="cmd">::math::statistics::histogram-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">limits</i> <i class="arg">number</i></a></li>
<li><a href="#93"><b class="cmd">::math::statistics::incompleteGamma</b> <i class="arg">x</i> <i class="arg">p</i> <span class="opt">?tol?</span></a></li>
<li><a href="#94"><b class="cmd">::math::statistics::incompleteBeta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">x</i> <span class="opt">?tol?</span></a></li>
<li><a href="#95"><b class="cmd">::math::statistics::estimate-pareto</b> <i class="arg">values</i></a></li>



<li><a href="#96"><b class="cmd">::math::statistics::filter</b> <i class="arg">varname</i> <i class="arg">data</i> <i class="arg">expression</i></a></li>
<li><a href="#97"><b class="cmd">::math::statistics::map</b> <i class="arg">varname</i> <i class="arg">data</i> <i class="arg">expression</i></a></li>
<li><a href="#98"><b class="cmd">::math::statistics::samplescount</b> <i class="arg">varname</i> <i class="arg">list</i> <i class="arg">expression</i></a></li>
<li><a href="#99"><b class="cmd">::math::statistics::subdivide</b></a></li>
<li><a href="#100"><b class="cmd">::math::statistics::plot-scale</b> <i class="arg">canvas</i> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">ymin</i> <i class="arg">ymax</i></a></li>
<li><a href="#101"><b class="cmd">::math::statistics::plot-xydata</b> <i class="arg">canvas</i> <i class="arg">xdata</i> <i class="arg">ydata</i> <i class="arg">tag</i></a></li>
<li><a href="#102"><b class="cmd">::math::statistics::plot-xyline</b> <i class="arg">canvas</i> <i class="arg">xdata</i> <i class="arg">ydata</i> <i class="arg">tag</i></a></li>
<li><a href="#103"><b class="cmd">::math::statistics::plot-tdata</b> <i class="arg">canvas</i> <i class="arg">tdata</i> <i class="arg">tag</i></a></li>
<li><a href="#104"><b class="cmd">::math::statistics::plot-tline</b> <i class="arg">canvas</i> <i class="arg">tdata</i> <i class="arg">tag</i></a></li>
<li><a href="#105"><b class="cmd">::math::statistics::plot-histogram</b> <i class="arg">canvas</i> <i class="arg">counts</i> <i class="arg">limits</i> <i class="arg">tag</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>The <b class="package">math::statistics</b> package contains functions and procedures for
basic statistical data analysis, such as:</p>
<ul class="doctools_itemized">







>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
>
>
>
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
>
>
>
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
>
>
>
|
|
|
|
>
>
>
|
|
|
|
|
|
|
|
|
|







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
<li><a href="#31"><b class="cmd">::math::statistics::print-2x2</b> <i class="arg">n11</i> <i class="arg">n21</i> <i class="arg">n12</i> <i class="arg">n22</i></a></li>
<li><a href="#32"><b class="cmd">::math::statistics::control-xbar</b> <i class="arg">data</i> <span class="opt">?nsamples?</span></a></li>
<li><a href="#33"><b class="cmd">::math::statistics::control-Rchart</b> <i class="arg">data</i> <span class="opt">?nsamples?</span></a></li>
<li><a href="#34"><b class="cmd">::math::statistics::test-xbar</b> <i class="arg">control</i> <i class="arg">data</i></a></li>
<li><a href="#35"><b class="cmd">::math::statistics::test-Rchart</b> <i class="arg">control</i> <i class="arg">data</i></a></li>
<li><a href="#36"><b class="cmd">::math::statistics::test-Kruskal-Wallis</b> <i class="arg">confidence</i> <i class="arg">args</i></a></li>
<li><a href="#37"><b class="cmd">::math::statistics::analyse-Kruskal-Wallis</b> <i class="arg">args</i></a></li>
<li><a href="#38"><b class="cmd">::math::statistics::test-Levene</b> <i class="arg">groups</i></a></li>
<li><a href="#39"><b class="cmd">::math::statistics::test-Brown-Forsythe</b> <i class="arg">groups</i></a></li>
<li><a href="#40"><b class="cmd">::math::statistics::group-rank</b> <i class="arg">args</i></a></li>
<li><a href="#41"><b class="cmd">::math::statistics::test-Wilcoxon</b> <i class="arg">sample_a</i> <i class="arg">sample_b</i></a></li>
<li><a href="#42"><b class="cmd">::math::statistics::spearman-rank</b> <i class="arg">sample_a</i> <i class="arg">sample_b</i></a></li>
<li><a href="#43"><b class="cmd">::math::statistics::spearman-rank-extended</b> <i class="arg">sample_a</i> <i class="arg">sample_b</i></a></li>
<li><a href="#44"><b class="cmd">::math::statistics::kernel-density</b> <i class="arg">data</i> opt <i class="arg">-option value</i> ...</a></li>
<li><a href="#45"><b class="cmd">::math::statistics::bootstrap</b> <i class="arg">data</i> <i class="arg">sampleSize</i> <span class="opt">?numberSamples?</span></a></li>
<li><a href="#46"><b class="cmd">::math::statistics::wasserstein-distance</b> <i class="arg">prob1</i> <i class="arg">prob2</i></a></li>
<li><a href="#47"><b class="cmd">::math::statistics::kl-divergence</b> <i class="arg">prob1</i> <i class="arg">prob2</i></a></li>
<li><a href="#48"><b class="cmd">::math::statistics::logistic-model</b> <i class="arg">xdata</i> <i class="arg">ydata</i></a></li>
<li><a href="#49"><b class="cmd">::math::statistics::logistic-probability</b> <i class="arg">coeffs</i> <i class="arg">x</i></a></li>
<li><a href="#50"><b class="cmd">::math::statistics::tstat</b> <i class="arg">dof</i> <span class="opt">?alpha?</span></a></li>
<li><a href="#51"><b class="cmd">::math::statistics::mv-wls</b> <i class="arg">wt1</i> <i class="arg">weights_and_values</i></a></li>
<li><a href="#52"><b class="cmd">::math::statistics::mv-ols</b> <i class="arg">values</i></a></li>
<li><a href="#53"><b class="cmd">::math::statistics::pdf-normal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></li>
<li><a href="#54"><b class="cmd">::math::statistics::pdf-lognormal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></li>
<li><a href="#55"><b class="cmd">::math::statistics::pdf-exponential</b> <i class="arg">mean</i> <i class="arg">value</i></a></li>
<li><a href="#56"><b class="cmd">::math::statistics::pdf-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></li>
<li><a href="#57"><b class="cmd">::math::statistics::pdf-triangular</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></li>
<li><a href="#58"><b class="cmd">::math::statistics::pdf-symmetric-triangular</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></li>
<li><a href="#59"><b class="cmd">::math::statistics::pdf-gamma</b> <i class="arg">alpha</i> <i class="arg">beta</i> <i class="arg">value</i></a></li>
<li><a href="#60"><b class="cmd">::math::statistics::pdf-poisson</b> <i class="arg">mu</i> <i class="arg">k</i></a></li>
<li><a href="#61"><b class="cmd">::math::statistics::pdf-chisquare</b> <i class="arg">df</i> <i class="arg">value</i></a></li>
<li><a href="#62"><b class="cmd">::math::statistics::pdf-student-t</b> <i class="arg">df</i> <i class="arg">value</i></a></li>
<li><a href="#63"><b class="cmd">::math::statistics::pdf-gamma</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></li>
<li><a href="#64"><b class="cmd">::math::statistics::pdf-beta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></li>
<li><a href="#65"><b class="cmd">::math::statistics::pdf-weibull</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></li>
<li><a href="#66"><b class="cmd">::math::statistics::pdf-gumbel</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></li>
<li><a href="#67"><b class="cmd">::math::statistics::pdf-pareto</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></li>
<li><a href="#68"><b class="cmd">::math::statistics::pdf-cauchy</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></li>
<li><a href="#69"><b class="cmd">::math::statistics::pdf-laplace</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></li>
<li><a href="#70"><b class="cmd">::math::statistics::pdf-kumaraswamy</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></li>
<li><a href="#71"><b class="cmd">::math::statistics::pdf-negative-binomial</b> <i class="arg">r</i> <i class="arg">p</i> <i class="arg">value</i></a></li>
<li><a href="#72"><b class="cmd">::math::statistics::cdf-normal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></li>
<li><a href="#73"><b class="cmd">::math::statistics::cdf-lognormal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></li>
<li><a href="#74"><b class="cmd">::math::statistics::cdf-exponential</b> <i class="arg">mean</i> <i class="arg">value</i></a></li>
<li><a href="#75"><b class="cmd">::math::statistics::cdf-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></li>
<li><a href="#76"><b class="cmd">::math::statistics::cdf-triangular</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></li>
<li><a href="#77"><b class="cmd">::math::statistics::cdf-symmetric-triangular</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></li>
<li><a href="#78"><b class="cmd">::math::statistics::cdf-students-t</b> <i class="arg">degrees</i> <i class="arg">value</i></a></li>
<li><a href="#79"><b class="cmd">::math::statistics::cdf-gamma</b> <i class="arg">alpha</i> <i class="arg">beta</i> <i class="arg">value</i></a></li>
<li><a href="#80"><b class="cmd">::math::statistics::cdf-poisson</b> <i class="arg">mu</i> <i class="arg">k</i></a></li>
<li><a href="#81"><b class="cmd">::math::statistics::cdf-beta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></li>
<li><a href="#82"><b class="cmd">::math::statistics::cdf-weibull</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></li>
<li><a href="#83"><b class="cmd">::math::statistics::cdf-gumbel</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></li>
<li><a href="#84"><b class="cmd">::math::statistics::cdf-pareto</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></li>
<li><a href="#85"><b class="cmd">::math::statistics::cdf-cauchy</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></li>
<li><a href="#86"><b class="cmd">::math::statistics::cdf-F</b> <i class="arg">nf1</i> <i class="arg">nf2</i> <i class="arg">value</i></a></li>
<li><a href="#87"><b class="cmd">::math::statistics::cdf-laplace</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></li>
<li><a href="#88"><b class="cmd">::math::statistics::cdf-kumaraswamy</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></li>
<li><a href="#89"><b class="cmd">::math::statistics::cdf-negative-binomial</b> <i class="arg">r</i> <i class="arg">p</i> <i class="arg">value</i></a></li>
<li><a href="#90"><b class="cmd">::math::statistics::empirical-distribution</b> <i class="arg">values</i></a></li>
<li><a href="#91"><b class="cmd">::math::statistics::random-normal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">number</i></a></li>
<li><a href="#92"><b class="cmd">::math::statistics::random-lognormal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">number</i></a></li>
<li><a href="#93"><b class="cmd">::math::statistics::random-exponential</b> <i class="arg">mean</i> <i class="arg">number</i></a></li>
<li><a href="#94"><b class="cmd">::math::statistics::random-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">number</i></a></li>
<li><a href="#95"><b class="cmd">::math::statistics::random-triangular</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">number</i></a></li>
<li><a href="#96"><b class="cmd">::math::statistics::random-symmetric-triangular</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">number</i></a></li>
<li><a href="#97"><b class="cmd">::math::statistics::random-gamma</b> <i class="arg">alpha</i> <i class="arg">beta</i> <i class="arg">number</i></a></li>
<li><a href="#98"><b class="cmd">::math::statistics::random-poisson</b> <i class="arg">mu</i> <i class="arg">number</i></a></li>
<li><a href="#99"><b class="cmd">::math::statistics::random-chisquare</b> <i class="arg">df</i> <i class="arg">number</i></a></li>
<li><a href="#100"><b class="cmd">::math::statistics::random-student-t</b> <i class="arg">df</i> <i class="arg">number</i></a></li>
<li><a href="#101"><b class="cmd">::math::statistics::random-beta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">number</i></a></li>
<li><a href="#102"><b class="cmd">::math::statistics::random-weibull</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">number</i></a></li>
<li><a href="#103"><b class="cmd">::math::statistics::random-gumbel</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">number</i></a></li>
<li><a href="#104"><b class="cmd">::math::statistics::random-pareto</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">number</i></a></li>
<li><a href="#105"><b class="cmd">::math::statistics::random-cauchy</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">number</i></a></li>
<li><a href="#106"><b class="cmd">::math::statistics::random-laplace</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">number</i></a></li>
<li><a href="#107"><b class="cmd">::math::statistics::random-kumaraswamy</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">number</i></a></li>
<li><a href="#108"><b class="cmd">::math::statistics::random-negative-binomial</b> <i class="arg">r</i> <i class="arg">p</i> <i class="arg">number</i></a></li>
<li><a href="#109"><b class="cmd">::math::statistics::histogram-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">limits</i> <i class="arg">number</i></a></li>
<li><a href="#110"><b class="cmd">::math::statistics::incompleteGamma</b> <i class="arg">x</i> <i class="arg">p</i> <span class="opt">?tol?</span></a></li>
<li><a href="#111"><b class="cmd">::math::statistics::incompleteBeta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">x</i> <span class="opt">?tol?</span></a></li>
<li><a href="#112"><b class="cmd">::math::statistics::estimate-pareto</b> <i class="arg">values</i></a></li>
<li><a href="#113"><b class="cmd">::math::statistics::estimate-exponential</b> <i class="arg">values</i></a></li>
<li><a href="#114"><b class="cmd">::math::statistics::estimate-laplace</b> <i class="arg">values</i></a></li>
<li><a href="#115"><b class="cmd">::math::statistics::estimante-negative-binomial</b> <i class="arg">r</i> <i class="arg">values</i></a></li>
<li><a href="#116"><b class="cmd">::math::statistics::filter</b> <i class="arg">varname</i> <i class="arg">data</i> <i class="arg">expression</i></a></li>
<li><a href="#117"><b class="cmd">::math::statistics::map</b> <i class="arg">varname</i> <i class="arg">data</i> <i class="arg">expression</i></a></li>
<li><a href="#118"><b class="cmd">::math::statistics::samplescount</b> <i class="arg">varname</i> <i class="arg">list</i> <i class="arg">expression</i></a></li>
<li><a href="#119"><b class="cmd">::math::statistics::subdivide</b></a></li>
<li><a href="#120"><b class="cmd">::math::statistics::plot-scale</b> <i class="arg">canvas</i> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">ymin</i> <i class="arg">ymax</i></a></li>
<li><a href="#121"><b class="cmd">::math::statistics::plot-xydata</b> <i class="arg">canvas</i> <i class="arg">xdata</i> <i class="arg">ydata</i> <i class="arg">tag</i></a></li>
<li><a href="#122"><b class="cmd">::math::statistics::plot-xyline</b> <i class="arg">canvas</i> <i class="arg">xdata</i> <i class="arg">ydata</i> <i class="arg">tag</i></a></li>
<li><a href="#123"><b class="cmd">::math::statistics::plot-tdata</b> <i class="arg">canvas</i> <i class="arg">tdata</i> <i class="arg">tag</i></a></li>
<li><a href="#124"><b class="cmd">::math::statistics::plot-tline</b> <i class="arg">canvas</i> <i class="arg">tdata</i> <i class="arg">tag</i></a></li>
<li><a href="#125"><b class="cmd">::math::statistics::plot-histogram</b> <i class="arg">canvas</i> <i class="arg">counts</i> <i class="arg">limits</i> <i class="arg">tag</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>The <b class="package">math::statistics</b> package contains functions and procedures for
basic statistical data analysis, such as:</p>
<ul class="doctools_itemized">
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
Returns the Kruskal-Wallis statistic and the probability that that
value would occur assuming the medians of the populations are
equal.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">args</i></dt>
<dd><p>- Two or more lists of data</p></dd>
</dl></dd>



















<dt><a name="38"><b class="cmd">::math::statistics::group-rank</b> <i class="arg">args</i></a></dt>
<dd><p>Rank the groups of data with respect to the complete set.
Returns a list consisting of the group ID, the value and the rank
(possibly a rational number, in case of ties) for each data item.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">args</i></dt>
<dd><p>- Two or more lists of data</p></dd>
</dl></dd>
<dt><a name="39"><b class="cmd">::math::statistics::test-Wilcoxon</b> <i class="arg">sample_a</i> <i class="arg">sample_b</i></a></dt>
<dd><p>Compute the Wilcoxon test statistic to determine if two samples have the
same median or not. (The statistic can be regarded as standard normal, if the
sample sizes are both larger than 10. Returns the value of this statistic.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">sample_a</i></dt>
<dd><p>- List of data comprising the first sample</p></dd>
<dt>list <i class="arg">sample_b</i></dt>
<dd><p>- List of data comprising the second sample</p></dd>
</dl></dd>
<dt><a name="40"><b class="cmd">::math::statistics::spearman-rank</b> <i class="arg">sample_a</i> <i class="arg">sample_b</i></a></dt>
<dd><p>Return the Spearman rank correlation as an alternative to the ordinary (Pearson's) correlation
coefficient. The two samples should have the same number of data.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">sample_a</i></dt>
<dd><p>- First list of data</p></dd>
<dt>list <i class="arg">sample_b</i></dt>
<dd><p>- Second list of data</p></dd>
</dl></dd>
<dt><a name="41"><b class="cmd">::math::statistics::spearman-rank-extended</b> <i class="arg">sample_a</i> <i class="arg">sample_b</i></a></dt>
<dd><p>Return the Spearman rank correlation as an alternative to the ordinary (Pearson's) correlation
coefficient as well as additional data. The two samples should have the same number of data.
The procedure returns the correlation coefficient, the number of data pairs used and the
z-score, an approximately standard normal statistic, indicating the significance of the correlation.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">sample_a</i></dt>
<dd><p>- First list of data</p></dd>
<dt>list <i class="arg">sample_b</i></dt>
<dd><p>- Second list of data</p></dd>
</dl></dd>
<dt><a name="42"><b class="cmd">::math::statistics::kernel-density</b> <i class="arg">data</i> opt <i class="arg">-option value</i> ...</a></dt>
<dd><p>Return the density function based on kernel density estimation. The procedure is controlled by
a small set of options, each of which is given a reasonable default.</p>
<p>The return value consists of three lists: the centres of the bins, the associated probability
density and a list of computational parameters (begin and end of the interval, mean and standard
deviation and the used bandwidth). The computational parameters can be used for further analysis.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">data</i></dt>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







|


|






|








|










|







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
Returns the Kruskal-Wallis statistic and the probability that that
value would occur assuming the medians of the populations are
equal.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">args</i></dt>
<dd><p>- Two or more lists of data</p></dd>
</dl></dd>
<dt><a name="38"><b class="cmd">::math::statistics::test-Levene</b> <i class="arg">groups</i></a></dt>
<dd><p>Compute the Levene statistic to determine if groups of data have the
same variance (are homoscadastic) or not. The data are organised
in groups. This version uses the mean of the data as the measure
to determine the deviations. The statistic is equivalent to an
F statistic with degrees of freedom k-1 and N-k, k being the
number of groups and N the total number of data.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">groups</i></dt>
<dd><p>- List of groups of data</p></dd>
</dl></dd>
<dt><a name="39"><b class="cmd">::math::statistics::test-Brown-Forsythe</b> <i class="arg">groups</i></a></dt>
<dd><p>Compute the Brown-Forsythe statistic to determine if groups of data have the
same variance (are homoscadastic) or not. Like the Levene test, but this
version uses the median of the data.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">groups</i></dt>
<dd><p>- List of groups of data</p></dd>
</dl></dd>
<dt><a name="40"><b class="cmd">::math::statistics::group-rank</b> <i class="arg">args</i></a></dt>
<dd><p>Rank the groups of data with respect to the complete set.
Returns a list consisting of the group ID, the value and the rank
(possibly a rational number, in case of ties) for each data item.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">args</i></dt>
<dd><p>- Two or more lists of data</p></dd>
</dl></dd>
<dt><a name="41"><b class="cmd">::math::statistics::test-Wilcoxon</b> <i class="arg">sample_a</i> <i class="arg">sample_b</i></a></dt>
<dd><p>Compute the Wilcoxon test statistic to determine if two samples have the
same median or not. (The statistic can be regarded as standard normal, if the
sample sizes are both larger than 10.) Returns the value of this statistic.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">sample_a</i></dt>
<dd><p>- List of data comprising the first sample</p></dd>
<dt>list <i class="arg">sample_b</i></dt>
<dd><p>- List of data comprising the second sample</p></dd>
</dl></dd>
<dt><a name="42"><b class="cmd">::math::statistics::spearman-rank</b> <i class="arg">sample_a</i> <i class="arg">sample_b</i></a></dt>
<dd><p>Return the Spearman rank correlation as an alternative to the ordinary (Pearson's) correlation
coefficient. The two samples should have the same number of data.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">sample_a</i></dt>
<dd><p>- First list of data</p></dd>
<dt>list <i class="arg">sample_b</i></dt>
<dd><p>- Second list of data</p></dd>
</dl></dd>
<dt><a name="43"><b class="cmd">::math::statistics::spearman-rank-extended</b> <i class="arg">sample_a</i> <i class="arg">sample_b</i></a></dt>
<dd><p>Return the Spearman rank correlation as an alternative to the ordinary (Pearson's) correlation
coefficient as well as additional data. The two samples should have the same number of data.
The procedure returns the correlation coefficient, the number of data pairs used and the
z-score, an approximately standard normal statistic, indicating the significance of the correlation.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">sample_a</i></dt>
<dd><p>- First list of data</p></dd>
<dt>list <i class="arg">sample_b</i></dt>
<dd><p>- Second list of data</p></dd>
</dl></dd>
<dt><a name="44"><b class="cmd">::math::statistics::kernel-density</b> <i class="arg">data</i> opt <i class="arg">-option value</i> ...</a></dt>
<dd><p>Return the density function based on kernel density estimation. The procedure is controlled by
a small set of options, each of which is given a reasonable default.</p>
<p>The return value consists of three lists: the centres of the bins, the associated probability
density and a list of computational parameters (begin and end of the interval, mean and standard
deviation and the used bandwidth). The computational parameters can be used for further analysis.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">data</i></dt>
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
<dd><p>Begin and end of the interval for
which the density is returned (default: mean +/- 3*standard deviation)</p></dd>
<dt><b class="option">-kernel</b> <i class="arg">function</i></dt>
<dd><p>Kernel to be used (One of: gaussian, cosine,
epanechnikov, uniform, triangular, biweight, logistic; default: gaussian)</p></dd>
</dl></dd>
</dl></dd>
<dt><a name="43"><b class="cmd">::math::statistics::bootstrap</b> <i class="arg">data</i> <i class="arg">sampleSize</i> <span class="opt">?numberSamples?</span></a></dt>
<dd><p>Create a subsample or subsamples from a given list of data. The data in the samples are chosen
from this list - multiples may occur. If there is only one subsample, the sample itself
is returned (as a list of &quot;sampleSize&quot; values), otherwise a list of samples is returned.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">data</i></dt>
<dd><p>List of values to chose from</p></dd>
<dt>int <i class="arg">sampleSize</i></dt>
<dd><p>Number of values per sample</p></dd>
<dt>int <i class="arg">numberSamples</i></dt>
<dd><p>Number of samples (default: 1)</p></dd>
</dl></dd>
<dt><a name="44"><b class="cmd">::math::statistics::wasserstein-distance</b> <i class="arg">prob1</i> <i class="arg">prob2</i></a></dt>
<dd><p>Compute the Wasserstein distance or earth mover's distance for two equidstantly spaced histograms
or probability densities. The histograms need not to be normalised to sum to one,
but they must have the same number of entries.</p>
<p>Note: the histograms are assumed to be based on the same equidistant intervals.
As the bounds are not passed, the value is expressed in the length of the intervals.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">prob1</i></dt>
<dd><p>List of values for the first histogram/probability density</p></dd>
<dt>list <i class="arg">prob2</i></dt>
<dd><p>List of values for the second histogram/probability density</p></dd>
</dl></dd>
<dt><a name="45"><b class="cmd">::math::statistics::kl-divergence</b> <i class="arg">prob1</i> <i class="arg">prob2</i></a></dt>
<dd><p>Compute the Kullback-Leibler (KL) divergence for two equidstantly spaced histograms
or probability densities. The histograms need not to be normalised to sum to one,
but they must have the same number of entries.</p>
<p>Note: the histograms are assumed to be based on the same equidistant intervals.
As the bounds are not passed, the value is expressed in the length of the intervals.</p>
<p>Note also that the KL divergence is not symmetric and that the second histogram
should not contain zeroes in places where the first histogram has non-zero values.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">prob1</i></dt>
<dd><p>List of values for the first histogram/probability density</p></dd>
<dt>list <i class="arg">prob2</i></dt>
<dd><p>List of values for the second histogram/probability density</p></dd>
</dl></dd>
<dt><a name="46"><b class="cmd">::math::statistics::logistic-model</b> <i class="arg">xdata</i> <i class="arg">ydata</i></a></dt>
<dd><p>Estimate the coefficients of the logistic model that fits the data best. The data consist
of independent x-values and the outcome 0 or 1 for each of the x-values. The result
can be used to estimate the probability that a certain x-value gives 1.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">xdata</i></dt>
<dd><p>List of values for which the success (1) or failure (0) is known</p></dd>
<dt>list <i class="arg">ydata</i></dt>
<dd><p>List of successes or failures corresponding to each value in <i class="term">xdata</i>.</p></dd>
</dl></dd>
<dt><a name="47"><b class="cmd">::math::statistics::logistic-probability</b> <i class="arg">coeffs</i> <i class="arg">x</i></a></dt>
<dd><p>Calculate the probability of success for the value <i class="term">x</i> given the coefficients of the
logistic model.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">coeffs</i></dt>
<dd><p>List of coefficients as determine by the <b class="cmd">logistic-model</b> command</p></dd>
<dt>float <i class="arg">x</i></dt>
<dd><p>X-value for which the probability needs to be determined</p></dd>







|











|











|













|









|







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
<dd><p>Begin and end of the interval for
which the density is returned (default: mean +/- 3*standard deviation)</p></dd>
<dt><b class="option">-kernel</b> <i class="arg">function</i></dt>
<dd><p>Kernel to be used (One of: gaussian, cosine,
epanechnikov, uniform, triangular, biweight, logistic; default: gaussian)</p></dd>
</dl></dd>
</dl></dd>
<dt><a name="45"><b class="cmd">::math::statistics::bootstrap</b> <i class="arg">data</i> <i class="arg">sampleSize</i> <span class="opt">?numberSamples?</span></a></dt>
<dd><p>Create a subsample or subsamples from a given list of data. The data in the samples are chosen
from this list - multiples may occur. If there is only one subsample, the sample itself
is returned (as a list of &quot;sampleSize&quot; values), otherwise a list of samples is returned.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">data</i></dt>
<dd><p>List of values to chose from</p></dd>
<dt>int <i class="arg">sampleSize</i></dt>
<dd><p>Number of values per sample</p></dd>
<dt>int <i class="arg">numberSamples</i></dt>
<dd><p>Number of samples (default: 1)</p></dd>
</dl></dd>
<dt><a name="46"><b class="cmd">::math::statistics::wasserstein-distance</b> <i class="arg">prob1</i> <i class="arg">prob2</i></a></dt>
<dd><p>Compute the Wasserstein distance or earth mover's distance for two equidstantly spaced histograms
or probability densities. The histograms need not to be normalised to sum to one,
but they must have the same number of entries.</p>
<p>Note: the histograms are assumed to be based on the same equidistant intervals.
As the bounds are not passed, the value is expressed in the length of the intervals.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">prob1</i></dt>
<dd><p>List of values for the first histogram/probability density</p></dd>
<dt>list <i class="arg">prob2</i></dt>
<dd><p>List of values for the second histogram/probability density</p></dd>
</dl></dd>
<dt><a name="47"><b class="cmd">::math::statistics::kl-divergence</b> <i class="arg">prob1</i> <i class="arg">prob2</i></a></dt>
<dd><p>Compute the Kullback-Leibler (KL) divergence for two equidstantly spaced histograms
or probability densities. The histograms need not to be normalised to sum to one,
but they must have the same number of entries.</p>
<p>Note: the histograms are assumed to be based on the same equidistant intervals.
As the bounds are not passed, the value is expressed in the length of the intervals.</p>
<p>Note also that the KL divergence is not symmetric and that the second histogram
should not contain zeroes in places where the first histogram has non-zero values.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">prob1</i></dt>
<dd><p>List of values for the first histogram/probability density</p></dd>
<dt>list <i class="arg">prob2</i></dt>
<dd><p>List of values for the second histogram/probability density</p></dd>
</dl></dd>
<dt><a name="48"><b class="cmd">::math::statistics::logistic-model</b> <i class="arg">xdata</i> <i class="arg">ydata</i></a></dt>
<dd><p>Estimate the coefficients of the logistic model that fits the data best. The data consist
of independent x-values and the outcome 0 or 1 for each of the x-values. The result
can be used to estimate the probability that a certain x-value gives 1.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">xdata</i></dt>
<dd><p>List of values for which the success (1) or failure (0) is known</p></dd>
<dt>list <i class="arg">ydata</i></dt>
<dd><p>List of successes or failures corresponding to each value in <i class="term">xdata</i>.</p></dd>
</dl></dd>
<dt><a name="49"><b class="cmd">::math::statistics::logistic-probability</b> <i class="arg">coeffs</i> <i class="arg">x</i></a></dt>
<dd><p>Calculate the probability of success for the value <i class="term">x</i> given the coefficients of the
logistic model.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">coeffs</i></dt>
<dd><p>List of coefficients as determine by the <b class="cmd">logistic-model</b> command</p></dd>
<dt>float <i class="arg">x</i></dt>
<dd><p>X-value for which the probability needs to be determined</p></dd>
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
<p>In addition to these two, it provides a procedure (tstat)
for calculating the value of the t-statistic for the specified number of
degrees of freedom that is required to demonstrate a given level of
significance.</p>
<p>Note: These procedures depend on the math::linearalgebra package.</p>
<p><em>Description of the procedures</em></p>
<dl class="doctools_definitions">
<dt><a name="48"><b class="cmd">::math::statistics::tstat</b> <i class="arg">dof</i> <span class="opt">?alpha?</span></a></dt>
<dd><p>Returns the value of the t-distribution t* satisfying</p>
<pre class="doctools_example">
    P(t*)  =  1 - alpha/2
    P(-t*) =  alpha/2
</pre>
<p>for the number of degrees of freedom dof.</p>
<p>Given a sample of normally-distributed data x, with an







|







868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
<p>In addition to these two, it provides a procedure (tstat)
for calculating the value of the t-statistic for the specified number of
degrees of freedom that is required to demonstrate a given level of
significance.</p>
<p>Note: These procedures depend on the math::linearalgebra package.</p>
<p><em>Description of the procedures</em></p>
<dl class="doctools_definitions">
<dt><a name="50"><b class="cmd">::math::statistics::tstat</b> <i class="arg">dof</i> <span class="opt">?alpha?</span></a></dt>
<dd><p>Returns the value of the t-distribution t* satisfying</p>
<pre class="doctools_example">
    P(t*)  =  1 - alpha/2
    P(-t*) =  alpha/2
</pre>
<p>for the number of degrees of freedom dof.</p>
<p>Given a sample of normally-distributed data x, with an
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
the given confidence level.</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">dof</i></dt>
<dd><p>Number of degrees of freedom</p></dd>
<dt>float <i class="arg">alpha</i></dt>
<dd><p>Confidence level of the t-distribution. Defaults to 0.05.</p></dd>
</dl></dd>
<dt><a name="49"><b class="cmd">::math::statistics::mv-wls</b> <i class="arg">wt1</i> <i class="arg">weights_and_values</i></a></dt>
<dd><p>Carries out a weighted least squares linear regression for
the data points provided, with weights assigned to each point.</p>
<p>The linear model is of the form</p>
<pre class="doctools_example">
    y = b0 + b1 * x1 + b2 * x2 ... + bN * xN + error
</pre>
<p>and each point satisfies</p>







|







892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
the given confidence level.</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">dof</i></dt>
<dd><p>Number of degrees of freedom</p></dd>
<dt>float <i class="arg">alpha</i></dt>
<dd><p>Confidence level of the t-distribution. Defaults to 0.05.</p></dd>
</dl></dd>
<dt><a name="51"><b class="cmd">::math::statistics::mv-wls</b> <i class="arg">wt1</i> <i class="arg">weights_and_values</i></a></dt>
<dd><p>Carries out a weighted least squares linear regression for
the data points provided, with weights assigned to each point.</p>
<p>The linear model is of the form</p>
<pre class="doctools_example">
    y = b0 + b1 * x1 + b2 * x2 ... + bN * xN + error
</pre>
<p>and each point satisfies</p>
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
<dt>list <i class="arg">weights_and_values</i></dt>
<dd><p>A list consisting of: the weight for the first observation, the data
for the first observation (as a sublist), the weight for the second
observation (as a sublist) and so on. The sublists of data are organised
as lists of the value of the dependent variable y and the independent
variables x1, x2 to xN.</p></dd>
</dl></dd>
<dt><a name="50"><b class="cmd">::math::statistics::mv-ols</b> <i class="arg">values</i></a></dt>
<dd><p>Carries out an ordinary least squares linear regression for
the data points provided.</p>
<p>This procedure simply calls ::mvlinreg::wls with the weights
set to 1.0, and returns the same information.</p></dd>
</dl>
<p><em>Example of the use:</em></p>
<pre class="doctools_example">







|







922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
<dt>list <i class="arg">weights_and_values</i></dt>
<dd><p>A list consisting of: the weight for the first observation, the data
for the first observation (as a sublist), the weight for the second
observation (as a sublist) and so on. The sublists of data are organised
as lists of the value of the dependent variable y and the independent
variables x1, x2 to xN.</p></dd>
</dl></dd>
<dt><a name="52"><b class="cmd">::math::statistics::mv-ols</b> <i class="arg">values</i></a></dt>
<dd><p>Carries out an ordinary least squares linear regression for
the data points provided.</p>
<p>This procedure simply calls ::mvlinreg::wls with the weights
set to 1.0, and returns the same information.</p></dd>
</dl>
<p><em>Example of the use:</em></p>
<pre class="doctools_example">
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
<li><p>The cumulative density (cdf-*)</p></li>
<li><p>Quantiles for the given distribution (quantiles-*)</p></li>
<li><p>Histograms for the given distribution (histogram-*)</p></li>
<li><p>List of random values with the given distribution (random-*)</p></li>
</ul>
<p>The following procedures have been implemented:</p>
<dl class="doctools_definitions">
<dt><a name="51"><b class="cmd">::math::statistics::pdf-normal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a normal distribution with
given mean and standard deviation.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">stdev</i></dt>
<dd><p>- Standard deviation of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="52"><b class="cmd">::math::statistics::pdf-lognormal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a log-normal distribution with
given mean and standard deviation.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">stdev</i></dt>
<dd><p>- Standard deviation of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="53"><b class="cmd">::math::statistics::pdf-exponential</b> <i class="arg">mean</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for an exponential
distribution with given mean.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="54"><b class="cmd">::math::statistics::pdf-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a uniform
distribution with given extremes.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum value of the distribution</p></dd>
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Maximum value of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
























<dt><a name="55"><b class="cmd">::math::statistics::pdf-gamma</b> <i class="arg">alpha</i> <i class="arg">beta</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Gamma
distribution with given shape and rate parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">alpha</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">beta</i></dt>
<dd><p>- Rate parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="56"><b class="cmd">::math::statistics::pdf-poisson</b> <i class="arg">mu</i> <i class="arg">k</i></a></dt>
<dd><p>Return the probability of a given number of occurrences in the same
interval (k) for a Poisson distribution with given mean (mu)</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mu</i></dt>
<dd><p>- Mean number of occurrences</p></dd>
<dt>int <i class="arg">k</i></dt>
<dd><p>- Number of occurences</p></dd>
</dl></dd>
<dt><a name="57"><b class="cmd">::math::statistics::pdf-chisquare</b> <i class="arg">df</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a chi square
distribution with given degrees of freedom</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">df</i></dt>
<dd><p>- Degrees of freedom</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="58"><b class="cmd">::math::statistics::pdf-student-t</b> <i class="arg">df</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Student's t
distribution with given degrees of freedom</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">df</i></dt>
<dd><p>- Degrees of freedom</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="59"><b class="cmd">::math::statistics::pdf-gamma</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Gamma
distribution with given shape and rate parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">a</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">b</i></dt>
<dd><p>- Rate parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="60"><b class="cmd">::math::statistics::pdf-beta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Beta
distribution with given shape parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">a</i></dt>
<dd><p>- First shape parameter</p></dd>
<dt>float <i class="arg">b</i></dt>
<dd><p>- Second shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="61"><b class="cmd">::math::statistics::pdf-weibull</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Weibull
distribution with given scale and shape parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="62"><b class="cmd">::math::statistics::pdf-gumbel</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Gumbel
distribution with given location and shape parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Location parameter</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="63"><b class="cmd">::math::statistics::pdf-pareto</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Pareto
distribution with given scale and shape parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">shape</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="64"><b class="cmd">::math::statistics::pdf-cauchy</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Cauchy
distribution with given location and shape parameters. Note that the Cauchy distribution
has no finite higher-order moments.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Location parameter</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>




































<dt><a name="65"><b class="cmd">::math::statistics::cdf-normal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a normal
distribution with given mean and standard deviation, that is the
probability for values up to the given one.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">stdev</i></dt>
<dd><p>- Standard deviation of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="66"><b class="cmd">::math::statistics::cdf-lognormal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a log-normal
distribution with given mean and standard deviation, that is the
probability for values up to the given one.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">stdev</i></dt>
<dd><p>- Standard deviation of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="67"><b class="cmd">::math::statistics::cdf-exponential</b> <i class="arg">mean</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for an exponential
distribution with given mean.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="68"><b class="cmd">::math::statistics::cdf-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a uniform
distribution with given extremes.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum value of the distribution</p></dd>
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Maximum value of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>























<dt><a name="69"><b class="cmd">::math::statistics::cdf-students-t</b> <i class="arg">degrees</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Student's t
distribution with given number of degrees.</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">degrees</i></dt>
<dd><p>- Number of degrees of freedom</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="70"><b class="cmd">::math::statistics::cdf-gamma</b> <i class="arg">alpha</i> <i class="arg">beta</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Gamma
distribution with given shape and rate parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">alpha</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">beta</i></dt>
<dd><p>- Rate parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the cumulative probability is required</p></dd>
</dl></dd>
<dt><a name="71"><b class="cmd">::math::statistics::cdf-poisson</b> <i class="arg">mu</i> <i class="arg">k</i></a></dt>
<dd><p>Return the cumulative probability of a given number of occurrences in
the same interval (k) for a Poisson distribution with given mean (mu).</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mu</i></dt>
<dd><p>- Mean number of occurrences</p></dd>
<dt>int <i class="arg">k</i></dt>
<dd><p>- Number of occurences</p></dd>
</dl></dd>
<dt><a name="72"><b class="cmd">::math::statistics::cdf-beta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Beta
distribution with given shape parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">a</i></dt>
<dd><p>- First shape parameter</p></dd>
<dt>float <i class="arg">b</i></dt>
<dd><p>- Second shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="73"><b class="cmd">::math::statistics::cdf-weibull</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Weibull
distribution with given scale and shape parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">shape</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="74"><b class="cmd">::math::statistics::cdf-gumbel</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Gumbel
distribution with given location and scale parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Location parameter</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="75"><b class="cmd">::math::statistics::cdf-pareto</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Pareto
distribution with given scale and shape parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">shape</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="76"><b class="cmd">::math::statistics::cdf-cauchy</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Cauchy
distribution with given location and scale parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Location parameter</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="77"><b class="cmd">::math::statistics::cdf-F</b> <i class="arg">nf1</i> <i class="arg">nf2</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for an F
distribution with nf1 and nf2 degrees of freedom.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">nf1</i></dt>
<dd><p>- Degrees of freedom for the numerator</p></dd>
<dt>float <i class="arg">nf2</i></dt>
<dd><p>- Degrees of freedom for the denominator</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>




































<dt><a name="78"><b class="cmd">::math::statistics::empirical-distribution</b> <i class="arg">values</i></a></dt>
<dd><p>Return a list of values and their empirical probability. The values are sorted in increasing order.
(The implementation follows the description at the corresponding Wikipedia page)</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">values</i></dt>
<dd><p>- List of data to be examined</p></dd>
</dl></dd>
<dt><a name="79"><b class="cmd">::math::statistics::random-normal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying a normal
distribution with given mean and standard deviation.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">stdev</i></dt>
<dd><p>- Standard deviation of the distribution</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="80"><b class="cmd">::math::statistics::random-lognormal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying a log-normal
distribution with given mean and standard deviation.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">stdev</i></dt>
<dd><p>- Standard deviation of the distribution</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="81"><b class="cmd">::math::statistics::random-exponential</b> <i class="arg">mean</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying an exponential
distribution with given mean.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="82"><b class="cmd">::math::statistics::random-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying a uniform
distribution with given extremes.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum value of the distribution</p></dd>
<dt>float <i class="arg">xmax</i></dt>
<dd><p>- Maximum value of the distribution</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>























<dt><a name="83"><b class="cmd">::math::statistics::random-gamma</b> <i class="arg">alpha</i> <i class="arg">beta</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Gamma distribution with given shape and rate parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">alpha</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">beta</i></dt>
<dd><p>- Rate parameter</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="84"><b class="cmd">::math::statistics::random-poisson</b> <i class="arg">mu</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Poisson distribution with given mean.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mu</i></dt>
<dd><p>- Mean of the distribution</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="85"><b class="cmd">::math::statistics::random-chisquare</b> <i class="arg">df</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a chi square distribution with given degrees of freedom.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">df</i></dt>
<dd><p>- Degrees of freedom</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="86"><b class="cmd">::math::statistics::random-student-t</b> <i class="arg">df</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Student's t distribution with given degrees of freedom.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">df</i></dt>
<dd><p>- Degrees of freedom</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="87"><b class="cmd">::math::statistics::random-beta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Beta distribution with given shape parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">a</i></dt>
<dd><p>- First shape parameter</p></dd>
<dt>float <i class="arg">b</i></dt>
<dd><p>- Second shape parameter</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="88"><b class="cmd">::math::statistics::random-weibull</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Weibull distribution with given scale and shape parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">shape</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="89"><b class="cmd">::math::statistics::random-gumbel</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Gumbel distribution with given location and scale parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Location parameter</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="90"><b class="cmd">::math::statistics::random-pareto</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Pareto distribution with given scale and shape parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">shape</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="91"><b class="cmd">::math::statistics::random-cauchy</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Cauchy distribution with given location and scale parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Location parameter</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>



































<dt><a name="92"><b class="cmd">::math::statistics::histogram-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">limits</i> <i class="arg">number</i></a></dt>
<dd><p>Return the expected histogram for a uniform distribution.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum value of the distribution</p></dd>
<dt>float <i class="arg">xmax</i></dt>
<dd><p>- Maximum value of the distribution</p></dd>
<dt>list <i class="arg">limits</i></dt>
<dd><p>- Upper limits for the buckets in the histogram</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Total number of &quot;observations&quot; in the histogram</p></dd>
</dl></dd>
<dt><a name="93"><b class="cmd">::math::statistics::incompleteGamma</b> <i class="arg">x</i> <i class="arg">p</i> <span class="opt">?tol?</span></a></dt>
<dd><p>Evaluate the incomplete Gamma integral</p>
<pre class="doctools_example">
                    1       / x               p-1
      P(p,x) =  --------   |   dt exp(-t) * t
                Gamma(p)  / 0
</pre>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>- Value of x (limit of the integral)</p></dd>
<dt>float <i class="arg">p</i></dt>
<dd><p>- Value of p in the integrand</p></dd>
<dt>float <i class="arg">tol</i></dt>
<dd><p>- Required tolerance (default: 1.0e-9)</p></dd>
</dl></dd>
<dt><a name="94"><b class="cmd">::math::statistics::incompleteBeta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">x</i> <span class="opt">?tol?</span></a></dt>
<dd><p>Evaluate the incomplete Beta integral</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">a</i></dt>
<dd><p>- First shape parameter</p></dd>
<dt>float <i class="arg">b</i></dt>
<dd><p>- Second shape parameter</p></dd>
<dt>float <i class="arg">x</i></dt>
<dd><p>- Value of x (limit of the integral)</p></dd>
<dt>float <i class="arg">tol</i></dt>
<dd><p>- Required tolerance (default: 1.0e-9)</p></dd>
</dl></dd>
<dt><a name="95"><b class="cmd">::math::statistics::estimate-pareto</b> <i class="arg">values</i></a></dt>
<dd><p>Estimate the parameters for the Pareto distribution that comes closest to the given values.
Returns the estimated scale and shape parameters, as well as the standard error for the shape parameter.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">values</i></dt>
<dd><p>- List of values, assumed to be distributed according to a Pareto distribution</p></dd>























</dl></dd>
</dl>
<p>TO DO: more function descriptions to be added</p>
</div>
<div id="section5" class="doctools_section"><h2><a name="section5">DATA MANIPULATION</a></h2>
<p>The data manipulation procedures act on lists or lists of lists:</p>
<dl class="doctools_definitions">
<dt><a name="96"><b class="cmd">::math::statistics::filter</b> <i class="arg">varname</i> <i class="arg">data</i> <i class="arg">expression</i></a></dt>
<dd><p>Return a list consisting of the data for which the logical
expression is true (this command works analogously to the command <b class="cmd"><a href="../../../../index.html#foreach">foreach</a></b>).</p>
<dl class="doctools_arguments">
<dt>string <i class="arg">varname</i></dt>
<dd><p>- Name of the variable used in the expression</p></dd>
<dt>list <i class="arg">data</i></dt>
<dd><p>- List of data</p></dd>
<dt>string <i class="arg">expression</i></dt>
<dd><p>- Logical expression using the variable name</p></dd>
</dl></dd>
<dt><a name="97"><b class="cmd">::math::statistics::map</b> <i class="arg">varname</i> <i class="arg">data</i> <i class="arg">expression</i></a></dt>
<dd><p>Return a list consisting of the data that are transformed via the
expression.</p>
<dl class="doctools_arguments">
<dt>string <i class="arg">varname</i></dt>
<dd><p>- Name of the variable used in the expression</p></dd>
<dt>list <i class="arg">data</i></dt>
<dd><p>- List of data</p></dd>
<dt>string <i class="arg">expression</i></dt>
<dd><p>- Expression to be used to transform (map) the data</p></dd>
</dl></dd>
<dt><a name="98"><b class="cmd">::math::statistics::samplescount</b> <i class="arg">varname</i> <i class="arg">list</i> <i class="arg">expression</i></a></dt>
<dd><p>Return a list consisting of the <i class="term">counts</i> of all data in the
sublists of the &quot;list&quot; argument for which the expression is true.</p>
<dl class="doctools_arguments">
<dt>string <i class="arg">varname</i></dt>
<dd><p>- Name of the variable used in the expression</p></dd>
<dt>list <i class="arg">data</i></dt>
<dd><p>- List of sublists, each containing the data</p></dd>
<dt>string <i class="arg">expression</i></dt>
<dd><p>- Logical expression to test the data (defaults to
&quot;true&quot;).</p></dd>
</dl></dd>
<dt><a name="99"><b class="cmd">::math::statistics::subdivide</b></a></dt>
<dd><p>Routine <em>PM</em> - not implemented yet</p></dd>
</dl>
</div>
<div id="section6" class="doctools_section"><h2><a name="section6">PLOT PROCEDURES</a></h2>
<p>The following simple plotting procedures are available:</p>
<dl class="doctools_definitions">
<dt><a name="100"><b class="cmd">::math::statistics::plot-scale</b> <i class="arg">canvas</i> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">ymin</i> <i class="arg">ymax</i></a></dt>
<dd><p>Set the scale for a plot in the given canvas. All plot routines expect
this function to be called first. There is no automatic scaling
provided.</p>
<dl class="doctools_arguments">
<dt>widget <i class="arg">canvas</i></dt>
<dd><p>- Canvas widget to use</p></dd>
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum x value</p></dd>
<dt>float <i class="arg">xmax</i></dt>
<dd><p>- Maximum x value</p></dd>
<dt>float <i class="arg">ymin</i></dt>
<dd><p>- Minimum y value</p></dd>
<dt>float <i class="arg">ymax</i></dt>
<dd><p>- Maximum y value</p></dd>
</dl></dd>
<dt><a name="101"><b class="cmd">::math::statistics::plot-xydata</b> <i class="arg">canvas</i> <i class="arg">xdata</i> <i class="arg">ydata</i> <i class="arg">tag</i></a></dt>
<dd><p>Create a simple XY plot in the given canvas - the data are
shown as a collection of dots. The tag can be used to manipulate the
appearance.</p>
<dl class="doctools_arguments">
<dt>widget <i class="arg">canvas</i></dt>
<dd><p>- Canvas widget to use</p></dd>
<dt>float <i class="arg">xdata</i></dt>
<dd><p>- Series of independent data</p></dd>
<dt>float <i class="arg">ydata</i></dt>
<dd><p>- Series of dependent data</p></dd>
<dt>string <i class="arg">tag</i></dt>
<dd><p>- Tag to give to the plotted data (defaults to xyplot)</p></dd>
</dl></dd>
<dt><a name="102"><b class="cmd">::math::statistics::plot-xyline</b> <i class="arg">canvas</i> <i class="arg">xdata</i> <i class="arg">ydata</i> <i class="arg">tag</i></a></dt>
<dd><p>Create a simple XY plot in the given canvas - the data are
shown as a line through the data points. The tag can be used to
manipulate the appearance.</p>
<dl class="doctools_arguments">
<dt>widget <i class="arg">canvas</i></dt>
<dd><p>- Canvas widget to use</p></dd>
<dt>list <i class="arg">xdata</i></dt>
<dd><p>- Series of independent data</p></dd>
<dt>list <i class="arg">ydata</i></dt>
<dd><p>- Series of dependent data</p></dd>
<dt>string <i class="arg">tag</i></dt>
<dd><p>- Tag to give to the plotted data (defaults to xyplot)</p></dd>
</dl></dd>
<dt><a name="103"><b class="cmd">::math::statistics::plot-tdata</b> <i class="arg">canvas</i> <i class="arg">tdata</i> <i class="arg">tag</i></a></dt>
<dd><p>Create a simple XY plot in the given canvas - the data are
shown as a collection of dots. The horizontal coordinate is equal to the
index. The tag can be used to manipulate the appearance.
This type of presentation is suitable for autocorrelation functions for
instance or for inspecting the time-dependent behaviour.</p>
<dl class="doctools_arguments">
<dt>widget <i class="arg">canvas</i></dt>
<dd><p>- Canvas widget to use</p></dd>
<dt>list <i class="arg">tdata</i></dt>
<dd><p>- Series of dependent data</p></dd>
<dt>string <i class="arg">tag</i></dt>
<dd><p>- Tag to give to the plotted data (defaults to xyplot)</p></dd>
</dl></dd>
<dt><a name="104"><b class="cmd">::math::statistics::plot-tline</b> <i class="arg">canvas</i> <i class="arg">tdata</i> <i class="arg">tag</i></a></dt>
<dd><p>Create a simple XY plot in the given canvas - the data are
shown as a line. See plot-tdata for an explanation.</p>
<dl class="doctools_arguments">
<dt>widget <i class="arg">canvas</i></dt>
<dd><p>- Canvas widget to use</p></dd>
<dt>list <i class="arg">tdata</i></dt>
<dd><p>- Series of dependent data</p></dd>
<dt>string <i class="arg">tag</i></dt>
<dd><p>- Tag to give to the plotted data (defaults to xyplot)</p></dd>
</dl></dd>
<dt><a name="105"><b class="cmd">::math::statistics::plot-histogram</b> <i class="arg">canvas</i> <i class="arg">counts</i> <i class="arg">limits</i> <i class="arg">tag</i></a></dt>
<dd><p>Create a simple histogram in the given canvas</p>
<dl class="doctools_arguments">
<dt>widget <i class="arg">canvas</i></dt>
<dd><p>- Canvas widget to use</p></dd>
<dt>list <i class="arg">counts</i></dt>
<dd><p>- Series of bucket counts</p></dd>
<dt>list <i class="arg">limits</i></dt>







|










|










|








|










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|










|








|








|








|










|










|










|










|










|











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|











|











|








|










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|








|










|








|










|










|










|










|










|










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|






|










|










|








|










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|










|








|








|








|










|










|










|










|










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|











|














|











|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|










|










|











|






|















|













|













|













|










|







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
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
<li><p>The cumulative density (cdf-*)</p></li>
<li><p>Quantiles for the given distribution (quantiles-*)</p></li>
<li><p>Histograms for the given distribution (histogram-*)</p></li>
<li><p>List of random values with the given distribution (random-*)</p></li>
</ul>
<p>The following procedures have been implemented:</p>
<dl class="doctools_definitions">
<dt><a name="53"><b class="cmd">::math::statistics::pdf-normal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a normal distribution with
given mean and standard deviation.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">stdev</i></dt>
<dd><p>- Standard deviation of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="54"><b class="cmd">::math::statistics::pdf-lognormal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a log-normal distribution with
given mean and standard deviation.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">stdev</i></dt>
<dd><p>- Standard deviation of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="55"><b class="cmd">::math::statistics::pdf-exponential</b> <i class="arg">mean</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for an exponential
distribution with given mean.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="56"><b class="cmd">::math::statistics::pdf-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a uniform
distribution with given extremes.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum value of the distribution</p></dd>
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Maximum value of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="57"><b class="cmd">::math::statistics::pdf-triangular</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a triangular
distribution with given extremes. If the argument min is lower than the argument max, then smaller
values have higher probability and vice versa. In the first case the probability
density function is of the form <em>f(x) = 2(1-x)</em> and the other case it is of the form <em>f(x) = 2x</em>.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum value of the distribution</p></dd>
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Maximum value of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="58"><b class="cmd">::math::statistics::pdf-symmetric-triangular</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a symmetric triangular
distribution with given extremes.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum value of the distribution</p></dd>
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Maximum value of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="59"><b class="cmd">::math::statistics::pdf-gamma</b> <i class="arg">alpha</i> <i class="arg">beta</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Gamma
distribution with given shape and rate parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">alpha</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">beta</i></dt>
<dd><p>- Rate parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="60"><b class="cmd">::math::statistics::pdf-poisson</b> <i class="arg">mu</i> <i class="arg">k</i></a></dt>
<dd><p>Return the probability of a given number of occurrences in the same
interval (k) for a Poisson distribution with given mean (mu)</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mu</i></dt>
<dd><p>- Mean number of occurrences</p></dd>
<dt>int <i class="arg">k</i></dt>
<dd><p>- Number of occurences</p></dd>
</dl></dd>
<dt><a name="61"><b class="cmd">::math::statistics::pdf-chisquare</b> <i class="arg">df</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a chi square
distribution with given degrees of freedom</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">df</i></dt>
<dd><p>- Degrees of freedom</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="62"><b class="cmd">::math::statistics::pdf-student-t</b> <i class="arg">df</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Student's t
distribution with given degrees of freedom</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">df</i></dt>
<dd><p>- Degrees of freedom</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="63"><b class="cmd">::math::statistics::pdf-gamma</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Gamma
distribution with given shape and rate parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">a</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">b</i></dt>
<dd><p>- Rate parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="64"><b class="cmd">::math::statistics::pdf-beta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Beta
distribution with given shape parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">a</i></dt>
<dd><p>- First shape parameter</p></dd>
<dt>float <i class="arg">b</i></dt>
<dd><p>- Second shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="65"><b class="cmd">::math::statistics::pdf-weibull</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Weibull
distribution with given scale and shape parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="66"><b class="cmd">::math::statistics::pdf-gumbel</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Gumbel
distribution with given location and shape parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Location parameter</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="67"><b class="cmd">::math::statistics::pdf-pareto</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Pareto
distribution with given scale and shape parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">shape</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="68"><b class="cmd">::math::statistics::pdf-cauchy</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Cauchy
distribution with given location and shape parameters. Note that the Cauchy distribution
has no finite higher-order moments.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Location parameter</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="69"><b class="cmd">::math::statistics::pdf-laplace</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Laplace
distribution with given location and shape parameters. The Laplace distribution
consists of two exponential functions, is peaked and has heavier tails than the
normal distribution.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Location parameter (mean)</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="70"><b class="cmd">::math::statistics::pdf-kumaraswamy</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a Kumaraswamy
distribution with given parameters a and b. The Kumaraswamy distribution
is related to the Beta distribution, but has a tractable cumulative distribution function.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">a</i></dt>
<dd><p>- Parameter a</p></dd>
<dt>float <i class="arg">b</i></dt>
<dd><p>- Parameter b</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="71"><b class="cmd">::math::statistics::pdf-negative-binomial</b> <i class="arg">r</i> <i class="arg">p</i> <i class="arg">value</i></a></dt>
<dd><p>Return the probability of a given value for a negative binomial
distribution with an allowed number of failures and the probability of success.</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">r</i></dt>
<dd><p>- Allowed number of failures (at least 1)</p></dd>
<dt>float <i class="arg">p</i></dt>
<dd><p>- Probability of success</p></dd>
<dt>int <i class="arg">value</i></dt>
<dd><p>- Number of successes for which the probability is to be returned</p></dd>
</dl></dd>
<dt><a name="72"><b class="cmd">::math::statistics::cdf-normal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a normal
distribution with given mean and standard deviation, that is the
probability for values up to the given one.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">stdev</i></dt>
<dd><p>- Standard deviation of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="73"><b class="cmd">::math::statistics::cdf-lognormal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a log-normal
distribution with given mean and standard deviation, that is the
probability for values up to the given one.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">stdev</i></dt>
<dd><p>- Standard deviation of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="74"><b class="cmd">::math::statistics::cdf-exponential</b> <i class="arg">mean</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for an exponential
distribution with given mean.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="75"><b class="cmd">::math::statistics::cdf-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a uniform
distribution with given extremes.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum value of the distribution</p></dd>
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Maximum value of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="76"><b class="cmd">::math::statistics::cdf-triangular</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a triangular
distribution with given extremes. If xmin &lt; xmax, then lower values have
a higher probability and vice versa, see also <em>pdf-triangular</em></p>
<dl class="doctools_arguments">
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum value of the distribution</p></dd>
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Maximum value of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="77"><b class="cmd">::math::statistics::cdf-symmetric-triangular</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a symmetric triangular
distribution with given extremes.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum value of the distribution</p></dd>
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Maximum value of the distribution</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="78"><b class="cmd">::math::statistics::cdf-students-t</b> <i class="arg">degrees</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Student's t
distribution with given number of degrees.</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">degrees</i></dt>
<dd><p>- Number of degrees of freedom</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="79"><b class="cmd">::math::statistics::cdf-gamma</b> <i class="arg">alpha</i> <i class="arg">beta</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Gamma
distribution with given shape and rate parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">alpha</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">beta</i></dt>
<dd><p>- Rate parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the cumulative probability is required</p></dd>
</dl></dd>
<dt><a name="80"><b class="cmd">::math::statistics::cdf-poisson</b> <i class="arg">mu</i> <i class="arg">k</i></a></dt>
<dd><p>Return the cumulative probability of a given number of occurrences in
the same interval (k) for a Poisson distribution with given mean (mu).</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mu</i></dt>
<dd><p>- Mean number of occurrences</p></dd>
<dt>int <i class="arg">k</i></dt>
<dd><p>- Number of occurences</p></dd>
</dl></dd>
<dt><a name="81"><b class="cmd">::math::statistics::cdf-beta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Beta
distribution with given shape parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">a</i></dt>
<dd><p>- First shape parameter</p></dd>
<dt>float <i class="arg">b</i></dt>
<dd><p>- Second shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="82"><b class="cmd">::math::statistics::cdf-weibull</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Weibull
distribution with given scale and shape parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">shape</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="83"><b class="cmd">::math::statistics::cdf-gumbel</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Gumbel
distribution with given location and scale parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Location parameter</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="84"><b class="cmd">::math::statistics::cdf-pareto</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Pareto
distribution with given scale and shape parameters</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">shape</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="85"><b class="cmd">::math::statistics::cdf-cauchy</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Cauchy
distribution with given location and scale parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Location parameter</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="86"><b class="cmd">::math::statistics::cdf-F</b> <i class="arg">nf1</i> <i class="arg">nf2</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for an F
distribution with nf1 and nf2 degrees of freedom.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">nf1</i></dt>
<dd><p>- Degrees of freedom for the numerator</p></dd>
<dt>float <i class="arg">nf2</i></dt>
<dd><p>- Degrees of freedom for the denominator</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="87"><b class="cmd">::math::statistics::cdf-laplace</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Laplace
distribution with given location and shape parameters. The Laplace distribution
consists of two exponential functions, is peaked and has heavier tails than the
normal distribution.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Location parameter (mean)</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="88"><b class="cmd">::math::statistics::cdf-kumaraswamy</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a Kumaraswamy
distribution with given parameters a and b. The Kumaraswamy distribution
is related to the Beta distribution, but has a tractable cumulative distribution function.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">a</i></dt>
<dd><p>- Parameter a</p></dd>
<dt>float <i class="arg">b</i></dt>
<dd><p>- Parameter b</p></dd>
<dt>float <i class="arg">value</i></dt>
<dd><p>- Value for which the probability is required</p></dd>
</dl></dd>
<dt><a name="89"><b class="cmd">::math::statistics::cdf-negative-binomial</b> <i class="arg">r</i> <i class="arg">p</i> <i class="arg">value</i></a></dt>
<dd><p>Return the cumulative probability of a given value for a negative binomial
distribution with an allowed number of failures and the probability of success.</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">r</i></dt>
<dd><p>- Allowed number of failures (at least 1)</p></dd>
<dt>float <i class="arg">p</i></dt>
<dd><p>- Probability of success</p></dd>
<dt>int <i class="arg">value</i></dt>
<dd><p>- Greatest number of successes</p></dd>
</dl></dd>
<dt><a name="90"><b class="cmd">::math::statistics::empirical-distribution</b> <i class="arg">values</i></a></dt>
<dd><p>Return a list of values and their empirical probability. The values are sorted in increasing order.
(The implementation follows the description at the corresponding Wikipedia page)</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">values</i></dt>
<dd><p>- List of data to be examined</p></dd>
</dl></dd>
<dt><a name="91"><b class="cmd">::math::statistics::random-normal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying a normal
distribution with given mean and standard deviation.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">stdev</i></dt>
<dd><p>- Standard deviation of the distribution</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="92"><b class="cmd">::math::statistics::random-lognormal</b> <i class="arg">mean</i> <i class="arg">stdev</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying a log-normal
distribution with given mean and standard deviation.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>float <i class="arg">stdev</i></dt>
<dd><p>- Standard deviation of the distribution</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="93"><b class="cmd">::math::statistics::random-exponential</b> <i class="arg">mean</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying an exponential
distribution with given mean.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>- Mean value of the distribution</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="94"><b class="cmd">::math::statistics::random-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying a uniform
distribution with given extremes.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum value of the distribution</p></dd>
<dt>float <i class="arg">xmax</i></dt>
<dd><p>- Maximum value of the distribution</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="95"><b class="cmd">::math::statistics::random-triangular</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying a triangular
distribution with given extremes. If xmin &lt; xmax, then lower values have a higher probability
and vice versa (see also <em>pdf-triangular</em>.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum value of the distribution</p></dd>
<dt>float <i class="arg">xmax</i></dt>
<dd><p>- Maximum value of the distribution</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="96"><b class="cmd">::math::statistics::random-symmetric-triangular</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying a symmetric triangular
distribution with given extremes.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum value of the distribution</p></dd>
<dt>float <i class="arg">xmax</i></dt>
<dd><p>- Maximum value of the distribution</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="97"><b class="cmd">::math::statistics::random-gamma</b> <i class="arg">alpha</i> <i class="arg">beta</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Gamma distribution with given shape and rate parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">alpha</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>float <i class="arg">beta</i></dt>
<dd><p>- Rate parameter</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="98"><b class="cmd">::math::statistics::random-poisson</b> <i class="arg">mu</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Poisson distribution with given mean.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mu</i></dt>
<dd><p>- Mean of the distribution</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="99"><b class="cmd">::math::statistics::random-chisquare</b> <i class="arg">df</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a chi square distribution with given degrees of freedom.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">df</i></dt>
<dd><p>- Degrees of freedom</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="100"><b class="cmd">::math::statistics::random-student-t</b> <i class="arg">df</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Student's t distribution with given degrees of freedom.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">df</i></dt>
<dd><p>- Degrees of freedom</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="101"><b class="cmd">::math::statistics::random-beta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Beta distribution with given shape parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">a</i></dt>
<dd><p>- First shape parameter</p></dd>
<dt>float <i class="arg">b</i></dt>
<dd><p>- Second shape parameter</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="102"><b class="cmd">::math::statistics::random-weibull</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Weibull distribution with given scale and shape parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">shape</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="103"><b class="cmd">::math::statistics::random-gumbel</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Gumbel distribution with given location and scale parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Location parameter</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="104"><b class="cmd">::math::statistics::random-pareto</b> <i class="arg">scale</i> <i class="arg">shape</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Pareto distribution with given scale and shape parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>float <i class="arg">shape</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="105"><b class="cmd">::math::statistics::random-cauchy</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying
a Cauchy distribution with given location and scale parameters.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Location parameter</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Scale parameter</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="106"><b class="cmd">::math::statistics::random-laplace</b> <i class="arg">location</i> <i class="arg">scale</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisfying a Laplace
distribution with given location and shape parameters. The Laplace distribution
consists of two exponential functions, is peaked and has heavier tails than the
normal distribution.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">location</i></dt>
<dd><p>- Location parameter (mean)</p></dd>
<dt>float <i class="arg">scale</i></dt>
<dd><p>- Shape parameter</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="107"><b class="cmd">::math::statistics::random-kumaraswamy</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisying a Kumaraswamy
distribution with given parameters a and b. The Kumaraswamy distribution
is related to the Beta distribution, but has a tractable cumulative distribution function.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">a</i></dt>
<dd><p>- Parameter a</p></dd>
<dt>float <i class="arg">b</i></dt>
<dd><p>- Parameter b</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="108"><b class="cmd">::math::statistics::random-negative-binomial</b> <i class="arg">r</i> <i class="arg">p</i> <i class="arg">number</i></a></dt>
<dd><p>Return a list of &quot;number&quot; random values satisying a negative binomial distribution.</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">r</i></dt>
<dd><p>- Allowed number of failures (at least 1)</p></dd>
<dt>float <i class="arg">p</i></dt>
<dd><p>- Probability of success</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Number of values to be returned</p></dd>
</dl></dd>
<dt><a name="109"><b class="cmd">::math::statistics::histogram-uniform</b> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">limits</i> <i class="arg">number</i></a></dt>
<dd><p>Return the expected histogram for a uniform distribution.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum value of the distribution</p></dd>
<dt>float <i class="arg">xmax</i></dt>
<dd><p>- Maximum value of the distribution</p></dd>
<dt>list <i class="arg">limits</i></dt>
<dd><p>- Upper limits for the buckets in the histogram</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- Total number of &quot;observations&quot; in the histogram</p></dd>
</dl></dd>
<dt><a name="110"><b class="cmd">::math::statistics::incompleteGamma</b> <i class="arg">x</i> <i class="arg">p</i> <span class="opt">?tol?</span></a></dt>
<dd><p>Evaluate the incomplete Gamma integral</p>
<pre class="doctools_example">
                    1       / x               p-1
      P(p,x) =  --------   |   dt exp(-t) * t
                Gamma(p)  / 0
</pre>
<dl class="doctools_arguments">
<dt>float <i class="arg">x</i></dt>
<dd><p>- Value of x (limit of the integral)</p></dd>
<dt>float <i class="arg">p</i></dt>
<dd><p>- Value of p in the integrand</p></dd>
<dt>float <i class="arg">tol</i></dt>
<dd><p>- Required tolerance (default: 1.0e-9)</p></dd>
</dl></dd>
<dt><a name="111"><b class="cmd">::math::statistics::incompleteBeta</b> <i class="arg">a</i> <i class="arg">b</i> <i class="arg">x</i> <span class="opt">?tol?</span></a></dt>
<dd><p>Evaluate the incomplete Beta integral</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">a</i></dt>
<dd><p>- First shape parameter</p></dd>
<dt>float <i class="arg">b</i></dt>
<dd><p>- Second shape parameter</p></dd>
<dt>float <i class="arg">x</i></dt>
<dd><p>- Value of x (limit of the integral)</p></dd>
<dt>float <i class="arg">tol</i></dt>
<dd><p>- Required tolerance (default: 1.0e-9)</p></dd>
</dl></dd>
<dt><a name="112"><b class="cmd">::math::statistics::estimate-pareto</b> <i class="arg">values</i></a></dt>
<dd><p>Estimate the parameters for the Pareto distribution that comes closest to the given values.
Returns the estimated scale and shape parameters, as well as the standard error for the shape parameter.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">values</i></dt>
<dd><p>- List of values, assumed to be distributed according to a Pareto distribution</p></dd>
</dl></dd>
<dt><a name="113"><b class="cmd">::math::statistics::estimate-exponential</b> <i class="arg">values</i></a></dt>
<dd><p>Estimate the parameter for the exponential distribution that comes closest to the given values.
Returns an estimate of the one parameter and of the standard error.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">values</i></dt>
<dd><p>- List of values, assumed to be distributed according to an exponential distribution</p></dd>
</dl></dd>
<dt><a name="114"><b class="cmd">::math::statistics::estimate-laplace</b> <i class="arg">values</i></a></dt>
<dd><p>Estimate the parameters for the Laplace distribution that comes closest to the given values.
Returns an estimate of respectively the location and scale parameters, based on maximum likelihood.</p>
<dl class="doctools_arguments">
<dt>list <i class="arg">values</i></dt>
<dd><p>- List of values, assumed to be distributed according to an exponential distribution</p></dd>
</dl></dd>
<dt><a name="115"><b class="cmd">::math::statistics::estimante-negative-binomial</b> <i class="arg">r</i> <i class="arg">values</i></a></dt>
<dd><p>Estimate the probability of success for the negative binomial distribution that comes closest to the given values.
The allowed number of failures must be given.</p>
<dl class="doctools_arguments">
<dt>int <i class="arg">r</i></dt>
<dd><p>- Allowed number of failures (at least 1)</p></dd>
<dt>int <i class="arg">number</i></dt>
<dd><p>- List of values, assumed to be distributed according to a negative binomial distribution.</p></dd>
</dl></dd>
</dl>
<p>TO DO: more function descriptions to be added</p>
</div>
<div id="section5" class="doctools_section"><h2><a name="section5">DATA MANIPULATION</a></h2>
<p>The data manipulation procedures act on lists or lists of lists:</p>
<dl class="doctools_definitions">
<dt><a name="116"><b class="cmd">::math::statistics::filter</b> <i class="arg">varname</i> <i class="arg">data</i> <i class="arg">expression</i></a></dt>
<dd><p>Return a list consisting of the data for which the logical
expression is true (this command works analogously to the command <b class="cmd"><a href="../../../../index.html#foreach">foreach</a></b>).</p>
<dl class="doctools_arguments">
<dt>string <i class="arg">varname</i></dt>
<dd><p>- Name of the variable used in the expression</p></dd>
<dt>list <i class="arg">data</i></dt>
<dd><p>- List of data</p></dd>
<dt>string <i class="arg">expression</i></dt>
<dd><p>- Logical expression using the variable name</p></dd>
</dl></dd>
<dt><a name="117"><b class="cmd">::math::statistics::map</b> <i class="arg">varname</i> <i class="arg">data</i> <i class="arg">expression</i></a></dt>
<dd><p>Return a list consisting of the data that are transformed via the
expression.</p>
<dl class="doctools_arguments">
<dt>string <i class="arg">varname</i></dt>
<dd><p>- Name of the variable used in the expression</p></dd>
<dt>list <i class="arg">data</i></dt>
<dd><p>- List of data</p></dd>
<dt>string <i class="arg">expression</i></dt>
<dd><p>- Expression to be used to transform (map) the data</p></dd>
</dl></dd>
<dt><a name="118"><b class="cmd">::math::statistics::samplescount</b> <i class="arg">varname</i> <i class="arg">list</i> <i class="arg">expression</i></a></dt>
<dd><p>Return a list consisting of the <i class="term">counts</i> of all data in the
sublists of the &quot;list&quot; argument for which the expression is true.</p>
<dl class="doctools_arguments">
<dt>string <i class="arg">varname</i></dt>
<dd><p>- Name of the variable used in the expression</p></dd>
<dt>list <i class="arg">data</i></dt>
<dd><p>- List of sublists, each containing the data</p></dd>
<dt>string <i class="arg">expression</i></dt>
<dd><p>- Logical expression to test the data (defaults to
&quot;true&quot;).</p></dd>
</dl></dd>
<dt><a name="119"><b class="cmd">::math::statistics::subdivide</b></a></dt>
<dd><p>Routine <em>PM</em> - not implemented yet</p></dd>
</dl>
</div>
<div id="section6" class="doctools_section"><h2><a name="section6">PLOT PROCEDURES</a></h2>
<p>The following simple plotting procedures are available:</p>
<dl class="doctools_definitions">
<dt><a name="120"><b class="cmd">::math::statistics::plot-scale</b> <i class="arg">canvas</i> <i class="arg">xmin</i> <i class="arg">xmax</i> <i class="arg">ymin</i> <i class="arg">ymax</i></a></dt>
<dd><p>Set the scale for a plot in the given canvas. All plot routines expect
this function to be called first. There is no automatic scaling
provided.</p>
<dl class="doctools_arguments">
<dt>widget <i class="arg">canvas</i></dt>
<dd><p>- Canvas widget to use</p></dd>
<dt>float <i class="arg">xmin</i></dt>
<dd><p>- Minimum x value</p></dd>
<dt>float <i class="arg">xmax</i></dt>
<dd><p>- Maximum x value</p></dd>
<dt>float <i class="arg">ymin</i></dt>
<dd><p>- Minimum y value</p></dd>
<dt>float <i class="arg">ymax</i></dt>
<dd><p>- Maximum y value</p></dd>
</dl></dd>
<dt><a name="121"><b class="cmd">::math::statistics::plot-xydata</b> <i class="arg">canvas</i> <i class="arg">xdata</i> <i class="arg">ydata</i> <i class="arg">tag</i></a></dt>
<dd><p>Create a simple XY plot in the given canvas - the data are
shown as a collection of dots. The tag can be used to manipulate the
appearance.</p>
<dl class="doctools_arguments">
<dt>widget <i class="arg">canvas</i></dt>
<dd><p>- Canvas widget to use</p></dd>
<dt>float <i class="arg">xdata</i></dt>
<dd><p>- Series of independent data</p></dd>
<dt>float <i class="arg">ydata</i></dt>
<dd><p>- Series of dependent data</p></dd>
<dt>string <i class="arg">tag</i></dt>
<dd><p>- Tag to give to the plotted data (defaults to xyplot)</p></dd>
</dl></dd>
<dt><a name="122"><b class="cmd">::math::statistics::plot-xyline</b> <i class="arg">canvas</i> <i class="arg">xdata</i> <i class="arg">ydata</i> <i class="arg">tag</i></a></dt>
<dd><p>Create a simple XY plot in the given canvas - the data are
shown as a line through the data points. The tag can be used to
manipulate the appearance.</p>
<dl class="doctools_arguments">
<dt>widget <i class="arg">canvas</i></dt>
<dd><p>- Canvas widget to use</p></dd>
<dt>list <i class="arg">xdata</i></dt>
<dd><p>- Series of independent data</p></dd>
<dt>list <i class="arg">ydata</i></dt>
<dd><p>- Series of dependent data</p></dd>
<dt>string <i class="arg">tag</i></dt>
<dd><p>- Tag to give to the plotted data (defaults to xyplot)</p></dd>
</dl></dd>
<dt><a name="123"><b class="cmd">::math::statistics::plot-tdata</b> <i class="arg">canvas</i> <i class="arg">tdata</i> <i class="arg">tag</i></a></dt>
<dd><p>Create a simple XY plot in the given canvas - the data are
shown as a collection of dots. The horizontal coordinate is equal to the
index. The tag can be used to manipulate the appearance.
This type of presentation is suitable for autocorrelation functions for
instance or for inspecting the time-dependent behaviour.</p>
<dl class="doctools_arguments">
<dt>widget <i class="arg">canvas</i></dt>
<dd><p>- Canvas widget to use</p></dd>
<dt>list <i class="arg">tdata</i></dt>
<dd><p>- Series of dependent data</p></dd>
<dt>string <i class="arg">tag</i></dt>
<dd><p>- Tag to give to the plotted data (defaults to xyplot)</p></dd>
</dl></dd>
<dt><a name="124"><b class="cmd">::math::statistics::plot-tline</b> <i class="arg">canvas</i> <i class="arg">tdata</i> <i class="arg">tag</i></a></dt>
<dd><p>Create a simple XY plot in the given canvas - the data are
shown as a line. See plot-tdata for an explanation.</p>
<dl class="doctools_arguments">
<dt>widget <i class="arg">canvas</i></dt>
<dd><p>- Canvas widget to use</p></dd>
<dt>list <i class="arg">tdata</i></dt>
<dd><p>- Series of dependent data</p></dd>
<dt>string <i class="arg">tag</i></dt>
<dd><p>- Tag to give to the plotted data (defaults to xyplot)</p></dd>
</dl></dd>
<dt><a name="125"><b class="cmd">::math::statistics::plot-histogram</b> <i class="arg">canvas</i> <i class="arg">counts</i> <i class="arg">limits</i> <i class="arg">tag</i></a></dt>
<dd><p>Create a simple histogram in the given canvas</p>
<dl class="doctools_arguments">
<dt>widget <i class="arg">canvas</i></dt>
<dd><p>- Canvas widget to use</p></dd>
<dt>list <i class="arg">counts</i></dt>
<dd><p>- Series of bucket counts</p></dd>
<dt>list <i class="arg">limits</i></dt>

Changes to idoc/www/tcllib/files/modules/mime/mime.html.

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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">mime(n) 1.6 tcllib &quot;Mime&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>mime - Manipulation of MIME body parts</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">KNOWN BUGS</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#see-also">See Also</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">mime <span class="opt">?1.6?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::mime::initialize</b> <span class="opt">?<b class="option">-canonical</b> <i class="arg">type/subtype</i> <span class="opt">?<b class="option">-param</b> {<i class="arg">key value</i>}...?</span> <span class="opt">?<b class="option">-encoding</b> <i class="arg">value</i>?</span> <span class="opt">?<b class="option">-header</b> {<i class="arg">key value</i>}...?</span>?</span> (<b class="option">-file</b> <i class="arg">name</i> | <b class="option">-string</b> <i class="arg">value</i> | <b class="option">-parts</b> {<i class="arg">token1</i> ... <i class="arg">tokenN</i>})</a></li>
<li><a href="#2"><b class="cmd">::mime::finalize</b> <i class="arg">token</i> <span class="opt">?<b class="option">-subordinates</b> <b class="const">all</b> | <b class="const">dynamic</b> | <b class="const">none</b>?</span></a></li>
<li><a href="#3"><b class="cmd">::mime::getproperty</b> <i class="arg">token</i> <span class="opt">?<i class="arg">property</i> | <b class="option">-names</b>?</span></a></li>
<li><a href="#4"><b class="cmd">::mime::getheader</b> <i class="arg">token</i> <span class="opt">?<i class="arg">key</i> | <b class="option">-names</b>?</span></a></li>
<li><a href="#5"><b class="cmd">::mime::setheader</b> <i class="arg">token</i> <i class="arg">key value</i> <span class="opt">?<b class="option">-mode</b> <b class="const">write</b> | <b class="const">append</b> | <b class="const">delete</b>?</span></a></li>







|




















|







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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">mime(n) 1.6.2 tcllib &quot;Mime&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>mime - Manipulation of MIME body parts</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">KNOWN BUGS</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#see-also">See Also</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">mime <span class="opt">?1.6.2?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::mime::initialize</b> <span class="opt">?<b class="option">-canonical</b> <i class="arg">type/subtype</i> <span class="opt">?<b class="option">-param</b> {<i class="arg">key value</i>}...?</span> <span class="opt">?<b class="option">-encoding</b> <i class="arg">value</i>?</span> <span class="opt">?<b class="option">-header</b> {<i class="arg">key value</i>}...?</span>?</span> (<b class="option">-file</b> <i class="arg">name</i> | <b class="option">-string</b> <i class="arg">value</i> | <b class="option">-parts</b> {<i class="arg">token1</i> ... <i class="arg">tokenN</i>})</a></li>
<li><a href="#2"><b class="cmd">::mime::finalize</b> <i class="arg">token</i> <span class="opt">?<b class="option">-subordinates</b> <b class="const">all</b> | <b class="const">dynamic</b> | <b class="const">none</b>?</span></a></li>
<li><a href="#3"><b class="cmd">::mime::getproperty</b> <i class="arg">token</i> <span class="opt">?<i class="arg">property</i> | <b class="option">-names</b>?</span></a></li>
<li><a href="#4"><b class="cmd">::mime::getheader</b> <i class="arg">token</i> <span class="opt">?<i class="arg">key</i> | <b class="option">-names</b>?</span></a></li>
<li><a href="#5"><b class="cmd">::mime::setheader</b> <i class="arg">token</i> <i class="arg">key value</i> <span class="opt">?<b class="option">-mode</b> <b class="const">write</b> | <b class="const">append</b> | <b class="const">delete</b>?</span></a></li>

Changes to idoc/www/tcllib/files/modules/mime/smtp.html.

239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
and <b class="package"><a href="../ripemd/ripemd160.html">ripemd160</a></b>.</p>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">EXAMPLE</a></h2>
<pre class="doctools_example">
proc send_simple_message {recipient email_server subject body} {
    package require smtp
    package require mime
    set token [mime::initialize -canonical text/plain \\
	-string $body]
    mime::setheader $token Subject $subject
    smtp::sendmessage $token \\
	-recipients $recipient -servers $email_server
    mime::finalize $token
}
send_simple_message [email protected] localhost \\
    &quot;This is the subject.&quot; &quot;This is the message.&quot;
</pre>
</div>
<div id="section4" class="doctools_section"><h2><a name="section4">TLS Security Considerations</a></h2>
<p>This package uses the <b class="package"><a href="../../../../index.html#tls">TLS</a></b> package to handle the
security for <b class="const">https</b> urls and other socket connections.</p>
<p>Policy decisions like the set of protocols to support and what







|


|



|







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
and <b class="package"><a href="../ripemd/ripemd160.html">ripemd160</a></b>.</p>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">EXAMPLE</a></h2>
<pre class="doctools_example">
proc send_simple_message {recipient email_server subject body} {
    package require smtp
    package require mime
    set token [mime::initialize -canonical text/plain \
	-string $body]
    mime::setheader $token Subject $subject
    smtp::sendmessage $token \
	-recipients $recipient -servers $email_server
    mime::finalize $token
}
send_simple_message [email protected] localhost \
    &quot;This is the subject.&quot; &quot;This is the message.&quot;
</pre>
</div>
<div id="section4" class="doctools_section"><h2><a name="section4">TLS Security Considerations</a></h2>
<p>This package uses the <b class="package"><a href="../../../../index.html#tls">TLS</a></b> package to handle the
security for <b class="const">https</b> urls and other socket connections.</p>
<p>Policy decisions like the set of protocols to support and what

Changes to idoc/www/tcllib/files/modules/ncgi/ncgi.html.

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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">ncgi(n) 1.4.3 tcllib &quot;CGI Support&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>ncgi - Procedures to manipulate CGI values.</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">EXAMPLES</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#see-also">See Also</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">ncgi <span class="opt">?1.4.3?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::ncgi::cookie</b> <i class="arg">cookie</i></a></li>
<li><a href="#2"><b class="cmd">::ncgi::decode</b> <i class="arg">str</i></a></li>
<li><a href="#3"><b class="cmd">::ncgi::empty</b> <i class="arg">name</i></a></li>
<li><a href="#4"><b class="cmd">::ncgi::exists</b> <i class="arg">name</i></a></li>
<li><a href="#5"><b class="cmd">::ncgi::encode</b> <i class="arg">string</i></a></li>







|



















|







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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">ncgi(n) 1.4.4 tcllib &quot;CGI Support&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>ncgi - Procedures to manipulate CGI values.</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">EXAMPLES</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#see-also">See Also</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">ncgi <span class="opt">?1.4.4?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::ncgi::cookie</b> <i class="arg">cookie</i></a></li>
<li><a href="#2"><b class="cmd">::ncgi::decode</b> <i class="arg">str</i></a></li>
<li><a href="#3"><b class="cmd">::ncgi::empty</b> <i class="arg">name</i></a></li>
<li><a href="#4"><b class="cmd">::ncgi::exists</b> <i class="arg">name</i></a></li>
<li><a href="#5"><b class="cmd">::ncgi::encode</b> <i class="arg">string</i></a></li>

Changes to idoc/www/tcllib/files/modules/oauth/oauth.html.

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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">oauth(n) 1.0.2 tcllib &quot;oauth&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>oauth - oauth API base signature</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">TLS Security Considerations</a></li>
<li class="doctools_section"><a href="#section3">Commands</a></li>
<li class="doctools_section"><a href="#section4">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">oauth <span class="opt">?1.0.2?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::oauth::config</b></a></li>
<li><a href="#2"><b class="cmd">::oauth::config</b> <span class="opt">?<i class="arg">options</i>...?</span></a></li>
<li><a href="#3"><b class="cmd">::oauth::header</b> <i class="arg">baseURL</i> <span class="opt">?<i class="arg">postQuery</i>?</span></a></li>
<li><a href="#4"><b class="cmd">::oauth::query</b> <i class="arg">baseURL</i> <span class="opt">?<i class="arg">postQuery</i>?</span></a></li>
</ul>







|




















|







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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">oauth(n) 1.0.3 tcllib &quot;oauth&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>oauth - oauth API base signature</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">TLS Security Considerations</a></li>
<li class="doctools_section"><a href="#section3">Commands</a></li>
<li class="doctools_section"><a href="#section4">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">oauth <span class="opt">?1.0.3?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::oauth::config</b></a></li>
<li><a href="#2"><b class="cmd">::oauth::config</b> <span class="opt">?<i class="arg">options</i>...?</span></a></li>
<li><a href="#3"><b class="cmd">::oauth::header</b> <i class="arg">baseURL</i> <span class="opt">?<i class="arg">postQuery</i>?</span></a></li>
<li><a href="#4"><b class="cmd">::oauth::query</b> <i class="arg">baseURL</i> <span class="opt">?<i class="arg">postQuery</i>?</span></a></li>
</ul>

Changes to idoc/www/tcllib/files/modules/pki/pki.html.

182
183
184
185
186
187
188
189
190
191


192
193





194

195
196
197






198
199
200
201
202
203
204
<dd><p>Decrypt a message using PKI (probably RSA). See <b class="cmd">::pki::encrypt</b> for option handling.</p>
<p>Mapping to OpenSSL's <b class="syscmd">openssl</b> application:</p>
<ol class="doctools_enumerated">
<li><p>&quot;openssl rsautl -decrypt&quot; == &quot;::pki::decrypt -binary -priv&quot;</p></li>
<li><p>&quot;openssl rsautl -verify&quot;  == &quot;::pki::decrypt -binary -pub&quot;</p></li>
</ol></dd>
<dt><a name="3"><b class="cmd">::pki::sign</b> <i class="arg">input</i> <i class="arg">key</i> <span class="opt">?<i class="arg">algo</i>?</span></a></dt>
<dd><p>Digitally sign message <i class="arg">input</i> using the private <i class="arg">key</i>.  If <i class="arg">algo</i>
is ommited &quot;sha1&quot; is assumed.  Possible values for <i class="arg">algo</i> include
&quot;md5&quot;, &quot;sha1&quot;, &quot;sha256&quot;, and &quot;raw&quot;.  Specifyin &quot;raw&quot; for <i class="arg">algo</i> will


inhibit the building of an ASN.1 structure to encode which hashing
algorithm was chosen.





The <i class="arg">input</i> should be the plain text, hashing will be performed on it.

The <i class="arg">key</i> should include the private key.</p></dd>
<dt><a name="4"><b class="cmd">::pki::verify</b> <i class="arg">signedmessage</i> <i class="arg">plaintext</i> <i class="arg">key</i> <span class="opt">?<i class="arg">algo</i>?</span></a></dt>
<dd><p>Verify a digital signature using a public <i class="arg">key</i>.  Returns true or false.</p></dd>






<dt><a name="5"><b class="cmd">::pki::key</b> <i class="arg">key</i> <span class="opt">?<i class="arg">password</i>?</span> <span class="opt">?<i class="arg">encodePem</i>?</span></a></dt>
<dd><p>Convert a key structure into a serialized PEM (default) or DER encoded private key suitable for other applications.  For RSA keys this means PKCS#1.</p></dd>
<dt><a name="6"><b class="cmd">::pki::pkcs::parse_key</b> <i class="arg">key</i> <span class="opt">?<i class="arg">password</i>?</span></a></dt>
<dd><p>Convert a PKCS#1 private <i class="arg">key</i> into a usable key, i.e. one which
can be used as argument for
<b class="cmd">::pki::encrypt</b>,
<b class="cmd">::pki::decrypt</b>,







|
|
|
>
>
|
|
>
>
>
>
>
|
>
|

|
>
>
>
>
>
>







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
<dd><p>Decrypt a message using PKI (probably RSA). See <b class="cmd">::pki::encrypt</b> for option handling.</p>
<p>Mapping to OpenSSL's <b class="syscmd">openssl</b> application:</p>
<ol class="doctools_enumerated">
<li><p>&quot;openssl rsautl -decrypt&quot; == &quot;::pki::decrypt -binary -priv&quot;</p></li>
<li><p>&quot;openssl rsautl -verify&quot;  == &quot;::pki::decrypt -binary -pub&quot;</p></li>
</ol></dd>
<dt><a name="3"><b class="cmd">::pki::sign</b> <i class="arg">input</i> <i class="arg">key</i> <span class="opt">?<i class="arg">algo</i>?</span></a></dt>
<dd><p>Digitally sign message <i class="arg">input</i> using the private <i class="arg">key</i>.</p>
<p>If <i class="arg">algo</i> is ommited &quot;sha1&quot; is assumed. Possible values for
<i class="arg">algo</i> include &quot;<b class="const">md5</b>&quot;, &quot;<b class="const">sha1</b>&quot;, &quot;<b class="const">sha256</b>&quot;,
and &quot;<b class="const">raw</b>&quot;.</p>
<p>Specifying &quot;<b class="const">raw</b>&quot; for <i class="arg">algo</i> will inhibit the
building of an ASN.1 structure to encode which hashing algorithm was
chosen.
<em>Attention</em>: In this case the corresponding <b class="cmd">pkgi::verify</b>
must be called <b class="const">with</b> algorithm information.
Conversely, specifying a non-&quot;<b class="const">raw</b>&quot; algorithm here means that
the corresponding <b class="cmd">pkgi::verify</b> invokation has to be made
<em>without</em> algorithm information.</p>
<p>The <i class="arg">input</i> should be the plain text, hashing will be
performed on it.</p>
<p>The <i class="arg">key</i> should include the private key.</p></dd>
<dt><a name="4"><b class="cmd">::pki::verify</b> <i class="arg">signedmessage</i> <i class="arg">plaintext</i> <i class="arg">key</i> <span class="opt">?<i class="arg">algo</i>?</span></a></dt>
<dd><p>Verify a digital signature using a public <i class="arg">key</i>.  Returns true or false.</p>
<p><em>Attention</em>: The algorithm information <i class="arg">algo</i> has to
be specified if and only if the <b class="cmd">pki::sign</b> which generated the
<i class="arg">signedmessage</i> was called with algorithm &quot;<b class="const">raw</b>&quot;. This
inhibited the building of the ASN.1 structure encoding the chosen
hashing algorithm. Conversely, if a proper algorithm was specified
during signing then you <em>must not</em> specify an algorithm here.</p></dd>
<dt><a name="5"><b class="cmd">::pki::key</b> <i class="arg">key</i> <span class="opt">?<i class="arg">password</i>?</span> <span class="opt">?<i class="arg">encodePem</i>?</span></a></dt>
<dd><p>Convert a key structure into a serialized PEM (default) or DER encoded private key suitable for other applications.  For RSA keys this means PKCS#1.</p></dd>
<dt><a name="6"><b class="cmd">::pki::pkcs::parse_key</b> <i class="arg">key</i> <span class="opt">?<i class="arg">password</i>?</span></a></dt>
<dd><p>Convert a PKCS#1 private <i class="arg">key</i> into a usable key, i.e. one which
can be used as argument for
<b class="cmd">::pki::encrypt</b>,
<b class="cmd">::pki::decrypt</b>,

Changes to idoc/www/tcllib/files/modules/pop3/pop3.html.

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
of the <b class="cmd">tls::socket</b> command when opening the connection. This is
suitable for POP3 servers which expect SSL connections only. These will
generally be listening on port 995.</p>
<pre class="doctools_example">
	package require tls
	tls::init -cafile /path/to/ca/cert -keyfile ...
	# Create secured pop3 channel
	pop3::open -socketcmd tls::socket \\
		$thehost $theuser $thepassword
	...
</pre>
<p>The second method, option <b class="option">-stls</b>, will connect to the standard POP3
port and then perform an STARTTLS handshake. This will only work for POP3
servers which have this capability. The package will confirm that the
server supports STARTTLS and the handshake was performed correctly before
proceeding with authentication.</p>
<pre class="doctools_example">
	package require tls
	tls::init -cafile /path/to/ca/cert -keyfile ...
	# Create secured pop3 channel
	pop3::open -stls 1 \\
		$thehost $theuser $thepassword
	...
</pre>
</div>
<div id="section5" class="doctools_section"><h2><a name="section5">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.







|












|







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
of the <b class="cmd">tls::socket</b> command when opening the connection. This is
suitable for POP3 servers which expect SSL connections only. These will
generally be listening on port 995.</p>
<pre class="doctools_example">
	package require tls
	tls::init -cafile /path/to/ca/cert -keyfile ...
	# Create secured pop3 channel
	pop3::open -socketcmd tls::socket \
		$thehost $theuser $thepassword
	...
</pre>
<p>The second method, option <b class="option">-stls</b>, will connect to the standard POP3
port and then perform an STARTTLS handshake. This will only work for POP3
servers which have this capability. The package will confirm that the
server supports STARTTLS and the handshake was performed correctly before
proceeding with authentication.</p>
<pre class="doctools_example">
	package require tls
	tls::init -cafile /path/to/ca/cert -keyfile ...
	# Create secured pop3 channel
	pop3::open -stls 1 \
		$thehost $theuser $thepassword
	...
</pre>
</div>
<div id="section5" class="doctools_section"><h2><a name="section5">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.

Changes to idoc/www/tcllib/files/modules/pop3d/pop3d.html.

305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
<div id="section5" class="doctools_section"><h2><a name="section5">Secure mail transfer</a></h2>
<p>The option <b class="option">-socket</b> (see <span class="sectref"><a href="#section2">Options</a></span>) enables users of
the package to override how the server opens its listening socket.
The envisioned main use is the specification of the <b class="cmd">tls::socket</b>
command, see package <b class="package"><a href="../../../../index.html#tls">tls</a></b>, to secure the communication.</p>
<pre class="doctools_example">
	package require tls
	tls::init \\
		...
	pop3d::new S -socket tls::socket
	...
</pre>
</div>
<div id="section6" class="doctools_section"><h2><a name="section6">References</a></h2>
<ol class="doctools_enumerated">







|







305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
<div id="section5" class="doctools_section"><h2><a name="section5">Secure mail transfer</a></h2>
<p>The option <b class="option">-socket</b> (see <span class="sectref"><a href="#section2">Options</a></span>) enables users of
the package to override how the server opens its listening socket.
The envisioned main use is the specification of the <b class="cmd">tls::socket</b>
command, see package <b class="package"><a href="../../../../index.html#tls">tls</a></b>, to secure the communication.</p>
<pre class="doctools_example">
	package require tls
	tls::init \
		...
	pop3d::new S -socket tls::socket
	...
</pre>
</div>
<div id="section6" class="doctools_section"><h2><a name="section6">References</a></h2>
<ol class="doctools_enumerated">

Changes to idoc/www/tcllib/files/modules/practcl/practcl.html.

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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">practcl(n) 0.11 tcllib &quot;The The Proper Rational API for C to Tool Command Language Module&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>practcl - The Practcl Module</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">COMMANDS</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>






































<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">TclOO 1.0</b></li>
<li>package require <b class="pkgname">practcl 0.11</b></li>
</ul>
<ul class="doctools_syntax">





<li><a href="#1"><b class="cmd">CPUTS</b> <i class="arg">varname</i> <i class="arg">body</i> <span class="opt">?<i class="arg">body</i>...?</span></a></li>











<li><a href="#2"><b class="cmd">practcl::_isdirectory</b> <i class="arg">path</i></a></li>
























































































<li><a href="#3"><b class="cmd">practcl::object</b> <i class="arg">parent</i> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></li>





<li><a href="#4"><b class="cmd">practcl::library</b> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></li>



























































<li><a href="#5"><b class="cmd">practcl::exe</b> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></li>
<li><a href="#6"><b class="cmd">practcl::product</b> <i class="arg">parent</i> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></li>





<li><a href="#7"><b class="cmd">practcl::cheader</b> <i class="arg">parent</i> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></li>













<li><a href="#8"><b class="cmd">practcl::csource</b> <i class="arg">parent</i> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></li>






<li><a href="#9"><b class="cmd">practcl::module</b> <i class="arg">parent</i> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></li>





















































<li><a href="#10"><b class="cmd">practcl::submodule</b> <i class="arg">parent</i> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></li>

















































</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>The Practcl module is a tool for integrating large modules for C API
Tcl code that requires custom Tcl types and TclOO objects.</p>









</div>
<div id="section2" class="doctools_section"><h2><a name="section2">COMMANDS</a></h2>













































































































































































































































<dl class="doctools_definitions">


<dt><a name="1"><b class="cmd">CPUTS</b> <i class="arg">varname</i> <i class="arg">body</i> <span class="opt">?<i class="arg">body</i>...?</span></a></dt>
<dd><p>Appends blocks of text to a buffer. This command tries to reduce the number





































of line breaks between bodies.</p></dd>
















































































































































































































<dt><a name="2"><b class="cmd">practcl::_isdirectory</b> <i class="arg">path</i></a></dt>











<dd><p>Returns true if <i class="arg">path</i> is a directory, using the test</p></dd>























































































</dl>





<dl class="doctools_definitions">


























































<dt><a name="3"><b class="cmd">practcl::object</b> <i class="arg">parent</i> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></dt>
<dd><p>A generic Practcl object</p></dd>












<dt><a name="4"><b class="cmd">practcl::library</b> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></dt>





<dd><p>A Practcl object representing a library container</p></dd>

































<dt><a name="5"><b class="cmd">practcl::exe</b> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></dt>






























































<dd><p>A Practcl object representing a wrapped executable</p></dd>
















<dt><a name="6"><b class="cmd">practcl::product</b> <i class="arg">parent</i> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></dt>
<dd><p>A Practcl object representing a compiled product</p></dd>
































<dt><a name="7"><b class="cmd">practcl::cheader</b> <i class="arg">parent</i> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></dt>

























<dd><p>A Practcl object representing an externally generated c header</p></dd>













































<dt><a name="8"><b class="cmd">practcl::csource</b> <i class="arg">parent</i> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></dt>


































<dd><p>A Practcl object representing an externally generated c source file</p></dd>























































<dt><a name="9"><b class="cmd">practcl::module</b> <i class="arg">parent</i> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></dt>
<dd><p>A Practcl object representing a dynamically generated C/H/Tcl suite</p></dd>












<dt><a name="10"><b class="cmd">practcl::submodule</b> <i class="arg">parent</i> <span class="opt">?<i class="arg">keyvaluelist</i>?</span></a></dt>





<dd><p>A Practcl object representing a dynamically generated C/H/Tcl suite, subordinate to a module</p></dd>
























</dl>
</div>







































<div id="section3" class="doctools_section"><h2><a name="section3">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>practcl</em> of the
<a href="http://core.tcl.tk/tcllib/reportlist">Tcllib Trackers</a>.
Please also report any ideas for enhancements you may have for either
package and/or documentation.</p>
<p>When proposing code changes, please provide <em>unified diffs</em>,







|








|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









<


>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






>
>
>
>
>
>
>
>
>

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">practcl(n) 0.16.4 tcllib &quot;The The Proper Rational API for C to Tool Command Language Module&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>practcl - The Practcl Module</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Commands</a></li>
<li class="doctools_section"><a href="#section3">Classes</a>
<ul>
<li class="doctools_subsection"><a href="#subsection1">Class  practcl::doctool</a></li>
<li class="doctools_subsection"><a href="#subsection2">Class  practcl::metaclass</a></li>
<li class="doctools_subsection"><a href="#subsection3">Class  practcl::toolset</a></li>
<li class="doctools_subsection"><a href="#subsection4">Class  practcl::toolset.gcc</a></li>
<li class="doctools_subsection"><a href="#subsection5">Class  practcl::toolset.msvc</a></li>
<li class="doctools_subsection"><a href="#subsection6">Class  practcl::make_obj</a></li>
<li class="doctools_subsection"><a href="#subsection7">Class  practcl::object</a></li>
<li class="doctools_subsection"><a href="#subsection8">Class  practcl::dynamic</a></li>
<li class="doctools_subsection"><a href="#subsection9">Class  practcl::product</a></li>
<li class="doctools_subsection"><a href="#subsection10">Class  practcl::product.cheader</a></li>
<li class="doctools_subsection"><a href="#subsection11">Class  practcl::product.csource</a></li>
<li class="doctools_subsection"><a href="#subsection12">Class  practcl::product.clibrary</a></li>
<li class="doctools_subsection"><a href="#subsection13">Class  practcl::product.dynamic</a></li>
<li class="doctools_subsection"><a href="#subsection14">Class  practcl::product.critcl</a></li>
<li class="doctools_subsection"><a href="#subsection15">Class  practcl::module</a></li>
<li class="doctools_subsection"><a href="#subsection16">Class  practcl::project</a></li>
<li class="doctools_subsection"><a href="#subsection17">Class  practcl::library</a></li>
<li class="doctools_subsection"><a href="#subsection18">Class  practcl::tclkit</a></li>
<li class="doctools_subsection"><a href="#subsection19">Class  practcl::distribution</a></li>
<li class="doctools_subsection"><a href="#subsection20">Class  practcl::distribution.snapshot</a></li>
<li class="doctools_subsection"><a href="#subsection21">Class  practcl::distribution.fossil</a></li>
<li class="doctools_subsection"><a href="#subsection22">Class  practcl::distribution.git</a></li>
<li class="doctools_subsection"><a href="#subsection23">Class  practcl::subproject</a></li>
<li class="doctools_subsection"><a href="#subsection24">Class  practcl::subproject.source</a></li>
<li class="doctools_subsection"><a href="#subsection25">Class  practcl::subproject.teapot</a></li>
<li class="doctools_subsection"><a href="#subsection26">Class  practcl::subproject.kettle</a></li>
<li class="doctools_subsection"><a href="#subsection27">Class  practcl::subproject.critcl</a></li>
<li class="doctools_subsection"><a href="#subsection28">Class  practcl::subproject.sak</a></li>
<li class="doctools_subsection"><a href="#subsection29">Class  practcl::subproject.practcl</a></li>
<li class="doctools_subsection"><a href="#subsection30">Class  practcl::subproject.binary</a></li>
<li class="doctools_subsection"><a href="#subsection31">Class  practcl::subproject.tea</a></li>
<li class="doctools_subsection"><a href="#subsection32">Class  practcl::subproject.library</a></li>
<li class="doctools_subsection"><a href="#subsection33">Class  practcl::subproject.external</a></li>
<li class="doctools_subsection"><a href="#subsection34">Class  practcl::subproject.core</a></li>
</ul>
</li>
<li class="doctools_section"><a href="#section4">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">TclOO 1.0</b></li>

</ul>
<ul class="doctools_syntax">
<li><a href="#1">proc <b class="cmd">practcl::cat</b> <i class="arg">fname</i></a></li>
<li><a href="#2">proc <b class="cmd">practcl::docstrip</b> <i class="arg">text</i></a></li>
<li><a href="#3">proc <b class="cmd">putb</b> <span class="opt">?<i class="arg">map</i>?</span> <i class="arg">text</i></a></li>
<li><a href="#4">proc <b class="cmd"><a href="../../../../index.html#proc">Proc</a></b> <i class="arg">name</i> <i class="arg">arglist</i> <i class="arg">body</i></a></li>
<li><a href="#5">proc <b class="cmd">noop</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#6">proc <b class="cmd">practcl::debug</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#7">proc <b class="cmd">practcl::doexec</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#8">proc <b class="cmd">practcl::doexec_in</b> <i class="arg">path</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#9">proc <b class="cmd">practcl::dotclexec</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#10">proc <b class="cmd">practcl::domake</b> <i class="arg">path</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#11">proc <b class="cmd">practcl::domake.tcl</b> <i class="arg">path</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#12">proc <b class="cmd">practcl::fossil</b> <i class="arg">path</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#13">proc <b class="cmd">practcl::fossil_status</b> <i class="arg">dir</i></a></li>
<li><a href="#14">proc <b class="cmd">practcl::os</b></a></li>
<li><a href="#15">proc <b class="cmd">practcl::mkzip</b> <i class="arg">exename</i> <i class="arg">barekit</i> <i class="arg">vfspath</i></a></li>
<li><a href="#16">proc <b class="cmd">practcl::sort_dict</b> <i class="arg">list</i></a></li>
<li><a href="#17">proc <b class="cmd">practcl::local_os</b></a></li>
<li><a href="#18">proc <b class="cmd">practcl::config.tcl</b> <i class="arg">path</i></a></li>
<li><a href="#19">proc <b class="cmd">practcl::read_configuration</b> <i class="arg">path</i></a></li>
<li><a href="#20">proc <b class="cmd">practcl::tcllib_require</b> <i class="arg">pkg</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#21">proc <b class="cmd">practcl::platform::tcl_core_options</b> <i class="arg">os</i></a></li>
<li><a href="#22">proc <b class="cmd">practcl::platform::tk_core_options</b> <i class="arg">os</i></a></li>
<li><a href="#23">proc <b class="cmd">practcl::read_rc_file</b> <i class="arg">filename</i> <span class="opt">?<i class="arg">localdat</i> <b class="const"></b>?</span></a></li>
<li><a href="#24">proc <b class="cmd">practcl::read_sh_subst</b> <i class="arg">line</i> <i class="arg">info</i></a></li>
<li><a href="#25">proc <b class="cmd">practcl::read_sh_file</b> <i class="arg">filename</i> <span class="opt">?<i class="arg">localdat</i> <b class="const"></b>?</span></a></li>
<li><a href="#26">proc <b class="cmd">practcl::read_Config.sh</b> <i class="arg">filename</i></a></li>
<li><a href="#27">proc <b class="cmd">practcl::read_Makefile</b> <i class="arg">filename</i></a></li>
<li><a href="#28">proc <b class="cmd">practcl::cputs</b> <i class="arg">varname</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#29">proc <b class="cmd">practcl::tcl_to_c</b> <i class="arg">body</i></a></li>
<li><a href="#30">proc <b class="cmd">practcl::_tagblock</b> <i class="arg">text</i> <span class="opt">?<i class="arg">style</i> <b class="const">tcl</b>?</span> <span class="opt">?<i class="arg">note</i> <b class="const"></b>?</span></a></li>
<li><a href="#31">proc <b class="cmd">practcl::de_shell</b> <i class="arg">data</i></a></li>
<li><a href="#32">proc <b class="cmd">practcl::grep</b> <i class="arg">pattern</i> <span class="opt">?<i class="arg">files</i> <b class="const"></b>?</span></a></li>
<li><a href="#33">proc <b class="cmd">practcl::file_lexnormalize</b> <i class="arg">sp</i></a></li>
<li><a href="#34">proc <b class="cmd">practcl::file_relative</b> <i class="arg">base</i> <i class="arg">dst</i></a></li>
<li><a href="#35">proc <b class="cmd">practcl::findByPattern</b> <i class="arg">basedir</i> <i class="arg">patterns</i></a></li>
<li><a href="#36">proc <b class="cmd">practcl::log</b> <i class="arg">fname</i> <i class="arg">comment</i></a></li>
<li><a href="#37">proc <b class="cmd">practcl::_pkgindex_simpleIndex</b> <i class="arg">path</i></a></li>
<li><a href="#38">proc <b class="cmd">practcl::_pkgindex_directory</b> <i class="arg">path</i></a></li>
<li><a href="#39">proc <b class="cmd">practcl::_pkgindex_path_subdir</b> <i class="arg">path</i></a></li>
<li><a href="#40">proc <b class="cmd">practcl::pkgindex_path</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#41">proc <b class="cmd">practcl::installDir</b> <i class="arg">d1</i> <i class="arg">d2</i></a></li>
<li><a href="#42">proc <b class="cmd">practcl::copyDir</b> <i class="arg">d1</i> <i class="arg">d2</i> <span class="opt">?<i class="arg">toplevel</i> <b class="const">1</b>?</span></a></li>
<li><a href="#43">proc <b class="cmd">practcl::buildModule</b> <i class="arg">modpath</i></a></li>
<li><a href="#44">proc <b class="cmd">practcl::installModule</b> <i class="arg">modpath</i> <i class="arg">DEST</i></a></li>
<li><a href="#45">proc <b class="cmd">practcl::trigger</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#46">proc <b class="cmd">practcl::depends</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#47">proc <b class="cmd">practcl::target</b> <i class="arg">name</i> <i class="arg">info</i> <span class="opt">?<i class="arg">action</i> <b class="const"></b>?</span></a></li>
<li><a href="#48">method <b class="cmd">constructor</b></a></li>
<li><a href="#49">method <b class="cmd">argspec</b> <i class="arg">argspec</i></a></li>
<li><a href="#50">method <b class="cmd"><a href="../../../../index.html#comment">comment</a></b> <i class="arg">block</i></a></li>
<li><a href="#51">method <b class="cmd">keyword.Annotation</b> <i class="arg">resultvar</i> <i class="arg">commentblock</i> <i class="arg">type</i> <i class="arg">name</i> <i class="arg">body</i></a></li>
<li><a href="#52">method <b class="cmd">keyword.Class</b> <i class="arg">resultvar</i> <i class="arg">commentblock</i> <i class="arg">name</i> <i class="arg">body</i></a></li>
<li><a href="#53">method <b class="cmd">keyword.class</b> <i class="arg">resultvar</i> <i class="arg">commentblock</i> <i class="arg">name</i> <i class="arg">body</i></a></li>
<li><a href="#54">method <b class="cmd">keyword.Class_Method</b> <i class="arg">resultvar</i> <i class="arg">commentblock</i> <i class="arg">name</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#55">method <b class="cmd">keyword.method</b> <i class="arg">resultvar</i> <i class="arg">commentblock</i> <i class="arg">name</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#56">method <b class="cmd">keyword.proc</b> <i class="arg">commentblock</i> <i class="arg">name</i> <i class="arg">argspec</i></a></li>
<li><a href="#57">method <b class="cmd">reset</b></a></li>
<li><a href="#58">method <b class="cmd">Main</b></a></li>
<li><a href="#59">method <b class="cmd">section.method</b> <i class="arg">keyword</i> <i class="arg">method</i> <i class="arg">minfo</i></a></li>
<li><a href="#60">method <b class="cmd">section.annotation</b> <i class="arg">type</i> <i class="arg">name</i> <i class="arg">iinfo</i></a></li>
<li><a href="#61">method <b class="cmd">section.class</b> <i class="arg">class_name</i> <i class="arg">class_info</i></a></li>
<li><a href="#62">method <b class="cmd">section.command</b> <i class="arg">procinfo</i></a></li>
<li><a href="#63">method <b class="cmd"><a href="../../../../index.html#manpage">manpage</a></b> <span class="opt">?<b class="option">header <em>value</em></b>?</span> <span class="opt">?<b class="option">footer <em>value</em></b>?</span> <span class="opt">?<b class="option">authors <em>list</em></b>?</span></a></li>
<li><a href="#64">method <b class="cmd">scan_text</b> <i class="arg">text</i></a></li>
<li><a href="#65">method <b class="cmd">scan_file</b> <i class="arg">filename</i></a></li>
<li><a href="#66">method <b class="cmd">_MorphPatterns</b></a></li>
<li><a href="#67">method <b class="cmd"><a href="../../../../index.html#define">define</a></b> <i class="arg">submethod</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#68">method <b class="cmd">graft</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#69">method <b class="cmd">initialize</b></a></li>
<li><a href="#70">method <b class="cmd">link</b> <i class="arg">command</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#71">method <b class="cmd">morph</b> <i class="arg">classname</i></a></li>
<li><a href="#72">method <b class="cmd">script</b> <i class="arg">script</i></a></li>
<li><a href="#73">method <b class="cmd">select</b></a></li>
<li><a href="#74">method <b class="cmd"><a href="../../../../index.html#source">source</a></b> <i class="arg">filename</i></a></li>
<li><a href="#75">classmethod <b class="cmd">select</b> <i class="arg">object</i></a></li>
<li><a href="#76">method <b class="cmd">config.sh</b></a></li>
<li><a href="#77">method <b class="cmd">BuildDir</b> <i class="arg">PWD</i></a></li>
<li><a href="#78">method <b class="cmd">MakeDir</b> <i class="arg">srcdir</i></a></li>
<li><a href="#79">method <b class="cmd">read_configuration</b></a></li>
<li><a href="#80">method <b class="cmd">build-cflags</b> <i class="arg">PROJECT</i> <i class="arg">DEFS</i> <i class="arg">namevar</i> <i class="arg">versionvar</i> <i class="arg">defsvar</i></a></li>
<li><a href="#81">method <b class="cmd">critcl</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#82">method <b class="cmd">Autoconf</b></a></li>
<li><a href="#83">method <b class="cmd">BuildDir</b> <i class="arg">PWD</i></a></li>
<li><a href="#84">method <b class="cmd">ConfigureOpts</b></a></li>
<li><a href="#85">method <b class="cmd">MakeDir</b> <i class="arg">srcdir</i></a></li>
<li><a href="#86">method <b class="cmd">make {} autodetect</b></a></li>
<li><a href="#87">method <b class="cmd">make {} clean</b></a></li>
<li><a href="#88">method <b class="cmd">make {} compile</b></a></li>
<li><a href="#89">method <b class="cmd">make {} install</b> <i class="arg">DEST</i></a></li>
<li><a href="#90">method <b class="cmd">build-compile-sources</b> <i class="arg">PROJECT</i> <i class="arg">COMPILE</i> <i class="arg">CPPCOMPILE</i> <i class="arg">INCLUDES</i></a></li>
<li><a href="#91">method <b class="cmd">build-Makefile</b> <i class="arg">path</i> <i class="arg">PROJECT</i></a></li>
<li><a href="#92">method <b class="cmd">build-library</b> <i class="arg">outfile</i> <i class="arg">PROJECT</i></a></li>
<li><a href="#93">method <b class="cmd">build-tclsh</b> <i class="arg">outfile</i> <i class="arg">PROJECT</i> <span class="opt">?<i class="arg">path</i> <b class="const">auto</b>?</span></a></li>
<li><a href="#94">method <b class="cmd">BuildDir</b> <i class="arg">PWD</i></a></li>
<li><a href="#95">method <b class="cmd">make {} autodetect</b></a></li>
<li><a href="#96">method <b class="cmd">make {} clean</b></a></li>
<li><a href="#97">method <b class="cmd">make {} compile</b></a></li>
<li><a href="#98">method <b class="cmd">make {} install</b> <i class="arg">DEST</i></a></li>
<li><a href="#99">method <b class="cmd">MakeDir</b> <i class="arg">srcdir</i></a></li>
<li><a href="#100">method <b class="cmd">NmakeOpts</b></a></li>
<li><a href="#101">method <b class="cmd">constructor</b> <i class="arg">module_object</i> <i class="arg">name</i> <i class="arg">info</i> <span class="opt">?<i class="arg">action_body</i> <b class="const"></b>?</span></a></li>
<li><a href="#102">method <b class="cmd"><a href="../../../../index.html#do">do</a></b></a></li>
<li><a href="#103">method <b class="cmd">check</b></a></li>
<li><a href="#104">method <b class="cmd">output</b></a></li>
<li><a href="#105">method <b class="cmd">reset</b></a></li>
<li><a href="#106">method <b class="cmd">triggers</b></a></li>
<li><a href="#107">method <b class="cmd">constructor</b> <i class="arg">parent</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#108">method <b class="cmd">child</b> <i class="arg">method</i></a></li>
<li><a href="#109">method <b class="cmd">go</b></a></li>
<li><a href="#110">method <b class="cmd">cstructure</b> <i class="arg">name</i> <i class="arg">definition</i> <span class="opt">?<i class="arg">argdat</i> <b class="const"></b>?</span></a></li>
<li><a href="#111">method <b class="cmd">include</b> <i class="arg">header</i></a></li>
<li><a href="#112">method <b class="cmd">include_dir</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#113">method <b class="cmd">include_directory</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#114">method <b class="cmd">c_header</b> <i class="arg">body</i></a></li>
<li><a href="#115">method <b class="cmd">c_code</b> <i class="arg">body</i></a></li>
<li><a href="#116">method <b class="cmd">c_function</b> <i class="arg">header</i> <i class="arg">body</i> <span class="opt">?<i class="arg">info</i> <b class="const"></b>?</span></a></li>
<li><a href="#117">method <b class="cmd">c_tcloomethod</b> <i class="arg">name</i> <i class="arg">body</i> <span class="opt">?<i class="arg">arginfo</i> <b class="const"></b>?</span></a></li>
<li><a href="#118">method <b class="cmd">cmethod</b> <i class="arg">name</i> <i class="arg">body</i> <span class="opt">?<i class="arg">arginfo</i> <b class="const"></b>?</span></a></li>
<li><a href="#119">method <b class="cmd">c_tclproc_nspace</b> <i class="arg">nspace</i></a></li>
<li><a href="#120">method <b class="cmd">c_tclcmd</b> <i class="arg">name</i> <i class="arg">body</i> <span class="opt">?<i class="arg">arginfo</i> <b class="const"></b>?</span></a></li>
<li><a href="#121">method <b class="cmd">c_tclproc_raw</b> <i class="arg">name</i> <i class="arg">body</i> <span class="opt">?<i class="arg">arginfo</i> <b class="const"></b>?</span></a></li>
<li><a href="#122">method <b class="cmd">tcltype</b> <i class="arg">name</i> <i class="arg">argdat</i></a></li>
<li><a href="#123">method <b class="cmd">project-compile-products</b></a></li>
<li><a href="#124">method <b class="cmd">implement</b> <i class="arg">path</i></a></li>
<li><a href="#125">method <b class="cmd">initialize</b></a></li>
<li><a href="#126">method <b class="cmd">linktype</b></a></li>
<li><a href="#127">method <b class="cmd">generate-cfile-constant</b></a></li>
<li><a href="#128">method <b class="cmd">generate-cfile-header</b></a></li>
<li><a href="#129">method <b class="cmd">generate-cfile-tclapi</b></a></li>
<li><a href="#130">method <b class="cmd">generate-loader-module</b></a></li>
<li><a href="#131">method <b class="cmd">Collate_Source</b> <i class="arg">CWD</i></a></li>
<li><a href="#132">method <b class="cmd">select</b></a></li>
<li><a href="#133">classmethod <b class="cmd">select</b> <i class="arg">object</i></a></li>
<li><a href="#134">method <b class="cmd">code</b> <i class="arg">section</i> <i class="arg">body</i></a></li>
<li><a href="#135">method <b class="cmd">Collate_Source</b> <i class="arg">CWD</i></a></li>
<li><a href="#136">method <b class="cmd">project-compile-products</b></a></li>
<li><a href="#137">method <b class="cmd">generate-debug</b> <span class="opt">?<i class="arg">spaces</i> <b class="const"></b>?</span></a></li>
<li><a href="#138">method <b class="cmd">generate-cfile-constant</b></a></li>
<li><a href="#139">method <b class="cmd">generate-cfile-public-structure</b></a></li>
<li><a href="#140">method <b class="cmd">generate-cfile-header</b></a></li>
<li><a href="#141">method <b class="cmd">generate-cfile-global</b></a></li>
<li><a href="#142">method <b class="cmd">generate-cfile-private-typedef</b></a></li>
<li><a href="#143">method <b class="cmd">generate-cfile-private-structure</b></a></li>
<li><a href="#144">method <b class="cmd">generate-cfile-functions</b></a></li>
<li><a href="#145">method <b class="cmd">generate-cfile-tclapi</b></a></li>
<li><a href="#146">method <b class="cmd">generate-hfile-public-define</b></a></li>
<li><a href="#147">method <b class="cmd">generate-hfile-public-macro</b></a></li>
<li><a href="#148">method <b class="cmd">generate-hfile-public-typedef</b></a></li>
<li><a href="#149">method <b class="cmd">generate-hfile-public-structure</b></a></li>
<li><a href="#150">method <b class="cmd">generate-hfile-public-headers</b></a></li>
<li><a href="#151">method <b class="cmd">generate-hfile-public-function</b></a></li>
<li><a href="#152">method <b class="cmd">generate-hfile-public-includes</b></a></li>
<li><a href="#153">method <b class="cmd">generate-hfile-public-verbatim</b></a></li>
<li><a href="#154">method <b class="cmd">generate-loader-external</b></a></li>
<li><a href="#155">method <b class="cmd">generate-loader-module</b></a></li>
<li><a href="#156">method <b class="cmd">generate-stub-function</b></a></li>
<li><a href="#157">method <b class="cmd">IncludeAdd</b> <i class="arg">headervar</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#158">method <b class="cmd">generate-tcl-loader</b></a></li>
<li><a href="#159">method <b class="cmd">generate-tcl-pre</b></a></li>
<li><a href="#160">method <b class="cmd">generate-tcl-post</b></a></li>
<li><a href="#161">method <b class="cmd">linktype</b></a></li>
<li><a href="#162">method <b class="cmd">Ofile</b> <i class="arg">filename</i></a></li>
<li><a href="#163">method <b class="cmd">project-static-packages</b></a></li>
<li><a href="#164">method <b class="cmd">toolset-include-directory</b></a></li>
<li><a href="#165">method <b class="cmd">target</b> <i class="arg">method</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#166">method <b class="cmd">project-compile-products</b></a></li>
<li><a href="#167">method <b class="cmd">generate-loader-module</b></a></li>
<li><a href="#168">method <b class="cmd">project-compile-products</b></a></li>
<li><a href="#169">method <b class="cmd">linker-products</b> <i class="arg">configdict</i></a></li>
<li><a href="#170">method <b class="cmd">initialize</b></a></li>
<li><a href="#171">variable <b class="cmd">make_object</b></a></li>
<li><a href="#172">method <b class="cmd">_MorphPatterns</b></a></li>
<li><a href="#173">method <b class="cmd">add</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#174">method <b class="cmd">install-headers</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#175">method <b class="cmd">make {} _preamble</b></a></li>
<li><a href="#176">method <b class="cmd">make {} pkginfo</b></a></li>
<li><a href="#177">method <b class="cmd">make {} objects</b></a></li>
<li><a href="#178">method <b class="cmd">make {} object</b> <i class="arg">name</i></a></li>
<li><a href="#179">method <b class="cmd">make {} reset</b></a></li>
<li><a href="#180">method <b class="cmd">make {} trigger</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#181">method <b class="cmd">make {} depends</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#182">method <b class="cmd">make {} filename</b> <i class="arg">name</i></a></li>
<li><a href="#183">method <b class="cmd">make {} target</b> <i class="arg">name</i> <i class="arg">Info</i> <i class="arg">body</i></a></li>
<li><a href="#184">method <b class="cmd">make {} todo</b></a></li>
<li><a href="#185">method <b class="cmd">make {} do</b></a></li>
<li><a href="#186">method <b class="cmd">child</b> <i class="arg">which</i></a></li>
<li><a href="#187">method <b class="cmd">generate-c</b></a></li>
<li><a href="#188">method <b class="cmd">generate-h</b></a></li>
<li><a href="#189">method <b class="cmd">generate-loader</b></a></li>
<li><a href="#190">method <b class="cmd">initialize</b></a></li>
<li><a href="#191">method <b class="cmd">implement</b> <i class="arg">path</i></a></li>
<li><a href="#192">method <b class="cmd">linktype</b></a></li>
<li><a href="#193">method <b class="cmd">_MorphPatterns</b></a></li>
<li><a href="#194">method <b class="cmd">constructor</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#195">method <b class="cmd">add_object</b> <i class="arg">object</i></a></li>
<li><a href="#196">method <b class="cmd">add_project</b> <i class="arg">pkg</i> <i class="arg">info</i> <span class="opt">?<i class="arg">oodefine</i> <b class="const"></b>?</span></a></li>
<li><a href="#197">method <b class="cmd">add_tool</b> <i class="arg">pkg</i> <i class="arg">info</i> <span class="opt">?<i class="arg">oodefine</i> <b class="const"></b>?</span></a></li>
<li><a href="#198">method <b class="cmd">build-tclcore</b></a></li>
<li><a href="#199">method <b class="cmd">child</b> <i class="arg">which</i></a></li>
<li><a href="#200">method <b class="cmd">linktype</b></a></li>
<li><a href="#201">method <b class="cmd">project</b> <i class="arg">pkg</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#202">method <b class="cmd">tclcore</b></a></li>
<li><a href="#203">method <b class="cmd">tkcore</b></a></li>
<li><a href="#204">method <b class="cmd"><a href="../tool/tool.html">tool</a></b> <i class="arg">pkg</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#205">method <b class="cmd">clean</b> <i class="arg">PATH</i></a></li>
<li><a href="#206">method <b class="cmd">project-compile-products</b></a></li>
<li><a href="#207">method <b class="cmd">go</b></a></li>
<li><a href="#208">method <b class="cmd">generate-decls</b> <i class="arg">pkgname</i> <i class="arg">path</i></a></li>
<li><a href="#209">method <b class="cmd">implement</b> <i class="arg">path</i></a></li>
<li><a href="#210">method <b class="cmd">generate-make</b> <i class="arg">path</i></a></li>
<li><a href="#211">method <b class="cmd">linktype</b></a></li>
<li><a href="#212">method <b class="cmd">package-ifneeded</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#213">method <b class="cmd">shared_library</b> <span class="opt">?<i class="arg">filename</i> <b class="const"></b>?</span></a></li>
<li><a href="#214">method <b class="cmd">static_library</b> <span class="opt">?<i class="arg">filename</i> <b class="const"></b>?</span></a></li>
<li><a href="#215">method <b class="cmd">build-tclkit_main</b> <i class="arg">PROJECT</i> <i class="arg">PKG_OBJS</i></a></li>
<li><a href="#216">method <b class="cmd">Collate_Source</b> <i class="arg">CWD</i></a></li>
<li><a href="#217">method <b class="cmd">wrap</b> <i class="arg">PWD</i> <i class="arg">exename</i> <i class="arg">vfspath</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#218">classmethod <b class="cmd">Sandbox</b> <i class="arg">object</i></a></li>
<li><a href="#219">classmethod <b class="cmd">select</b> <i class="arg">object</i></a></li>
<li><a href="#220">classmethod <b class="cmd">claim_option</b></a></li>
<li><a href="#221">classmethod <b class="cmd">claim_object</b> <i class="arg">object</i></a></li>
<li><a href="#222">classmethod <b class="cmd">claim_path</b> <i class="arg">path</i></a></li>
<li><a href="#223">method <b class="cmd">scm_info</b></a></li>
<li><a href="#224">method <b class="cmd">DistroMixIn</b></a></li>
<li><a href="#225">method <b class="cmd">Sandbox</b></a></li>
<li><a href="#226">method <b class="cmd">SrcDir</b></a></li>
<li><a href="#227">method <b class="cmd">ScmTag</b></a></li>
<li><a href="#228">method <b class="cmd">ScmClone</b></a></li>
<li><a href="#229">method <b class="cmd">ScmUnpack</b></a></li>
<li><a href="#230">method <b class="cmd">ScmUpdate</b></a></li>
<li><a href="#231">method <b class="cmd">Unpack</b></a></li>
<li><a href="#232">classmethod <b class="cmd">claim_object</b> <i class="arg">object</i></a></li>
<li><a href="#233">classmethod <b class="cmd">claim_option</b></a></li>
<li><a href="#234">classmethod <b class="cmd">claim_path</b> <i class="arg">path</i></a></li>
<li><a href="#235">method <b class="cmd">ScmUnpack</b></a></li>
<li><a href="#236">classmethod <b class="cmd">claim_object</b> <i class="arg">obj</i></a></li>
<li><a href="#237">classmethod <b class="cmd">claim_option</b></a></li>
<li><a href="#238">classmethod <b class="cmd">claim_path</b> <i class="arg">path</i></a></li>
<li><a href="#239">method <b class="cmd">scm_info</b></a></li>
<li><a href="#240">method <b class="cmd">ScmClone</b></a></li>
<li><a href="#241">method <b class="cmd">ScmTag</b></a></li>
<li><a href="#242">method <b class="cmd">ScmUnpack</b></a></li>
<li><a href="#243">method <b class="cmd">ScmUpdate</b></a></li>
<li><a href="#244">classmethod <b class="cmd">claim_object</b> <i class="arg">obj</i></a></li>
<li><a href="#245">classmethod <b class="cmd">claim_option</b></a></li>
<li><a href="#246">classmethod <b class="cmd">claim_path</b> <i class="arg">path</i></a></li>
<li><a href="#247">method <b class="cmd">ScmTag</b></a></li>
<li><a href="#248">method <b class="cmd">ScmUnpack</b></a></li>
<li><a href="#249">method <b class="cmd">ScmUpdate</b></a></li>
<li><a href="#250">method <b class="cmd">_MorphPatterns</b></a></li>
<li><a href="#251">method <b class="cmd">BuildDir</b> <i class="arg">PWD</i></a></li>
<li><a href="#252">method <b class="cmd">child</b> <i class="arg">which</i></a></li>
<li><a href="#253">method <b class="cmd">compile</b></a></li>
<li><a href="#254">method <b class="cmd">go</b></a></li>
<li><a href="#255">method <b class="cmd">install</b> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#256">method <b class="cmd">linktype</b></a></li>
<li><a href="#257">method <b class="cmd">linker-products</b> <i class="arg">configdict</i></a></li>
<li><a href="#258">method <b class="cmd">linker-external</b> <i class="arg">configdict</i></a></li>
<li><a href="#259">method <b class="cmd">linker-extra</b> <i class="arg">configdict</i></a></li>
<li><a href="#260">method <b class="cmd">env-bootstrap</b></a></li>
<li><a href="#261">method <b class="cmd">env-exec</b></a></li>
<li><a href="#262">method <b class="cmd">env-install</b></a></li>
<li><a href="#263">method <b class="cmd">env-load</b></a></li>
<li><a href="#264">method <b class="cmd">env-present</b></a></li>
<li><a href="#265">method <b class="cmd">sources</b></a></li>
<li><a href="#266">method <b class="cmd"><a href="../../../../index.html#update">update</a></b></a></li>
<li><a href="#267">method <b class="cmd">unpack</b></a></li>
<li><a href="#268">method <b class="cmd">env-bootstrap</b></a></li>
<li><a href="#269">method <b class="cmd">env-present</b></a></li>
<li><a href="#270">method <b class="cmd">linktype</b></a></li>
<li><a href="#271">method <b class="cmd">env-bootstrap</b></a></li>
<li><a href="#272">method <b class="cmd">env-install</b></a></li>
<li><a href="#273">method <b class="cmd">env-present</b></a></li>
<li><a href="#274">method <b class="cmd">install</b> <i class="arg">DEST</i></a></li>
<li><a href="#275">method <b class="cmd">kettle</b> <i class="arg">path</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#276">method <b class="cmd">install</b> <i class="arg">DEST</i></a></li>
<li><a href="#277">method <b class="cmd">install</b> <i class="arg">DEST</i></a></li>
<li><a href="#278">method <b class="cmd">env-bootstrap</b></a></li>
<li><a href="#279">method <b class="cmd">env-install</b></a></li>
<li><a href="#280">method <b class="cmd">env-present</b></a></li>
<li><a href="#281">method <b class="cmd">install</b> <i class="arg">DEST</i></a></li>
<li><a href="#282">method <b class="cmd">install-module</b> <i class="arg">DEST</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#283">method <b class="cmd">env-bootstrap</b></a></li>
<li><a href="#284">method <b class="cmd">env-install</b></a></li>
<li><a href="#285">method <b class="cmd">install</b> <i class="arg">DEST</i></a></li>
<li><a href="#286">method <b class="cmd">install-module</b> <i class="arg">DEST</i> <span class="opt">?<i class="arg">args</i>?</span></a></li>
<li><a href="#287">method <b class="cmd">clean</b></a></li>
<li><a href="#288">method <b class="cmd">env-install</b></a></li>
<li><a href="#289">method <b class="cmd">project-compile-products</b></a></li>
<li><a href="#290">method <b class="cmd">ComputeInstall</b></a></li>
<li><a href="#291">method <b class="cmd">go</b></a></li>
<li><a href="#292">method <b class="cmd">linker-products</b> <i class="arg">configdict</i></a></li>
<li><a href="#293">method <b class="cmd">project-static-packages</b></a></li>
<li><a href="#294">method <b class="cmd">BuildDir</b> <i class="arg">PWD</i></a></li>
<li><a href="#295">method <b class="cmd">compile</b></a></li>
<li><a href="#296">method <b class="cmd">Configure</b></a></li>
<li><a href="#297">method <b class="cmd">install</b> <i class="arg">DEST</i></a></li>
<li><a href="#298">method <b class="cmd">install</b> <i class="arg">DEST</i></a></li>
<li><a href="#299">method <b class="cmd">install</b> <i class="arg">DEST</i></a></li>
<li><a href="#300">method <b class="cmd">env-bootstrap</b></a></li>
<li><a href="#301">method <b class="cmd">env-present</b></a></li>
<li><a href="#302">method <b class="cmd">env-install</b></a></li>
<li><a href="#303">method <b class="cmd">go</b></a></li>
<li><a href="#304">method <b class="cmd">linktype</b></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>The Practcl module is a tool for integrating large modules for C API
Tcl code that requires custom Tcl types and TclOO objects.</p>
<p>The concept with Practcl is that is a single file package that can
assist any tcl based project with distribution, compilation, linking,
VFS preparation, executable assembly, and installation. Practcl also
allows one project to invoke the build system from another project,
allowing complex projects such as a statically linked basekit to be
assembled with relative ease.</p>
<p>Practcl ships as a single file, and aside from a Tcl 8.6 interpreter,
has no external dependencies.</p>
<p>Making a practcl project</p>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">Commands</a></h2>
<dl class="doctools_definitions">
<dt><a name="1">proc <b class="cmd">practcl::cat</b> <i class="arg">fname</i></a></dt>
<dd><p>Concatenate a file</p></dd>
<dt><a name="2">proc <b class="cmd">practcl::docstrip</b> <i class="arg">text</i></a></dt>
<dd><p>Strip the global comments from tcl code. Used to
 prevent the documentation markup comments from clogging
 up files intended for distribution in machine readable format.</p></dd>
<dt><a name="3">proc <b class="cmd">putb</b> <span class="opt">?<i class="arg">map</i>?</span> <i class="arg">text</i></a></dt>
<dd><p>Append a line of text to a variable. Optionally apply a string mapping.</p></dd>
<dt><a name="4">proc <b class="cmd"><a href="../../../../index.html#proc">Proc</a></b> <i class="arg">name</i> <i class="arg">arglist</i> <i class="arg">body</i></a></dt>
<dd><p>Generate a proc if no command already exists by that name</p></dd>
<dt><a name="5">proc <b class="cmd">noop</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>A command to do nothing. A handy way of
 negating an instruction without
 having to comment it completely out.
 It's also a handy attachment point for
 an object to be named later</p></dd>
<dt><a name="6">proc <b class="cmd">practcl::debug</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="7">proc <b class="cmd">practcl::doexec</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Drop in a static copy of Tcl</p></dd>
<dt><a name="8">proc <b class="cmd">practcl::doexec_in</b> <i class="arg">path</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="9">proc <b class="cmd">practcl::dotclexec</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="10">proc <b class="cmd">practcl::domake</b> <i class="arg">path</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="11">proc <b class="cmd">practcl::domake.tcl</b> <i class="arg">path</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="12">proc <b class="cmd">practcl::fossil</b> <i class="arg">path</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="13">proc <b class="cmd">practcl::fossil_status</b> <i class="arg">dir</i></a></dt>
<dd></dd>
<dt><a name="14">proc <b class="cmd">practcl::os</b></a></dt>
<dd></dd>
<dt><a name="15">proc <b class="cmd">practcl::mkzip</b> <i class="arg">exename</i> <i class="arg">barekit</i> <i class="arg">vfspath</i></a></dt>
<dd><p>Build a zipfile. On tcl8.6 this invokes the native Zip implementation
 on older interpreters this invokes zip via exec</p></dd>
<dt><a name="16">proc <b class="cmd">practcl::sort_dict</b> <i class="arg">list</i></a></dt>
<dd><p>Dictionary sort a key/value list. Needed because pre tcl8.6
 does not have <em>lsort -stride 2</em></p></dd>
<dt><a name="17">proc <b class="cmd">practcl::local_os</b></a></dt>
<dd><p>Returns a dictionary describing the local operating system.
 Fields return include:</p>
<ul class="doctools_itemized">
 
<li><p>download - Filesystem path where fossil repositories and source tarballs are downloaded for the current user</p></li>
<li><p>EXEEXT - The extension to give to executables. (i.e. .exe on windows)</p></li>
<li><p>fossil_mirror - A URI for a local network web server who acts as a fossil repository mirror</p></li>
<li><p>local_install - Filesystem path where packages for local consumption by the current user are installed</p></li>
<li><p>prefix - The prefix as given to the Tcl core/TEA for installation to local_install in ./configure</p></li>
<li><p>sandbox - The file location where this project unpacks external projects</p></li>
<li><p>TEACUP_PROFILE - The ActiveState/Teacup canonical name for this platform (i.e. win32-ix86 macosx10.5-i386-x86_84)</p></li>
<li><p>TEACUP_OS - The local operating system (windows, macosx, openbsd, etc). Gives the same answer as tcl.m4, except that macosx is given as macosx instead of Darwin.</p></li>
<li><p>TEA_PLATFORM - The platform returned by uname -s-uname -r (on Unix), or &quot;windows&quot; on Windows</p></li>
<li><p>TEACUP_ARCH - The processor architecture for the local os (i.e. ix86, x86_64)</p></li>
<li><p>TEACUP_ARCH - The processor architecture for the local os (i.e. ix86, x86_64)</p></li>
<li><p>teapot - Filesystem path where teapot package files are downloaded for the current user</p></li>
<li><p>userhome - File path to store localized preferences, cache download files, etc for the current user</p></li>
</ul>
<p>This command uses a combination of local checks with Exec, any tclConfig.sh file that is
 resident, autoconf data where already computed, and data gleaned from a file named
 practcl.rc in userhome. The location for userhome varies by platform and operating system:</p>
<ul class="doctools_itemized">
 
<li><p>Windows: ::env(LOCALAPPDATA)/Tcl</p></li>
<li><p>Macos: ~/Library/Application Support/Tcl</p></li>
<li><p>Other: ~/tcl</p></li>
</ul></dd>
<dt><a name="18">proc <b class="cmd">practcl::config.tcl</b> <i class="arg">path</i></a></dt>
<dd><p>A transparent call to ::practcl::read_configuration to preserve backward compadibility
 with older copies of Practcl</p></dd>
<dt><a name="19">proc <b class="cmd">practcl::read_configuration</b> <i class="arg">path</i></a></dt>
<dd><p>Detect local platform. This command looks for data gleaned by autoconf or autosetup
 in the path specified, or perform its own logic tests if neither has been run.
 A file named config.site present in the location indicates that this project is
 cross compiling, and the data stored in that file is used for the compiler and linker.</p>
<p>This command looks for information from the following files, in the following order:</p>
<ul class="doctools_itemized">
 
<li><p>config.tcl - A file generated by autoconf/configure in newer editions of TEA, encoded as a Tcl script.</p></li>
<li><p>config.site - A file containing cross compiler information, encoded as a SH script</p></li>
<li><p>::env(VisualStudioVersion) - On Windows, and environmental value that indicates MS Visual Studio is installed</p></li>
</ul>
<p>This command returns a dictionary containing all of the data cleaned from the sources above.
 In the absence of any guidance this command returns the same output as ::practcl::local_os.
 In this mode, if the environmental variable VisualStudioVersion exists, this command
 will provide a template of fields that are appropriate for compiling on Windows under
 Microsoft Visual Studio. The USEMSVC flag in the dictionary is a boolean flag to indicate
 if this is indeed the case.</p></dd>
<dt><a name="20">proc <b class="cmd">practcl::tcllib_require</b> <i class="arg">pkg</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Try to load  a package, and failing that
 retrieve tcllib</p></dd>
<dt><a name="21">proc <b class="cmd">practcl::platform::tcl_core_options</b> <i class="arg">os</i></a></dt>
<dd><p>Return the string to pass to ./configure to compile the Tcl core for the given OS.</p>
<ul class="doctools_itemized">
 
<li><p>windows: --with-tzdata --with-encoding utf-8</p></li>
<li><p>macosx: --enable-corefoundation=yes  --enable-framework=no --with-tzdata --with-encoding utf-8</p></li>
<li><p>other: --with-tzdata --with-encoding utf-8</p></li>
</ul></dd>
<dt><a name="22">proc <b class="cmd">practcl::platform::tk_core_options</b> <i class="arg">os</i></a></dt>
<dd></dd>
<dt><a name="23">proc <b class="cmd">practcl::read_rc_file</b> <i class="arg">filename</i> <span class="opt">?<i class="arg">localdat</i> <b class="const"></b>?</span></a></dt>
<dd><p>Read a stylized key/value list stored in a file</p></dd>
<dt><a name="24">proc <b class="cmd">practcl::read_sh_subst</b> <i class="arg">line</i> <i class="arg">info</i></a></dt>
<dd><p>Converts a XXX.sh file into a series of Tcl variables</p></dd>
<dt><a name="25">proc <b class="cmd">practcl::read_sh_file</b> <i class="arg">filename</i> <span class="opt">?<i class="arg">localdat</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
<dt><a name="26">proc <b class="cmd">practcl::read_Config.sh</b> <i class="arg">filename</i></a></dt>
<dd><p>A simpler form of read_sh_file tailored
 to pulling data from (tcl|tk)Config.sh</p></dd>
<dt><a name="27">proc <b class="cmd">practcl::read_Makefile</b> <i class="arg">filename</i></a></dt>
<dd><p>A simpler form of read_sh_file tailored
 to pulling data from a Makefile</p></dd>
<dt><a name="28">proc <b class="cmd">practcl::cputs</b> <i class="arg">varname</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Append arguments to a buffer
 The command works like puts in that each call will also insert
 a line feed. Unlike puts, blank links in the interstitial are
 suppressed</p></dd>
<dt><a name="29">proc <b class="cmd">practcl::tcl_to_c</b> <i class="arg">body</i></a></dt>
<dd></dd>
<dt><a name="30">proc <b class="cmd">practcl::_tagblock</b> <i class="arg">text</i> <span class="opt">?<i class="arg">style</i> <b class="const">tcl</b>?</span> <span class="opt">?<i class="arg">note</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
<dt><a name="31">proc <b class="cmd">practcl::de_shell</b> <i class="arg">data</i></a></dt>
<dd></dd>
<dt><a name="32">proc <b class="cmd">practcl::grep</b> <i class="arg">pattern</i> <span class="opt">?<i class="arg">files</i> <b class="const"></b>?</span></a></dt>
<dd><p>Search for the pattern <em>pattern</em> amongst $files</p></dd>
<dt><a name="33">proc <b class="cmd">practcl::file_lexnormalize</b> <i class="arg">sp</i></a></dt>
<dd></dd>
<dt><a name="34">proc <b class="cmd">practcl::file_relative</b> <i class="arg">base</i> <i class="arg">dst</i></a></dt>
<dd><p>Calculate a relative path between base and dst</p>
<p>Example:</p>
<pre class="doctools_example">  ::practcl::file_relative ~/build/tcl/unix ~/build/tcl/library
  &gt; ../library
</pre>
</dd>
<dt><a name="35">proc <b class="cmd">practcl::findByPattern</b> <i class="arg">basedir</i> <i class="arg">patterns</i></a></dt>
<dd></dd>
<dt><a name="36">proc <b class="cmd">practcl::log</b> <i class="arg">fname</i> <i class="arg">comment</i></a></dt>
<dd><p>Record an event in the practcl log</p></dd>
<dt><a name="37">proc <b class="cmd">practcl::_pkgindex_simpleIndex</b> <i class="arg">path</i></a></dt>
<dd></dd>
<dt><a name="38">proc <b class="cmd">practcl::_pkgindex_directory</b> <i class="arg">path</i></a></dt>
<dd><p>Return true if the pkgindex file contains
 any statement other than &quot;package ifneeded&quot;
 and/or if any package ifneeded loads a DLL</p></dd>
<dt><a name="39">proc <b class="cmd">practcl::_pkgindex_path_subdir</b> <i class="arg">path</i></a></dt>
<dd><p>Helper function for ::practcl::pkgindex_path</p></dd>
<dt><a name="40">proc <b class="cmd">practcl::pkgindex_path</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Index all paths given as though they will end up in the same
 virtual file system</p></dd>
<dt><a name="41">proc <b class="cmd">practcl::installDir</b> <i class="arg">d1</i> <i class="arg">d2</i></a></dt>
<dd><p>Delete the contents of <em>d2</em>, and then
 recusively Ccopy the contents of <em>d1</em> to <em>d2</em>.</p></dd>
<dt><a name="42">proc <b class="cmd">practcl::copyDir</b> <i class="arg">d1</i> <i class="arg">d2</i> <span class="opt">?<i class="arg">toplevel</i> <b class="const">1</b>?</span></a></dt>
<dd><p>Recursively copy the contents of <em>d1</em> to <em>d2</em></p></dd>
<dt><a name="43">proc <b class="cmd">practcl::buildModule</b> <i class="arg">modpath</i></a></dt>
<dd></dd>
<dt><a name="44">proc <b class="cmd">practcl::installModule</b> <i class="arg">modpath</i> <i class="arg">DEST</i></a></dt>
<dd><p>Install a module from MODPATH to the directory specified.
 <em>dpath</em> is assumed to be the fully qualified path where module is to be placed.
 Any existing files will be deleted at that path.
 If the path is symlink the process will return with no error and no action.
 If the module has contents in the build/ directory that are newer than the
 .tcl files in the module source directory, and a build/build.tcl file exists,
 the build/build.tcl file is run.
 If the source directory includes a file named index.tcl, the directory is assumed
 to be in the tao style of modules, and the entire directory (and all subdirectories)
 are copied verbatim.
 If no index.tcl file is present, all .tcl files are copied from the module source
 directory, and a pkgIndex.tcl file is generated if non yet exists.
 I a folder named htdocs exists in the source directory, that directory is copied
 verbatim to the destination.</p></dd>
<dt><a name="45">proc <b class="cmd">practcl::trigger</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Trigger build targets, and recompute dependencies</p>
<p>Internals:</p>
<pre class="doctools_example">
  ::practcl::LOCAL make trigger {*}$args
  foreach {name obj} [::practcl::LOCAL make objects] {
    set ::make($name) [$obj do]
  }
</pre>
</dd>
<dt><a name="46">proc <b class="cmd">practcl::depends</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Calculate if a dependency for any of the arguments needs to
 be fulfilled or rebuilt.</p>
<p>Internals:</p>
<pre class="doctools_example">
  ::practcl::LOCAL make depends {*}$args
</pre>
</dd>
<dt><a name="47">proc <b class="cmd">practcl::target</b> <i class="arg">name</i> <i class="arg">info</i> <span class="opt">?<i class="arg">action</i> <b class="const"></b>?</span></a></dt>
<dd><p>Declare a build product. This proc is just a shorthand for
 <em>::practcl::LOCAL make task $name $info $action</em></p>
<p>Registering a build product with this command will create
 an entry in the global  array, and populate
 a value in the global  array.</p>
<p>Internals:</p>
<pre class="doctools_example">
  set obj [::practcl::LOCAL make task $name $info $action]
  set ::make($name) 0
  set filename [$obj define get filename]
  if {$filename ne {}} {
    set ::target($name) $filename
  }
</pre>
</dd>
</dl>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">Classes</a></h2>
<div id="subsection1" class="doctools_subsection"><h3><a name="subsection1">Class  practcl::doctool</a></h3>
<pre class="doctools_example">{ set authors {
   {John Doe} {[email protected]}
   {Tom RichardHarry} {[email protected]}
 }
 # Create the object
 ::practcl::doctool create AutoDoc
 set fout [open [file join $moddir module.tcl] w]
 foreach file [glob [file join $srcdir *.tcl]] {
   set content [::practcl::cat [file join $srcdir $file]]
    # Scan the file
    AutoDoc scan_text $content
    # Strip the comments from the distribution
    puts $fout [::practcl::docstrip $content]
 }
 # Write out the manual page
 set manout [open [file join $moddir module.man] w]
 dict set args header [string map $modmap [::practcl::cat [file join $srcdir manual.txt]]]
 dict set args footer [string map $modmap [::practcl::cat [file join $srcdir footer.txt]]]
 dict set args authors $authors
 puts $manout [AutoDoc manpage {*}$args]
 close $manout
}</pre>
<p>Tool for build scripts to dynamically generate manual files from comments
 in source code files</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="48">method <b class="cmd">constructor</b></a></dt>
<dd></dd>
<dt><a name="49">method <b class="cmd">argspec</b> <i class="arg">argspec</i></a></dt>
<dd><p>Process an argument list into an informational dict.
 This method also understands non-positional
 arguments expressed in the notation of Tip 471
 <a href="https://core.tcl-lang.org/tips/doc/trunk/tip/479.md">https://core.tcl-lang.org/tips/doc/trunk/tip/479.md</a>.</p>
<p>The output will be a dictionary of all of the fields and whether the fields
 are <b class="const">positional</b>, <b class="const">mandatory</b>, and whether they have a
 <b class="const">default</b> value.</p>
<p>Example:</p>
<pre class="doctools_example">   my argspec {a b {c 10}}
   &gt; a {positional 1 mandatory 1} b {positional 1 mandatory 1} c {positional 1 mandatory 0 default 10}
</pre>
</dd>
<dt><a name="50">method <b class="cmd"><a href="../../../../index.html#comment">comment</a></b> <i class="arg">block</i></a></dt>
<dd><p>Convert a block of comments into an informational dictionary.
 If lines in the comment start with a single word ending in a colon,
 all subsequent lines are appended to a dictionary field of that name.
 If no fields are given, all of the text is appended to the <b class="const">description</b>
 field.</p>
<p>Example:</p>
<pre class="doctools_example"> my comment {Does something cool}
 &gt; description {Does something cool}
 my comment {
 title : Something really cool
 author : Sean Woods
 author : John Doe
 description :
 This does something really cool!
 }
 &gt; description {This does something really cool!}
   title {Something really cool}
   author {Sean Woods
   John Doe}
</pre>
</dd>
<dt><a name="51">method <b class="cmd">keyword.Annotation</b> <i class="arg">resultvar</i> <i class="arg">commentblock</i> <i class="arg">type</i> <i class="arg">name</i> <i class="arg">body</i></a></dt>
<dd></dd>
<dt><a name="52">method <b class="cmd">keyword.Class</b> <i class="arg">resultvar</i> <i class="arg">commentblock</i> <i class="arg">name</i> <i class="arg">body</i></a></dt>
<dd><p>Process an oo::objdefine call that modifies the class object
 itself</p></dd>
<dt><a name="53">method <b class="cmd">keyword.class</b> <i class="arg">resultvar</i> <i class="arg">commentblock</i> <i class="arg">name</i> <i class="arg">body</i></a></dt>
<dd><p>Process an oo::define, clay::define, etc statement.</p></dd>
<dt><a name="54">method <b class="cmd">keyword.Class_Method</b> <i class="arg">resultvar</i> <i class="arg">commentblock</i> <i class="arg">name</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Process a statement for a clay style class method</p></dd>
<dt><a name="55">method <b class="cmd">keyword.method</b> <i class="arg">resultvar</i> <i class="arg">commentblock</i> <i class="arg">name</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Process a statement for a tcloo style object method</p></dd>
<dt><a name="56">method <b class="cmd">keyword.proc</b> <i class="arg">commentblock</i> <i class="arg">name</i> <i class="arg">argspec</i></a></dt>
<dd><p>Process a proc statement</p></dd>
<dt><a name="57">method <b class="cmd">reset</b></a></dt>
<dd><p>Reset the state of the object and its embedded coroutine</p></dd>
<dt><a name="58">method <b class="cmd">Main</b></a></dt>
<dd><p>Main body of the embedded coroutine for the object</p></dd>
<dt><a name="59">method <b class="cmd">section.method</b> <i class="arg">keyword</i> <i class="arg">method</i> <i class="arg">minfo</i></a></dt>
<dd><p>Generate the manual page text for a method or proc</p></dd>
<dt><a name="60">method <b class="cmd">section.annotation</b> <i class="arg">type</i> <i class="arg">name</i> <i class="arg">iinfo</i></a></dt>
<dd></dd>
<dt><a name="61">method <b class="cmd">section.class</b> <i class="arg">class_name</i> <i class="arg">class_info</i></a></dt>
<dd><p>Generate the manual page text for a class</p></dd>
<dt><a name="62">method <b class="cmd">section.command</b> <i class="arg">procinfo</i></a></dt>
<dd><p>Generate the manual page text for the commands section</p></dd>
<dt><a name="63">method <b class="cmd"><a href="../../../../index.html#manpage">manpage</a></b> <span class="opt">?<b class="option">header <em>value</em></b>?</span> <span class="opt">?<b class="option">footer <em>value</em></b>?</span> <span class="opt">?<b class="option">authors <em>list</em></b>?</span></a></dt>
<dd><p>Generate the manual page. Returns the completed text suitable for saving in .man file.
 The header argument is a block of doctools text to go in before the machine generated
 section. footer is a block of doctools text to go in after the machine generated
 section. authors is a list of individual authors and emails in the form of AUTHOR EMAIL ?AUTHOR EMAIL?...</p></dd>
<dt><a name="64">method <b class="cmd">scan_text</b> <i class="arg">text</i></a></dt>
<dd><p>Scan a block of text</p></dd>
<dt><a name="65">method <b class="cmd">scan_file</b> <i class="arg">filename</i></a></dt>
<dd><p>Scan a file of text</p></dd>
</dl>
</div>
<div id="subsection2" class="doctools_subsection"><h3><a name="subsection2">Class  practcl::metaclass</a></h3>
<p>The metaclass for all practcl objects</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="66">method <b class="cmd">_MorphPatterns</b></a></dt>
<dd></dd>
<dt><a name="67">method <b class="cmd"><a href="../../../../index.html#define">define</a></b> <i class="arg">submethod</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="68">method <b class="cmd">graft</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="69">method <b class="cmd">initialize</b></a></dt>
<dd></dd>
<dt><a name="70">method <b class="cmd">link</b> <i class="arg">command</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="71">method <b class="cmd">morph</b> <i class="arg">classname</i></a></dt>
<dd></dd>
<dt><a name="72">method <b class="cmd">script</b> <i class="arg">script</i></a></dt>
<dd></dd>
<dt><a name="73">method <b class="cmd">select</b></a></dt>
<dd></dd>
<dt><a name="74">method <b class="cmd"><a href="../../../../index.html#source">source</a></b> <i class="arg">filename</i></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection3" class="doctools_subsection"><h3><a name="subsection3">Class  practcl::toolset</a></h3>
<p>Ancestor-less class intended to be a mixin
 which defines a family of build related behaviors
 that are modified when targetting either gcc or msvc</p>
<p><b class="class">Class Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="75">classmethod <b class="cmd">select</b> <i class="arg">object</i></a></dt>
<dd><p>Perform the selection for the toolset mixin</p></dd>
</dl>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="76">method <b class="cmd">config.sh</b></a></dt>
<dd><p>find or fake a key/value list describing this project</p></dd>
<dt><a name="77">method <b class="cmd">BuildDir</b> <i class="arg">PWD</i></a></dt>
<dd><p>Compute the location where the product will be built</p></dd>
<dt><a name="78">method <b class="cmd">MakeDir</b> <i class="arg">srcdir</i></a></dt>
<dd><p>Return where the Makefile is located relative to <em>srcdir</em>.
 For this implementation the MakeDir is always srcdir.</p></dd>
<dt><a name="79">method <b class="cmd">read_configuration</b></a></dt>
<dd><p>Read information about the build process for this package.
 For this implementation, data is sought in the following locations
 in the following order:
 config.tcl (generated by practcl.) PKGConfig.sh. The Makefile</p>
<p>If the Makefile needs to be consulted, but does not exist, the
 Configure method is invoked</p></dd>
<dt><a name="80">method <b class="cmd">build-cflags</b> <i class="arg">PROJECT</i> <i class="arg">DEFS</i> <i class="arg">namevar</i> <i class="arg">versionvar</i> <i class="arg">defsvar</i></a></dt>
<dd><p>method DEFS
 This method populates 4 variables:
 name - The name of the package
 version - The version of the package
 defs - C flags passed to the compiler
 includedir - A list of paths to feed to the compiler for finding headers</p></dd>
<dt><a name="81">method <b class="cmd">critcl</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Invoke critcl in an external process</p></dd>
</dl>
</div>
<div id="subsection4" class="doctools_subsection"><h3><a name="subsection4">Class  practcl::toolset.gcc</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::toolset</b></p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="82">method <b class="cmd">Autoconf</b></a></dt>
<dd></dd>
<dt><a name="83">method <b class="cmd">BuildDir</b> <i class="arg">PWD</i></a></dt>
<dd></dd>
<dt><a name="84">method <b class="cmd">ConfigureOpts</b></a></dt>
<dd></dd>
<dt><a name="85">method <b class="cmd">MakeDir</b> <i class="arg">srcdir</i></a></dt>
<dd><p>Detect what directory contains the Makefile template</p></dd>
<dt><a name="86">method <b class="cmd">make {} autodetect</b></a></dt>
<dd></dd>
<dt><a name="87">method <b class="cmd">make {} clean</b></a></dt>
<dd></dd>
<dt><a name="88">method <b class="cmd">make {} compile</b></a></dt>
<dd></dd>
<dt><a name="89">method <b class="cmd">make {} install</b> <i class="arg">DEST</i></a></dt>
<dd></dd>
<dt><a name="90">method <b class="cmd">build-compile-sources</b> <i class="arg">PROJECT</i> <i class="arg">COMPILE</i> <i class="arg">CPPCOMPILE</i> <i class="arg">INCLUDES</i></a></dt>
<dd></dd>
<dt><a name="91">method <b class="cmd">build-Makefile</b> <i class="arg">path</i> <i class="arg">PROJECT</i></a></dt>
<dd></dd>
<dt><a name="92">method <b class="cmd">build-library</b> <i class="arg">outfile</i> <i class="arg">PROJECT</i></a></dt>
<dd><p>Produce a static or dynamic library</p></dd>
<dt><a name="93">method <b class="cmd">build-tclsh</b> <i class="arg">outfile</i> <i class="arg">PROJECT</i> <span class="opt">?<i class="arg">path</i> <b class="const">auto</b>?</span></a></dt>
<dd><p>Produce a static executable</p></dd>
</dl>
</div>
<div id="subsection5" class="doctools_subsection"><h3><a name="subsection5">Class  practcl::toolset.msvc</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::toolset</b></p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="94">method <b class="cmd">BuildDir</b> <i class="arg">PWD</i></a></dt>
<dd><p>MSVC always builds in the source directory</p></dd>
<dt><a name="95">method <b class="cmd">make {} autodetect</b></a></dt>
<dd><p>Do nothing</p></dd>
<dt><a name="96">method <b class="cmd">make {} clean</b></a></dt>
<dd></dd>
<dt><a name="97">method <b class="cmd">make {} compile</b></a></dt>
<dd></dd>
<dt><a name="98">method <b class="cmd">make {} install</b> <i class="arg">DEST</i></a></dt>
<dd></dd>
<dt><a name="99">method <b class="cmd">MakeDir</b> <i class="arg">srcdir</i></a></dt>
<dd><p>Detect what directory contains the Makefile template</p></dd>
<dt><a name="100">method <b class="cmd">NmakeOpts</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection6" class="doctools_subsection"><h3><a name="subsection6">Class  practcl::make_obj</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::metaclass</b></p>
<p>A build deliverable object. Normally an object file, header, or tcl script
 which must be compiled or generated in some way</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="101">method <b class="cmd">constructor</b> <i class="arg">module_object</i> <i class="arg">name</i> <i class="arg">info</i> <span class="opt">?<i class="arg">action_body</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
<dt><a name="102">method <b class="cmd"><a href="../../../../index.html#do">do</a></b></a></dt>
<dd></dd>
<dt><a name="103">method <b class="cmd">check</b></a></dt>
<dd></dd>
<dt><a name="104">method <b class="cmd">output</b></a></dt>
<dd></dd>
<dt><a name="105">method <b class="cmd">reset</b></a></dt>
<dd></dd>
<dt><a name="106">method <b class="cmd">triggers</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection7" class="doctools_subsection"><h3><a name="subsection7">Class  practcl::object</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::metaclass</b></p>
<p>A generic Practcl object</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="107">method <b class="cmd">constructor</b> <i class="arg">parent</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="108">method <b class="cmd">child</b> <i class="arg">method</i></a></dt>
<dd></dd>
<dt><a name="109">method <b class="cmd">go</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection8" class="doctools_subsection"><h3><a name="subsection8">Class  practcl::dynamic</a></h3>
<p>Dynamic blocks do not generate their own .c files,
 instead the contribute to the amalgamation
 of the main library file</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="110">method <b class="cmd">cstructure</b> <i class="arg">name</i> <i class="arg">definition</i> <span class="opt">?<i class="arg">argdat</i> <b class="const"></b>?</span></a></dt>
<dd><p>Parser functions</p></dd>
<dt><a name="111">method <b class="cmd">include</b> <i class="arg">header</i></a></dt>
<dd></dd>
<dt><a name="112">method <b class="cmd">include_dir</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="113">method <b class="cmd">include_directory</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="114">method <b class="cmd">c_header</b> <i class="arg">body</i></a></dt>
<dd></dd>
<dt><a name="115">method <b class="cmd">c_code</b> <i class="arg">body</i></a></dt>
<dd></dd>
<dt><a name="116">method <b class="cmd">c_function</b> <i class="arg">header</i> <i class="arg">body</i> <span class="opt">?<i class="arg">info</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
<dt><a name="117">method <b class="cmd">c_tcloomethod</b> <i class="arg">name</i> <i class="arg">body</i> <span class="opt">?<i class="arg">arginfo</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
<dt><a name="118">method <b class="cmd">cmethod</b> <i class="arg">name</i> <i class="arg">body</i> <span class="opt">?<i class="arg">arginfo</i> <b class="const"></b>?</span></a></dt>
<dd><p>Alias to classic name</p></dd>
<dt><a name="119">method <b class="cmd">c_tclproc_nspace</b> <i class="arg">nspace</i></a></dt>
<dd></dd>
<dt><a name="120">method <b class="cmd">c_tclcmd</b> <i class="arg">name</i> <i class="arg">body</i> <span class="opt">?<i class="arg">arginfo</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
<dt><a name="121">method <b class="cmd">c_tclproc_raw</b> <i class="arg">name</i> <i class="arg">body</i> <span class="opt">?<i class="arg">arginfo</i> <b class="const"></b>?</span></a></dt>
<dd><p>Alias to classic name</p></dd>
<dt><a name="122">method <b class="cmd">tcltype</b> <i class="arg">name</i> <i class="arg">argdat</i></a></dt>
<dd></dd>
<dt><a name="123">method <b class="cmd">project-compile-products</b></a></dt>
<dd><p>Module interactions</p></dd>
<dt><a name="124">method <b class="cmd">implement</b> <i class="arg">path</i></a></dt>
<dd></dd>
<dt><a name="125">method <b class="cmd">initialize</b></a></dt>
<dd><p>Practcl internals</p></dd>
<dt><a name="126">method <b class="cmd">linktype</b></a></dt>
<dd></dd>
<dt><a name="127">method <b class="cmd">generate-cfile-constant</b></a></dt>
<dd></dd>
<dt><a name="128">method <b class="cmd">generate-cfile-header</b></a></dt>
<dd></dd>
<dt><a name="129">method <b class="cmd">generate-cfile-tclapi</b></a></dt>
<dd><p>Generate code that provides implements Tcl API
 calls</p></dd>
<dt><a name="130">method <b class="cmd">generate-loader-module</b></a></dt>
<dd><p>Generate code that runs when the package/module is
 initialized into the interpreter</p></dd>
<dt><a name="131">method <b class="cmd">Collate_Source</b> <i class="arg">CWD</i></a></dt>
<dd></dd>
<dt><a name="132">method <b class="cmd">select</b></a></dt>
<dd><p>Once an object marks itself as some
 flavor of dynamic, stop trying to morph
 it into something else</p></dd>
</dl>
</div>
<div id="subsection9" class="doctools_subsection"><h3><a name="subsection9">Class  practcl::product</a></h3>
<p>A deliverable for the build system</p>
<p><b class="class">Class Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="133">classmethod <b class="cmd">select</b> <i class="arg">object</i></a></dt>
<dd></dd>
</dl>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="134">method <b class="cmd">code</b> <i class="arg">section</i> <i class="arg">body</i></a></dt>
<dd></dd>
<dt><a name="135">method <b class="cmd">Collate_Source</b> <i class="arg">CWD</i></a></dt>
<dd></dd>
<dt><a name="136">method <b class="cmd">project-compile-products</b></a></dt>
<dd></dd>
<dt><a name="137">method <b class="cmd">generate-debug</b> <span class="opt">?<i class="arg">spaces</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
<dt><a name="138">method <b class="cmd">generate-cfile-constant</b></a></dt>
<dd></dd>
<dt><a name="139">method <b class="cmd">generate-cfile-public-structure</b></a></dt>
<dd><p>Populate const static data structures</p></dd>
<dt><a name="140">method <b class="cmd">generate-cfile-header</b></a></dt>
<dd></dd>
<dt><a name="141">method <b class="cmd">generate-cfile-global</b></a></dt>
<dd></dd>
<dt><a name="142">method <b class="cmd">generate-cfile-private-typedef</b></a></dt>
<dd></dd>
<dt><a name="143">method <b class="cmd">generate-cfile-private-structure</b></a></dt>
<dd></dd>
<dt><a name="144">method <b class="cmd">generate-cfile-functions</b></a></dt>
<dd><p>Generate code that provides subroutines called by
 Tcl API methods</p></dd>
<dt><a name="145">method <b class="cmd">generate-cfile-tclapi</b></a></dt>
<dd><p>Generate code that provides implements Tcl API
 calls</p></dd>
<dt><a name="146">method <b class="cmd">generate-hfile-public-define</b></a></dt>
<dd></dd>
<dt><a name="147">method <b class="cmd">generate-hfile-public-macro</b></a></dt>
<dd></dd>
<dt><a name="148">method <b class="cmd">generate-hfile-public-typedef</b></a></dt>
<dd></dd>
<dt><a name="149">method <b class="cmd">generate-hfile-public-structure</b></a></dt>
<dd></dd>
<dt><a name="150">method <b class="cmd">generate-hfile-public-headers</b></a></dt>
<dd></dd>
<dt><a name="151">method <b class="cmd">generate-hfile-public-function</b></a></dt>
<dd></dd>
<dt><a name="152">method <b class="cmd">generate-hfile-public-includes</b></a></dt>
<dd></dd>
<dt><a name="153">method <b class="cmd">generate-hfile-public-verbatim</b></a></dt>
<dd></dd>
<dt><a name="154">method <b class="cmd">generate-loader-external</b></a></dt>
<dd></dd>
<dt><a name="155">method <b class="cmd">generate-loader-module</b></a></dt>
<dd></dd>
<dt><a name="156">method <b class="cmd">generate-stub-function</b></a></dt>
<dd></dd>
<dt><a name="157">method <b class="cmd">IncludeAdd</b> <i class="arg">headervar</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="158">method <b class="cmd">generate-tcl-loader</b></a></dt>
<dd></dd>
<dt><a name="159">method <b class="cmd">generate-tcl-pre</b></a></dt>
<dd><p>This methods generates any Tcl script file
 which is required to pre-initialize the C library</p></dd>
<dt><a name="160">method <b class="cmd">generate-tcl-post</b></a></dt>
<dd></dd>
<dt><a name="161">method <b class="cmd">linktype</b></a></dt>
<dd></dd>
<dt><a name="162">method <b class="cmd">Ofile</b> <i class="arg">filename</i></a></dt>
<dd></dd>
<dt><a name="163">method <b class="cmd">project-static-packages</b></a></dt>
<dd><p>Methods called by the master project</p></dd>
<dt><a name="164">method <b class="cmd">toolset-include-directory</b></a></dt>
<dd><p>Methods called by the toolset</p></dd>
<dt><a name="165">method <b class="cmd">target</b> <i class="arg">method</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection10" class="doctools_subsection"><h3><a name="subsection10">Class  practcl::product.cheader</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::product</b></p>
<p>A product which generated from a C header file. Which is to say, nothing.</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="166">method <b class="cmd">project-compile-products</b></a></dt>
<dd></dd>
<dt><a name="167">method <b class="cmd">generate-loader-module</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection11" class="doctools_subsection"><h3><a name="subsection11">Class  practcl::product.csource</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::product</b></p>
<p>A product which generated from a C source file. Normally an object (.o) file.</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="168">method <b class="cmd">project-compile-products</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection12" class="doctools_subsection"><h3><a name="subsection12">Class  practcl::product.clibrary</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::product</b></p>
<p>A product which is generated from a compiled C library.
 Usually a .a or a .dylib file, but in complex cases may
 actually just be a conduit for one project to integrate the
 source code of another</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="169">method <b class="cmd">linker-products</b> <i class="arg">configdict</i></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection13" class="doctools_subsection"><h3><a name="subsection13">Class  practcl::product.dynamic</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::dynamic</b> <b class="class">practcl::product</b></p>
<p>A product which is generated from C code that itself is generated
 by practcl or some other means. This C file may or may not produce
 its own .o file, depending on whether it is eligible to become part
 of an amalgamation</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="170">method <b class="cmd">initialize</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection14" class="doctools_subsection"><h3><a name="subsection14">Class  practcl::product.critcl</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::dynamic</b> <b class="class">practcl::product</b></p>
<p>A binary product produced by critcl. Note: The implementation is not
 written yet, this class does nothing.</p>
</div>
<div id="subsection15" class="doctools_subsection"><h3><a name="subsection15">Class  practcl::module</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::object</b> <b class="class">practcl::product.dynamic</b></p>
<p>In the end, all C code must be loaded into a module
 This will either be a dynamically loaded library implementing
 a tcl extension, or a compiled in segment of a custom shell/app</p>
<p><b class="class">Variable</b></p>
<dl class="doctools_definitions">
<dt><a name="171">variable <b class="cmd">make_object</b></a></dt>
<dd></dd>
</dl>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="172">method <b class="cmd">_MorphPatterns</b></a></dt>
<dd></dd>
<dt><a name="173">method <b class="cmd">add</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="174">method <b class="cmd">install-headers</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="175">method <b class="cmd">make {} _preamble</b></a></dt>
<dd></dd>
<dt><a name="176">method <b class="cmd">make {} pkginfo</b></a></dt>
<dd></dd>
<dt><a name="177">method <b class="cmd">make {} objects</b></a></dt>
<dd><p>Return a dictionary of all handles and associated objects</p></dd>
<dt><a name="178">method <b class="cmd">make {} object</b> <i class="arg">name</i></a></dt>
<dd><p>Return the object associated with handle <em>name</em></p></dd>
<dt><a name="179">method <b class="cmd">make {} reset</b></a></dt>
<dd><p>Reset all deputy objects</p></dd>
<dt><a name="180">method <b class="cmd">make {} trigger</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Exercise the triggers method for all handles listed</p></dd>
<dt><a name="181">method <b class="cmd">make {} depends</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Exercise the check method for all handles listed</p></dd>
<dt><a name="182">method <b class="cmd">make {} filename</b> <i class="arg">name</i></a></dt>
<dd><p>Return the file name of the build product for the listed
 handle</p></dd>
<dt><a name="183">method <b class="cmd">make {} target</b> <i class="arg">name</i> <i class="arg">Info</i> <i class="arg">body</i></a></dt>
<dd></dd>
<dt><a name="184">method <b class="cmd">make {} todo</b></a></dt>
<dd><p>Return a list of handles for object which return true for the
 do method</p></dd>
<dt><a name="185">method <b class="cmd">make {} do</b></a></dt>
<dd><p>For each target exercise the action specified in the <em>action</em>
 definition if the <em>do</em> method returns true</p></dd>
<dt><a name="186">method <b class="cmd">child</b> <i class="arg">which</i></a></dt>
<dd></dd>
<dt><a name="187">method <b class="cmd">generate-c</b></a></dt>
<dd><p>This methods generates the contents of an amalgamated .c file
 which implements the loader for a batch of tools</p></dd>
<dt><a name="188">method <b class="cmd">generate-h</b></a></dt>
<dd><p>This methods generates the contents of an amalgamated .h file
 which describes the public API of this module</p></dd>
<dt><a name="189">method <b class="cmd">generate-loader</b></a></dt>
<dd></dd>
<dt><a name="190">method <b class="cmd">initialize</b></a></dt>
<dd></dd>
<dt><a name="191">method <b class="cmd">implement</b> <i class="arg">path</i></a></dt>
<dd></dd>
<dt><a name="192">method <b class="cmd">linktype</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection16" class="doctools_subsection"><h3><a name="subsection16">Class  practcl::project</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::module</b></p>
<p>A toplevel project that is a collection of other projects</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="193">method <b class="cmd">_MorphPatterns</b></a></dt>
<dd></dd>
<dt><a name="194">method <b class="cmd">constructor</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="195">method <b class="cmd">add_object</b> <i class="arg">object</i></a></dt>
<dd></dd>
<dt><a name="196">method <b class="cmd">add_project</b> <i class="arg">pkg</i> <i class="arg">info</i> <span class="opt">?<i class="arg">oodefine</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
<dt><a name="197">method <b class="cmd">add_tool</b> <i class="arg">pkg</i> <i class="arg">info</i> <span class="opt">?<i class="arg">oodefine</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
<dt><a name="198">method <b class="cmd">build-tclcore</b></a></dt>
<dd><p>Compile the Tcl core. If the define <em>tk</em> is true, compile the
 Tk core as well</p></dd>
<dt><a name="199">method <b class="cmd">child</b> <i class="arg">which</i></a></dt>
<dd></dd>
<dt><a name="200">method <b class="cmd">linktype</b></a></dt>
<dd></dd>
<dt><a name="201">method <b class="cmd">project</b> <i class="arg">pkg</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Exercise the methods of a sub-object</p></dd>
<dt><a name="202">method <b class="cmd">tclcore</b></a></dt>
<dd></dd>
<dt><a name="203">method <b class="cmd">tkcore</b></a></dt>
<dd></dd>
<dt><a name="204">method <b class="cmd"><a href="../tool/tool.html">tool</a></b> <i class="arg">pkg</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection17" class="doctools_subsection"><h3><a name="subsection17">Class  practcl::library</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::project</b></p>
<p>A toplevel project that produces a library</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="205">method <b class="cmd">clean</b> <i class="arg">PATH</i></a></dt>
<dd></dd>
<dt><a name="206">method <b class="cmd">project-compile-products</b></a></dt>
<dd></dd>
<dt><a name="207">method <b class="cmd">go</b></a></dt>
<dd></dd>
<dt><a name="208">method <b class="cmd">generate-decls</b> <i class="arg">pkgname</i> <i class="arg">path</i></a></dt>
<dd></dd>
<dt><a name="209">method <b class="cmd">implement</b> <i class="arg">path</i></a></dt>
<dd></dd>
<dt><a name="210">method <b class="cmd">generate-make</b> <i class="arg">path</i></a></dt>
<dd><p>Backward compadible call</p></dd>
<dt><a name="211">method <b class="cmd">linktype</b></a></dt>
<dd></dd>
<dt><a name="212">method <b class="cmd">package-ifneeded</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Create a &quot;package ifneeded&quot;
 Args are a list of aliases for which this package will answer to</p></dd>
<dt><a name="213">method <b class="cmd">shared_library</b> <span class="opt">?<i class="arg">filename</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
<dt><a name="214">method <b class="cmd">static_library</b> <span class="opt">?<i class="arg">filename</i> <b class="const"></b>?</span></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection18" class="doctools_subsection"><h3><a name="subsection18">Class  practcl::tclkit</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::library</b></p>
<p>A toplevel project that produces a self-contained executable</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="215">method <b class="cmd">build-tclkit_main</b> <i class="arg">PROJECT</i> <i class="arg">PKG_OBJS</i></a></dt>
<dd></dd>
<dt><a name="216">method <b class="cmd">Collate_Source</b> <i class="arg">CWD</i></a></dt>
<dd></dd>
<dt><a name="217">method <b class="cmd">wrap</b> <i class="arg">PWD</i> <i class="arg">exename</i> <i class="arg">vfspath</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Wrap an executable</p></dd>
</dl>
</div>
<div id="subsection19" class="doctools_subsection"><h3><a name="subsection19">Class  practcl::distribution</a></h3>
<p>Standalone class to manage code distribution
 This class is intended to be mixed into another class
 (Thus the lack of ancestors)</p>
<p><b class="class">Class Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="218">classmethod <b class="cmd">Sandbox</b> <i class="arg">object</i></a></dt>
<dd></dd>
<dt><a name="219">classmethod <b class="cmd">select</b> <i class="arg">object</i></a></dt>
<dd></dd>
<dt><a name="220">classmethod <b class="cmd">claim_option</b></a></dt>
<dd></dd>
<dt><a name="221">classmethod <b class="cmd">claim_object</b> <i class="arg">object</i></a></dt>
<dd></dd>
<dt><a name="222">classmethod <b class="cmd">claim_path</b> <i class="arg">path</i></a></dt>
<dd></dd>
</dl>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="223">method <b class="cmd">scm_info</b></a></dt>
<dd></dd>
<dt><a name="224">method <b class="cmd">DistroMixIn</b></a></dt>
<dd></dd>
<dt><a name="225">method <b class="cmd">Sandbox</b></a></dt>
<dd></dd>
<dt><a name="226">method <b class="cmd">SrcDir</b></a></dt>
<dd></dd>
<dt><a name="227">method <b class="cmd">ScmTag</b></a></dt>
<dd></dd>
<dt><a name="228">method <b class="cmd">ScmClone</b></a></dt>
<dd></dd>
<dt><a name="229">method <b class="cmd">ScmUnpack</b></a></dt>
<dd></dd>
<dt><a name="230">method <b class="cmd">ScmUpdate</b></a></dt>
<dd></dd>
<dt><a name="231">method <b class="cmd">Unpack</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection20" class="doctools_subsection"><h3><a name="subsection20">Class  practcl::distribution.snapshot</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::distribution</b></p>
<p>A file distribution from zip, tarball, or other non-scm archive format</p>
<p><b class="class">Class Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="232">classmethod <b class="cmd">claim_object</b> <i class="arg">object</i></a></dt>
<dd></dd>
<dt><a name="233">classmethod <b class="cmd">claim_option</b></a></dt>
<dd></dd>
<dt><a name="234">classmethod <b class="cmd">claim_path</b> <i class="arg">path</i></a></dt>
<dd></dd>
</dl>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="235">method <b class="cmd">ScmUnpack</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection21" class="doctools_subsection"><h3><a name="subsection21">Class  practcl::distribution.fossil</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::distribution</b></p>
<p>A file distribution based on fossil</p>
<p><b class="class">Class Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="236">classmethod <b class="cmd">claim_object</b> <i class="arg">obj</i></a></dt>
<dd><p>Check for markers in the metadata</p></dd>
<dt><a name="237">classmethod <b class="cmd">claim_option</b></a></dt>
<dd></dd>
<dt><a name="238">classmethod <b class="cmd">claim_path</b> <i class="arg">path</i></a></dt>
<dd><p>Check for markers in the source root</p></dd>
</dl>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="239">method <b class="cmd">scm_info</b></a></dt>
<dd></dd>
<dt><a name="240">method <b class="cmd">ScmClone</b></a></dt>
<dd><p>Clone the source</p></dd>
<dt><a name="241">method <b class="cmd">ScmTag</b></a></dt>
<dd></dd>
<dt><a name="242">method <b class="cmd">ScmUnpack</b></a></dt>
<dd></dd>
<dt><a name="243">method <b class="cmd">ScmUpdate</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection22" class="doctools_subsection"><h3><a name="subsection22">Class  practcl::distribution.git</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::distribution</b></p>
<p>A file distribution based on git</p>
<p><b class="class">Class Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="244">classmethod <b class="cmd">claim_object</b> <i class="arg">obj</i></a></dt>
<dd></dd>
<dt><a name="245">classmethod <b class="cmd">claim_option</b></a></dt>
<dd></dd>
<dt><a name="246">classmethod <b class="cmd">claim_path</b> <i class="arg">path</i></a></dt>
<dd></dd>
</dl>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="247">method <b class="cmd">ScmTag</b></a></dt>
<dd></dd>
<dt><a name="248">method <b class="cmd">ScmUnpack</b></a></dt>
<dd></dd>
<dt><a name="249">method <b class="cmd">ScmUpdate</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection23" class="doctools_subsection"><h3><a name="subsection23">Class  practcl::subproject</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::module</b></p>
<p>A subordinate project</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="250">method <b class="cmd">_MorphPatterns</b></a></dt>
<dd></dd>
<dt><a name="251">method <b class="cmd">BuildDir</b> <i class="arg">PWD</i></a></dt>
<dd></dd>
<dt><a name="252">method <b class="cmd">child</b> <i class="arg">which</i></a></dt>
<dd></dd>
<dt><a name="253">method <b class="cmd">compile</b></a></dt>
<dd></dd>
<dt><a name="254">method <b class="cmd">go</b></a></dt>
<dd></dd>
<dt><a name="255">method <b class="cmd">install</b> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd><p>Install project into the local build system</p></dd>
<dt><a name="256">method <b class="cmd">linktype</b></a></dt>
<dd></dd>
<dt><a name="257">method <b class="cmd">linker-products</b> <i class="arg">configdict</i></a></dt>
<dd></dd>
<dt><a name="258">method <b class="cmd">linker-external</b> <i class="arg">configdict</i></a></dt>
<dd></dd>
<dt><a name="259">method <b class="cmd">linker-extra</b> <i class="arg">configdict</i></a></dt>
<dd></dd>
<dt><a name="260">method <b class="cmd">env-bootstrap</b></a></dt>
<dd><p>Methods for packages/tools that can be downloaded
 possibly built and used internally by this Practcl
 process
 Load the facility into the interpreter</p></dd>
<dt><a name="261">method <b class="cmd">env-exec</b></a></dt>
<dd><p>Return a file path that exec can call</p></dd>
<dt><a name="262">method <b class="cmd">env-install</b></a></dt>
<dd><p>Install the tool into the local environment</p></dd>
<dt><a name="263">method <b class="cmd">env-load</b></a></dt>
<dd><p>Do whatever is necessary to get the tool
 into the local environment</p></dd>
<dt><a name="264">method <b class="cmd">env-present</b></a></dt>
<dd><p>Check if tool is available for load/already loaded</p></dd>
<dt><a name="265">method <b class="cmd">sources</b></a></dt>
<dd></dd>
<dt><a name="266">method <b class="cmd"><a href="../../../../index.html#update">update</a></b></a></dt>
<dd></dd>
<dt><a name="267">method <b class="cmd">unpack</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection24" class="doctools_subsection"><h3><a name="subsection24">Class  practcl::subproject.source</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::subproject</b> <b class="class">practcl::library</b></p>
<p>A project which the kit compiles and integrates
 the source for itself</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="268">method <b class="cmd">env-bootstrap</b></a></dt>
<dd></dd>
<dt><a name="269">method <b class="cmd">env-present</b></a></dt>
<dd></dd>
<dt><a name="270">method <b class="cmd">linktype</b></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection25" class="doctools_subsection"><h3><a name="subsection25">Class  practcl::subproject.teapot</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::subproject</b></p>
<p>a copy from the teapot</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="271">method <b class="cmd">env-bootstrap</b></a></dt>
<dd></dd>
<dt><a name="272">method <b class="cmd">env-install</b></a></dt>
<dd></dd>
<dt><a name="273">method <b class="cmd">env-present</b></a></dt>
<dd></dd>
<dt><a name="274">method <b class="cmd">install</b> <i class="arg">DEST</i></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection26" class="doctools_subsection"><h3><a name="subsection26">Class  practcl::subproject.kettle</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::subproject</b></p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="275">method <b class="cmd">kettle</b> <i class="arg">path</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
<dt><a name="276">method <b class="cmd">install</b> <i class="arg">DEST</i></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection27" class="doctools_subsection"><h3><a name="subsection27">Class  practcl::subproject.critcl</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::subproject</b></p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="277">method <b class="cmd">install</b> <i class="arg">DEST</i></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection28" class="doctools_subsection"><h3><a name="subsection28">Class  practcl::subproject.sak</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::subproject</b></p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="278">method <b class="cmd">env-bootstrap</b></a></dt>
<dd></dd>
<dt><a name="279">method <b class="cmd">env-install</b></a></dt>
<dd></dd>
<dt><a name="280">method <b class="cmd">env-present</b></a></dt>
<dd></dd>
<dt><a name="281">method <b class="cmd">install</b> <i class="arg">DEST</i></a></dt>
<dd></dd>
<dt><a name="282">method <b class="cmd">install-module</b> <i class="arg">DEST</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection29" class="doctools_subsection"><h3><a name="subsection29">Class  practcl::subproject.practcl</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::subproject</b></p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="283">method <b class="cmd">env-bootstrap</b></a></dt>
<dd></dd>
<dt><a name="284">method <b class="cmd">env-install</b></a></dt>
<dd></dd>
<dt><a name="285">method <b class="cmd">install</b> <i class="arg">DEST</i></a></dt>
<dd></dd>
<dt><a name="286">method <b class="cmd">install-module</b> <i class="arg">DEST</i> <span class="opt">?<i class="arg">args</i>?</span></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection30" class="doctools_subsection"><h3><a name="subsection30">Class  practcl::subproject.binary</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::subproject</b></p>
<p>A subordinate binary package</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="287">method <b class="cmd">clean</b></a></dt>
<dd></dd>
<dt><a name="288">method <b class="cmd">env-install</b></a></dt>
<dd></dd>
<dt><a name="289">method <b class="cmd">project-compile-products</b></a></dt>
<dd></dd>
<dt><a name="290">method <b class="cmd">ComputeInstall</b></a></dt>
<dd></dd>
<dt><a name="291">method <b class="cmd">go</b></a></dt>
<dd></dd>
<dt><a name="292">method <b class="cmd">linker-products</b> <i class="arg">configdict</i></a></dt>
<dd></dd>
<dt><a name="293">method <b class="cmd">project-static-packages</b></a></dt>
<dd></dd>
<dt><a name="294">method <b class="cmd">BuildDir</b> <i class="arg">PWD</i></a></dt>
<dd></dd>
<dt><a name="295">method <b class="cmd">compile</b></a></dt>
<dd></dd>
<dt><a name="296">method <b class="cmd">Configure</b></a></dt>
<dd></dd>
<dt><a name="297">method <b class="cmd">install</b> <i class="arg">DEST</i></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection31" class="doctools_subsection"><h3><a name="subsection31">Class  practcl::subproject.tea</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::subproject.binary</b></p>
<p>A subordinate TEA based binary package</p>
</div>
<div id="subsection32" class="doctools_subsection"><h3><a name="subsection32">Class  practcl::subproject.library</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::subproject.binary</b> <b class="class">practcl::library</b></p>
<p>A subordinate C library built by this project</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="298">method <b class="cmd">install</b> <i class="arg">DEST</i></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection33" class="doctools_subsection"><h3><a name="subsection33">Class  practcl::subproject.external</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::subproject.binary</b></p>
<p>A subordinate external C library</p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="299">method <b class="cmd">install</b> <i class="arg">DEST</i></a></dt>
<dd></dd>
</dl>
</div>
<div id="subsection34" class="doctools_subsection"><h3><a name="subsection34">Class  practcl::subproject.core</a></h3>
<p><em>ancestors</em>: <b class="class">practcl::subproject.binary</b></p>
<p><b class="class">Methods</b></p>
<dl class="doctools_definitions">
<dt><a name="300">method <b class="cmd">env-bootstrap</b></a></dt>
<dd></dd>
<dt><a name="301">method <b class="cmd">env-present</b></a></dt>
<dd></dd>
<dt><a name="302">method <b class="cmd">env-install</b></a></dt>
<dd></dd>
<dt><a name="303">method <b class="cmd">go</b></a></dt>
<dd></dd>
<dt><a name="304">method <b class="cmd">linktype</b></a></dt>
<dd></dd>
</dl>
</div>
</div>
<div id="section4" class="doctools_section"><h2><a name="section4">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>practcl</em> of the
<a href="http://core.tcl.tk/tcllib/reportlist">Tcllib Trackers</a>.
Please also report any ideas for enhancements you may have for either
package and/or documentation.</p>
<p>When proposing code changes, please provide <em>unified diffs</em>,

Changes to idoc/www/tcllib/files/modules/profiler/profiler.html.

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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">profiler(n) 0.3 tcllib &quot;Tcl Profiler&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>profiler - Tcl source code profiler</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">COMMANDS</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.3</b></li>
<li>package require <b class="pkgname">profiler <span class="opt">?0.3?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::profiler::init</b></a></li>
<li><a href="#2"><b class="cmd">::profiler::dump</b> <i class="arg">pattern</i></a></li>
<li><a href="#3"><b class="cmd">::profiler::print</b> <span class="opt">?<i class="arg">pattern</i>?</span></a></li>
<li><a href="#4"><b class="cmd">::profiler::reset</b> <span class="opt">?<i class="arg">pattern</i>?</span></a></li>
<li><a href="#5"><b class="cmd">::profiler::suspend</b> <span class="opt">?<i class="arg">pattern</i>?</span></a></li>
<li><a href="#6"><b class="cmd">::profiler::resume</b> <span class="opt">?<i class="arg">pattern</i>?</span></a></li>
<li><a href="#7"><b class="cmd">::profiler::sortFunctions</b> <i class="arg">key</i></a></li>


</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>The <b class="package">profiler</b> package provides a simple Tcl source code
profiler.  It is a function-level profiler; that is, it collects only
function-level information, not the more detailed line-level







|


















|








|
>
>







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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">profiler(n) 0.5 tcllib &quot;Tcl Profiler&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>profiler - Tcl source code profiler</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">COMMANDS</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.3</b></li>
<li>package require <b class="pkgname">profiler <span class="opt">?0.5?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::profiler::init</b></a></li>
<li><a href="#2"><b class="cmd">::profiler::dump</b> <i class="arg">pattern</i></a></li>
<li><a href="#3"><b class="cmd">::profiler::print</b> <span class="opt">?<i class="arg">pattern</i>?</span></a></li>
<li><a href="#4"><b class="cmd">::profiler::reset</b> <span class="opt">?<i class="arg">pattern</i>?</span></a></li>
<li><a href="#5"><b class="cmd">::profiler::suspend</b> <span class="opt">?<i class="arg">pattern</i>?</span></a></li>
<li><a href="#6"><b class="cmd">::profiler::resume</b> <span class="opt">?<i class="arg">pattern</i>?</span></a></li>
<li><a href="#7"><b class="cmd">::profiler::new-disabled</b></a></li>
<li><a href="#8"><b class="cmd">::profiler::new-enabled</b></a></li>
<li><a href="#9"><b class="cmd">::profiler::sortFunctions</b> <i class="arg">key</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>The <b class="package">profiler</b> package provides a simple Tcl source code
profiler.  It is a function-level profiler; that is, it collects only
function-level information, not the more detailed line-level
193
194
195
196
197
198
199










200
201
202
203
204
205
206
207
has been gathered previously.  Use resume command to re-enable
profiling.</p></dd>
<dt><a name="6"><b class="cmd">::profiler::resume</b> <span class="opt">?<i class="arg">pattern</i>?</span></a></dt>
<dd><p>Resume profiling for all functions matching <i class="arg">pattern</i>.  If no
pattern is specified, profiling will be resumed for all functions.
This command should be invoked after suspending the profiler in the
code.</p></dd>










<dt><a name="7"><b class="cmd">::profiler::sortFunctions</b> <i class="arg">key</i></a></dt>
<dd><p>Return a list of functions sorted by a particular profiling statistic.
Supported values for <i class="arg">key</i> are: <b class="const">calls</b>,
<b class="const">exclusiveTime</b>, <b class="const">compileTime</b>, <b class="const">nonCompileTime</b>,
<b class="const">totalRuntime</b>, <b class="const">avgExclusiveTime</b>, and
<b class="const">avgRuntime</b>.  The return result is a list of lists, where each
sublist consists of a function name and the value of <i class="arg">key</i> for
that function.</p></dd>







>
>
>
>
>
>
>
>
>
>
|







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
has been gathered previously.  Use resume command to re-enable
profiling.</p></dd>
<dt><a name="6"><b class="cmd">::profiler::resume</b> <span class="opt">?<i class="arg">pattern</i>?</span></a></dt>
<dd><p>Resume profiling for all functions matching <i class="arg">pattern</i>.  If no
pattern is specified, profiling will be resumed for all functions.
This command should be invoked after suspending the profiler in the
code.</p></dd>
<dt><a name="7"><b class="cmd">::profiler::new-disabled</b></a></dt>
<dd><p>Change the initial profiling state for new procedures. Invoking this
command disables profiling for all procedures created after this
command until <b class="cmd">new-enabled</b> is invoked. Activate profiling of
specific procedures via <b class="cmd">resume</b>.</p></dd>
<dt><a name="8"><b class="cmd">::profiler::new-enabled</b></a></dt>
<dd><p>Change the initial profiling state for new procedures. Invoking this
command enables profiling for all procedures created after this
command until <b class="cmd">new-disabled</b> is invoked. Prevent profiling of
specific procedures via <b class="cmd">suspend</b>.</p></dd>
<dt><a name="9"><b class="cmd">::profiler::sortFunctions</b> <i class="arg">key</i></a></dt>
<dd><p>Return a list of functions sorted by a particular profiling statistic.
Supported values for <i class="arg">key</i> are: <b class="const">calls</b>,
<b class="const">exclusiveTime</b>, <b class="const">compileTime</b>, <b class="const">nonCompileTime</b>,
<b class="const">totalRuntime</b>, <b class="const">avgExclusiveTime</b>, and
<b class="const">avgRuntime</b>.  The return result is a list of lists, where each
sublist consists of a function name and the value of <i class="arg">key</i> for
that function.</p></dd>

Changes to idoc/www/tcllib/files/modules/pt/pt_peg_export.html.

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">pt::peg::export(n) 1 tcllib &quot;Parser Tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>pt::peg::export - PEG Export</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>







|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">pt::peg::export(n) 1.0.1 tcllib &quot;Parser Tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>pt::peg::export - PEG Export</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">snit</b></li>
<li>package require <b class="pkgname">configuration</b></li>
<li>package require <b class="pkgname">pt::peg</b></li>
<li>package require <b class="pkgname">pluginmgr</b></li>
<li>package require <b class="pkgname">pt::peg::export <span class="opt">?1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::pt::peg::export</b> <i class="arg">objectName</i></a></li>
<li><a href="#2"><b class="cmd">objectName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
<li><a href="#3"><i class="arg">objectName</i> <b class="method">destroy</b></a></li>
<li><a href="#4"><i class="arg">objectName</i> <b class="method">export serial</b> <i class="arg">serial</i> <span class="opt">?<i class="arg">format</i>?</span></a></li>
<li><a href="#5"><i class="arg">objectName</i> <b class="method">export object</b> <i class="arg">object</i> <span class="opt">?<i class="arg">format</i>?</span></a></li>







|


|







140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">snit</b></li>
<li>package require <b class="pkgname">struct::map</b></li>
<li>package require <b class="pkgname">pt::peg</b></li>
<li>package require <b class="pkgname">pluginmgr</b></li>
<li>package require <b class="pkgname">pt::peg::export <span class="opt">?1.0.1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::pt::peg::export</b> <i class="arg">objectName</i></a></li>
<li><a href="#2"><b class="cmd">objectName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
<li><a href="#3"><i class="arg">objectName</i> <b class="method">destroy</b></a></li>
<li><a href="#4"><i class="arg">objectName</i> <b class="method">export serial</b> <i class="arg">serial</i> <span class="opt">?<i class="arg">format</i>?</span></a></li>
<li><a href="#5"><i class="arg">objectName</i> <b class="method">export object</b> <i class="arg">object</i> <span class="opt">?<i class="arg">format</i>?</span></a></li>

Changes to idoc/www/tcllib/files/modules/pt/pt_peg_import.html.

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">pt::peg::import(n) 1 tcllib &quot;Parser Tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>pt::peg::import - PEG Import</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>







|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">pt::peg::import(n) 1.0.1 tcllib &quot;Parser Tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>pt::peg::import - PEG Import</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
139
140
141
142
143
144
145

146
147
148
149
150
151
152
153
154
155
156
157
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>

<li>package require <b class="pkgname">snit</b></li>
<li>package require <b class="pkgname">configuration</b></li>
<li>package require <b class="pkgname">pt::peg</b></li>
<li>package require <b class="pkgname">pluginmgr</b></li>
<li>package require <b class="pkgname">pt::peg::import <span class="opt">?1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::pt::peg::import</b> <i class="arg">objectName</i></a></li>
<li><a href="#2"><b class="cmd">objectName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
<li><a href="#3"><i class="arg">objectName</i> <b class="method">destroy</b></a></li>
<li><a href="#4"><i class="arg">objectName</i> <b class="method">import text</b> <i class="arg">text</i> <span class="opt">?<i class="arg">format</i>?</span></a></li>
<li><a href="#5"><i class="arg">objectName</i> <b class="method">import file</b> <i class="arg">path</i> <span class="opt">?<i class="arg">format</i>?</span></a></li>







>

|


|







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">snit</b></li>
<li>package require <b class="pkgname">fileutil::paths</b></li>
<li>package require <b class="pkgname">pt::peg</b></li>
<li>package require <b class="pkgname">pluginmgr</b></li>
<li>package require <b class="pkgname">pt::peg::import <span class="opt">?1.0.1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::pt::peg::import</b> <i class="arg">objectName</i></a></li>
<li><a href="#2"><b class="cmd">objectName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
<li><a href="#3"><i class="arg">objectName</i> <b class="method">destroy</b></a></li>
<li><a href="#4"><i class="arg">objectName</i> <b class="method">import text</b> <i class="arg">text</i> <span class="opt">?<i class="arg">format</i>?</span></a></li>
<li><a href="#5"><i class="arg">objectName</i> <b class="method">import file</b> <i class="arg">path</i> <span class="opt">?<i class="arg">format</i>?</span></a></li>

Changes to idoc/www/tcllib/files/modules/pt/pt_peg_to_tclparam.html.

280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
containing a canned configuration which will generate immediately
useful full parsers. These are</p>
<dl class="doctools_definitions">
<dt><b class="package"><a href="pt_tclparam_config_snit.html">pt::tclparam::configuration::snit</a></b></dt>
<dd><p>Generated parsers are classes based on the <b class="package"><a href="../snit/snit.html">snit</a></b> package,
i.e. snit::type's.</p></dd>
<dt><b class="package"><a href="pt_tclparam_config_tcloo.html">pt::tclparam::configuration::tcloo</a></b></dt>
<dd><p>Generated parsers are classes based on the <b class="package">OO</b> package.</p></dd>
</dl>
</div>
<div id="section4" class="doctools_section"><h2><a name="section4">Tcl/PARAM code representation of parsing expression grammars</a></h2>
<p>The Tcl/PARAM representation of parsing expression grammars is Tcl
code whose execution will parse input per the grammar. The code is
based on the virtual machine documented in the
<i class="term"><a href="pt_param.html">PackRat Machine Specification</a></i>, using its instructions







|







280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
containing a canned configuration which will generate immediately
useful full parsers. These are</p>
<dl class="doctools_definitions">
<dt><b class="package"><a href="pt_tclparam_config_snit.html">pt::tclparam::configuration::snit</a></b></dt>
<dd><p>Generated parsers are classes based on the <b class="package"><a href="../snit/snit.html">snit</a></b> package,
i.e. snit::type's.</p></dd>
<dt><b class="package"><a href="pt_tclparam_config_tcloo.html">pt::tclparam::configuration::tcloo</a></b></dt>
<dd><p>Generated parsers are classes based on the <b class="package"><a href="../../../../index.html#oo">OO</a></b> package.</p></dd>
</dl>
</div>
<div id="section4" class="doctools_section"><h2><a name="section4">Tcl/PARAM code representation of parsing expression grammars</a></h2>
<p>The Tcl/PARAM representation of parsing expression grammars is Tcl
code whose execution will parse input per the grammar. The code is
based on the virtual machine documented in the
<i class="term"><a href="pt_param.html">PackRat Machine Specification</a></i>, using its instructions

Changes to idoc/www/tcllib/files/modules/pt/pt_tclparam_config_tcloo.html.

140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
In that case please read the overview provided by the
<i class="term"><a href="pt_introduction.html">Introduction to Parser Tools</a></i>. This document is the
entrypoint to the whole system the current package is a part of.</p>
<p>This package is an adjunct to <b class="package"><a href="pt_peg_to_tclparam.html">pt::peg::to::tclparam</a></b>, to make
the use of this highly configurable package easier by providing a
canned configuration. When applied this configuration causes the
package <b class="package"><a href="pt_peg_to_tclparam.html">pt::peg::to::tclparam</a></b> to generate
<b class="package">OO</b>-based parser packages.</p>
<p>It is a supporting package in the Core Layer of Parser Tools.</p>
<p><img alt="arch_core_support" src="../../../../image/arch_core_support.png"></p>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">API</a></h2>
<dl class="doctools_definitions">
<dt><a name="1"><b class="cmd">::pt::tclparam::configuration::tcloo</b> <b class="method">def</b> <i class="arg">name</i> <i class="arg">pkg</i> <i class="arg">version</i> <i class="arg">cmdprefix</i></a></dt>
<dd><p>The command applies the configuration provided by this package to the
<i class="arg">cmdprefix</i>, causing the creation of <b class="package">OO</b>-based parsers
whose class is <i class="arg">name</i>, in package <i class="arg">pkg</i> with <i class="arg">version</i>.</p>
<p>The use of a command prefix as API allows application of the
configuration to not only <b class="package"><a href="pt_peg_to_tclparam.html">pt::peg::to::tclparam</a></b>
(<b class="cmd">pt::peg::to::tclparam configure</b>), but also export manager
instances and PEG containers (<b class="cmd">$export configuration set</b> and
<b class="cmd">[$container exporter] configuration set</b> respectively).</p>
<p>Or anything other command prefix accepting two arguments, option and







|







|







140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
In that case please read the overview provided by the
<i class="term"><a href="pt_introduction.html">Introduction to Parser Tools</a></i>. This document is the
entrypoint to the whole system the current package is a part of.</p>
<p>This package is an adjunct to <b class="package"><a href="pt_peg_to_tclparam.html">pt::peg::to::tclparam</a></b>, to make
the use of this highly configurable package easier by providing a
canned configuration. When applied this configuration causes the
package <b class="package"><a href="pt_peg_to_tclparam.html">pt::peg::to::tclparam</a></b> to generate
<b class="package"><a href="../../../../index.html#oo">OO</a></b>-based parser packages.</p>
<p>It is a supporting package in the Core Layer of Parser Tools.</p>
<p><img alt="arch_core_support" src="../../../../image/arch_core_support.png"></p>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">API</a></h2>
<dl class="doctools_definitions">
<dt><a name="1"><b class="cmd">::pt::tclparam::configuration::tcloo</b> <b class="method">def</b> <i class="arg">name</i> <i class="arg">pkg</i> <i class="arg">version</i> <i class="arg">cmdprefix</i></a></dt>
<dd><p>The command applies the configuration provided by this package to the
<i class="arg">cmdprefix</i>, causing the creation of <b class="package"><a href="../../../../index.html#oo">OO</a></b>-based parsers
whose class is <i class="arg">name</i>, in package <i class="arg">pkg</i> with <i class="arg">version</i>.</p>
<p>The use of a command prefix as API allows application of the
configuration to not only <b class="package"><a href="pt_peg_to_tclparam.html">pt::peg::to::tclparam</a></b>
(<b class="cmd">pt::peg::to::tclparam configure</b>), but also export manager
instances and PEG containers (<b class="cmd">$export configuration set</b> and
<b class="cmd">[$container exporter] configuration set</b> respectively).</p>
<p>Or anything other command prefix accepting two arguments, option and

Changes to idoc/www/tcllib/files/modules/sha1/sha1.html.

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">sha1(n) 2.0.3 tcllib &quot;SHA-x Message-Digest Algorithm&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>sha1 - SHA1 Message-Digest Algorithm</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>







|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">sha1(n) 2.0.4 tcllib &quot;SHA-x Message-Digest Algorithm&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>sha1 - SHA1 Message-Digest Algorithm</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">sha1 <span class="opt">?2.0.3?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::sha1::sha1</b> <span class="opt">?<b class="option">-hex|-bin</b>?</span> [ <b class="option">-channel channel</b> | <b class="option">-file filename</b> | <span class="opt">?<b class="option">--</b>?</span> <i class="arg">string</i> ]</a></li>
<li><a href="#2"><b class="cmd">::sha1::hmac</b> <i class="arg">key</i> <i class="arg">string</i></a></li>
<li><a href="#3"><b class="cmd">::sha1::hmac</b> <span class="opt">?<b class="option">-hex|-bin</b>?</span> <b class="option">-key key</b> [ <b class="option">-channel channel</b> | <b class="option">-file filename</b> | <span class="opt">?<b class="option">--</b>?</span> <i class="arg">string</i> ]</a></li>
<li><a href="#4"><b class="cmd">::sha1::SHA1Init</b></a></li>
<li><a href="#5"><b class="cmd">::sha1::SHA1Update</b> <i class="arg">token</i> <i class="arg">data</i></a></li>







|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">sha1 <span class="opt">?2.0.4?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::sha1::sha1</b> <span class="opt">?<b class="option">-hex|-bin</b>?</span> [ <b class="option">-channel channel</b> | <b class="option">-file filename</b> | <span class="opt">?<b class="option">--</b>?</span> <i class="arg">string</i> ]</a></li>
<li><a href="#2"><b class="cmd">::sha1::hmac</b> <i class="arg">key</i> <i class="arg">string</i></a></li>
<li><a href="#3"><b class="cmd">::sha1::hmac</b> <span class="opt">?<b class="option">-hex|-bin</b>?</span> <b class="option">-key key</b> [ <b class="option">-channel channel</b> | <b class="option">-file filename</b> | <span class="opt">?<b class="option">--</b>?</span> <i class="arg">string</i> ]</a></li>
<li><a href="#4"><b class="cmd">::sha1::SHA1Init</b></a></li>
<li><a href="#5"><b class="cmd">::sha1::SHA1Update</b> <i class="arg">token</i> <i class="arg">data</i></a></li>

Changes to idoc/www/tcllib/files/modules/sha1/sha256.html.

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">sha256(n) 1.0.3 tcllib &quot;SHA-x Message-Digest Algorithm&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>sha256 - SHA256 Message-Digest Algorithm</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>







|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">sha256(n) 1.0.4 tcllib &quot;SHA-x Message-Digest Algorithm&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>sha256 - SHA256 Message-Digest Algorithm</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">sha256 <span class="opt">?1.0.3?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::sha2::sha256</b> <span class="opt">?<b class="option">-hex|-bin</b>?</span> [ <b class="option">-channel channel</b> | <b class="option">-file filename</b> | <span class="opt">?<b class="option">--</b>?</span> <i class="arg">string</i> ]</a></li>
<li><a href="#2"><b class="cmd">::sha2::sha224</b> <span class="opt">?<b class="option">-hex|-bin</b>?</span> [ <b class="option">-channel channel</b> | <b class="option">-file filename</b> | <span class="opt">?<b class="option">--</b>?</span> <i class="arg">string</i> ]</a></li>
<li><a href="#3"><b class="cmd">::sha2::hmac</b> <i class="arg">key</i> <i class="arg">string</i></a></li>
<li><a href="#4"><b class="cmd">::sha2::hmac</b> <span class="opt">?<b class="option">-hex|-bin</b>?</span> <b class="option">-key key</b> [ <b class="option">-channel channel</b> | <b class="option">-file filename</b> | <span class="opt">?<b class="option">--</b>?</span> <i class="arg">string</i> ]</a></li>
<li><a href="#5"><b class="cmd">::sha2::SHA256Init</b></a></li>







|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">sha256 <span class="opt">?1.0.4?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::sha2::sha256</b> <span class="opt">?<b class="option">-hex|-bin</b>?</span> [ <b class="option">-channel channel</b> | <b class="option">-file filename</b> | <span class="opt">?<b class="option">--</b>?</span> <i class="arg">string</i> ]</a></li>
<li><a href="#2"><b class="cmd">::sha2::sha224</b> <span class="opt">?<b class="option">-hex|-bin</b>?</span> [ <b class="option">-channel channel</b> | <b class="option">-file filename</b> | <span class="opt">?<b class="option">--</b>?</span> <i class="arg">string</i> ]</a></li>
<li><a href="#3"><b class="cmd">::sha2::hmac</b> <i class="arg">key</i> <i class="arg">string</i></a></li>
<li><a href="#4"><b class="cmd">::sha2::hmac</b> <span class="opt">?<b class="option">-hex|-bin</b>?</span> <b class="option">-key key</b> [ <b class="option">-channel channel</b> | <b class="option">-file filename</b> | <span class="opt">?<b class="option">--</b>?</span> <i class="arg">string</i> ]</a></li>
<li><a href="#5"><b class="cmd">::sha2::SHA256Init</b></a></li>

Changes to idoc/www/tcllib/files/modules/simulation/simulation_random.html.

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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">simulation::random(n) 0.1 tcllib &quot;Tcl Simulation Tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>simulation::random - Pseudo-random number generators</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">PROCEDURES</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl <span class="opt">?8.4?</span></b></li>
<li>package require <b class="pkgname">simulation::random 0.1</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::simulation::random::prng_Bernoulli</b> <i class="arg">p</i></a></li>
<li><a href="#2"><b class="cmd">::simulation::random::prng_Discrete</b> <i class="arg">n</i></a></li>
<li><a href="#3"><b class="cmd">::simulation::random::prng_Poisson</b> <i class="arg">lambda</i></a></li>
<li><a href="#4"><b class="cmd">::simulation::random::prng_Uniform</b> <i class="arg">min</i> <i class="arg">max</i></a></li>


<li><a href="#5"><b class="cmd">::simulation::random::prng_Exponential</b> <i class="arg">min</i> <i class="arg">mean</i></a></li>
<li><a href="#6"><b class="cmd">::simulation::random::prng_Normal</b> <i class="arg">mean</i> <i class="arg">stdev</i></a></li>
<li><a href="#7"><b class="cmd">::simulation::random::prng_Pareto</b> <i class="arg">min</i> <i class="arg">steep</i></a></li>
<li><a href="#8"><b class="cmd">::simulation::random::prng_Gumbel</b> <i class="arg">min</i> <i class="arg">f</i></a></li>
<li><a href="#9"><b class="cmd">::simulation::random::prng_chiSquared</b> <i class="arg">df</i></a></li>
<li><a href="#10"><b class="cmd">::simulation::random::prng_Disk</b> <i class="arg">rad</i></a></li>
<li><a href="#11"><b class="cmd">::simulation::random::prng_Sphere</b> <i class="arg">rad</i></a></li>
<li><a href="#12"><b class="cmd">::simulation::random::prng_Ball</b> <i class="arg">rad</i></a></li>
<li><a href="#13"><b class="cmd">::simulation::random::prng_Rectangle</b> <i class="arg">length</i> <i class="arg">width</i></a></li>
<li><a href="#14"><b class="cmd">::simulation::random::prng_Block</b> <i class="arg">length</i> <i class="arg">width</i> <i class="arg">depth</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>This package consists of commands to generate pseudo-random number
generators. These new commands deliver</p>
<ul class="doctools_itemized">







|


















|






>
>
|
|
|
|
|
|
|
|
|
|







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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">simulation::random(n) 0.4 tcllib &quot;Tcl Simulation Tools&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>simulation::random - Pseudo-random number generators</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">PROCEDURES</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl <span class="opt">?8.4?</span></b></li>
<li>package require <b class="pkgname">simulation::random 0.4</b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::simulation::random::prng_Bernoulli</b> <i class="arg">p</i></a></li>
<li><a href="#2"><b class="cmd">::simulation::random::prng_Discrete</b> <i class="arg">n</i></a></li>
<li><a href="#3"><b class="cmd">::simulation::random::prng_Poisson</b> <i class="arg">lambda</i></a></li>
<li><a href="#4"><b class="cmd">::simulation::random::prng_Uniform</b> <i class="arg">min</i> <i class="arg">max</i></a></li>
<li><a href="#5"><b class="cmd">::simulation::random::prng_Triangular</b> <i class="arg">min</i> <i class="arg">max</i></a></li>
<li><a href="#6"><b class="cmd">::simulation::random::prng_SymmTriangular</b> <i class="arg">min</i> <i class="arg">max</i></a></li>
<li><a href="#7"><b class="cmd">::simulation::random::prng_Exponential</b> <i class="arg">min</i> <i class="arg">mean</i></a></li>
<li><a href="#8"><b class="cmd">::simulation::random::prng_Normal</b> <i class="arg">mean</i> <i class="arg">stdev</i></a></li>
<li><a href="#9"><b class="cmd">::simulation::random::prng_Pareto</b> <i class="arg">min</i> <i class="arg">steep</i></a></li>
<li><a href="#10"><b class="cmd">::simulation::random::prng_Gumbel</b> <i class="arg">min</i> <i class="arg">f</i></a></li>
<li><a href="#11"><b class="cmd">::simulation::random::prng_chiSquared</b> <i class="arg">df</i></a></li>
<li><a href="#12"><b class="cmd">::simulation::random::prng_Disk</b> <i class="arg">rad</i></a></li>
<li><a href="#13"><b class="cmd">::simulation::random::prng_Sphere</b> <i class="arg">rad</i></a></li>
<li><a href="#14"><b class="cmd">::simulation::random::prng_Ball</b> <i class="arg">rad</i></a></li>
<li><a href="#15"><b class="cmd">::simulation::random::prng_Rectangle</b> <i class="arg">length</i> <i class="arg">width</i></a></li>
<li><a href="#16"><b class="cmd">::simulation::random::prng_Block</b> <i class="arg">length</i> <i class="arg">width</i> <i class="arg">depth</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>This package consists of commands to generate pseudo-random number
generators. These new commands deliver</p>
<ul class="doctools_itemized">
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
between &quot;min&quot; and &quot;max&quot;.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">min</i></dt>
<dd><p>Minimum number that will be generated</p></dd>
<dt>float <i class="arg">max</i></dt>
<dd><p>Maximum number that will be generated</p></dd>
</dl></dd>




















<dt><a name="5"><b class="cmd">::simulation::random::prng_Exponential</b> <i class="arg">min</i> <i class="arg">mean</i></a></dt>
<dd><p>Create a command (PRNG) that generates exponentially distributed numbers
with a given minimum value and a given mean value.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">min</i></dt>
<dd><p>Minimum number that will be generated</p></dd>
<dt>float <i class="arg">mean</i></dt>
<dd><p>Mean value for the numbers</p></dd>
</dl></dd>
<dt><a name="6"><b class="cmd">::simulation::random::prng_Normal</b> <i class="arg">mean</i> <i class="arg">stdev</i></a></dt>
<dd><p>Create a command (PRNG) that generates normally distributed numbers
with a given mean value and a given standard deviation.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>Mean value for the numbers</p></dd>
<dt>float <i class="arg">stdev</i></dt>
<dd><p>Standard deviation</p></dd>
</dl></dd>
<dt><a name="7"><b class="cmd">::simulation::random::prng_Pareto</b> <i class="arg">min</i> <i class="arg">steep</i></a></dt>
<dd><p>Create a command (PRNG) that generates numbers distributed according to
Pareto with a given minimum value and a given distribution steepness.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">min</i></dt>
<dd><p>Minimum number that will be generated</p></dd>
<dt>float <i class="arg">steep</i></dt>
<dd><p>Steepness of the distribution</p></dd>
</dl></dd>
<dt><a name="8"><b class="cmd">::simulation::random::prng_Gumbel</b> <i class="arg">min</i> <i class="arg">f</i></a></dt>
<dd><p>Create a command (PRNG) that generates numbers distributed according to
Gumbel with a given minimum value and a given scale factor. The
probability density function is:</p>
<pre class="doctools_example">
     P(v) = exp( -exp(f*(v-min)))
</pre>
<dl class="doctools_arguments">
<dt>float <i class="arg">min</i></dt>
<dd><p>Minimum number that will be generated</p></dd>
<dt>float <i class="arg">f</i></dt>
<dd><p>Scale factor for the values</p></dd>
</dl></dd>
<dt><a name="9"><b class="cmd">::simulation::random::prng_chiSquared</b> <i class="arg">df</i></a></dt>
<dd><p>Create a command (PRNG) that generates numbers distributed according to
the chi-squared distribution with df degrees of freedom. The mean is 0
and the standard deviation is 1.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">df</i></dt>
<dd><p>Degrees of freedom</p></dd>
</dl></dd>
</dl>
<p>The package defines the following public procedures for random point sets:</p>
<dl class="doctools_definitions">
<dt><a name="10"><b class="cmd">::simulation::random::prng_Disk</b> <i class="arg">rad</i></a></dt>
<dd><p>Create a command (PRNG) that generates (x,y)-coordinates for points
uniformly spread over a disk of given radius.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">rad</i></dt>
<dd><p>Radius of the disk</p></dd>
</dl></dd>
<dt><a name="11"><b class="cmd">::simulation::random::prng_Sphere</b> <i class="arg">rad</i></a></dt>
<dd><p>Create a command (PRNG) that generates (x,y,z)-coordinates for points
uniformly spread over the surface of a sphere of given radius.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">rad</i></dt>
<dd><p>Radius of the disk</p></dd>
</dl></dd>
<dt><a name="12"><b class="cmd">::simulation::random::prng_Ball</b> <i class="arg">rad</i></a></dt>
<dd><p>Create a command (PRNG) that generates (x,y,z)-coordinates for points
uniformly spread within a ball of given radius.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">rad</i></dt>
<dd><p>Radius of the ball</p></dd>
</dl></dd>
<dt><a name="13"><b class="cmd">::simulation::random::prng_Rectangle</b> <i class="arg">length</i> <i class="arg">width</i></a></dt>
<dd><p>Create a command (PRNG) that generates (x,y)-coordinates for points
uniformly spread over a rectangle.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">length</i></dt>
<dd><p>Length of the rectangle (x-direction)</p></dd>
<dt>float <i class="arg">width</i></dt>
<dd><p>Width of the rectangle (y-direction)</p></dd>
</dl></dd>
<dt><a name="14"><b class="cmd">::simulation::random::prng_Block</b> <i class="arg">length</i> <i class="arg">width</i> <i class="arg">depth</i></a></dt>
<dd><p>Create a command (PRNG) that generates (x,y,z)-coordinates for points
uniformly spread over a block</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">length</i></dt>
<dd><p>Length of the block (x-direction)</p></dd>
<dt>float <i class="arg">width</i></dt>
<dd><p>Width of the block (y-direction)</p></dd>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|








|








|








|












|










|






|






|






|








|







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
between &quot;min&quot; and &quot;max&quot;.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">min</i></dt>
<dd><p>Minimum number that will be generated</p></dd>
<dt>float <i class="arg">max</i></dt>
<dd><p>Maximum number that will be generated</p></dd>
</dl></dd>
<dt><a name="5"><b class="cmd">::simulation::random::prng_Triangular</b> <i class="arg">min</i> <i class="arg">max</i></a></dt>
<dd><p>Create a command (PRNG) that generates triangularly distributed numbers
between &quot;min&quot; and &quot;max&quot;. If the argument min is lower than the argument max, then smaller
values have higher probability and vice versa. In the first case the probability
density function is of the form <em>f(x) = 2(1-x)</em> and the other case it is of the form <em>f(x) = 2x</em>.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">min</i></dt>
<dd><p>Minimum number that will be generated</p></dd>
<dt>float <i class="arg">max</i></dt>
<dd><p>Maximum number that will be generated</p></dd>
</dl></dd>
<dt><a name="6"><b class="cmd">::simulation::random::prng_SymmTriangular</b> <i class="arg">min</i> <i class="arg">max</i></a></dt>
<dd><p>Create a command (PRNG) that generates numbers distributed according to a symmetric triangle
around the mean of &quot;min&quot; and &quot;max&quot;.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">min</i></dt>
<dd><p>Minimum number that will be generated</p></dd>
<dt>float <i class="arg">max</i></dt>
<dd><p>Maximum number that will be generated</p></dd>
</dl></dd>
<dt><a name="7"><b class="cmd">::simulation::random::prng_Exponential</b> <i class="arg">min</i> <i class="arg">mean</i></a></dt>
<dd><p>Create a command (PRNG) that generates exponentially distributed numbers
with a given minimum value and a given mean value.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">min</i></dt>
<dd><p>Minimum number that will be generated</p></dd>
<dt>float <i class="arg">mean</i></dt>
<dd><p>Mean value for the numbers</p></dd>
</dl></dd>
<dt><a name="8"><b class="cmd">::simulation::random::prng_Normal</b> <i class="arg">mean</i> <i class="arg">stdev</i></a></dt>
<dd><p>Create a command (PRNG) that generates normally distributed numbers
with a given mean value and a given standard deviation.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">mean</i></dt>
<dd><p>Mean value for the numbers</p></dd>
<dt>float <i class="arg">stdev</i></dt>
<dd><p>Standard deviation</p></dd>
</dl></dd>
<dt><a name="9"><b class="cmd">::simulation::random::prng_Pareto</b> <i class="arg">min</i> <i class="arg">steep</i></a></dt>
<dd><p>Create a command (PRNG) that generates numbers distributed according to
Pareto with a given minimum value and a given distribution steepness.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">min</i></dt>
<dd><p>Minimum number that will be generated</p></dd>
<dt>float <i class="arg">steep</i></dt>
<dd><p>Steepness of the distribution</p></dd>
</dl></dd>
<dt><a name="10"><b class="cmd">::simulation::random::prng_Gumbel</b> <i class="arg">min</i> <i class="arg">f</i></a></dt>
<dd><p>Create a command (PRNG) that generates numbers distributed according to
Gumbel with a given minimum value and a given scale factor. The
probability density function is:</p>
<pre class="doctools_example">
     P(v) = exp( -exp(f*(v-min)))
</pre>
<dl class="doctools_arguments">
<dt>float <i class="arg">min</i></dt>
<dd><p>Minimum number that will be generated</p></dd>
<dt>float <i class="arg">f</i></dt>
<dd><p>Scale factor for the values</p></dd>
</dl></dd>
<dt><a name="11"><b class="cmd">::simulation::random::prng_chiSquared</b> <i class="arg">df</i></a></dt>
<dd><p>Create a command (PRNG) that generates numbers distributed according to
the chi-squared distribution with df degrees of freedom. The mean is 0
and the standard deviation is 1.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">df</i></dt>
<dd><p>Degrees of freedom</p></dd>
</dl></dd>
</dl>
<p>The package defines the following public procedures for random point sets:</p>
<dl class="doctools_definitions">
<dt><a name="12"><b class="cmd">::simulation::random::prng_Disk</b> <i class="arg">rad</i></a></dt>
<dd><p>Create a command (PRNG) that generates (x,y)-coordinates for points
uniformly spread over a disk of given radius.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">rad</i></dt>
<dd><p>Radius of the disk</p></dd>
</dl></dd>
<dt><a name="13"><b class="cmd">::simulation::random::prng_Sphere</b> <i class="arg">rad</i></a></dt>
<dd><p>Create a command (PRNG) that generates (x,y,z)-coordinates for points
uniformly spread over the surface of a sphere of given radius.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">rad</i></dt>
<dd><p>Radius of the disk</p></dd>
</dl></dd>
<dt><a name="14"><b class="cmd">::simulation::random::prng_Ball</b> <i class="arg">rad</i></a></dt>
<dd><p>Create a command (PRNG) that generates (x,y,z)-coordinates for points
uniformly spread within a ball of given radius.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">rad</i></dt>
<dd><p>Radius of the ball</p></dd>
</dl></dd>
<dt><a name="15"><b class="cmd">::simulation::random::prng_Rectangle</b> <i class="arg">length</i> <i class="arg">width</i></a></dt>
<dd><p>Create a command (PRNG) that generates (x,y)-coordinates for points
uniformly spread over a rectangle.</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">length</i></dt>
<dd><p>Length of the rectangle (x-direction)</p></dd>
<dt>float <i class="arg">width</i></dt>
<dd><p>Width of the rectangle (y-direction)</p></dd>
</dl></dd>
<dt><a name="16"><b class="cmd">::simulation::random::prng_Block</b> <i class="arg">length</i> <i class="arg">width</i> <i class="arg">depth</i></a></dt>
<dd><p>Create a command (PRNG) that generates (x,y,z)-coordinates for points
uniformly spread over a block</p>
<dl class="doctools_arguments">
<dt>float <i class="arg">length</i></dt>
<dd><p>Length of the block (x-direction)</p></dd>
<dt>float <i class="arg">width</i></dt>
<dd><p>Width of the block (y-direction)</p></dd>

Changes to idoc/www/tcllib/files/modules/struct/graph.html.

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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'graph.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2002-2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- struct::graph.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">struct::graph(n) 2.4.1 tcllib &quot;Tcl Data Structures&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>struct::graph - Create and manipulate directed graph objects</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Changes for 2.0</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">struct::graph <span class="opt">?2.4.1?</span></b></li>
<li>package require <b class="pkgname">struct::list <span class="opt">?1.5?</span></b></li>
<li>package require <b class="pkgname">struct::set <span class="opt">?2.2.3?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::struct::graph</b> <span class="opt">?<i class="arg">graphName</i>?</span> <span class="opt">?<b class="const">=</b>|<b class="const">:=</b>|<b class="const">as</b>|<b class="const">deserialize</b> <i class="arg">source</i>?</span></a></li>
<li><a href="#2"><b class="cmd">graphName</b> <i class="arg">option</i> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
<li><a href="#3"><i class="arg">graphName</i> <b class="method">=</b> <i class="arg">sourcegraph</i></a></li>







|













|



















|







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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'graph.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2002-2009,2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- struct::graph.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">struct::graph(n) 2.4.3 tcllib &quot;Tcl Data Structures&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>struct::graph - Create and manipulate directed graph objects</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Changes for 2.0</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.4</b></li>
<li>package require <b class="pkgname">struct::graph <span class="opt">?2.4.3?</span></b></li>
<li>package require <b class="pkgname">struct::list <span class="opt">?1.5?</span></b></li>
<li>package require <b class="pkgname">struct::set <span class="opt">?2.2.3?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::struct::graph</b> <span class="opt">?<i class="arg">graphName</i>?</span> <span class="opt">?<b class="const">=</b>|<b class="const">:=</b>|<b class="const">as</b>|<b class="const">deserialize</b> <i class="arg">source</i>?</span></a></li>
<li><a href="#2"><b class="cmd">graphName</b> <i class="arg">option</i> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
<li><a href="#3"><i class="arg">graphName</i> <b class="method">=</b> <i class="arg">sourcegraph</i></a></li>
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
list containing all arcs is returned. Restrictions can limit the list
of returned arcs based on the nodes that are connected by the arc, on
the keyed values associated with the arc, or both. A general filter
command can be used as well. The restrictions that involve connected
nodes take a variable number of nodes as argument, specified after the
name of the restriction itself.</p>
<p>The restrictions imposed by either <b class="option">-in</b>, <b class="option">-out</b>,
<b class="option">-adj</b>, <b class="option">-inner</b>, or <b class="option">-embedded</b> are applied
first. Specifying more than one of them is illegal.</p>
<p>After that the restrictions set via <b class="option">-key</b> (and
<b class="option">-value</b>) are applied. Specifying more than one <b class="option">-key</b>
(and <b class="option">-value</b>) is illegal. Specifying <b class="option">-value</b> alone,
without <b class="option">-key</b> is illegal as well.</p>
<p>Any restriction set through <b class="option">-filter</b> is applied
last. Specifying more than one <b class="option">-filter</b> is illegal.</p>







|







427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
list containing all arcs is returned. Restrictions can limit the list
of returned arcs based on the nodes that are connected by the arc, on
the keyed values associated with the arc, or both. A general filter
command can be used as well. The restrictions that involve connected
nodes take a variable number of nodes as argument, specified after the
name of the restriction itself.</p>
<p>The restrictions imposed by either <b class="option">-in</b>, <b class="option">-out</b>,
<b class="option">-adj</b>, <b class="option">-inner</b>, or <b class="option">-embedding</b> are applied
first. Specifying more than one of them is illegal.</p>
<p>After that the restrictions set via <b class="option">-key</b> (and
<b class="option">-value</b>) are applied. Specifying more than one <b class="option">-key</b>
(and <b class="option">-value</b>) is illegal. Specifying <b class="option">-value</b> alone,
without <b class="option">-key</b> is illegal as well.</p>
<p>Any restriction set through <b class="option">-filter</b> is applied
last. Specifying more than one <b class="option">-filter</b> is illegal.</p>
458
459
460
461
462
463
464








465
466
467
468
469
470
471
<dd><p>Return a list of all arcs which are adjacent to two of the nodes in
the set. This is the set of arcs in the subgraph spawned by the
specified nodes.</p></dd>
<dt><b class="option">-embedding</b></dt>
<dd><p>Return a list of all arcs adjacent to exactly one of the nodes in the
set. This is the set of arcs connecting the subgraph spawned by the
specified nodes to the rest of the graph.</p></dd>








<dt><b class="option">-key</b> <i class="arg">key</i></dt>
<dd><p>Limit the list of arcs that are returned to those arcs that have an
associated key <i class="arg">key</i>.</p></dd>
<dt><b class="option">-value</b> <i class="arg">value</i></dt>
<dd><p>This restriction can only be used in combination with
<b class="option">-key</b>. It limits the list of arcs that are returned to those
arcs whose associated key <i class="arg">key</i> has the value <i class="arg">value</i>.</p></dd>







>
>
>
>
>
>
>
>







458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
<dd><p>Return a list of all arcs which are adjacent to two of the nodes in
the set. This is the set of arcs in the subgraph spawned by the
specified nodes.</p></dd>
<dt><b class="option">-embedding</b></dt>
<dd><p>Return a list of all arcs adjacent to exactly one of the nodes in the
set. This is the set of arcs connecting the subgraph spawned by the
specified nodes to the rest of the graph.</p></dd>
</dl>
<p><em>Attention</em>: After the above options any word with a leading dash
which is not a valid option is treated as a node name instead of an
invalid option to error out on. This condition holds until either a
valid option terminates the list of nodes, or the end of the command
is reached, whichever comes first.</p>
<p>The remaining filter options are:</p>
<dl class="doctools_definitions">
<dt><b class="option">-key</b> <i class="arg">key</i></dt>
<dd><p>Limit the list of arcs that are returned to those arcs that have an
associated key <i class="arg">key</i>.</p></dd>
<dt><b class="option">-value</b> <i class="arg">value</i></dt>
<dd><p>This restriction can only be used in combination with
<b class="option">-key</b>. It limits the list of arcs that are returned to those
arcs whose associated key <i class="arg">key</i> has the value <i class="arg">value</i>.</p></dd>
561
562
563
564
565
566
567
568
569



570
571
572
573
574
575
576
577
nothing if the <i class="arg">key</i> does not exist.</p></dd>
<dt><a name="58"><i class="arg">graphName</i> <b class="method">nodes</b> <span class="opt">?-key <i class="arg">key</i>?</span> <span class="opt">?-value <i class="arg">value</i>?</span> <span class="opt">?-filter <i class="arg">cmdprefix</i>?</span> <span class="opt">?-in|-out|-adj|-inner|-embedding <i class="arg">node</i> <i class="arg">node</i>...?</span></a></dt>
<dd><p>Return a list of nodes in the graph. Restrictions can limit the list
of returned nodes based on neighboring nodes, or based on the keyed
values associated with the node. The restrictions that involve
neighboring nodes have a list of nodes as argument, specified after
the name of the restriction itself.</p>
<p>The possible restrictions are the same as for method
<b class="method">arcs</b>. The exact meanings change slightly, as they operate on



nodes instead of arcs. The command recognizes:</p>
<dl class="doctools_definitions">
<dt><b class="option">-in</b></dt>
<dd><p>Return a list of all nodes with at least one outgoing arc ending in a
node found in the specified set of nodes. Alternatively specified as
the set of source nodes for the <b class="option">-in</b> arcs of the node set. The
<i class="term">incoming neighbours</i>.</p></dd>
<dt><b class="option">-out</b></dt>







|
|
>
>
>
|







569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
nothing if the <i class="arg">key</i> does not exist.</p></dd>
<dt><a name="58"><i class="arg">graphName</i> <b class="method">nodes</b> <span class="opt">?-key <i class="arg">key</i>?</span> <span class="opt">?-value <i class="arg">value</i>?</span> <span class="opt">?-filter <i class="arg">cmdprefix</i>?</span> <span class="opt">?-in|-out|-adj|-inner|-embedding <i class="arg">node</i> <i class="arg">node</i>...?</span></a></dt>
<dd><p>Return a list of nodes in the graph. Restrictions can limit the list
of returned nodes based on neighboring nodes, or based on the keyed
values associated with the node. The restrictions that involve
neighboring nodes have a list of nodes as argument, specified after
the name of the restriction itself.</p>
<p>The possible restrictions are the same as for method <b class="method">arcs</b>.
Note that while the exact meanings change slightly, as they operate on
nodes instead of arcs, the general behaviour is the same, especially
when it comes to the handling of words with a leading dash in node
lists.</p>
<p>The command recognizes:</p>
<dl class="doctools_definitions">
<dt><b class="option">-in</b></dt>
<dd><p>Return a list of all nodes with at least one outgoing arc ending in a
node found in the specified set of nodes. Alternatively specified as
the set of source nodes for the <b class="option">-in</b> arcs of the node set. The
<i class="term">incoming neighbours</i>.</p></dd>
<dt><b class="option">-out</b></dt>
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
attributes, and the values are the values for each name.</p>
<p><em>Note:</em> The order of the nodes in the serialization has no
relevance, nor has the order of the arcs per node.</p>
<pre class="doctools_example">
    # A possible serialization for the graph structure
    #
    #        d -----&gt; %2
    #       /         ^ \\
    #      /         /   \\
    #     /         b     \\
    #    /         /       \\
    #  %1 &lt;- a - %0         e
    #    ^         \\      /
    #     \\        c     /
    #      \\        \\  /
    #       \\        v v
    #        f ------ %3
    # is







|
|
|
|







682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
attributes, and the values are the values for each name.</p>
<p><em>Note:</em> The order of the nodes in the serialization has no
relevance, nor has the order of the arcs per node.</p>
<pre class="doctools_example">
    # A possible serialization for the graph structure
    #
    #        d -----&gt; %2
    #       /         ^ \
    #      /         /   \
    #     /         b     \
    #    /         /       \
    #  %1 &lt;- a - %0         e
    #    ^         \\      /
    #     \\        c     /
    #      \\        \\  /
    #       \\        v v
    #        f ------ %3
    # is
784
785
786
787
788
789
790
791
792
793
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#adjacent">adjacent</a>, <a href="../../../../index.html#arc">arc</a>, <a href="../../../../index.html#cgraph">cgraph</a>, <a href="../../../../index.html#degree">degree</a>, <a href="../../../../index.html#edge">edge</a>, <a href="../../../../index.html#graph">graph</a>, <a href="../../../../index.html#loop">loop</a>, <a href="../../../../index.html#neighbour">neighbour</a>, <a href="../../../../index.html#node">node</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#subgraph">subgraph</a>, <a href="../../../../index.html#vertex">vertex</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Data structures</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2002-2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


795
796
797
798
799
800
801
802
803
804
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#adjacent">adjacent</a>, <a href="../../../../index.html#arc">arc</a>, <a href="../../../../index.html#cgraph">cgraph</a>, <a href="../../../../index.html#degree">degree</a>, <a href="../../../../index.html#edge">edge</a>, <a href="../../../../index.html#graph">graph</a>, <a href="../../../../index.html#loop">loop</a>, <a href="../../../../index.html#neighbour">neighbour</a>, <a href="../../../../index.html#node">node</a>, <a href="../../../../index.html#serialization">serialization</a>, <a href="../../../../index.html#subgraph">subgraph</a>, <a href="../../../../index.html#vertex">vertex</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Data structures</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2002-2009,2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/struct/matrix.html.

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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'matrix.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2002-2013 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- struct::matrix.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">struct::matrix(n) 2.0.3 tcllib &quot;Tcl Data Structures&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>struct::matrix - Create and manipulate matrix objects</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">EXAMPLES</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">struct::matrix <span class="opt">?2.0.3?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::struct::matrix</b> <span class="opt">?<i class="arg">matrixName</i>?</span> <span class="opt">?<b class="const">=</b>|<b class="const">:=</b>|<b class="const">as</b>|<b class="const">deserialize</b> <i class="arg">source</i>?</span></a></li>
<li><a href="#2"><b class="cmd">matrixName</b> <i class="arg">option</i> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
<li><a href="#3"><i class="arg">matrixName</i> <b class="method">=</b> <i class="arg">sourcematrix</i></a></li>
<li><a href="#4"><i class="arg">matrixName</i> <b class="method">--&gt;</b> <i class="arg">destmatrix</i></a></li>
<li><a href="#5"><i class="arg">matrixName</i> <b class="method">add column</b> <span class="opt">?<i class="arg">values</i>?</span></a></li>







|













|



















|







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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'matrix.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2002-2013,2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- struct::matrix.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">struct::matrix(n) 2.0.4 tcllib &quot;Tcl Data Structures&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>struct::matrix - Create and manipulate matrix objects</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">EXAMPLES</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">struct::matrix <span class="opt">?2.0.4?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::struct::matrix</b> <span class="opt">?<i class="arg">matrixName</i>?</span> <span class="opt">?<b class="const">=</b>|<b class="const">:=</b>|<b class="const">as</b>|<b class="const">deserialize</b> <i class="arg">source</i>?</span></a></li>
<li><a href="#2"><b class="cmd">matrixName</b> <i class="arg">option</i> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
<li><a href="#3"><i class="arg">matrixName</i> <b class="method">=</b> <i class="arg">sourcematrix</i></a></li>
<li><a href="#4"><i class="arg">matrixName</i> <b class="method">--&gt;</b> <i class="arg">destmatrix</i></a></li>
<li><a href="#5"><i class="arg">matrixName</i> <b class="method">add column</b> <span class="opt">?<i class="arg">values</i>?</span></a></li>
558
559
560
561
562
563
564
565
566
567
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#matrix">matrix</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Data structures</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2002-2013 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


558
559
560
561
562
563
564
565
566
567
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#matrix">matrix</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Data structures</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2002-2013,2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/struct/matrix1.html.

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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'matrix1.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2002 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- struct::matrix_v1.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">struct::matrix_v1(n) 1.2.1 tcllib &quot;Tcl Data Structures&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>struct::matrix_v1 - Create and manipulate matrix objects</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">EXAMPLES</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">struct::matrix <span class="opt">?1.2.1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">matrixName</b> <i class="arg">option</i> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
<li><a href="#2"><i class="arg">matrixName</i> <b class="method">add column</b> <span class="opt">?<i class="arg">values</i>?</span></a></li>
<li><a href="#3"><i class="arg">matrixName</i> <b class="method">add row</b> <span class="opt">?<i class="arg">values</i>?</span></a></li>
<li><a href="#4"><i class="arg">matrixName</i> <b class="method">add columns</b> <i class="arg">n</i></a></li>
<li><a href="#5"><i class="arg">matrixName</i> <b class="method">add rows</b> <i class="arg">n</i></a></li>







|













|



















|







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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'matrix1.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2002,2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- struct::matrix_v1.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">struct::matrix_v1(n) 1.2.2 tcllib &quot;Tcl Data Structures&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>struct::matrix_v1 - Create and manipulate matrix objects</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">EXAMPLES</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">struct::matrix <span class="opt">?1.2.2?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">matrixName</b> <i class="arg">option</i> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
<li><a href="#2"><i class="arg">matrixName</i> <b class="method">add column</b> <span class="opt">?<i class="arg">values</i>?</span></a></li>
<li><a href="#3"><i class="arg">matrixName</i> <b class="method">add row</b> <span class="opt">?<i class="arg">values</i>?</span></a></li>
<li><a href="#4"><i class="arg">matrixName</i> <b class="method">add columns</b> <i class="arg">n</i></a></li>
<li><a href="#5"><i class="arg">matrixName</i> <b class="method">add rows</b> <i class="arg">n</i></a></li>
446
447
448
449
450
451
452
453
454
455
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#matrix">matrix</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Data structures</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2002 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


446
447
448
449
450
451
452
453
454
455
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#matrix">matrix</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Data structures</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2002,2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/struct/record.html.

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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">struct::record(n) 1.2.1 tcllib &quot;Tcl Data Structures&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>struct::record - Define and create records (similar to 'C' structures)</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">RECORD MEMBERS</a></li>






<li class="doctools_section"><a href="#section3">RECORD COMMAND</a></li>
<li class="doctools_section"><a href="#section4">INSTANCE COMMAND</a></li>
<li class="doctools_section"><a href="#section5">EXAMPLES</a></li>





<li class="doctools_section"><a href="#section6">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">struct::record <span class="opt">?1.2.1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">record define</b> <i class="arg">recordName</i> <i class="arg">recordMembers</i> <span class="opt">?<i class="arg">instanceName1 instanceName2 ...</i>?</span></a></li>
<li><a href="#2"><b class="cmd">record show</b> <i class="arg">record</i></a></li>
<li><a href="#3"><b class="cmd">record show</b> <i class="arg">instances</i> <i class="arg">recordName</i></a></li>
<li><a href="#4"><b class="cmd">record show</b> <i class="arg">members</i> <i class="arg">recordName</i></a></li>
<li><a href="#5"><b class="cmd">record show</b> <i class="arg">values</i> <i class="arg">instanceName</i></a></li>
<li><a href="#6"><b class="cmd">record exists</b> <i class="arg">record</i> <i class="arg">recordName</i></a></li>
<li><a href="#7"><b class="cmd">record exists</b> <i class="arg">instance</i> <i class="arg">instanceName</i></a></li>
<li><a href="#8"><b class="cmd">record delete</b> <i class="arg">record</i> <i class="arg">recordName</i></a></li>
<li><a href="#9"><b class="cmd">record delete</b> <i class="arg">instance</i> <i class="arg">instanceName</i></a></li>







<li><a href="#10"><i class="arg">recordName</i> <b class="method"><i class="arg">instanceName|#auto</i></b> <span class="opt">?<i class="arg">-member1 value1 -member2 value2 ...</i>?</span></a></li>
<li><a href="#11"><i class="arg">instanceName</i> <b class="method">cget</b> <span class="opt">?<i class="arg">-member1 -member2 ...</i>?</span></a></li>
<li><a href="#12"><i class="arg">instanceName</i> <b class="method">configure</b> <span class="opt">?<i class="arg">-member1 value1 -member2 value2 ...</i>?</span></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>The <b class="cmd">::struct::record</b> package provides a mechanism to group variables together

as one data structure, similar to a 'C' structure. The members of a
record can be variables or other records. However, a record can not contain circular
record, i.e. records that contain the same record as a
member.</p>
<p>This package was structured so that it is very similar to how Tk objects work. Each record

definition creates a record object that encompasses that definition. Subsequently, that
record object can create instances of that record. These instances can then
be manipulated with the <b class="method">cget</b> and <b class="method">configure</b> methods.</p>
<p>The package only contains one top level command, but several sub commands (see below). It also obeys the namespace in which the record was define, hence the objects returned are fully qualified.</p>


<dl class="doctools_definitions">
<dt><a name="1"><b class="cmd">record define</b> <i class="arg">recordName</i> <i class="arg">recordMembers</i> <span class="opt">?<i class="arg">instanceName1 instanceName2 ...</i>?</span></a></dt>
<dd><p>Defines a record. <i class="arg">recordName</i> is the name of the record, and is also
used as an object command. This object command is used to create instances of the
record definition. <i class="arg">recordMembers</i> are the members of
the record that make up the record definition. These are variables
and other record. If optional <i class="arg">instanceName</i> args are given, then an instance

is generated after the definition is created for each <i class="arg">instanceName</i>.</p></dd>
<dt><a name="2"><b class="cmd">record show</b> <i class="arg">record</i></a></dt>
<dd><p>Returns a list of records that have been defined.</p></dd>
<dt><a name="3"><b class="cmd">record show</b> <i class="arg">instances</i> <i class="arg">recordName</i></a></dt>
<dd><p>Returns the instances that have been instantiated by
<i class="arg">recordName</i>.</p></dd>
<dt><a name="4"><b class="cmd">record show</b> <i class="arg">members</i> <i class="arg">recordName</i></a></dt>
<dd><p>Returns the members that are defined for
record <i class="arg">recordName</i>. It returns the same format as how the
records were defined.</p></dd>
<dt><a name="5"><b class="cmd">record show</b> <i class="arg">values</i> <i class="arg">instanceName</i></a></dt>
<dd><p>Returns a list of values that are set for the instance
<i class="arg">instanceName</i>. The output is a list of key/value pairs. If there
are nested records, then the values of the nested records will
itself be a list.</p></dd>
<dt><a name="6"><b class="cmd">record exists</b> <i class="arg">record</i> <i class="arg">recordName</i></a></dt>
<dd><p>Tests for the existence of a <i class="arg">record</i> with the
name <i class="arg">recordName</i>.</p></dd>
<dt><a name="7"><b class="cmd">record exists</b> <i class="arg">instance</i> <i class="arg">instanceName</i></a></dt>
<dd><p>Tests for the existence of a <i class="arg">instance</i> with the
name <i class="arg">instanceName</i>.</p></dd>
<dt><a name="8"><b class="cmd">record delete</b> <i class="arg">record</i> <i class="arg">recordName</i></a></dt>
<dd><p>Deletes <i class="arg">recordName</i>, and all instances of <i class="arg">recordName</i>. It will return
an error if the record does not exist.</p></dd>
<dt><a name="9"><b class="cmd">record delete</b> <i class="arg">instance</i> <i class="arg">instanceName</i></a></dt>
<dd><p>Deletes <i class="arg">instance</i> with the name of <i class="arg">instanceName</i>. It
will return an error if the instance does not exist.</p></dd>

</dl>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">RECORD MEMBERS</a></h2>
<p>Record members can either be variables, or other records, However, the
same record can not be nested witin itself (circular). To define a
nested record, you need to specify the <b class="const">record</b> keyword, along
the with name of the record, and the name of the instance of that
nested record. For example, it would look like this:</p>

<pre class="doctools_example">
# this is the nested record
record define mynestedrecord {
    nest1
    nest2
}
# This is the main record
record define myrecord {
    mem1
    mem2
    {record mynestedrecord mem3}
}
</pre>
<p>You can also assign default or initial values to the members of a record,
by enclosing the member entry in braces:</p>
<pre class="doctools_example">
record define myrecord {
    mem1
    {mem2 5}
}
</pre>
<p>All instances created from this record definition, will initially have 5 as

the value for <i class="arg">mem2</i>. If no default is given, then the value will be the empty string.</p>
<p><em>Getting Values</em></p>
<p>To get a value of a member, there are several ways to do this.</p>
<ol class="doctools_enumerated">

<li><p>To get a member value, then use the instance built-in <b class="method">cget</b> method:</p>



<p><i class="arg">instanceName</i> <b class="method">cget</b> -mem1</p></li>
<li><p>To get multiple member values, you can specify them all in one command:</p>


<p><i class="arg">instanceName</i> <b class="method">cget</b> -mem1 -mem2</p></li>

<li><p>To get a list of the key/value of all of the members, there are 3 ways:</p>
<p>- <i class="arg">instanceName</i> <b class="method">cget</b></p>

<p>- <i class="arg">instanceName</i> <b class="method">configure</b></p>

<p>- <i class="arg">instanceName</i></p></li>

<li><p>To get a value of a nested member, then use the dot notation:</p>
<p><i class="arg">instanceName</i> <b class="method">cget</b> -mem3.nest1</p></li>
</ol>

<p><em>Setting Values</em></p>
<p>To set a value of a member, there are several ways to do this.</p>
<ol class="doctools_enumerated">

<li><p>To set a member value, then use the instance built-in <b class="method">configure</b> method:</p>




<p><i class="arg">instanceName</i> <b class="method">configure</b> -mem1 val1</p></li>
<li><p>To set multiple member values, you can specify them all in one command:</p>


<p><i class="arg">instanceName</i> <b class="method">configure</b> -mem1 va1 -mem2 val2</p></li>
<li><p>To set a value of a nested member, then use the dot notation:</p>
<p><i class="arg">instanceName</i> <b class="method">configure</b> -mem3.nest1 value</p></li>

</ol>

<p><em>Alias access</em></p>
<p>In the original implementation, access was done by using dot notation similar to how 'C' structures are accessed. However,

there was a concensus to make the interface more Tcl like, which made sense. However, the original alias access still

exists. It might prove to be helpful to some.</p>
<p>Basically, for every member of every instance, an alias is created. This alias is used to get and set values for that

member. An example will illustrate the point, using the above defined records:</p>
<pre class="doctools_example">
# Create an instance first
% myrecord inst1
::inst1
% # To get a member of an instance, just use the
% # alias (it behaves like a Tcl command):
% inst1.mem1
%
% # To set a member via the alias, just include
% # a value (optionally the equal sign - syntactic sugar)
% inst1.mem1 = 5
5
% inst1.mem1
5
% # For nested records, just continue with the
% # dot notation (note no equal sign)
% inst1.mem3.nest1 10
10
% inst1.mem3.nest1
10
% # just the instance by itself gives all
% # member/values pairs for that instance
% inst1
-mem1 5 -mem2 {} -mem3 {-nest1 10 -nest2 {}}
% # and to get all members within the nested record
% inst1.mem3
-nest1 10 -nest2 {}
%
</pre>
</div>

<div id="section3" class="doctools_section"><h2><a name="section3">RECORD COMMAND</a></h2>
<p>The following subcommands and corresponding arguments are available to any
record command:</p>
<dl class="doctools_definitions">
<dt><a name="10"><i class="arg">recordName</i> <b class="method"><i class="arg">instanceName|#auto</i></b> <span class="opt">?<i class="arg">-member1 value1 -member2 value2 ...</i>?</span></a></dt>
<dd><p>Using the <i class="arg">recordName</i> object command that was created from the record definition,
instances of the record definition can be created. Once a instance is

created, then it inherits the members of the record definition, very

similar to how objects work. During instance generation, an object command for the instance
is created as well, using <i class="arg">instanceName</i>. This object command is used
to access the data members of the instance. During the instantiation, values for


that instance can be given, <em>but</em> all values must be given, and be given

in key/value pairs. Nested records, need to be in list format.</p>

<p>Optionally, <i class="arg">#auto</i> can be used in place of <i class="arg">instanceName</i>. When #auto is used,
then a instance name will automatically be generated, of the form recordName&lt;integer&gt;, where

&lt;integer&gt; is a unique integer (starting at 0) that is generated.</p></dd>
</dl>
</div>
<div id="section4" class="doctools_section"><h2><a name="section4">INSTANCE COMMAND</a></h2>
<p>The following subcommands and corresponding arguments are available to
any record instance command:</p>
<dl class="doctools_definitions">
<dt><a name="11"><i class="arg">instanceName</i> <b class="method">cget</b> <span class="opt">?<i class="arg">-member1 -member2 ...</i>?</span></a></dt>
<dd><p>Each instance has the sub command <b class="method">cget</b> associated with it. This
is very similar to how Tk widget's cget command works. It queries
the values of the member for that particular instance. If
no arguments are given, then a key/value list is returned.</p></dd>
<dt><a name="12"><i class="arg">instanceName</i> <b class="method">configure</b> <span class="opt">?<i class="arg">-member1 value1 -member2 value2 ...</i>?</span></a></dt>
<dd><p>Each instance has the sub command <b class="method">configure</b> associated with it. This
is very similar to how Tk widget's configure command works. It sets
the values of the particular member for that particular instance. If
no arguments are given, then a key/value list is returned.</p></dd>
</dl>
</div>
<div id="section5" class="doctools_section"><h2><a name="section5">EXAMPLES</a></h2>
<p>Two examples are provided to give an good illustration on how to use
this package.</p>
<p><em>Example 1</em></p>
<p>Probably the most obvious example would be to hold contact information,
such as addresses, phone numbers, comments, etc. Since a person can have
multiple phone numbers, multiple email addresses, etc, we will use nested
records to define these. So, the first thing we do is define the nested
records:</p>
<pre class="doctools_example">
##
##  This is an interactive example, to see what is
##  returned by each command as well.
##
% namespace import ::struct::record::*
% # define a nested record. Notice that country has default 'USA'.
% record define locations {
    street
    street2
    city







|








|
>
>
>
>
>
>


|
>
>
>
>
>










|











>
>
>
>
>
>
>
|
|
|




|
>
|
|
|
<
|
>
|
|
|
|
>
>


|
|
|
|
|
>
|






|
<
|












|
|

|
|
>







|
>













|
|






|
>
|
|

|
>
|
>
>
>
|
<
>
>
|
>
|
|
>
|
>
|
>
|
<
|
>
|

|
>
|
>
>
>
>
|
<
>
>
|
<
|
>
|
>
|
|
>
|
>
|
|
>
|

|


|
|

<
|
|




|
|




|
|





<


>

|
|

|
|
|
>
|
>
|
|
|
>
>
|
>
|
>
|
|
>
|






|
|
|
|
|
|
|
|
|
|



|

|
|
|
|
|
|


|
|







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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">struct::record(n) 1.2.2 tcllib &quot;Tcl Data Structures&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>struct::record - Define and create records (similar to 'C' structures)</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">RECORD MEMBERS</a>
<ul>
<li class="doctools_subsection"><a href="#subsection1">Getting Values</a></li>
<li class="doctools_subsection"><a href="#subsection2">Setting Values</a></li>
<li class="doctools_subsection"><a href="#subsection3">Alias access</a></li>
</ul>
</li>
<li class="doctools_section"><a href="#section3">RECORD COMMAND</a></li>
<li class="doctools_section"><a href="#section4">INSTANCE COMMAND</a></li>
<li class="doctools_section"><a href="#section5">EXAMPLES</a>
<ul>
<li class="doctools_subsection"><a href="#subsection4">Example 1 - Contact Information</a></li>
<li class="doctools_subsection"><a href="#subsection5">Example 2 - Linked List</a></li>
</ul>
</li>
<li class="doctools_section"><a href="#section6">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">struct::record <span class="opt">?1.2.2?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">record define</b> <i class="arg">recordName</i> <i class="arg">recordMembers</i> <span class="opt">?<i class="arg">instanceName1 instanceName2 ...</i>?</span></a></li>
<li><a href="#2"><b class="cmd">record show</b> <i class="arg">record</i></a></li>
<li><a href="#3"><b class="cmd">record show</b> <i class="arg">instances</i> <i class="arg">recordName</i></a></li>
<li><a href="#4"><b class="cmd">record show</b> <i class="arg">members</i> <i class="arg">recordName</i></a></li>
<li><a href="#5"><b class="cmd">record show</b> <i class="arg">values</i> <i class="arg">instanceName</i></a></li>
<li><a href="#6"><b class="cmd">record exists</b> <i class="arg">record</i> <i class="arg">recordName</i></a></li>
<li><a href="#7"><b class="cmd">record exists</b> <i class="arg">instance</i> <i class="arg">instanceName</i></a></li>
<li><a href="#8"><b class="cmd">record delete</b> <i class="arg">record</i> <i class="arg">recordName</i></a></li>
<li><a href="#9"><b class="cmd">record delete</b> <i class="arg">instance</i> <i class="arg">instanceName</i></a></li>
<li><a href="#10"><i class="arg">instanceName</i> <b class="method">cget</b> -<i class="arg">member</i></a></li>
<li><a href="#11"><i class="arg">instanceName</i> <b class="method">cget</b> -<i class="arg">member1</i> -<i class="arg">member2</i></a></li>
<li><a href="#12"><i class="arg">instanceName</i> <b class="method">cget</b></a></li>
<li><a href="#13"><i class="arg">instanceName</i> <b class="method">configure</b></a></li>
<li><a href="#14"><i class="arg">instanceName</i></a></li>
<li><a href="#15"><i class="arg">instanceName</i> <b class="method">configure</b> -<i class="arg">member</i> <i class="arg">value</i></a></li>
<li><a href="#16"><i class="arg">instanceName</i> <b class="method">configure</b> -<i class="arg">member1</i> <i class="arg">value1</i> -<i class="arg">member2</i> <i class="arg">value2</i></a></li>
<li><a href="#17"><i class="arg">recordName</i> <i class="arg">instanceName</i>|<b class="const">#auto</b> <span class="opt">?<i class="arg">-member1 value1 -member2 value2 ...</i>?</span></a></li>
<li><a href="#18"><i class="arg">instanceName</i> <b class="method">cget</b> <span class="opt">?<i class="arg">-member1 -member2 ...</i>?</span></a></li>
<li><a href="#19"><i class="arg">instanceName</i> <b class="method">configure</b> <span class="opt">?<i class="arg">-member1 value1 -member2 value2 ...</i>?</span></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>The <b class="cmd">::struct::record</b> package provides a mechanism to group
variables together as one data structure, similar to a <i class="term"><a href="../../../../index.html#c">C</a></i>
structure. The members of a record can be variables or other
records. However, a record can not contain circular records,
i.e. records that contain the same record as a member.</p>

<p>This package was structured so that it is very similar to how
Tk objects work. Each record definition creates a record object that
encompasses that definition. Subsequently, that record object can
create instances of that record. These instances can then be
manipulated with the <b class="method">cget</b> and <b class="method">configure</b> methods.</p>
<p>The package only contains one top level command, but several
sub commands (see below). It also obeys the namespace in which the
record was defined, hence the objects returned are fully qualified.</p>
<dl class="doctools_definitions">
<dt><a name="1"><b class="cmd">record define</b> <i class="arg">recordName</i> <i class="arg">recordMembers</i> <span class="opt">?<i class="arg">instanceName1 instanceName2 ...</i>?</span></a></dt>
<dd><p>Defines a record. <i class="arg">recordName</i> is the name of the record, and is
also used as an object command. This object command is used to create
instances of the record definition. The <i class="arg">recordMembers</i> are the
members of the record that make up the record definition. These are
variables and other records. If optional <i class="arg">instanceName</i> args are
specified, then an instance is generated after the definition is
created for each <i class="arg">instanceName</i>.</p></dd>
<dt><a name="2"><b class="cmd">record show</b> <i class="arg">record</i></a></dt>
<dd><p>Returns a list of records that have been defined.</p></dd>
<dt><a name="3"><b class="cmd">record show</b> <i class="arg">instances</i> <i class="arg">recordName</i></a></dt>
<dd><p>Returns the instances that have been instantiated by
<i class="arg">recordName</i>.</p></dd>
<dt><a name="4"><b class="cmd">record show</b> <i class="arg">members</i> <i class="arg">recordName</i></a></dt>
<dd><p>Returns the members that are defined for record <i class="arg">recordName</i>.

It returns the same format as how the records were defined.</p></dd>
<dt><a name="5"><b class="cmd">record show</b> <i class="arg">values</i> <i class="arg">instanceName</i></a></dt>
<dd><p>Returns a list of values that are set for the instance
<i class="arg">instanceName</i>. The output is a list of key/value pairs. If there
are nested records, then the values of the nested records will
itself be a list.</p></dd>
<dt><a name="6"><b class="cmd">record exists</b> <i class="arg">record</i> <i class="arg">recordName</i></a></dt>
<dd><p>Tests for the existence of a <i class="arg">record</i> with the
name <i class="arg">recordName</i>.</p></dd>
<dt><a name="7"><b class="cmd">record exists</b> <i class="arg">instance</i> <i class="arg">instanceName</i></a></dt>
<dd><p>Tests for the existence of a <i class="arg">instance</i> with the
name <i class="arg">instanceName</i>.</p></dd>
<dt><a name="8"><b class="cmd">record delete</b> <i class="arg">record</i> <i class="arg">recordName</i></a></dt>
<dd><p>Deletes <i class="arg">recordName</i>, and all instances of <i class="arg">recordName</i>.
It will return an error if the record does not exist.</p></dd>
<dt><a name="9"><b class="cmd">record delete</b> <i class="arg">instance</i> <i class="arg">instanceName</i></a></dt>
<dd><p>Deletes <i class="arg">instance</i> with the name of <i class="arg">instanceName</i>. It will
return an error if the instance does not exist. Note that this
recursively deletes any nested instances as well.</p></dd>
</dl>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">RECORD MEMBERS</a></h2>
<p>Record members can either be variables, or other records, However, the
same record can not be nested witin itself (circular). To define a
nested record, you need to specify the <b class="const">record</b> keyword, along
the with name of the record, and the name of the instance of that
nested record (within the container). For example, it would look like
this:</p>
<pre class="doctools_example">
# this is the nested record
record define mynestedrecord {
    nest1
    nest2
}
# This is the main record
record define myrecord {
    mem1
    mem2
    {record mynestedrecord mem3}
}
</pre>
<p>You can also assign default or initial values to the members of a
record, by enclosing the member entry in braces:</p>
<pre class="doctools_example">
record define myrecord {
    mem1
    {mem2 5}
}
</pre>
<p>All instances created from this record definition will initially have
<b class="const">5</b> as the value for member <i class="arg">mem2</i>. If no default is given,
then the value will be the empty string.</p>
<div id="subsection1" class="doctools_subsection"><h3><a name="subsection1">Getting Values</a></h3>
<p>To get a value of a member, there are several ways to do this.</p>
<dl class="doctools_definitions">
<dt><a name="10"><i class="arg">instanceName</i> <b class="method">cget</b> -<i class="arg">member</i></a></dt>
<dd><p>In this form the built-in <b class="method">cget</b> instance method returns the
value of the specified <i class="arg">member</i>. Note the leading dash.</p>
<p>To reach a nested member use <i class="term">dot notation</i>:</p>
<pre class="doctools_example">
<i class="arg">instanceName</i> <b class="method">cget</b> -mem3.nest1

</pre>
</dd>
<dt><a name="11"><i class="arg">instanceName</i> <b class="method">cget</b> -<i class="arg">member1</i> -<i class="arg">member2</i></a></dt>
<dd><p>In this form the built-in <b class="method">cget</b> instance method returns a list
containing the values of both specified members, in the order of specification.</p></dd>
<dt><a name="12"><i class="arg">instanceName</i> <b class="method">cget</b></a></dt>
<dd></dd>
<dt><a name="13"><i class="arg">instanceName</i> <b class="method">configure</b></a></dt>
<dd></dd>
<dt><a name="14"><i class="arg">instanceName</i></a></dt>
<dd><p>These forms are all equivalent. They return a dictionary of all
members and the associated values.</p></dd>

</dl>
</div>
<div id="subsection2" class="doctools_subsection"><h3><a name="subsection2">Setting Values</a></h3>
<p>To set a value of a member, there are several ways to do this.</p>
<dl class="doctools_definitions">
<dt><a name="15"><i class="arg">instanceName</i> <b class="method">configure</b> -<i class="arg">member</i> <i class="arg">value</i></a></dt>
<dd><p>In this form the built-in <b class="method">configure</b> instance method sets the
specified <i class="arg">member</i> to the given <i class="arg">value</i>. Note the leading
dash.</p>
<p>To reach a nested member use <i class="term">dot notation</i>:</p>
<pre class="doctools_example">
<i class="arg">instanceName</i> <b class="method">configure</b> -mem3.nest1 value

</pre>
</dd>
<dt><a name="16"><i class="arg">instanceName</i> <b class="method">configure</b> -<i class="arg">member1</i> <i class="arg">value1</i> -<i class="arg">member2</i> <i class="arg">value2</i></a></dt>

<dd><p>In this form the built-in <b class="method">configure</b> instance method sets all
specified members to the associated values.</p></dd>
</dl>
</div>
<div id="subsection3" class="doctools_subsection"><h3><a name="subsection3">Alias access</a></h3>
<p>In the original implementation, access was done by using dot notation
similar to how <i class="term"><a href="../../../../index.html#c">C</a></i> structures are accessed. However, there was a
concensus to make the interface more Tcl like, which made sense.
However, the original alias access still exists. It might prove to be
helpful to some.</p>
<p>Basically, for every member of every instance, an alias is
created. This alias is used to get and set values for that member.
An example will illustrate the point, using the above defined records:</p>
<pre class="doctools_example">
% # Create an instance first
% myrecord inst1
::inst1
% # To get a member of an instance, just use the alias. It behaves
% # like a Tcl command:
% inst1.mem1

% # To set a member via the alias, just include a value. And optionally
% # the equal sign - syntactic sugar.
% inst1.mem1 = 5
5
% inst1.mem1
5
% # For nested records, just continue with the dot notation.
% # note, no equal sign.
% inst1.mem3.nest1 10
10
% inst1.mem3.nest1
10
% # just the instance by itself gives all member/values pairs for that
% # instance
% inst1
-mem1 5 -mem2 {} -mem3 {-nest1 10 -nest2 {}}
% # and to get all members within the nested record
% inst1.mem3
-nest1 10 -nest2 {}

</pre>
</div>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">RECORD COMMAND</a></h2>
<p>The following subcommands and corresponding arguments are available to
any record command:</p>
<dl class="doctools_definitions">
<dt><a name="17"><i class="arg">recordName</i> <i class="arg">instanceName</i>|<b class="const">#auto</b> <span class="opt">?<i class="arg">-member1 value1 -member2 value2 ...</i>?</span></a></dt>
<dd><p>Using the <i class="arg">recordName</i> object command that was created from the
record definition, instances of the record definition can be
created.
Once an instance is created, it inherits the members of the record
definition, very similar to how objects work.
During instance generation, an object command for the instance is
created as well, using <i class="arg">instanceName</i>.</p>
<p>This object command is used to access the data members of the
instance.
During the instantiation, while values for that instance may be given,
when done, <em>all</em> values must be given, and be given as
key/value pairs, like for method <b class="method">configure</b>. Nested records
have to be in list format.</p>
<p>Optionally, <b class="const">#auto</b> can be used in place of
<i class="arg">instanceName</i>. When <b class="const">#auto</b> is used, the instance name will
be automatically generated, and of the form
<b class="const">recordName<b class="variable">N</b></b>, where <b class="variable">N</b> is a unique integer (starting
at 0) that is generated.</p></dd>
</dl>
</div>
<div id="section4" class="doctools_section"><h2><a name="section4">INSTANCE COMMAND</a></h2>
<p>The following subcommands and corresponding arguments are available to
any record instance command:</p>
<dl class="doctools_definitions">
<dt><a name="18"><i class="arg">instanceName</i> <b class="method">cget</b> <span class="opt">?<i class="arg">-member1 -member2 ...</i>?</span></a></dt>
<dd><p>Each instance has the method <b class="method">cget</b>. This is very similar to
how Tk widget's <b class="method">cget</b> command works. It queries the values of
the members for that particular instance. If no arguments are given,
then a dictionary is returned.</p></dd>
<dt><a name="19"><i class="arg">instanceName</i> <b class="method">configure</b> <span class="opt">?<i class="arg">-member1 value1 -member2 value2 ...</i>?</span></a></dt>
<dd><p>Each instance has the method <b class="method">configure</b>. This is very similar
to how Tk widget's <b class="method">configure</b> command works. It sets the
values of the particular members for that particular instance. If no
arguments are given, then a dictionary list is returned.</p></dd>
</dl>
</div>
<div id="section5" class="doctools_section"><h2><a name="section5">EXAMPLES</a></h2>
<p>Two examples are provided to give a good illustration on how to use
this package.</p>
<div id="subsection4" class="doctools_subsection"><h3><a name="subsection4">Example 1 - Contact Information</a></h3>
<p>Probably the most obvious example would be to hold contact
information, such as addresses, phone numbers, comments, etc. Since a
person can have multiple phone numbers, multiple email addresses, etc,
we will use nested records to define these. So, the first thing we do
is define the nested records:</p>
<pre class="doctools_example">
##
##  This is an interactive example, to see what is returned by
##  each command as well.
##
% namespace import ::struct::record::*
% # define a nested record. Notice that country has default 'USA'.
% record define locations {
    street
    street2
    city
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
::contacts2
% record show members contacts2
first middle last {record locations home} {record locations work}
% record show members contacts
first middle last {record locations home} {record locations work}
%
</pre>
<p><em>Example 1</em></p>

<p>This next example just illustrates a simple linked list</p>
<pre class="doctools_example">
% # define a very simple record for linked list
% record define llist {
    value
    next
}
::llist
% llist lstart
::lstart
% lstart config -value 1 -next [llist #auto]
% [lstart cget -next] config -value 2 -next [llist #auto]
% [[lstart cget -next] cget -next] config -value 3 -next &quot;end&quot;
% set next lstart
lstart
% while 1 {
lappend values [$next cget -value]
set next [$next cget -next]
if {[string match &quot;end&quot; $next]} {break}
}
% puts &quot;$values&quot;
1 2 3
% # cleanup linked list
% # We could just use delete record llist also
% foreach I [record show instances llist] {
record delete instance $I
}
% record show instances llist
%
</pre>

</div>
<div id="section6" class="doctools_section"><h2><a name="section6">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>struct :: record</em> of the
<a href="http://core.tcl.tk/tcllib/reportlist">Tcllib Trackers</a>.
Please also report any ideas for enhancements you may have for either







|
>



|



|
|

|
|




|
|
|




|
|
|

|


>







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
::contacts2
% record show members contacts2
first middle last {record locations home} {record locations work}
% record show members contacts
first middle last {record locations home} {record locations work}
%
</pre>
</div>
<div id="subsection5" class="doctools_subsection"><h3><a name="subsection5">Example 2 - Linked List</a></h3>
<p>This next example just illustrates a simple linked list</p>
<pre class="doctools_example">
% # define a very simple record for linked list
% record define linkedlist {
    value
    next
}
::linkedlist
% linkedlist lstart
::lstart
% lstart config -value 1 -next [linkedlist #auto]
% [lstart cget -next] config -value 2 -next [linkedlist #auto]
% [[lstart cget -next] cget -next] config -value 3 -next &quot;end&quot;
% set next lstart
lstart
% while 1 {
    lappend values [$next cget -value]
    set next [$next cget -next]
    if {[string match &quot;end&quot; $next]} break
}
% puts &quot;$values&quot;
1 2 3
% # cleanup linked list
% # We could just use delete record linkedlist also
% foreach I [record show instances linkedlist] {
    record delete instance $I
}
% record show instances linkedlist
%
</pre>
</div>
</div>
<div id="section6" class="doctools_section"><h2><a name="section6">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>struct :: record</em> of the
<a href="http://core.tcl.tk/tcllib/reportlist">Tcllib Trackers</a>.
Please also report any ideas for enhancements you may have for either

Added idoc/www/tcllib/files/modules/struct/struct_map.html.





























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
<!DOCTYPE html><html><head>
<title>struct::map - </title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
	color:	 	black;
    }
    DIV.doctools {
	margin-left:	10%;
	margin-right:	10%;
    }
    DIV.doctools H1,DIV.doctools H2 {
	margin-left:	-5%;
    }
    H1, H2, H3, H4 {
	margin-top: 	1em;
	font-family:	sans-serif;
	font-size:	large;
	color:		#005A9C;
	background: 	transparent;
	text-align:		left;
    }
    H1.doctools_title {
	text-align: center;
    }
    UL,OL {
	margin-right: 0em;
	margin-top: 3pt;
	margin-bottom: 3pt;
    }
    UL LI {
	list-style: disc;
    }
    OL LI {
	list-style: decimal;
    }
    DT {
	padding-top: 	1ex;
    }
    UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
	font:		normal 12pt/14pt sans-serif;
	list-style:	none;
    }
    LI.doctools_section, LI.doctools_subsection {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding: 	0em;
    }
    PRE {
	display: 	block;
	font-family:	monospace;
	white-space:	pre;
	margin:		0%;
	padding-top:	0.5ex;
	padding-bottom:	0.5ex;
	padding-left:	1ex;
	padding-right:	1ex;
	width:		100%;
    }
    PRE.doctools_example {
	color: 		black;
	background: 	#f5dcb3;
	border:		1px solid black;
    }
    UL.doctools_requirements LI, UL.doctools_syntax LI {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding:	0em;
    }
    DIV.doctools_synopsis {
	color: 		black;
	background: 	#80ffff;
	border:		1px solid black;
	font-family:	serif;
	margin-top: 	1em;
	margin-bottom: 	1em;
    }
    UL.doctools_syntax {
	margin-top: 	1em;
	border-top:	1px solid black;
    }
    UL.doctools_requirements {
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'struct_map.man' by tcllib/doctools with format 'html'
   -->
<!-- struct::map.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">struct::map(n) 1 tcllib &quot;&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>struct::map - Manage key/value maps</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">API</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">struct::map <span class="opt">?1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::struct::map</b> <i class="arg">mapName</i></a></li>
<li><a href="#2"><b class="cmd">mapName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></li>
<li><a href="#3"><i class="arg">mapName</i> <b class="method">get</b></a></li>
<li><a href="#4"><i class="arg">mapName</i> <b class="method">names</b></a></li>
<li><a href="#5"><i class="arg">mapName</i> <b class="method">set</b> <i class="arg">name</i> <span class="opt">?<i class="arg">value</i>?</span></a></li>
<li><a href="#6"><i class="arg">mapName</i> <b class="method">unset</b> <span class="opt">?<i class="arg">pattern</i>...?</span></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>Provides a snit class whose instances manage a key/value map.
In other words, an object wrapper around Tcl arrays.</p>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">API</a></h2>
<p>The main command provides construction of maps:</p>
<dl class="doctools_definitions">
<dt><a name="1"><b class="cmd">::struct::map</b> <i class="arg">mapName</i></a></dt>
<dd><p>Creates a new, empty map with an associated global Tcl command whose
name is <i class="arg">mapName</i>.
It may be used to invoke various operations on the map.
It has the following general form:</p>
<dl class="doctools_definitions">
<dt><a name="2"><b class="cmd">mapName</b> <b class="method">method</b> <span class="opt">?<i class="arg">arg arg ...</i>?</span></a></dt>
<dd><p><b class="method">method</b> and <i class="arg">arg</i>uments determine the exact behavior of
the command.</p></dd>
</dl>
<p>If <i class="arg">mapName</i> is specified as <b class="const">%AUTO%</b> a unique name will be
generated by the package itself.
The result of the command is the fully-qualified name of the instance
command.</p></dd>
</dl>
<p>The following commands are possible for map objects:</p>
<dl class="doctools_definitions">
<dt><a name="3"><i class="arg">mapName</i> <b class="method">get</b></a></dt>
<dd><p>Returns the entire map as a Tcl dictionary.</p></dd>
<dt><a name="4"><i class="arg">mapName</i> <b class="method">names</b></a></dt>
<dd><p>Returns the list of all keys known to the map, in arbitrary order.</p></dd>
<dt><a name="5"><i class="arg">mapName</i> <b class="method">set</b> <i class="arg">name</i> <span class="opt">?<i class="arg">value</i>?</span></a></dt>
<dd><p>Sets key <i class="arg">name</i> to the specified <i class="arg">value</i>, if the value specified.
Returns the value for the key.
Throws an error if the key is not known.</p></dd>
<dt><a name="6"><i class="arg">mapName</i> <b class="method">unset</b> <span class="opt">?<i class="arg">pattern</i>...?</span></a></dt>
<dd><p>Removes all keys matching at least one of the glob <i class="arg">pattern</i>s from
the map.
If no pattern is specified all keys are removed.
In other words, the default pattern is <b class="const">*</b>.
The result of the command is the empty string.</p></dd>
</dl>
</div>
<div id="section3" class="doctools_section"><h2><a name="section3">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>struct :: list</em> of the
<a href="http://core.tcl.tk/tcllib/reportlist">Tcllib Trackers</a>.
Please also report any ideas for enhancements you may have for either
package and/or documentation.</p>
<p>When proposing code changes, please provide <em>unified diffs</em>,
i.e the output of <b class="const">diff -u</b>.</p>
<p>Note further that <em>attachments</em> are strongly preferred over
inlined patches. Attachments can be made by going to the <b class="const">Edit</b>
form of the ticket immediately after its creation, and then using the
left-most button in the secondary navigation bar.</p>
</div>
</div></body></html>

Added idoc/www/tcllib/files/modules/textutil/patch.html.

























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
<!DOCTYPE html><html><head>
<title>textutil::patch - Text and string utilities</title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
	color:	 	black;
    }
    DIV.doctools {
	margin-left:	10%;
	margin-right:	10%;
    }
    DIV.doctools H1,DIV.doctools H2 {
	margin-left:	-5%;
    }
    H1, H2, H3, H4 {
	margin-top: 	1em;
	font-family:	sans-serif;
	font-size:	large;
	color:		#005A9C;
	background: 	transparent;
	text-align:		left;
    }
    H1.doctools_title {
	text-align: center;
    }
    UL,OL {
	margin-right: 0em;
	margin-top: 3pt;
	margin-bottom: 3pt;
    }
    UL LI {
	list-style: disc;
    }
    OL LI {
	list-style: decimal;
    }
    DT {
	padding-top: 	1ex;
    }
    UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
	font:		normal 12pt/14pt sans-serif;
	list-style:	none;
    }
    LI.doctools_section, LI.doctools_subsection {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding: 	0em;
    }
    PRE {
	display: 	block;
	font-family:	monospace;
	white-space:	pre;
	margin:		0%;
	padding-top:	0.5ex;
	padding-bottom:	0.5ex;
	padding-left:	1ex;
	padding-right:	1ex;
	width:		100%;
    }
    PRE.doctools_example {
	color: 		black;
	background: 	#f5dcb3;
	border:		1px solid black;
    }
    UL.doctools_requirements LI, UL.doctools_syntax LI {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding:	0em;
    }
    DIV.doctools_synopsis {
	color: 		black;
	background: 	#80ffff;
	border:		1px solid black;
	font-family:	serif;
	margin-top: 	1em;
	margin-bottom: 	1em;
    }
    UL.doctools_syntax {
	margin-top: 	1em;
	border-top:	1px solid black;
    }
    UL.doctools_requirements {
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'patch.man' by tcllib/doctools with format 'html'
   -->
<!-- textutil::patch.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">textutil::patch(n) 0.1 tcllib &quot;Text and string utilities&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>textutil::patch - Application of uni-diff patches to directory trees</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.2</b></li>
<li>package require <b class="pkgname">textutil::patch <span class="opt">?0.1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::textutil::patch::apply</b> <i class="arg">basedirectory</i> <i class="arg">striplevel</i> <i class="arg">patch</i> <i class="arg">reportcmd</i></a></li>
<li><a href="#2"><b class="cmd">{*}reportcmd</b> <b class="method">apply</b> <i class="arg">filename</i></a></li>
<li><a href="#3"><b class="cmd">{*}reportcmd</b> <b class="method">fail</b> <i class="arg">filename</i> <i class="arg">hunk</i> <i class="arg">expected</i> <i class="arg">seen</i></a></li>
<li><a href="#4"><b class="cmd">{*}reportcmd</b> <b class="method">fail-already</b> <i class="arg">filename</i> <i class="arg">hunk</i></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>This package provides a single command which applies a patch in
<a href="https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html">unified format</a>
to a directory tree.</p>
<dl class="doctools_definitions">
<dt><a name="1"><b class="cmd">::textutil::patch::apply</b> <i class="arg">basedirectory</i> <i class="arg">striplevel</i> <i class="arg">patch</i> <i class="arg">reportcmd</i></a></dt>
<dd><p>Applies the <i class="arg">patch</i> (text of the path, not file) to the files in
the <i class="arg">basedirectory</i> using the specified <i class="arg">striplevel</i>.
The result of the command is the empty string.</p>
<p>The <i class="arg">striplevel</i> argument is equivalent to option
<b class="option">-p</b> of the <b class="syscmd"><a href="../../../../index.html#patch">patch</a></b> command.</p>
<p>Errors are thrown when the <i class="arg">patch</i> does not parse, and
nothing is done to the files in <i class="arg">basedirectory</i>.</p>
<p>All activities during the application of the patch, including
the inability to apply a hunk are reported through the command prefix
<i class="arg">reportcmd</i> instead. Files with problems are left unchanged.  Note
however that this does <em>not prevent</em> changes to files with no
problems, before and after the problematic file(s).</p>
<p>The command prefix is called in 3 possible forms:</p>
<dl class="doctools_definitions">
<dt><a name="2"><b class="cmd">{*}reportcmd</b> <b class="method">apply</b> <i class="arg">filename</i></a></dt>
<dd><p>The caller begins operation on file <i class="arg">fname</i>, applying all hunks
collected for said file.</p></dd>
<dt><a name="3"><b class="cmd">{*}reportcmd</b> <b class="method">fail</b> <i class="arg">filename</i> <i class="arg">hunk</i> <i class="arg">expected</i> <i class="arg">seen</i></a></dt>
<dd><p>Application of hunk number <i class="arg">hunk</i> of file <i class="arg">filename</i> has failed.
The command expected to find the text <i class="arg">expected</i>, and saw <i class="arg">seen</i> instead.</p></dd>
<dt><a name="4"><b class="cmd">{*}reportcmd</b> <b class="method">fail-already</b> <i class="arg">filename</i> <i class="arg">hunk</i></a></dt>
<dd><p>Application of hunk number <i class="arg">hunk</i> of file <i class="arg">filename</i> has failed.
The command believes that this hunk has already been applied to the file.</p></dd>
</dl></dd>
</dl>
</div>
<div id="section2" class="doctools_section"><h2><a name="section2">Bugs, Ideas, Feedback</a></h2>
<p>This document, and the package it describes, will undoubtedly contain
bugs and other problems.
Please report such in the category <em>textutil</em> of the
<a href="http://core.tcl.tk/tcllib/reportlist">Tcllib Trackers</a>.
Please also report any ideas for enhancements you may have for either
package and/or documentation.</p>
<p>When proposing code changes, please provide <em>unified diffs</em>,
i.e the output of <b class="const">diff -u</b>.</p>
<p>Note further that <em>attachments</em> are strongly preferred over
inlined patches. Attachments can be made by going to the <b class="const">Edit</b>
form of the ticket immediately after its creation, and then using the
left-most button in the secondary navigation bar.</p>
</div>
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#diff_run">diff -ruN</a>, <a href="../../../../index.html#diff_unified_format">diff, unified format</a>, <a href="../../../../index.html#fossil">fossil</a>, <a href="../../../../index.html#git">git</a>, <a href="../../../../index.html#patch">patch</a>, <a href="../../../../index.html#unified_format_diff">unified format diff</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Text processing</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/treeql/treeql.html.

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
    #   values for the attribute 'data',
    #   for all nodes in the set which
    #   have such an attribute.
    # - And returns this information.
    # Below we can see the same query, but rewritten
    # to show the structure as it is seen by the query
    # interpreter.
    q query \\
	    root \\
	    children \\
	    get data
</pre>
<p>The operators of the TreeQL language available for this are explained
in the section about <span class="sectref"><a href="#section3">The Tree Query Language</a></span>. This section
also explains the term <i class="term">node set</i> used above.</p></dd>
<dt><a name="3"><i class="arg">qo</i> <b class="method">result</b></a></dt>
<dd><p>This method returns a list containing the current node set.</p></dd>







|
|
|







250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
    #   values for the attribute 'data',
    #   for all nodes in the set which
    #   have such an attribute.
    # - And returns this information.
    # Below we can see the same query, but rewritten
    # to show the structure as it is seen by the query
    # interpreter.
    q query \
	    root \
	    children \
	    get data
</pre>
<p>The operators of the TreeQL language available for this are explained
in the section about <span class="sectref"><a href="#section3">The Tree Query Language</a></span>. This section
also explains the term <i class="term">node set</i> used above.</p></dd>
<dt><a name="3"><i class="arg">qo</i> <b class="method">result</b></a></dt>
<dd><p>This method returns a list containing the current node set.</p></dd>

Changes to idoc/www/tcllib/files/modules/virtchannel_base/cat.html.

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">tcl::chan::cat(n) 1 tcllib &quot;Reflected/virtual channel support&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>tcl::chan::cat - Concatenation channel</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>







|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">tcl::chan::cat(n) 1.0.3 tcllib &quot;Reflected/virtual channel support&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>tcl::chan::cat - Concatenation channel</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">TclOO</b></li>
<li>package require <b class="pkgname">tcl::chan::core <span class="opt">?1?</span></b></li>
<li>package require <b class="pkgname">tcl::chan::cat <span class="opt">?1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::tcl::chan::cat</b> <i class="arg">chan</i>...</a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>







|







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">TclOO</b></li>
<li>package require <b class="pkgname">tcl::chan::core <span class="opt">?1?</span></b></li>
<li>package require <b class="pkgname">tcl::chan::cat <span class="opt">?1.0.3?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::tcl::chan::cat</b> <i class="arg">chan</i>...</a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>

Changes to idoc/www/tcllib/files/modules/virtchannel_base/halfpipe.html.

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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'halfpipe.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- tcl::chan::halfpipe.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">tcl::chan::halfpipe(n) 1 tcllib &quot;Reflected/virtual channel support&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>tcl::chan::halfpipe - In-memory channel, half of a fifo2</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>







|













|







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
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file 'halfpipe.man' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2009, 2019 Andreas Kupries &amp;lt;[email protected]&amp;gt;
   -->
<!-- tcl::chan::halfpipe.n
   -->
<body><hr> [
   <a href="../../../../../../../../home">Tcllib Home</a>
&#124; <a href="../../../../toc.html">Main Table Of Contents</a>
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">tcl::chan::halfpipe(n) 1.0.1 tcllib &quot;Reflected/virtual channel support&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>tcl::chan::halfpipe - In-memory channel, half of a fifo2</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">TclOO</b></li>
<li>package require <b class="pkgname">tcl::chan::events <span class="opt">?1?</span></b></li>
<li>package require <b class="pkgname">tcl::chan::halfpipe <span class="opt">?1?</span></b></li>
<li>package require <b class="pkgname">tcl::chan::halfpipe <span class="opt">?1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::tcl::chan::halfpipe</b> <span class="opt">?<b class="option">-option</b> <i class="arg">value</i>...?</span></a></li>
<li><a href="#2"><i class="arg">objectCmd</i> <b class="method">put</b> <i class="arg">bytes</i></a></li>
</ul>
</div>
</div>







|
<







126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.5</b></li>
<li>package require <b class="pkgname">TclOO</b></li>
<li>package require <b class="pkgname">tcl::chan::events <span class="opt">?1?</span></b></li>
<li>package require <b class="pkgname">tcl::chan::halfpipe <span class="opt">?1.0.1?</span></b></li>

</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::tcl::chan::halfpipe</b> <span class="opt">?<b class="option">-option</b> <i class="arg">value</i>...?</span></a></li>
<li><a href="#2"><i class="arg">objectCmd</i> <b class="method">put</b> <i class="arg">bytes</i></a></li>
</ul>
</div>
</div>
198
199
200
201
202
203
204
205
206
207
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#callbacks">callbacks</a>, <a href="../../../../index.html#fifo">fifo</a>, <a href="../../../../index.html#in_memory_channel">in-memory channel</a>, <a href="../../../../index.html#reflected_channel">reflected channel</a>, <a href="../../../../index.html#tip_219">tip 219</a>, <a href="../../../../index.html#virtual_channel">virtual channel</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Channels</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>







|


197
198
199
200
201
202
203
204
205
206
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2>
<p><a href="../../../../index.html#callbacks">callbacks</a>, <a href="../../../../index.html#fifo">fifo</a>, <a href="../../../../index.html#in_memory_channel">in-memory channel</a>, <a href="../../../../index.html#reflected_channel">reflected channel</a>, <a href="../../../../index.html#tip_219">tip 219</a>, <a href="../../../../index.html#virtual_channel">virtual channel</a></p>
</div>
<div id="category" class="doctools_section"><h2><a name="category">Category</a></h2>
<p>Channels</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2009, 2019 Andreas Kupries &lt;[email protected]&gt;</p>
</div>
</div></body></html>

Changes to idoc/www/tcllib/files/modules/zip/mkzip.html.

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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">zipfile::mkzip(n) 1.2 tcllib &quot;Zip archive creation&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>zipfile::mkzip - Build a zip archive</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">API</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.6</b></li>
<li>package require <b class="pkgname">zipfile::mkzip <span class="opt">?1.2?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::zipfile::mkzip::mkzip</b> <i class="arg">zipfile</i> <span class="opt">?<b class="option">-zipkit</b>?</span> <span class="opt">?<b class="option">-runtime</b> <i class="arg">prefix</i>?</span> <span class="opt">?<b class="option">-comment</b> <i class="arg">string</i>?</span> <span class="opt">?<b class="option">-directory</b> <i class="arg">rootpath</i>?</span> <span class="opt">?<b class="option">-exclude</b> <i class="arg">exclude</i>?</span> <span class="opt">?<b class="option">--</b>?</span> <span class="opt">?<i class="arg">path</i>...?</span></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>







|



















|







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
&#124; <a href="../../../toc.html">Table Of Contents</a>
&#124; <a href="../../../../index.html">Keyword Index</a>
&#124; <a href="../../../../toc0.html">Categories</a>
&#124; <a href="../../../../toc1.html">Modules</a>
&#124; <a href="../../../../toc2.html">Applications</a>
 ] <hr>
<div class="doctools">
<h1 class="doctools_title">zipfile::mkzip(n) 1.2.1 tcllib &quot;Zip archive creation&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>zipfile::mkzip - Build a zip archive</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#section2">API</a></li>
<li class="doctools_section"><a href="#section3">Bugs, Ideas, Feedback</a></li>
<li class="doctools_section"><a href="#keywords">Keywords</a></li>
<li class="doctools_section"><a href="#category">Category</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2>
<div class="doctools_synopsis">
<ul class="doctools_requirements">
<li>package require <b class="pkgname">Tcl 8.6</b></li>
<li>package require <b class="pkgname">zipfile::mkzip <span class="opt">?1.2.1?</span></b></li>
</ul>
<ul class="doctools_syntax">
<li><a href="#1"><b class="cmd">::zipfile::mkzip::mkzip</b> <i class="arg">zipfile</i> <span class="opt">?<b class="option">-zipkit</b>?</span> <span class="opt">?<b class="option">-runtime</b> <i class="arg">prefix</i>?</span> <span class="opt">?<b class="option">-comment</b> <i class="arg">string</i>?</span> <span class="opt">?<b class="option">-directory</b> <i class="arg">rootpath</i>?</span> <span class="opt">?<b class="option">-exclude</b> <i class="arg">exclude</i>?</span> <span class="opt">?<b class="option">--</b>?</span> <span class="opt">?<i class="arg">path</i>...?</span></a></li>
</ul>
</div>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>

Changes to idoc/www/tcllib/toc.html.

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
<td class="#doctools_tocright">Asynchronous in-memory cache</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='cksum'><a href="files/modules/crc/cksum.html">cksum</a></td>
<td class="#doctools_tocright">Calculate a cksum(1) compatible checksum</td>
</tr>
<tr class="#doctools_toceven" >




<td class="#doctools_tocleft" ><a name='clock_iso8601'><a href="files/modules/clock/iso8601.html">clock_iso8601</a></td>
<td class="#doctools_tocright">Parsing ISO 8601 dates/times</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='clock_rfc2822'><a href="files/modules/clock/rfc2822.html">clock_rfc2822</a></td>
<td class="#doctools_tocright">Parsing ISO 8601 dates/times</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='cmdline'><a href="files/modules/cmdline/cmdline.html">cmdline</a></td>
<td class="#doctools_tocright">Procedures to process command lines and options.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='comm'><a href="files/modules/comm/comm.html">comm</a></td>
<td class="#doctools_tocright">A remote communication facility for Tcl (8.3 and later)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='comm_wire'><a href="files/modules/comm/comm_wire.html">comm_wire</a></td>
<td class="#doctools_tocright">The comm wire protocol</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='control'><a href="files/modules/control/control.html">control</a></td>
<td class="#doctools_tocright">Procedures for control flow structures.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='coroutine'><a href="files/modules/coroutine/tcllib_coroutine.html">coroutine</a></td>
<td class="#doctools_tocright">Coroutine based event and IO handling</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='coroutine_auto'><a href="files/modules/coroutine/coro_auto.html">coroutine::auto</a></td>
<td class="#doctools_tocright">Automatic event and IO coroutine awareness</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='counter'><a href="files/modules/counter/counter.html">counter</a></td>
<td class="#doctools_tocright">Procedures for counters and histograms</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='crc16'><a href="files/modules/crc/crc16.html">crc16</a></td>
<td class="#doctools_tocright">Perform a 16bit Cyclic Redundancy Check</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='crc32'><a href="files/modules/crc/crc32.html">crc32</a></td>
<td class="#doctools_tocright">Perform a 32bit Cyclic Redundancy Check</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='cron'><a href="files/modules/cron/cron.html">cron</a></td>
<td class="#doctools_tocright">Tool for automating the period callback of commands</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='csv'><a href="files/modules/csv/csv.html">csv</a></td>
<td class="#doctools_tocright">Procedures to handle CSV data.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='debug'><a href="files/modules/debug/debug.html">debug</a></td>
<td class="#doctools_tocright">debug narrative - core</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='debug_caller'><a href="files/modules/debug/debug_caller.html">debug::caller</a></td>
<td class="#doctools_tocright">debug narrative - caller</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='debug_heartbeat'><a href="files/modules/debug/debug_heartbeat.html">debug::heartbeat</a></td>
<td class="#doctools_tocright">debug narrative - heartbeat</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='debug_timestamp'><a href="files/modules/debug/debug_timestamp.html">debug::timestamp</a></td>
<td class="#doctools_tocright">debug narrative - timestamping</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='defer'><a href="files/modules/defer/defer.html">defer</a></td>
<td class="#doctools_tocright">Defered execution</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='deleg_method'><a href="files/modules/interp/deleg_method.html">deleg_method</a></td>
<td class="#doctools_tocright">Creation of comm delegates (snit methods)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='deleg_proc'><a href="files/modules/interp/deleg_proc.html">deleg_proc</a></td>
<td class="#doctools_tocright">Creation of comm delegates (procedures)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='des'><a href="files/modules/des/des.html">des</a></td>
<td class="#doctools_tocright">Implementation of the DES and triple-DES ciphers</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='dicttool'><a href="files/modules/dicttool/dicttool.html">dicttool</a></td>
<td class="#doctools_tocright">Dictionary Tools</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='dns'><a href="files/modules/dns/tcllib_dns.html">dns</a></td>
<td class="#doctools_tocright">Tcl Domain Name Service Client</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='docidx_intro'><a href="files/modules/doctools/docidx_intro.html">docidx_intro</a></td>
<td class="#doctools_tocright">docidx introduction</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='docidx_lang_cmdref'><a href="files/modules/doctools/docidx_lang_cmdref.html">docidx_lang_cmdref</a></td>
<td class="#doctools_tocright">docidx language command reference</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='docidx_lang_faq'><a href="files/modules/doctools/docidx_lang_faq.html">docidx_lang_faq</a></td>
<td class="#doctools_tocright">docidx language faq</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='docidx_lang_intro'><a href="files/modules/doctools/docidx_lang_intro.html">docidx_lang_intro</a></td>
<td class="#doctools_tocright">docidx language introduction</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='docidx_lang_syntax'><a href="files/modules/doctools/docidx_lang_syntax.html">docidx_lang_syntax</a></td>
<td class="#doctools_tocright">docidx language syntax</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='docidx_plugin_apiref'><a href="files/modules/doctools/docidx_plugin_apiref.html">docidx_plugin_apiref</a></td>
<td class="#doctools_tocright">docidx plugin API reference</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='docstrip'><a href="files/modules/docstrip/docstrip.html">docstrip</a></td>
<td class="#doctools_tocright">Docstrip style source code extraction</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='docstrip_util'><a href="files/modules/docstrip/docstrip_util.html">docstrip_util</a></td>
<td class="#doctools_tocright">Docstrip-related utilities</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctoc_intro'><a href="files/modules/doctools/doctoc_intro.html">doctoc_intro</a></td>
<td class="#doctools_tocright">doctoc introduction</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctoc_lang_cmdref'><a href="files/modules/doctools/doctoc_lang_cmdref.html">doctoc_lang_cmdref</a></td>
<td class="#doctools_tocright">doctoc language command reference</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctoc_lang_faq'><a href="files/modules/doctools/doctoc_lang_faq.html">doctoc_lang_faq</a></td>
<td class="#doctools_tocright">doctoc language faq</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctoc_lang_intro'><a href="files/modules/doctools/doctoc_lang_intro.html">doctoc_lang_intro</a></td>
<td class="#doctools_tocright">doctoc language introduction</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctoc_lang_syntax'><a href="files/modules/doctools/doctoc_lang_syntax.html">doctoc_lang_syntax</a></td>
<td class="#doctools_tocright">doctoc language syntax</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctoc_plugin_apiref'><a href="files/modules/doctools/doctoc_plugin_apiref.html">doctoc_plugin_apiref</a></td>
<td class="#doctools_tocright">doctoc plugin API reference</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools'><a href="files/modules/doctools/doctools.html">doctools</a></td>
<td class="#doctools_tocright">doctools - Processing documents</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools2idx_introduction'><a href="files/modules/doctools2idx/idx_introduction.html">doctools2idx_introduction</a></td>
<td class="#doctools_tocright">DocTools - Keyword indices</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools2toc_introduction'><a href="files/modules/doctools2toc/toc_introduction.html">doctools2toc_introduction</a></td>
<td class="#doctools_tocright">DocTools - Tables of Contents</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_changelog'><a href="files/modules/doctools/changelog.html">doctools::changelog</a></td>
<td class="#doctools_tocright">Processing text in Emacs ChangeLog format</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_cvs'><a href="files/modules/doctools/cvs.html">doctools::cvs</a></td>
<td class="#doctools_tocright">Processing text in 'cvs log' format</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_html_cssdefaults'><a href="files/modules/doctools2base/html_cssdefaults.html">doctools::html::cssdefaults</a></td>
<td class="#doctools_tocright">Default CSS style for HTML export plugins</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_idx'><a href="files/modules/doctools/docidx.html">doctools::idx</a></td>
<td class="#doctools_tocright">docidx - Processing indices</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_idx'><a href="files/modules/doctools2idx/idx_container.html">doctools::idx</a></td>
<td class="#doctools_tocright">Holding keyword indices</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_idx_export'><a href="files/modules/doctools2idx/idx_export.html">doctools::idx::export</a></td>
<td class="#doctools_tocright">Exporting keyword indices</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_idx_export_docidx'><a href="files/modules/doctools2idx/export_docidx.html">doctools::idx::export::docidx</a></td>
<td class="#doctools_tocright">docidx export plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_idx_export_html'><a href="files/modules/doctools2idx/idx_export_html.html">doctools::idx::export::html</a></td>
<td class="#doctools_tocright">HTML export plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_idx_export_json'><a href="files/modules/doctools2idx/idx_export_json.html">doctools::idx::export::json</a></td>
<td class="#doctools_tocright">JSON export plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_idx_export_nroff'><a href="files/modules/doctools2idx/idx_export_nroff.html">doctools::idx::export::nroff</a></td>
<td class="#doctools_tocright">nroff export plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_idx_export_text'><a href="files/modules/doctools2idx/idx_export_text.html">doctools::idx::export::text</a></td>
<td class="#doctools_tocright">plain text export plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_idx_export_wiki'><a href="files/modules/doctools2idx/idx_export_wiki.html">doctools::idx::export::wiki</a></td>
<td class="#doctools_tocright">wiki export plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_idx_import'><a href="files/modules/doctools2idx/idx_import.html">doctools::idx::import</a></td>
<td class="#doctools_tocright">Importing keyword indices</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_idx_import_docidx'><a href="files/modules/doctools2idx/import_docidx.html">doctools::idx::import::docidx</a></td>
<td class="#doctools_tocright">docidx import plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_idx_import_json'><a href="files/modules/doctools2idx/idx_import_json.html">doctools::idx::import::json</a></td>
<td class="#doctools_tocright">JSON import plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_idx_parse'><a href="files/modules/doctools2idx/idx_parse.html">doctools::idx::parse</a></td>
<td class="#doctools_tocright">Parsing text in docidx format</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_idx_structure'><a href="files/modules/doctools2idx/idx_structure.html">doctools::idx::structure</a></td>
<td class="#doctools_tocright">Docidx serialization utilities</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_msgcat'><a href="files/modules/doctools2base/tcllib_msgcat.html">doctools::msgcat</a></td>
<td class="#doctools_tocright">Message catalog management for the various document parsers</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_idx_c'><a href="files/modules/doctools2idx/idx_msgcat_c.html">doctools::msgcat::idx::c</a></td>
<td class="#doctools_tocright">Message catalog for the docidx parser (C)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_idx_de'><a href="files/modules/doctools2idx/idx_msgcat_de.html">doctools::msgcat::idx::de</a></td>
<td class="#doctools_tocright">Message catalog for the docidx parser (DE)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_idx_en'><a href="files/modules/doctools2idx/idx_msgcat_en.html">doctools::msgcat::idx::en</a></td>
<td class="#doctools_tocright">Message catalog for the docidx parser (EN)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_idx_fr'><a href="files/modules/doctools2idx/idx_msgcat_fr.html">doctools::msgcat::idx::fr</a></td>
<td class="#doctools_tocright">Message catalog for the docidx parser (FR)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_toc_c'><a href="files/modules/doctools2toc/toc_msgcat_c.html">doctools::msgcat::toc::c</a></td>
<td class="#doctools_tocright">Message catalog for the doctoc parser (C)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_toc_de'><a href="files/modules/doctools2toc/toc_msgcat_de.html">doctools::msgcat::toc::de</a></td>
<td class="#doctools_tocright">Message catalog for the doctoc parser (DE)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_toc_en'><a href="files/modules/doctools2toc/toc_msgcat_en.html">doctools::msgcat::toc::en</a></td>
<td class="#doctools_tocright">Message catalog for the doctoc parser (EN)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_toc_fr'><a href="files/modules/doctools2toc/toc_msgcat_fr.html">doctools::msgcat::toc::fr</a></td>
<td class="#doctools_tocright">Message catalog for the doctoc parser (FR)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_nroff_man_macros'><a href="files/modules/doctools2base/nroff_manmacros.html">doctools::nroff::man_macros</a></td>
<td class="#doctools_tocright">Default CSS style for NROFF export plugins</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_tcl_parse'><a href="files/modules/doctools2base/tcl_parse.html">doctools::tcl::parse</a></td>
<td class="#doctools_tocright">Processing text in 'subst -novariables' format</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_toc'><a href="files/modules/doctools2toc/toc_container.html">doctools::toc</a></td>
<td class="#doctools_tocright">Holding tables of contents</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_toc'><a href="files/modules/doctools/doctoc.html">doctools::toc</a></td>
<td class="#doctools_tocright">doctoc - Processing tables of contents</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_toc_export'><a href="files/modules/doctools2toc/toc_export.html">doctools::toc::export</a></td>
<td class="#doctools_tocright">Exporting tables of contents</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_toc_export_doctoc'><a href="files/modules/doctools2toc/export_doctoc.html">doctools::toc::export::doctoc</a></td>
<td class="#doctools_tocright">doctoc export plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_toc_export_html'><a href="files/modules/doctools2toc/toc_export_html.html">doctools::toc::export::html</a></td>
<td class="#doctools_tocright">HTML export plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_toc_export_json'><a href="files/modules/doctools2toc/toc_export_json.html">doctools::toc::export::json</a></td>
<td class="#doctools_tocright">JSON export plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_toc_export_nroff'><a href="files/modules/doctools2toc/toc_export_nroff.html">doctools::toc::export::nroff</a></td>
<td class="#doctools_tocright">nroff export plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_toc_export_text'><a href="files/modules/doctools2toc/toc_export_text.html">doctools::toc::export::text</a></td>
<td class="#doctools_tocright">plain text export plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_toc_export_wiki'><a href="files/modules/doctools2toc/toc_export_wiki.html">doctools::toc::export::wiki</a></td>
<td class="#doctools_tocright">wiki export plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_toc_import'><a href="files/modules/doctools2toc/toc_import.html">doctools::toc::import</a></td>
<td class="#doctools_tocright">Importing keyword indices</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_toc_import_doctoc'><a href="files/modules/doctools2toc/import_doctoc.html">doctools::toc::import::doctoc</a></td>
<td class="#doctools_tocright">doctoc import plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_toc_import_json'><a href="files/modules/doctools2toc/toc_import_json.html">doctools::toc::import::json</a></td>
<td class="#doctools_tocright">JSON import plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_toc_parse'><a href="files/modules/doctools2toc/toc_parse.html">doctools::toc::parse</a></td>
<td class="#doctools_tocright">Parsing text in doctoc format</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_toc_structure'><a href="files/modules/doctools2toc/toc_structure.html">doctools::toc::structure</a></td>
<td class="#doctools_tocright">Doctoc serialization utilities</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_intro'><a href="files/modules/doctools/doctools_intro.html">doctools_intro</a></td>
<td class="#doctools_tocright">doctools introduction</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_lang_cmdref'><a href="files/modules/doctools/doctools_lang_cmdref.html">doctools_lang_cmdref</a></td>
<td class="#doctools_tocright">doctools language command reference</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_lang_faq'><a href="files/modules/doctools/doctools_lang_faq.html">doctools_lang_faq</a></td>
<td class="#doctools_tocright">doctools language faq</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_lang_intro'><a href="files/modules/doctools/doctools_lang_intro.html">doctools_lang_intro</a></td>
<td class="#doctools_tocright">doctools language introduction</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_lang_syntax'><a href="files/modules/doctools/doctools_lang_syntax.html">doctools_lang_syntax</a></td>
<td class="#doctools_tocright">doctools language syntax</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_plugin_apiref'><a href="files/modules/doctools/doctools_plugin_apiref.html">doctools_plugin_apiref</a></td>
<td class="#doctools_tocright">doctools plugin API reference</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='dtplite'><a href="files/apps/dtplite.html">dtplite</a></td>
<td class="#doctools_tocright">Lightweight DocTools Markup Processor</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='dtplite'><a href="files/modules/dtplite/pkg_dtplite.html">dtplite</a></td>
<td class="#doctools_tocright">Lightweight DocTools Markup Processor</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil'><a href="files/modules/fileutil/fileutil.html">fileutil</a></td>
<td class="#doctools_tocright">Procedures implementing some file utilities</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_magic_cfront'><a href="files/modules/fumagic/cfront.html">fileutil::magic::cfront</a></td>
<td class="#doctools_tocright">Generator core for compiler of magic(5) files</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_magic_cgen'><a href="files/modules/fumagic/cgen.html">fileutil::magic::cgen</a></td>
<td class="#doctools_tocright">Generator core for compiler of magic(5) files</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_magic_filetype'><a href="files/modules/fumagic/filetypes.html">fileutil::magic::filetype</a></td>
<td class="#doctools_tocright">Procedures implementing file-type recognition</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_magic_rt'><a href="files/modules/fumagic/rtcore.html">fileutil::magic::rt</a></td>
<td class="#doctools_tocright">Runtime core for file type recognition engines written in pure Tcl</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_multi'><a href="files/modules/fileutil/multi.html">fileutil::multi</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather, standard object</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_multi_op'><a href="files/modules/fileutil/multiop.html">fileutil::multi::op</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather</td>
</tr>




<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_traverse'><a href="files/modules/fileutil/traverse.html">fileutil_traverse</a></td>
<td class="#doctools_tocright">Iterative directory traversal</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='ftp'><a href="files/modules/ftp/ftp.html">ftp</a></td>
<td class="#doctools_tocright">Client-side tcl implementation of the ftp protocol</td>







>
>
>
>



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



>
>
>
>







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
<td class="#doctools_tocright">Asynchronous in-memory cache</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='cksum'><a href="files/modules/crc/cksum.html">cksum</a></td>
<td class="#doctools_tocright">Calculate a cksum(1) compatible checksum</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='clay'><a href="files/modules/clay/clay.html">clay</a></td>
<td class="#doctools_tocright">A minimalist framework for large scale OO Projects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='clock_iso8601'><a href="files/modules/clock/iso8601.html">clock_iso8601</a></td>
<td class="#doctools_tocright">Parsing ISO 8601 dates/times</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='clock_rfc2822'><a href="files/modules/clock/rfc2822.html">clock_rfc2822</a></td>
<td class="#doctools_tocright">Parsing ISO 8601 dates/times</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='cmdline'><a href="files/modules/cmdline/cmdline.html">cmdline</a></td>
<td class="#doctools_tocright">Procedures to process command lines and options.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='comm'><a href="files/modules/comm/comm.html">comm</a></td>
<td class="#doctools_tocright">A remote communication facility for Tcl (8.3 and later)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='comm_wire'><a href="files/modules/comm/comm_wire.html">comm_wire</a></td>
<td class="#doctools_tocright">The comm wire protocol</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='control'><a href="files/modules/control/control.html">control</a></td>
<td class="#doctools_tocright">Procedures for control flow structures.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='coroutine'><a href="files/modules/coroutine/tcllib_coroutine.html">coroutine</a></td>
<td class="#doctools_tocright">Coroutine based event and IO handling</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='coroutine_auto'><a href="files/modules/coroutine/coro_auto.html">coroutine::auto</a></td>
<td class="#doctools_tocright">Automatic event and IO coroutine awareness</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='counter'><a href="files/modules/counter/counter.html">counter</a></td>
<td class="#doctools_tocright">Procedures for counters and histograms</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='crc16'><a href="files/modules/crc/crc16.html">crc16</a></td>
<td class="#doctools_tocright">Perform a 16bit Cyclic Redundancy Check</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='crc32'><a href="files/modules/crc/crc32.html">crc32</a></td>
<td class="#doctools_tocright">Perform a 32bit Cyclic Redundancy Check</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='cron'><a href="files/modules/cron/cron.html">cron</a></td>
<td class="#doctools_tocright">Tool for automating the period callback of commands</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='csv'><a href="files/modules/csv/csv.html">csv</a></td>
<td class="#doctools_tocright">Procedures to handle CSV data.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='debug'><a href="files/modules/debug/debug.html">debug</a></td>
<td class="#doctools_tocright">debug narrative - core</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='debug_caller'><a href="files/modules/debug/debug_caller.html">debug::caller</a></td>
<td class="#doctools_tocright">debug narrative - caller</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='debug_heartbeat'><a href="files/modules/debug/debug_heartbeat.html">debug::heartbeat</a></td>
<td class="#doctools_tocright">debug narrative - heartbeat</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='debug_timestamp'><a href="files/modules/debug/debug_timestamp.html">debug::timestamp</a></td>
<td class="#doctools_tocright">debug narrative - timestamping</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='defer'><a href="files/modules/defer/defer.html">defer</a></td>
<td class="#doctools_tocright">Defered execution</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='deleg_method'><a href="files/modules/interp/deleg_method.html">deleg_method</a></td>
<td class="#doctools_tocright">Creation of comm delegates (snit methods)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='deleg_proc'><a href="files/modules/interp/deleg_proc.html">deleg_proc</a></td>
<td class="#doctools_tocright">Creation of comm delegates (procedures)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='des'><a href="files/modules/des/des.html">des</a></td>
<td class="#doctools_tocright">Implementation of the DES and triple-DES ciphers</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='dicttool'><a href="files/modules/dicttool/dicttool.html">dicttool</a></td>
<td class="#doctools_tocright">Dictionary Tools</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='dns'><a href="files/modules/dns/tcllib_dns.html">dns</a></td>
<td class="#doctools_tocright">Tcl Domain Name Service Client</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='docidx_intro'><a href="files/modules/doctools/docidx_intro.html">docidx_intro</a></td>
<td class="#doctools_tocright">docidx introduction</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='docidx_lang_cmdref'><a href="files/modules/doctools/docidx_lang_cmdref.html">docidx_lang_cmdref</a></td>
<td class="#doctools_tocright">docidx language command reference</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='docidx_lang_faq'><a href="files/modules/doctools/docidx_lang_faq.html">docidx_lang_faq</a></td>
<td class="#doctools_tocright">docidx language faq</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='docidx_lang_intro'><a href="files/modules/doctools/docidx_lang_intro.html">docidx_lang_intro</a></td>
<td class="#doctools_tocright">docidx language introduction</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='docidx_lang_syntax'><a href="files/modules/doctools/docidx_lang_syntax.html">docidx_lang_syntax</a></td>
<td class="#doctools_tocright">docidx language syntax</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='docidx_plugin_apiref'><a href="files/modules/doctools/docidx_plugin_apiref.html">docidx_plugin_apiref</a></td>
<td class="#doctools_tocright">docidx plugin API reference</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='docstrip'><a href="files/modules/docstrip/docstrip.html">docstrip</a></td>
<td class="#doctools_tocright">Docstrip style source code extraction</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='docstrip_util'><a href="files/modules/docstrip/docstrip_util.html">docstrip_util</a></td>
<td class="#doctools_tocright">Docstrip-related utilities</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctoc_intro'><a href="files/modules/doctools/doctoc_intro.html">doctoc_intro</a></td>
<td class="#doctools_tocright">doctoc introduction</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctoc_lang_cmdref'><a href="files/modules/doctools/doctoc_lang_cmdref.html">doctoc_lang_cmdref</a></td>
<td class="#doctools_tocright">doctoc language command reference</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctoc_lang_faq'><a href="files/modules/doctools/doctoc_lang_faq.html">doctoc_lang_faq</a></td>
<td class="#doctools_tocright">doctoc language faq</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctoc_lang_intro'><a href="files/modules/doctools/doctoc_lang_intro.html">doctoc_lang_intro</a></td>
<td class="#doctools_tocright">doctoc language introduction</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctoc_lang_syntax'><a href="files/modules/doctools/doctoc_lang_syntax.html">doctoc_lang_syntax</a></td>
<td class="#doctools_tocright">doctoc language syntax</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctoc_plugin_apiref'><a href="files/modules/doctools/doctoc_plugin_apiref.html">doctoc_plugin_apiref</a></td>
<td class="#doctools_tocright">doctoc plugin API reference</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools'><a href="files/modules/doctools/doctools.html">doctools</a></td>
<td class="#doctools_tocright">doctools - Processing documents</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools2idx_introduction'><a href="files/modules/doctools2idx/idx_introduction.html">doctools2idx_introduction</a></td>
<td class="#doctools_tocright">DocTools - Keyword indices</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools2toc_introduction'><a href="files/modules/doctools2toc/toc_introduction.html">doctools2toc_introduction</a></td>
<td class="#doctools_tocright">DocTools - Tables of Contents</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_changelog'><a href="files/modules/doctools/changelog.html">doctools::changelog</a></td>
<td class="#doctools_tocright">Processing text in Emacs ChangeLog format</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_cvs'><a href="files/modules/doctools/cvs.html">doctools::cvs</a></td>
<td class="#doctools_tocright">Processing text in 'cvs log' format</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_html_cssdefaults'><a href="files/modules/doctools2base/html_cssdefaults.html">doctools::html::cssdefaults</a></td>
<td class="#doctools_tocright">Default CSS style for HTML export plugins</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_idx'><a href="files/modules/doctools/docidx.html">doctools::idx</a></td>
<td class="#doctools_tocright">docidx - Processing indices</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_idx'><a href="files/modules/doctools2idx/idx_container.html">doctools::idx</a></td>
<td class="#doctools_tocright">Holding keyword indices</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_idx_export'><a href="files/modules/doctools2idx/idx_export.html">doctools::idx::export</a></td>
<td class="#doctools_tocright">Exporting keyword indices</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_idx_export_docidx'><a href="files/modules/doctools2idx/export_docidx.html">doctools::idx::export::docidx</a></td>
<td class="#doctools_tocright">docidx export plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_idx_export_html'><a href="files/modules/doctools2idx/idx_export_html.html">doctools::idx::export::html</a></td>
<td class="#doctools_tocright">HTML export plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_idx_export_json'><a href="files/modules/doctools2idx/idx_export_json.html">doctools::idx::export::json</a></td>
<td class="#doctools_tocright">JSON export plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_idx_export_nroff'><a href="files/modules/doctools2idx/idx_export_nroff.html">doctools::idx::export::nroff</a></td>
<td class="#doctools_tocright">nroff export plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_idx_export_text'><a href="files/modules/doctools2idx/idx_export_text.html">doctools::idx::export::text</a></td>
<td class="#doctools_tocright">plain text export plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_idx_export_wiki'><a href="files/modules/doctools2idx/idx_export_wiki.html">doctools::idx::export::wiki</a></td>
<td class="#doctools_tocright">wiki export plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_idx_import'><a href="files/modules/doctools2idx/idx_import.html">doctools::idx::import</a></td>
<td class="#doctools_tocright">Importing keyword indices</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_idx_import_docidx'><a href="files/modules/doctools2idx/import_docidx.html">doctools::idx::import::docidx</a></td>
<td class="#doctools_tocright">docidx import plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_idx_import_json'><a href="files/modules/doctools2idx/idx_import_json.html">doctools::idx::import::json</a></td>
<td class="#doctools_tocright">JSON import plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_idx_parse'><a href="files/modules/doctools2idx/idx_parse.html">doctools::idx::parse</a></td>
<td class="#doctools_tocright">Parsing text in docidx format</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_idx_structure'><a href="files/modules/doctools2idx/idx_structure.html">doctools::idx::structure</a></td>
<td class="#doctools_tocright">Docidx serialization utilities</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_msgcat'><a href="files/modules/doctools2base/tcllib_msgcat.html">doctools::msgcat</a></td>
<td class="#doctools_tocright">Message catalog management for the various document parsers</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_idx_c'><a href="files/modules/doctools2idx/idx_msgcat_c.html">doctools::msgcat::idx::c</a></td>
<td class="#doctools_tocright">Message catalog for the docidx parser (C)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_idx_de'><a href="files/modules/doctools2idx/idx_msgcat_de.html">doctools::msgcat::idx::de</a></td>
<td class="#doctools_tocright">Message catalog for the docidx parser (DE)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_idx_en'><a href="files/modules/doctools2idx/idx_msgcat_en.html">doctools::msgcat::idx::en</a></td>
<td class="#doctools_tocright">Message catalog for the docidx parser (EN)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_idx_fr'><a href="files/modules/doctools2idx/idx_msgcat_fr.html">doctools::msgcat::idx::fr</a></td>
<td class="#doctools_tocright">Message catalog for the docidx parser (FR)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_toc_c'><a href="files/modules/doctools2toc/toc_msgcat_c.html">doctools::msgcat::toc::c</a></td>
<td class="#doctools_tocright">Message catalog for the doctoc parser (C)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_toc_de'><a href="files/modules/doctools2toc/toc_msgcat_de.html">doctools::msgcat::toc::de</a></td>
<td class="#doctools_tocright">Message catalog for the doctoc parser (DE)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_toc_en'><a href="files/modules/doctools2toc/toc_msgcat_en.html">doctools::msgcat::toc::en</a></td>
<td class="#doctools_tocright">Message catalog for the doctoc parser (EN)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_msgcat_toc_fr'><a href="files/modules/doctools2toc/toc_msgcat_fr.html">doctools::msgcat::toc::fr</a></td>
<td class="#doctools_tocright">Message catalog for the doctoc parser (FR)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_nroff_man_macros'><a href="files/modules/doctools2base/nroff_manmacros.html">doctools::nroff::man_macros</a></td>
<td class="#doctools_tocright">Default CSS style for NROFF export plugins</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_tcl_parse'><a href="files/modules/doctools2base/tcl_parse.html">doctools::tcl::parse</a></td>
<td class="#doctools_tocright">Processing text in 'subst -novariables' format</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_toc'><a href="files/modules/doctools2toc/toc_container.html">doctools::toc</a></td>
<td class="#doctools_tocright">Holding tables of contents</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_toc'><a href="files/modules/doctools/doctoc.html">doctools::toc</a></td>
<td class="#doctools_tocright">doctoc - Processing tables of contents</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_toc_export'><a href="files/modules/doctools2toc/toc_export.html">doctools::toc::export</a></td>
<td class="#doctools_tocright">Exporting tables of contents</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_toc_export_doctoc'><a href="files/modules/doctools2toc/export_doctoc.html">doctools::toc::export::doctoc</a></td>
<td class="#doctools_tocright">doctoc export plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_toc_export_html'><a href="files/modules/doctools2toc/toc_export_html.html">doctools::toc::export::html</a></td>
<td class="#doctools_tocright">HTML export plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_toc_export_json'><a href="files/modules/doctools2toc/toc_export_json.html">doctools::toc::export::json</a></td>
<td class="#doctools_tocright">JSON export plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_toc_export_nroff'><a href="files/modules/doctools2toc/toc_export_nroff.html">doctools::toc::export::nroff</a></td>
<td class="#doctools_tocright">nroff export plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_toc_export_text'><a href="files/modules/doctools2toc/toc_export_text.html">doctools::toc::export::text</a></td>
<td class="#doctools_tocright">plain text export plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_toc_export_wiki'><a href="files/modules/doctools2toc/toc_export_wiki.html">doctools::toc::export::wiki</a></td>
<td class="#doctools_tocright">wiki export plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_toc_import'><a href="files/modules/doctools2toc/toc_import.html">doctools::toc::import</a></td>
<td class="#doctools_tocright">Importing keyword indices</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_toc_import_doctoc'><a href="files/modules/doctools2toc/import_doctoc.html">doctools::toc::import::doctoc</a></td>
<td class="#doctools_tocright">doctoc import plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_toc_import_json'><a href="files/modules/doctools2toc/toc_import_json.html">doctools::toc::import::json</a></td>
<td class="#doctools_tocright">JSON import plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_toc_parse'><a href="files/modules/doctools2toc/toc_parse.html">doctools::toc::parse</a></td>
<td class="#doctools_tocright">Parsing text in doctoc format</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_toc_structure'><a href="files/modules/doctools2toc/toc_structure.html">doctools::toc::structure</a></td>
<td class="#doctools_tocright">Doctoc serialization utilities</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_intro'><a href="files/modules/doctools/doctools_intro.html">doctools_intro</a></td>
<td class="#doctools_tocright">doctools introduction</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_lang_cmdref'><a href="files/modules/doctools/doctools_lang_cmdref.html">doctools_lang_cmdref</a></td>
<td class="#doctools_tocright">doctools language command reference</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_lang_faq'><a href="files/modules/doctools/doctools_lang_faq.html">doctools_lang_faq</a></td>
<td class="#doctools_tocright">doctools language faq</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_lang_intro'><a href="files/modules/doctools/doctools_lang_intro.html">doctools_lang_intro</a></td>
<td class="#doctools_tocright">doctools language introduction</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='doctools_lang_syntax'><a href="files/modules/doctools/doctools_lang_syntax.html">doctools_lang_syntax</a></td>
<td class="#doctools_tocright">doctools language syntax</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='doctools_plugin_apiref'><a href="files/modules/doctools/doctools_plugin_apiref.html">doctools_plugin_apiref</a></td>
<td class="#doctools_tocright">doctools plugin API reference</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='dtplite'><a href="files/apps/dtplite.html">dtplite</a></td>
<td class="#doctools_tocright">Lightweight DocTools Markup Processor</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='dtplite'><a href="files/modules/dtplite/pkg_dtplite.html">dtplite</a></td>
<td class="#doctools_tocright">Lightweight DocTools Markup Processor</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil'><a href="files/modules/fileutil/fileutil.html">fileutil</a></td>
<td class="#doctools_tocright">Procedures implementing some file utilities</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_magic_cfront'><a href="files/modules/fumagic/cfront.html">fileutil::magic::cfront</a></td>
<td class="#doctools_tocright">Generator core for compiler of magic(5) files</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_magic_cgen'><a href="files/modules/fumagic/cgen.html">fileutil::magic::cgen</a></td>
<td class="#doctools_tocright">Generator core for compiler of magic(5) files</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_magic_filetype'><a href="files/modules/fumagic/filetypes.html">fileutil::magic::filetype</a></td>
<td class="#doctools_tocright">Procedures implementing file-type recognition</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_magic_rt'><a href="files/modules/fumagic/rtcore.html">fileutil::magic::rt</a></td>
<td class="#doctools_tocright">Runtime core for file type recognition engines written in pure Tcl</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_multi'><a href="files/modules/fileutil/multi.html">fileutil::multi</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather, standard object</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_multi_op'><a href="files/modules/fileutil/multiop.html">fileutil::multi::op</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_paths'><a href="files/modules/fileutil/paths.html">fileutil::paths</a></td>
<td class="#doctools_tocright">Manage search path pools</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_traverse'><a href="files/modules/fileutil/traverse.html">fileutil_traverse</a></td>
<td class="#doctools_tocright">Iterative directory traversal</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='ftp'><a href="files/modules/ftp/ftp.html">ftp</a></td>
<td class="#doctools_tocright">Client-side tcl implementation of the ftp protocol</td>
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
<td class="#doctools_tocright">Procedures to generate HTML structures</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='htmlparse'><a href="files/modules/htmlparse/htmlparse.html">htmlparse</a></td>
<td class="#doctools_tocright">Procedures to parse HTML strings</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='huddle'><a href="files/modules/yaml/huddle.html">huddle</a></td>
<td class="#doctools_tocright">Create and manipulate huddle object</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='ident'><a href="files/modules/ident/ident.html">ident</a></td>
<td class="#doctools_tocright">Ident protocol client</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='imap4'><a href="files/modules/imap4/imap4.html">imap4</a></td>
<td class="#doctools_tocright">imap client-side tcl implementation of imap protocol</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='inifile'><a href="files/modules/inifile/ini.html">inifile</a></td>
<td class="#doctools_tocright">Parsing of Windows INI files</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='interp'><a href="files/modules/interp/tcllib_interp.html">interp</a></td>
<td class="#doctools_tocright">Interp creation and aliasing</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='irc'><a href="files/modules/irc/irc.html">irc</a></td>
<td class="#doctools_tocright">Create IRC connection and interface.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='javascript'><a href="files/modules/javascript/javascript.html">javascript</a></td>
<td class="#doctools_tocright">Procedures to generate HTML and Java Script structures.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='jpeg'><a href="files/modules/jpeg/jpeg.html">jpeg</a></td>
<td class="#doctools_tocright">JPEG querying and manipulation of meta data</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='json'><a href="files/modules/json/json.html">json</a></td>
<td class="#doctools_tocright">JSON parser</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='json_write'><a href="files/modules/json/json_write.html">json::write</a></td>
<td class="#doctools_tocright">JSON generation</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='lambda'><a href="files/modules/lambda/lambda.html">lambda</a></td>
<td class="#doctools_tocright">Utility commands for anonymous procedures</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='lazyset'><a href="files/modules/lazyset/lazyset.html">lazyset</a></td>
<td class="#doctools_tocright">Lazy evaluation</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='ldap'><a href="files/modules/ldap/ldap.html">ldap</a></td>
<td class="#doctools_tocright">LDAP client</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='ldapx'><a href="files/modules/ldap/ldapx.html">ldapx</a></td>
<td class="#doctools_tocright">LDAP extended object interface</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='log'><a href="files/modules/log/log.html">log</a></td>
<td class="#doctools_tocright">Procedures to log messages of libraries and applications.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='logger'><a href="files/modules/log/logger.html">logger</a></td>
<td class="#doctools_tocright">System to control logging of events.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='logger_appender'><a href="files/modules/log/loggerAppender.html">logger::appender</a></td>
<td class="#doctools_tocright">Collection of predefined appenders for logger</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='logger_utils'><a href="files/modules/log/loggerUtils.html">logger::utils</a></td>
<td class="#doctools_tocright">Utilities for logger</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='map_geocode_nominatim'><a href="files/modules/map/map_geocode_nominatim.html">map::geocode::nominatim</a></td>
<td class="#doctools_tocright">Resolving geographical names with a Nominatim service</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='map_slippy'><a href="files/modules/map/map_slippy.html">map::slippy</a></td>
<td class="#doctools_tocright">Common code for slippy based map packages</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='map_slippy_cache'><a href="files/modules/map/map_slippy_cache.html">map::slippy::cache</a></td>
<td class="#doctools_tocright">Management of a tile cache in the local filesystem</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='map_slippy_fetcher'><a href="files/modules/map/map_slippy_fetcher.html">map::slippy::fetcher</a></td>
<td class="#doctools_tocright">Accessing a server providing tiles for slippy-based maps</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='mapproj'><a href="files/modules/mapproj/mapproj.html">mapproj</a></td>
<td class="#doctools_tocright">Map projection routines</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='markdown'><a href="files/modules/markdown/markdown.html">markdown</a></td>
<td class="#doctools_tocright">Converts Markdown text to HTML</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math'><a href="files/modules/math/math.html">math</a></td>
<td class="#doctools_tocright">Tcl Math Library</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_bigfloat'><a href="files/modules/math/bigfloat.html">math::bigfloat</a></td>
<td class="#doctools_tocright">Arbitrary precision floating-point numbers</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_bignum'><a href="files/modules/math/bignum.html">math::bignum</a></td>
<td class="#doctools_tocright">Arbitrary precision integer numbers</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_calculus'><a href="files/modules/math/calculus.html">math::calculus</a></td>
<td class="#doctools_tocright">Integration and ordinary differential equations</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_calculus_romberg'><a href="files/modules/math/romberg.html">math::calculus::romberg</a></td>
<td class="#doctools_tocright">Romberg integration</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_calculus_symdiff'><a href="files/modules/math/symdiff.html">math::calculus::symdiff</a></td>
<td class="#doctools_tocright">Symbolic differentiation for Tcl</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_combinatorics'><a href="files/modules/math/combinatorics.html">math::combinatorics</a></td>
<td class="#doctools_tocright">Combinatorial functions in the Tcl Math Library</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_complexnumbers'><a href="files/modules/math/qcomplex.html">math::complexnumbers</a></td>
<td class="#doctools_tocright">Straightforward complex number package</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_constants'><a href="files/modules/math/constants.html">math::constants</a></td>
<td class="#doctools_tocright">Mathematical and numerical constants</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_decimal'><a href="files/modules/math/decimal.html">math::decimal</a></td>
<td class="#doctools_tocright">General decimal arithmetic</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_exact'><a href="files/modules/math/exact.html">math::exact</a></td>
<td class="#doctools_tocright">Exact Real Arithmetic</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_fourier'><a href="files/modules/math/fourier.html">math::fourier</a></td>
<td class="#doctools_tocright">Discrete and fast fourier transforms</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_fuzzy'><a href="files/modules/math/fuzzy.html">math::fuzzy</a></td>
<td class="#doctools_tocright">Fuzzy comparison of floating-point numbers</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_geometry'><a href="files/modules/math/math_geometry.html">math::geometry</a></td>
<td class="#doctools_tocright">Geometrical computations</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_interpolate'><a href="files/modules/math/interpolate.html">math::interpolate</a></td>
<td class="#doctools_tocright">Interpolation routines</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_linearalgebra'><a href="files/modules/math/linalg.html">math::linearalgebra</a></td>
<td class="#doctools_tocright">Linear Algebra</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_numtheory'><a href="files/modules/math/numtheory.html">math::numtheory</a></td>
<td class="#doctools_tocright">Number Theory</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_optimize'><a href="files/modules/math/optimize.html">math::optimize</a></td>
<td class="#doctools_tocright">Optimisation routines</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_pca'><a href="files/modules/math/pca.html">math::PCA</a></td>
<td class="#doctools_tocright">Package for Principal Component Analysis</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_polynomials'><a href="files/modules/math/polynomials.html">math::polynomials</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>




<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_rationalfunctions'><a href="files/modules/math/rational_funcs.html">math::rationalfunctions</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_roman'><a href="files/modules/math/roman.html">math::roman</a></td>
<td class="#doctools_tocright">Tools for creating and manipulating roman numerals</td>







>
>
>
>



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



>
>
>
>







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
<td class="#doctools_tocright">Procedures to generate HTML structures</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='htmlparse'><a href="files/modules/htmlparse/htmlparse.html">htmlparse</a></td>
<td class="#doctools_tocright">Procedures to parse HTML strings</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='httpd'><a href="files/modules/httpd/httpd.html">httpd</a></td>
<td class="#doctools_tocright">A TclOO and coroutine based web server</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='huddle'><a href="files/modules/yaml/huddle.html">huddle</a></td>
<td class="#doctools_tocright">Create and manipulate huddle object</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='ident'><a href="files/modules/ident/ident.html">ident</a></td>
<td class="#doctools_tocright">Ident protocol client</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='imap4'><a href="files/modules/imap4/imap4.html">imap4</a></td>
<td class="#doctools_tocright">imap client-side tcl implementation of imap protocol</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='inifile'><a href="files/modules/inifile/ini.html">inifile</a></td>
<td class="#doctools_tocright">Parsing of Windows INI files</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='interp'><a href="files/modules/interp/tcllib_interp.html">interp</a></td>
<td class="#doctools_tocright">Interp creation and aliasing</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='irc'><a href="files/modules/irc/irc.html">irc</a></td>
<td class="#doctools_tocright">Create IRC connection and interface.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='javascript'><a href="files/modules/javascript/javascript.html">javascript</a></td>
<td class="#doctools_tocright">Procedures to generate HTML and Java Script structures.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='jpeg'><a href="files/modules/jpeg/jpeg.html">jpeg</a></td>
<td class="#doctools_tocright">JPEG querying and manipulation of meta data</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='json'><a href="files/modules/json/json.html">json</a></td>
<td class="#doctools_tocright">JSON parser</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='json_write'><a href="files/modules/json/json_write.html">json::write</a></td>
<td class="#doctools_tocright">JSON generation</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='lambda'><a href="files/modules/lambda/lambda.html">lambda</a></td>
<td class="#doctools_tocright">Utility commands for anonymous procedures</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='lazyset'><a href="files/modules/lazyset/lazyset.html">lazyset</a></td>
<td class="#doctools_tocright">Lazy evaluation</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='ldap'><a href="files/modules/ldap/ldap.html">ldap</a></td>
<td class="#doctools_tocright">LDAP client</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='ldapx'><a href="files/modules/ldap/ldapx.html">ldapx</a></td>
<td class="#doctools_tocright">LDAP extended object interface</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='log'><a href="files/modules/log/log.html">log</a></td>
<td class="#doctools_tocright">Procedures to log messages of libraries and applications.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='logger'><a href="files/modules/log/logger.html">logger</a></td>
<td class="#doctools_tocright">System to control logging of events.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='logger_appender'><a href="files/modules/log/loggerAppender.html">logger::appender</a></td>
<td class="#doctools_tocright">Collection of predefined appenders for logger</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='logger_utils'><a href="files/modules/log/loggerUtils.html">logger::utils</a></td>
<td class="#doctools_tocright">Utilities for logger</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='map_geocode_nominatim'><a href="files/modules/map/map_geocode_nominatim.html">map::geocode::nominatim</a></td>
<td class="#doctools_tocright">Resolving geographical names with a Nominatim service</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='map_slippy'><a href="files/modules/map/map_slippy.html">map::slippy</a></td>
<td class="#doctools_tocright">Common code for slippy based map packages</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='map_slippy_cache'><a href="files/modules/map/map_slippy_cache.html">map::slippy::cache</a></td>
<td class="#doctools_tocright">Management of a tile cache in the local filesystem</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='map_slippy_fetcher'><a href="files/modules/map/map_slippy_fetcher.html">map::slippy::fetcher</a></td>
<td class="#doctools_tocright">Accessing a server providing tiles for slippy-based maps</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='mapproj'><a href="files/modules/mapproj/mapproj.html">mapproj</a></td>
<td class="#doctools_tocright">Map projection routines</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='markdown'><a href="files/modules/markdown/markdown.html">markdown</a></td>
<td class="#doctools_tocright">Converts Markdown text to HTML</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math'><a href="files/modules/math/math.html">math</a></td>
<td class="#doctools_tocright">Tcl Math Library</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_bigfloat'><a href="files/modules/math/bigfloat.html">math::bigfloat</a></td>
<td class="#doctools_tocright">Arbitrary precision floating-point numbers</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_bignum'><a href="files/modules/math/bignum.html">math::bignum</a></td>
<td class="#doctools_tocright">Arbitrary precision integer numbers</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_calculus'><a href="files/modules/math/calculus.html">math::calculus</a></td>
<td class="#doctools_tocright">Integration and ordinary differential equations</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_calculus_romberg'><a href="files/modules/math/romberg.html">math::calculus::romberg</a></td>
<td class="#doctools_tocright">Romberg integration</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_calculus_symdiff'><a href="files/modules/math/symdiff.html">math::calculus::symdiff</a></td>
<td class="#doctools_tocright">Symbolic differentiation for Tcl</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_combinatorics'><a href="files/modules/math/combinatorics.html">math::combinatorics</a></td>
<td class="#doctools_tocright">Combinatorial functions in the Tcl Math Library</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_complexnumbers'><a href="files/modules/math/qcomplex.html">math::complexnumbers</a></td>
<td class="#doctools_tocright">Straightforward complex number package</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_constants'><a href="files/modules/math/constants.html">math::constants</a></td>
<td class="#doctools_tocright">Mathematical and numerical constants</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_decimal'><a href="files/modules/math/decimal.html">math::decimal</a></td>
<td class="#doctools_tocright">General decimal arithmetic</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_exact'><a href="files/modules/math/exact.html">math::exact</a></td>
<td class="#doctools_tocright">Exact Real Arithmetic</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_fourier'><a href="files/modules/math/fourier.html">math::fourier</a></td>
<td class="#doctools_tocright">Discrete and fast fourier transforms</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_fuzzy'><a href="files/modules/math/fuzzy.html">math::fuzzy</a></td>
<td class="#doctools_tocright">Fuzzy comparison of floating-point numbers</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_geometry'><a href="files/modules/math/math_geometry.html">math::geometry</a></td>
<td class="#doctools_tocright">Geometrical computations</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_interpolate'><a href="files/modules/math/interpolate.html">math::interpolate</a></td>
<td class="#doctools_tocright">Interpolation routines</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_linearalgebra'><a href="files/modules/math/linalg.html">math::linearalgebra</a></td>
<td class="#doctools_tocright">Linear Algebra</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_numtheory'><a href="files/modules/math/numtheory.html">math::numtheory</a></td>
<td class="#doctools_tocright">Number Theory</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_optimize'><a href="files/modules/math/optimize.html">math::optimize</a></td>
<td class="#doctools_tocright">Optimisation routines</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_pca'><a href="files/modules/math/pca.html">math::PCA</a></td>
<td class="#doctools_tocright">Package for Principal Component Analysis</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_polynomials'><a href="files/modules/math/polynomials.html">math::polynomials</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_quasirandom'><a href="files/modules/math/quasirandom.html">math::quasirandom</a></td>
<td class="#doctools_tocright">Quasi-random points for integration and Monte Carlo type methods</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_rationalfunctions'><a href="files/modules/math/rational_funcs.html">math::rationalfunctions</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_roman'><a href="files/modules/math/roman.html">math::roman</a></td>
<td class="#doctools_tocright">Tools for creating and manipulating roman numerals</td>
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
<td class="#doctools_tocright">Create and manipulate directed graph objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_list'><a href="files/modules/struct/struct_list.html">struct::list</a></td>
<td class="#doctools_tocright">Procedures for manipulating lists</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='struct_matrix'><a href="files/modules/struct/matrix.html">struct::matrix</a></td>
<td class="#doctools_tocright">Create and manipulate matrix objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_matrix_v1'><a href="files/modules/struct/matrix1.html">struct::matrix_v1</a></td>
<td class="#doctools_tocright">Create and manipulate matrix objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_pool'><a href="files/modules/struct/pool.html">struct::pool</a></td>
<td class="#doctools_tocright">Create and manipulate pool objects (of discrete items)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_prioqueue'><a href="files/modules/struct/prioqueue.html">struct::prioqueue</a></td>
<td class="#doctools_tocright">Create and manipulate prioqueue objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_queue'><a href="files/modules/struct/queue.html">struct::queue</a></td>
<td class="#doctools_tocright">Create and manipulate queue objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_record'><a href="files/modules/struct/record.html">struct::record</a></td>
<td class="#doctools_tocright">Define and create records (similar to 'C' structures)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_set'><a href="files/modules/struct/struct_set.html">struct::set</a></td>
<td class="#doctools_tocright">Procedures for manipulating sets</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_skiplist'><a href="files/modules/struct/skiplist.html">struct::skiplist</a></td>
<td class="#doctools_tocright">Create and manipulate skiplists</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_stack'><a href="files/modules/struct/stack.html">struct::stack</a></td>
<td class="#doctools_tocright">Create and manipulate stack objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_tree'><a href="files/modules/struct/struct_tree.html">struct::tree</a></td>
<td class="#doctools_tocright">Create and manipulate tree objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_tree_v1'><a href="files/modules/struct/struct_tree1.html">struct::tree_v1</a></td>
<td class="#doctools_tocright">Create and manipulate tree objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='sum'><a href="files/modules/crc/sum.html">sum</a></td>
<td class="#doctools_tocright">Calculate a sum(1) compatible checksum</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='switched'><a href="files/modules/stooop/switched.html">switched</a></td>
<td class="#doctools_tocright">switch/option management.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tar'><a href="files/modules/tar/tar.html">tar</a></td>
<td class="#doctools_tocright">Tar file creation, extraction &amp; manipulation</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_cat'><a href="files/modules/virtchannel_base/cat.html">tcl::chan::cat</a></td>
<td class="#doctools_tocright">Concatenation channel</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_core'><a href="files/modules/virtchannel_core/core.html">tcl::chan::core</a></td>
<td class="#doctools_tocright">Basic reflected/virtual channel support</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_events'><a href="files/modules/virtchannel_core/events.html">tcl::chan::events</a></td>
<td class="#doctools_tocright">Event support for reflected/virtual channels</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_facade'><a href="files/modules/virtchannel_base/facade.html">tcl::chan::facade</a></td>
<td class="#doctools_tocright">Facade channel</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_fifo'><a href="files/modules/virtchannel_base/tcllib_fifo.html">tcl::chan::fifo</a></td>
<td class="#doctools_tocright">In-memory fifo channel</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_fifo2'><a href="files/modules/virtchannel_base/tcllib_fifo2.html">tcl::chan::fifo2</a></td>
<td class="#doctools_tocright">In-memory interconnected fifo channels</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_halfpipe'><a href="files/modules/virtchannel_base/halfpipe.html">tcl::chan::halfpipe</a></td>
<td class="#doctools_tocright">In-memory channel, half of a fifo2</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_memchan'><a href="files/modules/virtchannel_base/tcllib_memchan.html">tcl::chan::memchan</a></td>
<td class="#doctools_tocright">In-memory channel</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_null'><a href="files/modules/virtchannel_base/tcllib_null.html">tcl::chan::null</a></td>
<td class="#doctools_tocright">Null channel</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_nullzero'><a href="files/modules/virtchannel_base/nullzero.html">tcl::chan::nullzero</a></td>
<td class="#doctools_tocright">Null/Zero channel combination</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_random'><a href="files/modules/virtchannel_base/tcllib_random.html">tcl::chan::random</a></td>
<td class="#doctools_tocright">Random channel</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_std'><a href="files/modules/virtchannel_base/std.html">tcl::chan::std</a></td>
<td class="#doctools_tocright">Standard I/O, unification of stdin and stdout</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_string'><a href="files/modules/virtchannel_base/tcllib_string.html">tcl::chan::string</a></td>
<td class="#doctools_tocright">Read-only in-memory channel</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_textwindow'><a href="files/modules/virtchannel_base/textwindow.html">tcl::chan::textwindow</a></td>
<td class="#doctools_tocright">Textwindow channel</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_variable'><a href="files/modules/virtchannel_base/tcllib_variable.html">tcl::chan::variable</a></td>
<td class="#doctools_tocright">In-memory channel using variable for storage</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_zero'><a href="files/modules/virtchannel_base/tcllib_zero.html">tcl::chan::zero</a></td>
<td class="#doctools_tocright">Zero channel</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_randomseed'><a href="files/modules/virtchannel_base/randseed.html">tcl::randomseed</a></td>
<td class="#doctools_tocright">Utilities for random channels</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_transform_adler32'><a href="files/modules/virtchannel_transform/adler32.html">tcl::transform::adler32</a></td>
<td class="#doctools_tocright">Adler32 transformation</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_transform_base64'><a href="files/modules/virtchannel_transform/vt_base64.html">tcl::transform::base64</a></td>
<td class="#doctools_tocright">Base64 encoding transformation</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_transform_core'><a href="files/modules/virtchannel_core/transformcore.html">tcl::transform::core</a></td>
<td class="#doctools_tocright">Basic reflected/virtual channel transform support</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_transform_counter'><a href="files/modules/virtchannel_transform/vt_counter.html">tcl::transform::counter</a></td>
<td class="#doctools_tocright">Counter transformation</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_transform_crc32'><a href="files/modules/virtchannel_transform/vt_crc32.html">tcl::transform::crc32</a></td>
<td class="#doctools_tocright">Crc32 transformation</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_transform_hex'><a href="files/modules/virtchannel_transform/hex.html">tcl::transform::hex</a></td>
<td class="#doctools_tocright">Hexadecimal encoding transformation</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_transform_identity'><a href="files/modules/virtchannel_transform/identity.html">tcl::transform::identity</a></td>
<td class="#doctools_tocright">Identity transformation</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_transform_limitsize'><a href="files/modules/virtchannel_transform/limitsize.html">tcl::transform::limitsize</a></td>
<td class="#doctools_tocright">limiting input</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_transform_observe'><a href="files/modules/virtchannel_transform/observe.html">tcl::transform::observe</a></td>
<td class="#doctools_tocright">Observer transformation, stream copy</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_transform_otp'><a href="files/modules/virtchannel_transform/vt_otp.html">tcl::transform::otp</a></td>
<td class="#doctools_tocright">Encryption via one-time pad</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_transform_rot'><a href="files/modules/virtchannel_transform/rot.html">tcl::transform::rot</a></td>
<td class="#doctools_tocright">rot-encryption</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_transform_spacer'><a href="files/modules/virtchannel_transform/spacer.html">tcl::transform::spacer</a></td>
<td class="#doctools_tocright">Space insertation and removal</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_transform_zlib'><a href="files/modules/virtchannel_transform/tcllib_zlib.html">tcl::transform::zlib</a></td>
<td class="#doctools_tocright">zlib (de)compression</td>
</tr>




<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcldes'><a href="files/modules/des/tcldes.html">tclDES</a></td>
<td class="#doctools_tocright">Implementation of the DES and triple-DES ciphers</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcldesjr'><a href="files/modules/des/tcldesjr.html">tclDESjr</a></td>
<td class="#doctools_tocright">Implementation of the DES and triple-DES ciphers</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcldocstrip'><a href="files/apps/tcldocstrip.html">tcldocstrip</a></td>
<td class="#doctools_tocright">Tcl-based Docstrip Processor</td>
</tr>








<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcllib_ip'><a href="files/modules/dns/tcllib_ip.html">tcllib_ip</a></td>
<td class="#doctools_tocright">IPv4 and IPv6 address manipulation</td>
</tr>
<tr class="#doctools_tocodd"  >












<td class="#doctools_tocleft" ><a name='tclrep_machineparameters'><a href="files/modules/math/machineparameters.html">tclrep/machineparameters</a></td>
<td class="#doctools_tocright">Compute double precision machine parameters.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tepam'><a href="files/modules/tepam/tepam_introduction.html">tepam</a></td>
<td class="#doctools_tocright">An introduction into TEPAM, Tcl's Enhanced Procedure and Argument Manager</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tepam_argument_dialogbox'><a href="files/modules/tepam/tepam_argument_dialogbox.html">tepam::argument_dialogbox</a></td>
<td class="#doctools_tocright">TEPAM argument_dialogbox, reference manual</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tepam_doc_gen'><a href="files/modules/tepam/tepam_doc_gen.html">tepam::doc_gen</a></td>
<td class="#doctools_tocright">TEPAM DOC Generation, reference manual</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tepam_procedure'><a href="files/modules/tepam/tepam_procedure.html">tepam::procedure</a></td>
<td class="#doctools_tocright">TEPAM procedure, reference manual</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='term'><a href="files/modules/term/term.html">term</a></td>
<td class="#doctools_tocright">General terminal control</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='term_ansi_code'><a href="files/modules/term/ansi_code.html">term::ansi::code</a></td>
<td class="#doctools_tocright">Helper for control sequences</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='term_ansi_code_attr'><a href="files/modules/term/ansi_cattr.html">term::ansi::code::attr</a></td>
<td class="#doctools_tocright">ANSI attribute sequences</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='term_ansi_code_ctrl'><a href="files/modules/term/ansi_cctrl.html">term::ansi::code::ctrl</a></td>
<td class="#doctools_tocright">ANSI control sequences</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='term_ansi_code_macros'><a href="files/modules/term/ansi_cmacros.html">term::ansi::code::macros</a></td>
<td class="#doctools_tocright">Macro sequences</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='term_ansi_ctrl_unix'><a href="files/modules/term/ansi_ctrlu.html">term::ansi::ctrl::unix</a></td>
<td class="#doctools_tocright">Control operations and queries</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='term_ansi_send'><a href="files/modules/term/ansi_send.html">term::ansi::send</a></td>
<td class="#doctools_tocright">Output of ANSI control sequences to terminals</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='term_interact_menu'><a href="files/modules/term/imenu.html">term::interact::menu</a></td>
<td class="#doctools_tocright">Terminal widget, menu</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='term_interact_pager'><a href="files/modules/term/ipager.html">term::interact::pager</a></td>
<td class="#doctools_tocright">Terminal widget, paging</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='term_receive'><a href="files/modules/term/receive.html">term::receive</a></td>
<td class="#doctools_tocright">General input from terminals</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='term_receive_bind'><a href="files/modules/term/term_bind.html">term::receive::bind</a></td>
<td class="#doctools_tocright">Keyboard dispatch from terminals</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='term_send'><a href="files/modules/term/term_send.html">term::send</a></td>
<td class="#doctools_tocright">General output to terminals</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil'><a href="files/modules/textutil/textutil.html">textutil</a></td>
<td class="#doctools_tocright">Procedures to manipulate texts and strings.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_adjust'><a href="files/modules/textutil/adjust.html">textutil::adjust</a></td>
<td class="#doctools_tocright">Procedures to adjust, indent, and undent paragraphs</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_expander'><a href="files/modules/textutil/expander.html">textutil::expander</a></td>
<td class="#doctools_tocright">Procedures to process templates and expand text.</td>
</tr>




<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_repeat'><a href="files/modules/textutil/repeat.html">textutil::repeat</a></td>
<td class="#doctools_tocright">Procedures to repeat strings.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_split'><a href="files/modules/textutil/textutil_split.html">textutil::split</a></td>
<td class="#doctools_tocright">Procedures to split texts</td>







>
>
>
>



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



>
>
>
>












>
>
>
>
>
>
>
>





>
>
>
>
>
>
>
>
>
>
>
>



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



>
>
>
>







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
<td class="#doctools_tocright">Create and manipulate directed graph objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_list'><a href="files/modules/struct/struct_list.html">struct::list</a></td>
<td class="#doctools_tocright">Procedures for manipulating lists</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_map'><a href="files/modules/struct/struct_map.html">struct::map</a></td>
<td class="#doctools_tocright">Manage key/value maps</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_matrix'><a href="files/modules/struct/matrix.html">struct::matrix</a></td>
<td class="#doctools_tocright">Create and manipulate matrix objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_matrix_v1'><a href="files/modules/struct/matrix1.html">struct::matrix_v1</a></td>
<td class="#doctools_tocright">Create and manipulate matrix objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_pool'><a href="files/modules/struct/pool.html">struct::pool</a></td>
<td class="#doctools_tocright">Create and manipulate pool objects (of discrete items)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_prioqueue'><a href="files/modules/struct/prioqueue.html">struct::prioqueue</a></td>
<td class="#doctools_tocright">Create and manipulate prioqueue objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_queue'><a href="files/modules/struct/queue.html">struct::queue</a></td>
<td class="#doctools_tocright">Create and manipulate queue objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_record'><a href="files/modules/struct/record.html">struct::record</a></td>
<td class="#doctools_tocright">Define and create records (similar to 'C' structures)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_set'><a href="files/modules/struct/struct_set.html">struct::set</a></td>
<td class="#doctools_tocright">Procedures for manipulating sets</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_skiplist'><a href="files/modules/struct/skiplist.html">struct::skiplist</a></td>
<td class="#doctools_tocright">Create and manipulate skiplists</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_stack'><a href="files/modules/struct/stack.html">struct::stack</a></td>
<td class="#doctools_tocright">Create and manipulate stack objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_tree'><a href="files/modules/struct/struct_tree.html">struct::tree</a></td>
<td class="#doctools_tocright">Create and manipulate tree objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_tree_v1'><a href="files/modules/struct/struct_tree1.html">struct::tree_v1</a></td>
<td class="#doctools_tocright">Create and manipulate tree objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='sum'><a href="files/modules/crc/sum.html">sum</a></td>
<td class="#doctools_tocright">Calculate a sum(1) compatible checksum</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='switched'><a href="files/modules/stooop/switched.html">switched</a></td>
<td class="#doctools_tocright">switch/option management.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tar'><a href="files/modules/tar/tar.html">tar</a></td>
<td class="#doctools_tocright">Tar file creation, extraction &amp; manipulation</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_cat'><a href="files/modules/virtchannel_base/cat.html">tcl::chan::cat</a></td>
<td class="#doctools_tocright">Concatenation channel</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_core'><a href="files/modules/virtchannel_core/core.html">tcl::chan::core</a></td>
<td class="#doctools_tocright">Basic reflected/virtual channel support</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_events'><a href="files/modules/virtchannel_core/events.html">tcl::chan::events</a></td>
<td class="#doctools_tocright">Event support for reflected/virtual channels</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_facade'><a href="files/modules/virtchannel_base/facade.html">tcl::chan::facade</a></td>
<td class="#doctools_tocright">Facade channel</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_fifo'><a href="files/modules/virtchannel_base/tcllib_fifo.html">tcl::chan::fifo</a></td>
<td class="#doctools_tocright">In-memory fifo channel</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_fifo2'><a href="files/modules/virtchannel_base/tcllib_fifo2.html">tcl::chan::fifo2</a></td>
<td class="#doctools_tocright">In-memory interconnected fifo channels</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_halfpipe'><a href="files/modules/virtchannel_base/halfpipe.html">tcl::chan::halfpipe</a></td>
<td class="#doctools_tocright">In-memory channel, half of a fifo2</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_memchan'><a href="files/modules/virtchannel_base/tcllib_memchan.html">tcl::chan::memchan</a></td>
<td class="#doctools_tocright">In-memory channel</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_null'><a href="files/modules/virtchannel_base/tcllib_null.html">tcl::chan::null</a></td>
<td class="#doctools_tocright">Null channel</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_nullzero'><a href="files/modules/virtchannel_base/nullzero.html">tcl::chan::nullzero</a></td>
<td class="#doctools_tocright">Null/Zero channel combination</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_random'><a href="files/modules/virtchannel_base/tcllib_random.html">tcl::chan::random</a></td>
<td class="#doctools_tocright">Random channel</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_std'><a href="files/modules/virtchannel_base/std.html">tcl::chan::std</a></td>
<td class="#doctools_tocright">Standard I/O, unification of stdin and stdout</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_string'><a href="files/modules/virtchannel_base/tcllib_string.html">tcl::chan::string</a></td>
<td class="#doctools_tocright">Read-only in-memory channel</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_textwindow'><a href="files/modules/virtchannel_base/textwindow.html">tcl::chan::textwindow</a></td>
<td class="#doctools_tocright">Textwindow channel</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_chan_variable'><a href="files/modules/virtchannel_base/tcllib_variable.html">tcl::chan::variable</a></td>
<td class="#doctools_tocright">In-memory channel using variable for storage</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_chan_zero'><a href="files/modules/virtchannel_base/tcllib_zero.html">tcl::chan::zero</a></td>
<td class="#doctools_tocright">Zero channel</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_randomseed'><a href="files/modules/virtchannel_base/randseed.html">tcl::randomseed</a></td>
<td class="#doctools_tocright">Utilities for random channels</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_transform_adler32'><a href="files/modules/virtchannel_transform/adler32.html">tcl::transform::adler32</a></td>
<td class="#doctools_tocright">Adler32 transformation</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_transform_base64'><a href="files/modules/virtchannel_transform/vt_base64.html">tcl::transform::base64</a></td>
<td class="#doctools_tocright">Base64 encoding transformation</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_transform_core'><a href="files/modules/virtchannel_core/transformcore.html">tcl::transform::core</a></td>
<td class="#doctools_tocright">Basic reflected/virtual channel transform support</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_transform_counter'><a href="files/modules/virtchannel_transform/vt_counter.html">tcl::transform::counter</a></td>
<td class="#doctools_tocright">Counter transformation</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_transform_crc32'><a href="files/modules/virtchannel_transform/vt_crc32.html">tcl::transform::crc32</a></td>
<td class="#doctools_tocright">Crc32 transformation</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_transform_hex'><a href="files/modules/virtchannel_transform/hex.html">tcl::transform::hex</a></td>
<td class="#doctools_tocright">Hexadecimal encoding transformation</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_transform_identity'><a href="files/modules/virtchannel_transform/identity.html">tcl::transform::identity</a></td>
<td class="#doctools_tocright">Identity transformation</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_transform_limitsize'><a href="files/modules/virtchannel_transform/limitsize.html">tcl::transform::limitsize</a></td>
<td class="#doctools_tocright">limiting input</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_transform_observe'><a href="files/modules/virtchannel_transform/observe.html">tcl::transform::observe</a></td>
<td class="#doctools_tocright">Observer transformation, stream copy</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_transform_otp'><a href="files/modules/virtchannel_transform/vt_otp.html">tcl::transform::otp</a></td>
<td class="#doctools_tocright">Encryption via one-time pad</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_transform_rot'><a href="files/modules/virtchannel_transform/rot.html">tcl::transform::rot</a></td>
<td class="#doctools_tocright">rot-encryption</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_transform_spacer'><a href="files/modules/virtchannel_transform/spacer.html">tcl::transform::spacer</a></td>
<td class="#doctools_tocright">Space insertation and removal</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcl_transform_zlib'><a href="files/modules/virtchannel_transform/tcllib_zlib.html">tcl::transform::zlib</a></td>
<td class="#doctools_tocright">zlib (de)compression</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcl_community_communication'><a href="files/devdoc/tcl_community_communication.html">tcl_community_communication</a></td>
<td class="#doctools_tocright">Tcl Community - Kind Communication</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcldes'><a href="files/modules/des/tcldes.html">tclDES</a></td>
<td class="#doctools_tocright">Implementation of the DES and triple-DES ciphers</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcldesjr'><a href="files/modules/des/tcldesjr.html">tclDESjr</a></td>
<td class="#doctools_tocright">Implementation of the DES and triple-DES ciphers</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcldocstrip'><a href="files/apps/tcldocstrip.html">tcldocstrip</a></td>
<td class="#doctools_tocright">Tcl-based Docstrip Processor</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcllib_devguide'><a href="files/devdoc/tcllib_devguide.html">tcllib_devguide</a></td>
<td class="#doctools_tocright">Tcllib - The Developer's Guide</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcllib_install_guide'><a href="files/devdoc/tcllib_installer.html">tcllib_install_guide</a></td>
<td class="#doctools_tocright">Tcllib - The Installer's Guide</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcllib_ip'><a href="files/modules/dns/tcllib_ip.html">tcllib_ip</a></td>
<td class="#doctools_tocright">IPv4 and IPv6 address manipulation</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcllib_license'><a href="files/devdoc/tcllib_license.html">tcllib_license</a></td>
<td class="#doctools_tocright">Tcllib - License</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcllib_releasemgr'><a href="files/devdoc/tcllib_releasemgr.html">tcllib_releasemgr</a></td>
<td class="#doctools_tocright">Tcllib - The Release Manager's Guide</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tcllib_sources'><a href="files/devdoc/tcllib_sources.html">tcllib_sources</a></td>
<td class="#doctools_tocright">Tcllib - How To Get The Sources</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tclrep_machineparameters'><a href="files/modules/math/machineparameters.html">tclrep/machineparameters</a></td>
<td class="#doctools_tocright">Compute double precision machine parameters.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tepam'><a href="files/modules/tepam/tepam_introduction.html">tepam</a></td>
<td class="#doctools_tocright">An introduction into TEPAM, Tcl's Enhanced Procedure and Argument Manager</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tepam_argument_dialogbox'><a href="files/modules/tepam/tepam_argument_dialogbox.html">tepam::argument_dialogbox</a></td>
<td class="#doctools_tocright">TEPAM argument_dialogbox, reference manual</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tepam_doc_gen'><a href="files/modules/tepam/tepam_doc_gen.html">tepam::doc_gen</a></td>
<td class="#doctools_tocright">TEPAM DOC Generation, reference manual</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tepam_procedure'><a href="files/modules/tepam/tepam_procedure.html">tepam::procedure</a></td>
<td class="#doctools_tocright">TEPAM procedure, reference manual</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='term'><a href="files/modules/term/term.html">term</a></td>
<td class="#doctools_tocright">General terminal control</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='term_ansi_code'><a href="files/modules/term/ansi_code.html">term::ansi::code</a></td>
<td class="#doctools_tocright">Helper for control sequences</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='term_ansi_code_attr'><a href="files/modules/term/ansi_cattr.html">term::ansi::code::attr</a></td>
<td class="#doctools_tocright">ANSI attribute sequences</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='term_ansi_code_ctrl'><a href="files/modules/term/ansi_cctrl.html">term::ansi::code::ctrl</a></td>
<td class="#doctools_tocright">ANSI control sequences</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='term_ansi_code_macros'><a href="files/modules/term/ansi_cmacros.html">term::ansi::code::macros</a></td>
<td class="#doctools_tocright">Macro sequences</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='term_ansi_ctrl_unix'><a href="files/modules/term/ansi_ctrlu.html">term::ansi::ctrl::unix</a></td>
<td class="#doctools_tocright">Control operations and queries</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='term_ansi_send'><a href="files/modules/term/ansi_send.html">term::ansi::send</a></td>
<td class="#doctools_tocright">Output of ANSI control sequences to terminals</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='term_interact_menu'><a href="files/modules/term/imenu.html">term::interact::menu</a></td>
<td class="#doctools_tocright">Terminal widget, menu</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='term_interact_pager'><a href="files/modules/term/ipager.html">term::interact::pager</a></td>
<td class="#doctools_tocright">Terminal widget, paging</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='term_receive'><a href="files/modules/term/receive.html">term::receive</a></td>
<td class="#doctools_tocright">General input from terminals</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='term_receive_bind'><a href="files/modules/term/term_bind.html">term::receive::bind</a></td>
<td class="#doctools_tocright">Keyboard dispatch from terminals</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='term_send'><a href="files/modules/term/term_send.html">term::send</a></td>
<td class="#doctools_tocright">General output to terminals</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil'><a href="files/modules/textutil/textutil.html">textutil</a></td>
<td class="#doctools_tocright">Procedures to manipulate texts and strings.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_adjust'><a href="files/modules/textutil/adjust.html">textutil::adjust</a></td>
<td class="#doctools_tocright">Procedures to adjust, indent, and undent paragraphs</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_expander'><a href="files/modules/textutil/expander.html">textutil::expander</a></td>
<td class="#doctools_tocright">Procedures to process templates and expand text.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_patch'><a href="files/modules/textutil/patch.html">textutil::patch</a></td>
<td class="#doctools_tocright">Application of uni-diff patches to directory trees</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_repeat'><a href="files/modules/textutil/repeat.html">textutil::repeat</a></td>
<td class="#doctools_tocright">Procedures to repeat strings.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_split'><a href="files/modules/textutil/textutil_split.html">textutil::split</a></td>
<td class="#doctools_tocright">Procedures to split texts</td>
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
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
<td class="#doctools_tocright">Array persistence</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tiff'><a href="files/modules/tiff/tiff.html">tiff</a></td>
<td class="#doctools_tocright">TIFF reading, writing, and querying and manipulation of meta data</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tool'><a href="files/modules/httpd/httpd.html">tool</a></td>
<td class="#doctools_tocright">A TclOO and coroutine based web server</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tool'><a href="files/modules/tool/tool.html">tool</a></td>
<td class="#doctools_tocright">TclOO Library (TOOL) Framework</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tool_dict_ensemble'><a href="files/modules/tool/tool_dict_ensemble.html">tool::dict_ensemble</a></td>
<td class="#doctools_tocright">Dictionary Tools</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='transfer_connect'><a href="files/modules/transfer/connect.html">transfer::connect</a></td>
<td class="#doctools_tocright">Connection setup</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='transfer_copy'><a href="files/modules/transfer/copyops.html">transfer::copy</a></td>
<td class="#doctools_tocright">Data transfer foundation</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='transfer_copy_queue'><a href="files/modules/transfer/tqueue.html">transfer::copy::queue</a></td>
<td class="#doctools_tocright">Queued transfers</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='transfer_data_destination'><a href="files/modules/transfer/ddest.html">transfer::data::destination</a></td>
<td class="#doctools_tocright">Data destination</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='transfer_data_source'><a href="files/modules/transfer/dsource.html">transfer::data::source</a></td>
<td class="#doctools_tocright">Data source</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='transfer_receiver'><a href="files/modules/transfer/receiver.html">transfer::receiver</a></td>
<td class="#doctools_tocright">Data source</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='transfer_transmitter'><a href="files/modules/transfer/transmitter.html">transfer::transmitter</a></td>
<td class="#doctools_tocright">Data source</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='treeql'><a href="files/modules/treeql/treeql.html">treeql</a></td>
<td class="#doctools_tocright">Query tree objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='try'><a href="files/modules/try/tcllib_try.html">try</a></td>
<td class="#doctools_tocright">try - Trap and process errors and exceptions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='udpcluster'><a href="files/modules/udpcluster/udpcluster.html">udpcluster</a></td>
<td class="#doctools_tocright">UDP Peer-to-Peer cluster</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uevent'><a href="files/modules/uev/uevent.html">uevent</a></td>
<td class="#doctools_tocright">User events</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uevent_onidle'><a href="files/modules/uev/uevent_onidle.html">uevent::onidle</a></td>
<td class="#doctools_tocright">Request merging and deferal to idle time</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='unicode'><a href="files/modules/stringprep/unicode.html">unicode</a></td>
<td class="#doctools_tocright">Implementation of Unicode normalization</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='unicode_data'><a href="files/modules/stringprep/unicode_data.html">unicode::data</a></td>
<td class="#doctools_tocright">unicode data tables, generated, internal</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='units'><a href="files/modules/units/units.html">units</a></td>
<td class="#doctools_tocright">unit conversion</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uri'><a href="files/modules/uri/uri.html">uri</a></td>
<td class="#doctools_tocright">URI utilities</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uri_urn'><a href="files/modules/uri/urn-scheme.html">uri_urn</a></td>
<td class="#doctools_tocright">URI utilities, URN scheme</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uuencode'><a href="files/modules/base64/uuencode.html">uuencode</a></td>
<td class="#doctools_tocright">UU-encode/decode binary data</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uuid'><a href="files/modules/uuid/uuid.html">uuid</a></td>
<td class="#doctools_tocright">UUID generation and comparison</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='valtype_common'><a href="files/modules/valtype/valtype_common.html">valtype::common</a></td>
<td class="#doctools_tocright">Validation, common code</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='valtype_creditcard_amex'><a href="files/modules/valtype/cc_amex.html">valtype::creditcard::amex</a></td>
<td class="#doctools_tocright">Validation for AMEX creditcard number</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='valtype_creditcard_discover'><a href="files/modules/valtype/cc_discover.html">valtype::creditcard::discover</a></td>
<td class="#doctools_tocright">Validation for Discover creditcard number</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='valtype_creditcard_mastercard'><a href="files/modules/valtype/cc_mastercard.html">valtype::creditcard::mastercard</a></td>
<td class="#doctools_tocright">Validation for Mastercard creditcard number</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='valtype_creditcard_visa'><a href="files/modules/valtype/cc_visa.html">valtype::creditcard::visa</a></td>
<td class="#doctools_tocright">Validation for VISA creditcard number</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='valtype_gs1_ean13'><a href="files/modules/valtype/ean13.html">valtype::gs1::ean13</a></td>
<td class="#doctools_tocright">Validation for EAN13</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='valtype_iban'><a href="files/modules/valtype/iban.html">valtype::iban</a></td>
<td class="#doctools_tocright">Validation for IBAN</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='valtype_imei'><a href="files/modules/valtype/imei.html">valtype::imei</a></td>
<td class="#doctools_tocright">Validation for IMEI</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='valtype_isbn'><a href="files/modules/valtype/isbn.html">valtype::isbn</a></td>
<td class="#doctools_tocright">Validation for ISBN</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='valtype_luhn'><a href="files/modules/valtype/luhn.html">valtype::luhn</a></td>
<td class="#doctools_tocright">Validation for plain number with a LUHN checkdigit</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='valtype_luhn5'><a href="files/modules/valtype/luhn5.html">valtype::luhn5</a></td>
<td class="#doctools_tocright">Validation for plain number with a LUHN5 checkdigit</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='valtype_usnpi'><a href="files/modules/valtype/usnpi.html">valtype::usnpi</a></td>
<td class="#doctools_tocright">Validation for USNPI</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='valtype_verhoeff'><a href="files/modules/valtype/verhoeff.html">valtype::verhoeff</a></td>
<td class="#doctools_tocright">Validation for plain number with a VERHOEFF checkdigit</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='websocket'><a href="files/modules/websocket/websocket.html">websocket</a></td>
<td class="#doctools_tocright">Tcl implementation of the websocket protocol</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='wip'><a href="files/modules/wip/wip.html">wip</a></td>
<td class="#doctools_tocright">Word Interpreter</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='xsxp'><a href="files/modules/amazon-s3/xsxp.html">xsxp</a></td>
<td class="#doctools_tocright">eXtremely Simple Xml Parser</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='yaml'><a href="files/modules/yaml/yaml.html">yaml</a></td>
<td class="#doctools_tocright">YAML Format Encoder/Decoder</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='yencode'><a href="files/modules/base64/yencode.html">yencode</a></td>
<td class="#doctools_tocright">Y-encode/decode binary data</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='zipfile_decode'><a href="files/modules/zip/decode.html">zipfile::decode</a></td>
<td class="#doctools_tocright">Access to zip archives</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='zipfile_encode'><a href="files/modules/zip/encode.html">zipfile::encode</a></td>
<td class="#doctools_tocright">Generation of zip archives</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='zipfile_mkzip'><a href="files/modules/zip/mkzip.html">zipfile::mkzip</a></td>
<td class="#doctools_tocright">Build a zip archive</td>
</tr>
</table>
</dd></dl><hr></body></html>







<
<
<
<



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|





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
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
<td class="#doctools_tocright">Array persistence</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tiff'><a href="files/modules/tiff/tiff.html">tiff</a></td>
<td class="#doctools_tocright">TIFF reading, writing, and querying and manipulation of meta data</td>
</tr>
<tr class="#doctools_toceven" >




<td class="#doctools_tocleft" ><a name='tool'><a href="files/modules/tool/tool.html">tool</a></td>
<td class="#doctools_tocright">TclOO Library (TOOL) Framework</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tool_dict_ensemble'><a href="files/modules/tool/tool_dict_ensemble.html">tool::dict_ensemble</a></td>
<td class="#doctools_tocright">Dictionary Tools</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='transfer_connect'><a href="files/modules/transfer/connect.html">transfer::connect</a></td>
<td class="#doctools_tocright">Connection setup</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='transfer_copy'><a href="files/modules/transfer/copyops.html">transfer::copy</a></td>
<td class="#doctools_tocright">Data transfer foundation</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='transfer_copy_queue'><a href="files/modules/transfer/tqueue.html">transfer::copy::queue</a></td>
<td class="#doctools_tocright">Queued transfers</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='transfer_data_destination'><a href="files/modules/transfer/ddest.html">transfer::data::destination</a></td>
<td class="#doctools_tocright">Data destination</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='transfer_data_source'><a href="files/modules/transfer/dsource.html">transfer::data::source</a></td>
<td class="#doctools_tocright">Data source</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='transfer_receiver'><a href="files/modules/transfer/receiver.html">transfer::receiver</a></td>
<td class="#doctools_tocright">Data source</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='transfer_transmitter'><a href="files/modules/transfer/transmitter.html">transfer::transmitter</a></td>
<td class="#doctools_tocright">Data source</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='treeql'><a href="files/modules/treeql/treeql.html">treeql</a></td>
<td class="#doctools_tocright">Query tree objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='try'><a href="files/modules/try/tcllib_try.html">try</a></td>
<td class="#doctools_tocright">try - Trap and process errors and exceptions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='udpcluster'><a href="files/modules/udpcluster/udpcluster.html">udpcluster</a></td>
<td class="#doctools_tocright">UDP Peer-to-Peer cluster</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uevent'><a href="files/modules/uev/uevent.html">uevent</a></td>
<td class="#doctools_tocright">User events</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uevent_onidle'><a href="files/modules/uev/uevent_onidle.html">uevent::onidle</a></td>
<td class="#doctools_tocright">Request merging and deferal to idle time</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='unicode'><a href="files/modules/stringprep/unicode.html">unicode</a></td>
<td class="#doctools_tocright">Implementation of Unicode normalization</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='unicode_data'><a href="files/modules/stringprep/unicode_data.html">unicode::data</a></td>
<td class="#doctools_tocright">unicode data tables, generated, internal</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='units'><a href="files/modules/units/units.html">units</a></td>
<td class="#doctools_tocright">unit conversion</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uri'><a href="files/modules/uri/uri.html">uri</a></td>
<td class="#doctools_tocright">URI utilities</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uri_urn'><a href="files/modules/uri/urn-scheme.html">uri_urn</a></td>
<td class="#doctools_tocright">URI utilities, URN scheme</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uuencode'><a href="files/modules/base64/uuencode.html">uuencode</a></td>
<td class="#doctools_tocright">UU-encode/decode binary data</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uuid'><a href="files/modules/uuid/uuid.html">uuid</a></td>
<td class="#doctools_tocright">UUID generation and comparison</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='valtype_common'><a href="files/modules/valtype/valtype_common.html">valtype::common</a></td>
<td class="#doctools_tocright">Validation, common code</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='valtype_creditcard_amex'><a href="files/modules/valtype/cc_amex.html">valtype::creditcard::amex</a></td>
<td class="#doctools_tocright">Validation for AMEX creditcard number</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='valtype_creditcard_discover'><a href="files/modules/valtype/cc_discover.html">valtype::creditcard::discover</a></td>
<td class="#doctools_tocright">Validation for Discover creditcard number</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='valtype_creditcard_mastercard'><a href="files/modules/valtype/cc_mastercard.html">valtype::creditcard::mastercard</a></td>
<td class="#doctools_tocright">Validation for Mastercard creditcard number</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='valtype_creditcard_visa'><a href="files/modules/valtype/cc_visa.html">valtype::creditcard::visa</a></td>
<td class="#doctools_tocright">Validation for VISA creditcard number</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='valtype_gs1_ean13'><a href="files/modules/valtype/ean13.html">valtype::gs1::ean13</a></td>
<td class="#doctools_tocright">Validation for EAN13</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='valtype_iban'><a href="files/modules/valtype/iban.html">valtype::iban</a></td>
<td class="#doctools_tocright">Validation for IBAN</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='valtype_imei'><a href="files/modules/valtype/imei.html">valtype::imei</a></td>
<td class="#doctools_tocright">Validation for IMEI</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='valtype_isbn'><a href="files/modules/valtype/isbn.html">valtype::isbn</a></td>
<td class="#doctools_tocright">Validation for ISBN</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='valtype_luhn'><a href="files/modules/valtype/luhn.html">valtype::luhn</a></td>
<td class="#doctools_tocright">Validation for plain number with a LUHN checkdigit</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='valtype_luhn5'><a href="files/modules/valtype/luhn5.html">valtype::luhn5</a></td>
<td class="#doctools_tocright">Validation for plain number with a LUHN5 checkdigit</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='valtype_usnpi'><a href="files/modules/valtype/usnpi.html">valtype::usnpi</a></td>
<td class="#doctools_tocright">Validation for USNPI</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='valtype_verhoeff'><a href="files/modules/valtype/verhoeff.html">valtype::verhoeff</a></td>
<td class="#doctools_tocright">Validation for plain number with a VERHOEFF checkdigit</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='websocket'><a href="files/modules/websocket/websocket.html">websocket</a></td>
<td class="#doctools_tocright">Tcl implementation of the websocket protocol</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='wip'><a href="files/modules/wip/wip.html">wip</a></td>
<td class="#doctools_tocright">Word Interpreter</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='xsxp'><a href="files/modules/amazon-s3/xsxp.html">xsxp</a></td>
<td class="#doctools_tocright">eXtremely Simple Xml Parser</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='yaml'><a href="files/modules/yaml/yaml.html">yaml</a></td>
<td class="#doctools_tocright">YAML Format Encoder/Decoder</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='yencode'><a href="files/modules/base64/yencode.html">yencode</a></td>
<td class="#doctools_tocright">Y-encode/decode binary data</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='zipfile_decode'><a href="files/modules/zip/decode.html">zipfile::decode</a></td>
<td class="#doctools_tocright">Access to zip archives</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='zipfile_encode'><a href="files/modules/zip/encode.html">zipfile::encode</a></td>
<td class="#doctools_tocright">Generation of zip archives</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='zipfile_mkzip'><a href="files/modules/zip/mkzip.html">zipfile::mkzip</a></td>
<td class="#doctools_tocright">Build a zip archive</td>
</tr>
</table>
</dd></dl><hr></body></html>

Changes to idoc/www/toc.html.

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
<td class="#doctools_tocright">Package for Principal Component Analysis</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_polynomials'><a href="tcllib/files/modules/math/polynomials.html">math::polynomials</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='math_rationalfunctions'><a href="tcllib/files/modules/math/rational_funcs.html">math::rationalfunctions</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_roman'><a href="tcllib/files/modules/math/roman.html">math::roman</a></td>
<td class="#doctools_tocright">Tools for creating and manipulating roman numerals</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_special'><a href="tcllib/files/modules/math/special.html">math::special</a></td>
<td class="#doctools_tocright">Special mathematical functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_statistics'><a href="tcllib/files/modules/math/statistics.html">math::statistics</a></td>
<td class="#doctools_tocright">Basic statistical functions and procedures</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_trig'><a href="tcllib/files/modules/math/trig.html">math::trig</a></td>
<td class="#doctools_tocright">Trigonometric anf hyperbolic functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='simulation_annealing'><a href="tcllib/files/modules/simulation/annealing.html">simulation::annealing</a></td>
<td class="#doctools_tocright">Simulated annealing</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='simulation_montecarlo'><a href="tcllib/files/modules/simulation/montecarlo.html">simulation::montecarlo</a></td>
<td class="#doctools_tocright">Monte Carlo simulations</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='simulation_random'><a href="tcllib/files/modules/simulation/simulation_random.html">simulation::random</a></td>
<td class="#doctools_tocright">Pseudo-random number generators</td>
</tr>
</table></dl>
<dl><dt><a name='networking'>Networking</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>



|



|



|



|



|



|



|







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
<td class="#doctools_tocright">Package for Principal Component Analysis</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_polynomials'><a href="tcllib/files/modules/math/polynomials.html">math::polynomials</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_quasirandom'><a href="tcllib/files/modules/math/quasirandom.html">math::quasirandom</a></td>
<td class="#doctools_tocright">Quasi-random points for integration and Monte Carlo type methods</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_rationalfunctions'><a href="tcllib/files/modules/math/rational_funcs.html">math::rationalfunctions</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_roman'><a href="tcllib/files/modules/math/roman.html">math::roman</a></td>
<td class="#doctools_tocright">Tools for creating and manipulating roman numerals</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_special'><a href="tcllib/files/modules/math/special.html">math::special</a></td>
<td class="#doctools_tocright">Special mathematical functions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_statistics'><a href="tcllib/files/modules/math/statistics.html">math::statistics</a></td>
<td class="#doctools_tocright">Basic statistical functions and procedures</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_trig'><a href="tcllib/files/modules/math/trig.html">math::trig</a></td>
<td class="#doctools_tocright">Trigonometric anf hyperbolic functions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='simulation_annealing'><a href="tcllib/files/modules/simulation/annealing.html">simulation::annealing</a></td>
<td class="#doctools_tocright">Simulated annealing</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='simulation_montecarlo'><a href="tcllib/files/modules/simulation/montecarlo.html">simulation::montecarlo</a></td>
<td class="#doctools_tocright">Monte Carlo simulations</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='simulation_random'><a href="tcllib/files/modules/simulation/simulation_random.html">simulation::random</a></td>
<td class="#doctools_tocright">Pseudo-random number generators</td>
</tr>
</table></dl>
<dl><dt><a name='networking'>Networking</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
858
859
860
861
862
863
864




865
866
867




868
869
870
871
872
873
874
<td class="#doctools_tocright">Uri handler for ftp urls</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='ftpd'><a href="tcllib/files/modules/ftpd/ftpd.html">ftpd</a></td>
<td class="#doctools_tocright">Tcl FTP server implementation</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='ident'><a href="tcllib/files/modules/ident/ident.html">ident</a></td>
<td class="#doctools_tocright">Ident protocol client</td>
</tr>




<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='irc'><a href="tcllib/files/modules/irc/irc.html">irc</a></td>
<td class="#doctools_tocright">Create IRC connection and interface.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='ldap'><a href="tcllib/files/modules/ldap/ldap.html">ldap</a></td>
<td class="#doctools_tocright">LDAP client</td>







>
>
>
>



>
>
>
>







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
<td class="#doctools_tocright">Uri handler for ftp urls</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='ftpd'><a href="tcllib/files/modules/ftpd/ftpd.html">ftpd</a></td>
<td class="#doctools_tocright">Tcl FTP server implementation</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='httpd'><a href="tcllib/files/modules/httpd/httpd.html">httpd</a></td>
<td class="#doctools_tocright">A TclOO and coroutine based web server</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='ident'><a href="tcllib/files/modules/ident/ident.html">ident</a></td>
<td class="#doctools_tocright">Ident protocol client</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='imap4'><a href="tcllib/files/modules/imap4/imap4.html">imap4</a></td>
<td class="#doctools_tocright">imap client-side tcl implementation of imap protocol</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='irc'><a href="tcllib/files/modules/irc/irc.html">irc</a></td>
<td class="#doctools_tocright">Create IRC connection and interface.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='ldap'><a href="tcllib/files/modules/ldap/ldap.html">ldap</a></td>
<td class="#doctools_tocright">LDAP client</td>
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
<td class="#doctools_tocright">Tcl SMTP server implementation</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcllib_ip'><a href="tcllib/files/modules/dns/tcllib_ip.html">tcllib_ip</a></td>
<td class="#doctools_tocright">IPv4 and IPv6 address manipulation</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tool'><a href="tcllib/files/modules/httpd/httpd.html">tool</a></td>
<td class="#doctools_tocright">A TclOO and coroutine based web server</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='udpcluster'><a href="tcllib/files/modules/udpcluster/udpcluster.html">udpcluster</a></td>
<td class="#doctools_tocright">UDP Peer-to-Peer cluster</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uri'><a href="tcllib/files/modules/uri/uri.html">uri</a></td>
<td class="#doctools_tocright">URI utilities</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uri_urn'><a href="tcllib/files/modules/uri/urn-scheme.html">uri_urn</a></td>
<td class="#doctools_tocright">URI utilities, URN scheme</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='websocket'><a href="tcllib/files/modules/websocket/websocket.html">websocket</a></td>
<td class="#doctools_tocright">Tcl implementation of the websocket protocol</td>
</tr>
</table></dl>
<dl><dt><a name='page_parser_generator'>Page Parser Generator</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







<
<
<
<



|



|



|







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
<td class="#doctools_tocright">Tcl SMTP server implementation</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcllib_ip'><a href="tcllib/files/modules/dns/tcllib_ip.html">tcllib_ip</a></td>
<td class="#doctools_tocright">IPv4 and IPv6 address manipulation</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='udpcluster'><a href="tcllib/files/modules/udpcluster/udpcluster.html">udpcluster</a></td>
<td class="#doctools_tocright">UDP Peer-to-Peer cluster</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uri'><a href="tcllib/files/modules/uri/uri.html">uri</a></td>
<td class="#doctools_tocright">URI utilities</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uri_urn'><a href="tcllib/files/modules/uri/urn-scheme.html">uri_urn</a></td>
<td class="#doctools_tocright">URI utilities, URN scheme</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='websocket'><a href="tcllib/files/modules/websocket/websocket.html">websocket</a></td>
<td class="#doctools_tocright">Tcl implementation of the websocket protocol</td>
</tr>
</table></dl>
<dl><dt><a name='page_parser_generator'>Page Parser Generator</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
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
<td class="#doctools_tocleft" ><a name='tepam_procedure'><a href="tcllib/files/modules/tepam/tepam_procedure.html">tepam::procedure</a></td>
<td class="#doctools_tocright">TEPAM procedure, reference manual</td>
</tr>
</table></dl>
<dl><dt><a name='programming_tools'>Programming tools</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >




<td class="#doctools_tocleft" ><a name='cmdline'><a href="tcllib/files/modules/cmdline/cmdline.html">cmdline</a></td>
<td class="#doctools_tocright">Procedures to process command lines and options.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='comm'><a href="tcllib/files/modules/comm/comm.html">comm</a></td>
<td class="#doctools_tocright">A remote communication facility for Tcl (8.3 and later)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='comm_wire'><a href="tcllib/files/modules/comm/comm_wire.html">comm_wire</a></td>
<td class="#doctools_tocright">The comm wire protocol</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='control'><a href="tcllib/files/modules/control/control.html">control</a></td>
<td class="#doctools_tocright">Procedures for control flow structures.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='deleg_method'><a href="tcllib/files/modules/interp/deleg_method.html">deleg_method</a></td>
<td class="#doctools_tocright">Creation of comm delegates (snit methods)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='deleg_proc'><a href="tcllib/files/modules/interp/deleg_proc.html">deleg_proc</a></td>
<td class="#doctools_tocright">Creation of comm delegates (procedures)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil'><a href="tcllib/files/modules/fileutil/fileutil.html">fileutil</a></td>
<td class="#doctools_tocright">Procedures implementing some file utilities</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_magic_cfront'><a href="tcllib/files/modules/fumagic/cfront.html">fileutil::magic::cfront</a></td>
<td class="#doctools_tocright">Generator core for compiler of magic(5) files</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_magic_cgen'><a href="tcllib/files/modules/fumagic/cgen.html">fileutil::magic::cgen</a></td>
<td class="#doctools_tocright">Generator core for compiler of magic(5) files</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_magic_filetype'><a href="tcllib/files/modules/fumagic/filetypes.html">fileutil::magic::filetype</a></td>
<td class="#doctools_tocright">Procedures implementing file-type recognition</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_magic_rt'><a href="tcllib/files/modules/fumagic/rtcore.html">fileutil::magic::rt</a></td>
<td class="#doctools_tocright">Runtime core for file type recognition engines written in pure Tcl</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_multi'><a href="tcllib/files/modules/fileutil/multi.html">fileutil::multi</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather, standard object</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_multi_op'><a href="tcllib/files/modules/fileutil/multiop.html">fileutil::multi::op</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_traverse'><a href="tcllib/files/modules/fileutil/traverse.html">fileutil_traverse</a></td>
<td class="#doctools_tocright">Iterative directory traversal</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='hook'><a href="tcllib/files/modules/hook/hook.html">hook</a></td>
<td class="#doctools_tocright">Hooks</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='interp'><a href="tcllib/files/modules/interp/tcllib_interp.html">interp</a></td>
<td class="#doctools_tocright">Interp creation and aliasing</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='log'><a href="tcllib/files/modules/log/log.html">log</a></td>
<td class="#doctools_tocright">Procedures to log messages of libraries and applications.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='logger'><a href="tcllib/files/modules/log/logger.html">logger</a></td>
<td class="#doctools_tocright">System to control logging of events.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='logger_appender'><a href="tcllib/files/modules/log/loggerAppender.html">logger::appender</a></td>
<td class="#doctools_tocright">Collection of predefined appenders for logger</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='logger_utils'><a href="tcllib/files/modules/log/loggerUtils.html">logger::utils</a></td>
<td class="#doctools_tocright">Utilities for logger</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='multiplexer'><a href="tcllib/files/modules/multiplexer/multiplexer.html">multiplexer</a></td>
<td class="#doctools_tocright">One-to-many communication with sockets.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='pluginmgr'><a href="tcllib/files/modules/pluginmgr/pluginmgr.html">pluginmgr</a></td>
<td class="#doctools_tocright">Manage a plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='profiler'><a href="tcllib/files/modules/profiler/profiler.html">profiler</a></td>
<td class="#doctools_tocright">Tcl source code profiler</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='snit'><a href="tcllib/files/modules/snit/snit.html">snit</a></td>
<td class="#doctools_tocright">Snit's Not Incr Tcl</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='snitfaq'><a href="tcllib/files/modules/snit/snitfaq.html">snitfaq</a></td>
<td class="#doctools_tocright">Snit Frequently Asked Questions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='stooop'><a href="tcllib/files/modules/stooop/stooop.html">stooop</a></td>
<td class="#doctools_tocright">Object oriented extension.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='switched'><a href="tcllib/files/modules/stooop/switched.html">switched</a></td>
<td class="#doctools_tocright">switch/option management.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tie'><a href="tcllib/files/modules/tie/tie.html">tie</a></td>
<td class="#doctools_tocright">Array persistence</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tie'><a href="tcllib/files/modules/tie/tie_std.html">tie</a></td>
<td class="#doctools_tocright">Array persistence, standard data sources</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uevent'><a href="tcllib/files/modules/uev/uevent.html">uevent</a></td>
<td class="#doctools_tocright">User events</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='wip'><a href="tcllib/files/modules/wip/wip.html">wip</a></td>
<td class="#doctools_tocright">Word Interpreter</td>
</tr>
</table></dl>
<dl><dt><a name='system'>System</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|







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
<td class="#doctools_tocleft" ><a name='tepam_procedure'><a href="tcllib/files/modules/tepam/tepam_procedure.html">tepam::procedure</a></td>
<td class="#doctools_tocright">TEPAM procedure, reference manual</td>
</tr>
</table></dl>
<dl><dt><a name='programming_tools'>Programming tools</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='clay'><a href="tcllib/files/modules/clay/clay.html">clay</a></td>
<td class="#doctools_tocright">A minimalist framework for large scale OO Projects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='cmdline'><a href="tcllib/files/modules/cmdline/cmdline.html">cmdline</a></td>
<td class="#doctools_tocright">Procedures to process command lines and options.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='comm'><a href="tcllib/files/modules/comm/comm.html">comm</a></td>
<td class="#doctools_tocright">A remote communication facility for Tcl (8.3 and later)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='comm_wire'><a href="tcllib/files/modules/comm/comm_wire.html">comm_wire</a></td>
<td class="#doctools_tocright">The comm wire protocol</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='control'><a href="tcllib/files/modules/control/control.html">control</a></td>
<td class="#doctools_tocright">Procedures for control flow structures.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='deleg_method'><a href="tcllib/files/modules/interp/deleg_method.html">deleg_method</a></td>
<td class="#doctools_tocright">Creation of comm delegates (snit methods)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='deleg_proc'><a href="tcllib/files/modules/interp/deleg_proc.html">deleg_proc</a></td>
<td class="#doctools_tocright">Creation of comm delegates (procedures)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil'><a href="tcllib/files/modules/fileutil/fileutil.html">fileutil</a></td>
<td class="#doctools_tocright">Procedures implementing some file utilities</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_magic_cfront'><a href="tcllib/files/modules/fumagic/cfront.html">fileutil::magic::cfront</a></td>
<td class="#doctools_tocright">Generator core for compiler of magic(5) files</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_magic_cgen'><a href="tcllib/files/modules/fumagic/cgen.html">fileutil::magic::cgen</a></td>
<td class="#doctools_tocright">Generator core for compiler of magic(5) files</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_magic_filetype'><a href="tcllib/files/modules/fumagic/filetypes.html">fileutil::magic::filetype</a></td>
<td class="#doctools_tocright">Procedures implementing file-type recognition</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_magic_rt'><a href="tcllib/files/modules/fumagic/rtcore.html">fileutil::magic::rt</a></td>
<td class="#doctools_tocright">Runtime core for file type recognition engines written in pure Tcl</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_multi'><a href="tcllib/files/modules/fileutil/multi.html">fileutil::multi</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather, standard object</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_multi_op'><a href="tcllib/files/modules/fileutil/multiop.html">fileutil::multi::op</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_traverse'><a href="tcllib/files/modules/fileutil/traverse.html">fileutil_traverse</a></td>
<td class="#doctools_tocright">Iterative directory traversal</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='hook'><a href="tcllib/files/modules/hook/hook.html">hook</a></td>
<td class="#doctools_tocright">Hooks</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='interp'><a href="tcllib/files/modules/interp/tcllib_interp.html">interp</a></td>
<td class="#doctools_tocright">Interp creation and aliasing</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='log'><a href="tcllib/files/modules/log/log.html">log</a></td>
<td class="#doctools_tocright">Procedures to log messages of libraries and applications.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='logger'><a href="tcllib/files/modules/log/logger.html">logger</a></td>
<td class="#doctools_tocright">System to control logging of events.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='logger_appender'><a href="tcllib/files/modules/log/loggerAppender.html">logger::appender</a></td>
<td class="#doctools_tocright">Collection of predefined appenders for logger</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='logger_utils'><a href="tcllib/files/modules/log/loggerUtils.html">logger::utils</a></td>
<td class="#doctools_tocright">Utilities for logger</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='multiplexer'><a href="tcllib/files/modules/multiplexer/multiplexer.html">multiplexer</a></td>
<td class="#doctools_tocright">One-to-many communication with sockets.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='pluginmgr'><a href="tcllib/files/modules/pluginmgr/pluginmgr.html">pluginmgr</a></td>
<td class="#doctools_tocright">Manage a plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='profiler'><a href="tcllib/files/modules/profiler/profiler.html">profiler</a></td>
<td class="#doctools_tocright">Tcl source code profiler</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='snit'><a href="tcllib/files/modules/snit/snit.html">snit</a></td>
<td class="#doctools_tocright">Snit's Not Incr Tcl</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='snitfaq'><a href="tcllib/files/modules/snit/snitfaq.html">snitfaq</a></td>
<td class="#doctools_tocright">Snit Frequently Asked Questions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='stooop'><a href="tcllib/files/modules/stooop/stooop.html">stooop</a></td>
<td class="#doctools_tocright">Object oriented extension.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='switched'><a href="tcllib/files/modules/stooop/switched.html">switched</a></td>
<td class="#doctools_tocright">switch/option management.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tie'><a href="tcllib/files/modules/tie/tie.html">tie</a></td>
<td class="#doctools_tocright">Array persistence</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tie'><a href="tcllib/files/modules/tie/tie_std.html">tie</a></td>
<td class="#doctools_tocright">Array persistence, standard data sources</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uevent'><a href="tcllib/files/modules/uev/uevent.html">uevent</a></td>
<td class="#doctools_tocright">User events</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='wip'><a href="tcllib/files/modules/wip/wip.html">wip</a></td>
<td class="#doctools_tocright">Word Interpreter</td>
</tr>
</table></dl>
<dl><dt><a name='system'>System</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
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
<td class="#doctools_tocright">Procedures to manipulate texts and strings.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_adjust'><a href="tcllib/files/modules/textutil/adjust.html">textutil::adjust</a></td>
<td class="#doctools_tocright">Procedures to adjust, indent, and undent paragraphs</td>
</tr>
<tr class="#doctools_toceven" >




<td class="#doctools_tocleft" ><a name='textutil_repeat'><a href="tcllib/files/modules/textutil/repeat.html">textutil::repeat</a></td>
<td class="#doctools_tocright">Procedures to repeat strings.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_split'><a href="tcllib/files/modules/textutil/textutil_split.html">textutil::split</a></td>
<td class="#doctools_tocright">Procedures to split texts</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_string'><a href="tcllib/files/modules/textutil/textutil_string.html">textutil::string</a></td>
<td class="#doctools_tocright">Procedures to manipulate texts and strings.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_tabify'><a href="tcllib/files/modules/textutil/tabify.html">textutil::tabify</a></td>
<td class="#doctools_tocright">Procedures to (un)tabify strings</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_trim'><a href="tcllib/files/modules/textutil/trim.html">textutil::trim</a></td>
<td class="#doctools_tocright">Procedures to trim strings</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uuencode'><a href="tcllib/files/modules/base64/uuencode.html">uuencode</a></td>
<td class="#doctools_tocright">UU-encode/decode binary data</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='xsxp'><a href="tcllib/files/modules/amazon-s3/xsxp.html">xsxp</a></td>
<td class="#doctools_tocright">eXtremely Simple Xml Parser</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='yencode'><a href="tcllib/files/modules/base64/yencode.html">yencode</a></td>
<td class="#doctools_tocright">Y-encode/decode binary data</td>
</tr>
</table></dl>
<dl><dt><a name='transfer_module'>Transfer module</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>



|



|



|



|



|



|



|







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
<td class="#doctools_tocright">Procedures to manipulate texts and strings.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_adjust'><a href="tcllib/files/modules/textutil/adjust.html">textutil::adjust</a></td>
<td class="#doctools_tocright">Procedures to adjust, indent, and undent paragraphs</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_patch'><a href="tcllib/files/modules/textutil/patch.html">textutil::patch</a></td>
<td class="#doctools_tocright">Application of uni-diff patches to directory trees</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_repeat'><a href="tcllib/files/modules/textutil/repeat.html">textutil::repeat</a></td>
<td class="#doctools_tocright">Procedures to repeat strings.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_split'><a href="tcllib/files/modules/textutil/textutil_split.html">textutil::split</a></td>
<td class="#doctools_tocright">Procedures to split texts</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_string'><a href="tcllib/files/modules/textutil/textutil_string.html">textutil::string</a></td>
<td class="#doctools_tocright">Procedures to manipulate texts and strings.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_tabify'><a href="tcllib/files/modules/textutil/tabify.html">textutil::tabify</a></td>
<td class="#doctools_tocright">Procedures to (un)tabify strings</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_trim'><a href="tcllib/files/modules/textutil/trim.html">textutil::trim</a></td>
<td class="#doctools_tocright">Procedures to trim strings</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uuencode'><a href="tcllib/files/modules/base64/uuencode.html">uuencode</a></td>
<td class="#doctools_tocright">UU-encode/decode binary data</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='xsxp'><a href="tcllib/files/modules/amazon-s3/xsxp.html">xsxp</a></td>
<td class="#doctools_tocright">eXtremely Simple Xml Parser</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='yencode'><a href="tcllib/files/modules/base64/yencode.html">yencode</a></td>
<td class="#doctools_tocright">Y-encode/decode binary data</td>
</tr>
</table></dl>
<dl><dt><a name='transfer_module'>Transfer module</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
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
<dl><dt><a name='unfiled'>Unfiled</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='cache_async'><a href="tcllib/files/modules/cache/async.html">cache::async</a></td>
<td class="#doctools_tocright">Asynchronous in-memory cache</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='generator'><a href="tcllib/files/modules/generator/generator.html">generator</a></td>
<td class="#doctools_tocright">Procedures for creating and using generators.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='huddle'><a href="tcllib/files/modules/yaml/huddle.html">huddle</a></td>
<td class="#doctools_tocright">Create and manipulate huddle object</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='imap4'><a href="tcllib/files/modules/imap4/imap4.html">imap4</a></td>
<td class="#doctools_tocright">imap client-side tcl implementation of imap protocol</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='map_geocode_nominatim'><a href="tcllib/files/modules/map/map_geocode_nominatim.html">map::geocode::nominatim</a></td>
<td class="#doctools_tocright">Resolving geographical names with a Nominatim service</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='map_slippy'><a href="tcllib/files/modules/map/map_slippy.html">map::slippy</a></td>
<td class="#doctools_tocright">Common code for slippy based map packages</td>







>
>
>
>



|



<
<
<
<







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
<dl><dt><a name='unfiled'>Unfiled</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='cache_async'><a href="tcllib/files/modules/cache/async.html">cache::async</a></td>
<td class="#doctools_tocright">Asynchronous in-memory cache</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_paths'><a href="tcllib/files/modules/fileutil/paths.html">fileutil::paths</a></td>
<td class="#doctools_tocright">Manage search path pools</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='generator'><a href="tcllib/files/modules/generator/generator.html">generator</a></td>
<td class="#doctools_tocright">Procedures for creating and using generators.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='huddle'><a href="tcllib/files/modules/yaml/huddle.html">huddle</a></td>
<td class="#doctools_tocright">Create and manipulate huddle object</td>
</tr>




<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='map_geocode_nominatim'><a href="tcllib/files/modules/map/map_geocode_nominatim.html">map::geocode::nominatim</a></td>
<td class="#doctools_tocright">Resolving geographical names with a Nominatim service</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='map_slippy'><a href="tcllib/files/modules/map/map_slippy.html">map::slippy</a></td>
<td class="#doctools_tocright">Common code for slippy based map packages</td>
1691
1692
1693
1694
1695
1696
1697




1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
<td class="#doctools_tocright">Implementation of stringprep</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='stringprep_data'><a href="tcllib/files/modules/stringprep/stringprep_data.html">stringprep::data</a></td>
<td class="#doctools_tocright">stringprep data tables, generated, internal</td>
</tr>
<tr class="#doctools_toceven" >




<td class="#doctools_tocleft" ><a name='tclrep_machineparameters'><a href="tcllib/files/modules/math/machineparameters.html">tclrep/machineparameters</a></td>
<td class="#doctools_tocright">Compute double precision machine parameters.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uevent_onidle'><a href="tcllib/files/modules/uev/uevent_onidle.html">uevent::onidle</a></td>
<td class="#doctools_tocright">Request merging and deferal to idle time</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='unicode'><a href="tcllib/files/modules/stringprep/unicode.html">unicode</a></td>
<td class="#doctools_tocright">Implementation of Unicode normalization</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='unicode_data'><a href="tcllib/files/modules/stringprep/unicode_data.html">unicode::data</a></td>
<td class="#doctools_tocright">unicode data tables, generated, internal</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='units'><a href="tcllib/files/modules/units/units.html">units</a></td>
<td class="#doctools_tocright">unit conversion</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='yaml'><a href="tcllib/files/modules/yaml/yaml.html">yaml</a></td>
<td class="#doctools_tocright">YAML Format Encoder/Decoder</td>
</tr>
</table></dl>
<dl><dt><a name='utilities'>Utilities</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>



|



|



|



|



|







1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
<td class="#doctools_tocright">Implementation of stringprep</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='stringprep_data'><a href="tcllib/files/modules/stringprep/stringprep_data.html">stringprep::data</a></td>
<td class="#doctools_tocright">stringprep data tables, generated, internal</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_map'><a href="tcllib/files/modules/struct/struct_map.html">struct::map</a></td>
<td class="#doctools_tocright">Manage key/value maps</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tclrep_machineparameters'><a href="tcllib/files/modules/math/machineparameters.html">tclrep/machineparameters</a></td>
<td class="#doctools_tocright">Compute double precision machine parameters.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uevent_onidle'><a href="tcllib/files/modules/uev/uevent_onidle.html">uevent::onidle</a></td>
<td class="#doctools_tocright">Request merging and deferal to idle time</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='unicode'><a href="tcllib/files/modules/stringprep/unicode.html">unicode</a></td>
<td class="#doctools_tocright">Implementation of Unicode normalization</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='unicode_data'><a href="tcllib/files/modules/stringprep/unicode_data.html">unicode::data</a></td>
<td class="#doctools_tocright">unicode data tables, generated, internal</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='units'><a href="tcllib/files/modules/units/units.html">units</a></td>
<td class="#doctools_tocright">unit conversion</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='yaml'><a href="tcllib/files/modules/yaml/yaml.html">yaml</a></td>
<td class="#doctools_tocright">YAML Format Encoder/Decoder</td>
</tr>
</table></dl>
<dl><dt><a name='utilities'>Utilities</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
1963
1964
1965
1966
1967
1968
1969







1970
1971
1972
1973
1974
1975
1976
</table></dl>
<dl><dt><a name='cache'>cache</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='cache_async'><a href="tcllib/files/modules/cache/async.html">cache::async</a></td>
<td class="#doctools_tocright">Asynchronous in-memory cache</td>
</tr>







</table></dl>
<dl><dt><a name='clock'>clock</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='clock_iso8601'><a href="tcllib/files/modules/clock/iso8601.html">clock_iso8601</a></td>
<td class="#doctools_tocright">Parsing ISO 8601 dates/times</td>
</tr>







>
>
>
>
>
>
>







1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
</table></dl>
<dl><dt><a name='cache'>cache</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='cache_async'><a href="tcllib/files/modules/cache/async.html">cache::async</a></td>
<td class="#doctools_tocright">Asynchronous in-memory cache</td>
</tr>
</table></dl>
<dl><dt><a name='clay'>clay</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='clay'><a href="tcllib/files/modules/clay/clay.html">clay</a></td>
<td class="#doctools_tocright">A minimalist framework for large scale OO Projects</td>
</tr>
</table></dl>
<dl><dt><a name='clock'>clock</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='clock_iso8601'><a href="tcllib/files/modules/clock/iso8601.html">clock_iso8601</a></td>
<td class="#doctools_tocright">Parsing ISO 8601 dates/times</td>
</tr>
2411
2412
2413
2414
2415
2416
2417




2418
2419
2420
2421
2422
2423
2424
<td class="#doctools_tocright">Multi-file operation, scatter/gather, standard object</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_multi_op'><a href="tcllib/files/modules/fileutil/multiop.html">fileutil::multi::op</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='fileutil_traverse'><a href="tcllib/files/modules/fileutil/traverse.html">fileutil_traverse</a></td>
<td class="#doctools_tocright">Iterative directory traversal</td>
</tr>
</table></dl>
<dl><dt><a name='ftp'>ftp</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>







2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
<td class="#doctools_tocright">Multi-file operation, scatter/gather, standard object</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_multi_op'><a href="tcllib/files/modules/fileutil/multiop.html">fileutil::multi::op</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_paths'><a href="tcllib/files/modules/fileutil/paths.html">fileutil::paths</a></td>
<td class="#doctools_tocright">Manage search path pools</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_traverse'><a href="tcllib/files/modules/fileutil/traverse.html">fileutil_traverse</a></td>
<td class="#doctools_tocright">Iterative directory traversal</td>
</tr>
</table></dl>
<dl><dt><a name='ftp'>ftp</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
<td class="#doctools_tocleft" ><a name='autoproxy'><a href="tcllib/files/modules/http/autoproxy.html">autoproxy</a></td>
<td class="#doctools_tocright">Automatic HTTP proxy usage and authentication</td>
</tr>
</table></dl>
<dl><dt><a name='httpd'>httpd</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tool'><a href="tcllib/files/modules/httpd/httpd.html">tool</a></td>
<td class="#doctools_tocright">A TclOO and coroutine based web server</td>
</tr>
</table></dl>
<dl><dt><a name='ident'>ident</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='ident'><a href="tcllib/files/modules/ident/ident.html">ident</a></td>







|







2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
<td class="#doctools_tocleft" ><a name='autoproxy'><a href="tcllib/files/modules/http/autoproxy.html">autoproxy</a></td>
<td class="#doctools_tocright">Automatic HTTP proxy usage and authentication</td>
</tr>
</table></dl>
<dl><dt><a name='httpd'>httpd</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='httpd'><a href="tcllib/files/modules/httpd/httpd.html">httpd</a></td>
<td class="#doctools_tocright">A TclOO and coroutine based web server</td>
</tr>
</table></dl>
<dl><dt><a name='ident'>ident</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='ident'><a href="tcllib/files/modules/ident/ident.html">ident</a></td>
2805
2806
2807
2808
2809
2810
2811




2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
<td class="#doctools_tocright">Package for Principal Component Analysis</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_polynomials'><a href="tcllib/files/modules/math/polynomials.html">math::polynomials</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_toceven" >




<td class="#doctools_tocleft" ><a name='math_rationalfunctions'><a href="tcllib/files/modules/math/rational_funcs.html">math::rationalfunctions</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_roman'><a href="tcllib/files/modules/math/roman.html">math::roman</a></td>
<td class="#doctools_tocright">Tools for creating and manipulating roman numerals</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_special'><a href="tcllib/files/modules/math/special.html">math::special</a></td>
<td class="#doctools_tocright">Special mathematical functions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_statistics'><a href="tcllib/files/modules/math/statistics.html">math::statistics</a></td>
<td class="#doctools_tocright">Basic statistical functions and procedures</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_trig'><a href="tcllib/files/modules/math/trig.html">math::trig</a></td>
<td class="#doctools_tocright">Trigonometric anf hyperbolic functions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tclrep_machineparameters'><a href="tcllib/files/modules/math/machineparameters.html">tclrep/machineparameters</a></td>
<td class="#doctools_tocright">Compute double precision machine parameters.</td>
</tr>
</table></dl>
<dl><dt><a name='md4'>md4</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>



|



|



|



|



|







2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
<td class="#doctools_tocright">Package for Principal Component Analysis</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_polynomials'><a href="tcllib/files/modules/math/polynomials.html">math::polynomials</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_quasirandom'><a href="tcllib/files/modules/math/quasirandom.html">math::quasirandom</a></td>
<td class="#doctools_tocright">Quasi-random points for integration and Monte Carlo type methods</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_rationalfunctions'><a href="tcllib/files/modules/math/rational_funcs.html">math::rationalfunctions</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_roman'><a href="tcllib/files/modules/math/roman.html">math::roman</a></td>
<td class="#doctools_tocright">Tools for creating and manipulating roman numerals</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_special'><a href="tcllib/files/modules/math/special.html">math::special</a></td>
<td class="#doctools_tocright">Special mathematical functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_statistics'><a href="tcllib/files/modules/math/statistics.html">math::statistics</a></td>
<td class="#doctools_tocright">Basic statistical functions and procedures</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_trig'><a href="tcllib/files/modules/math/trig.html">math::trig</a></td>
<td class="#doctools_tocright">Trigonometric anf hyperbolic functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tclrep_machineparameters'><a href="tcllib/files/modules/math/machineparameters.html">tclrep/machineparameters</a></td>
<td class="#doctools_tocright">Compute double precision machine parameters.</td>
</tr>
</table></dl>
<dl><dt><a name='md4'>md4</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
3404
3405
3406
3407
3408
3409
3410




3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
<td class="#doctools_tocright">Create and manipulate directed graph objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_list'><a href="tcllib/files/modules/struct/struct_list.html">struct::list</a></td>
<td class="#doctools_tocright">Procedures for manipulating lists</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='struct_matrix'><a href="tcllib/files/modules/struct/matrix.html">struct::matrix</a></td>
<td class="#doctools_tocright">Create and manipulate matrix objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_matrix_v1'><a href="tcllib/files/modules/struct/matrix1.html">struct::matrix_v1</a></td>
<td class="#doctools_tocright">Create and manipulate matrix objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_pool'><a href="tcllib/files/modules/struct/pool.html">struct::pool</a></td>
<td class="#doctools_tocright">Create and manipulate pool objects (of discrete items)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_prioqueue'><a href="tcllib/files/modules/struct/prioqueue.html">struct::prioqueue</a></td>
<td class="#doctools_tocright">Create and manipulate prioqueue objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_queue'><a href="tcllib/files/modules/struct/queue.html">struct::queue</a></td>
<td class="#doctools_tocright">Create and manipulate queue objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_record'><a href="tcllib/files/modules/struct/record.html">struct::record</a></td>
<td class="#doctools_tocright">Define and create records (similar to 'C' structures)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_set'><a href="tcllib/files/modules/struct/struct_set.html">struct::set</a></td>
<td class="#doctools_tocright">Procedures for manipulating sets</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_skiplist'><a href="tcllib/files/modules/struct/skiplist.html">struct::skiplist</a></td>
<td class="#doctools_tocright">Create and manipulate skiplists</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_stack'><a href="tcllib/files/modules/struct/stack.html">struct::stack</a></td>
<td class="#doctools_tocright">Create and manipulate stack objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_tree'><a href="tcllib/files/modules/struct/struct_tree.html">struct::tree</a></td>
<td class="#doctools_tocright">Create and manipulate tree objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_tree_v1'><a href="tcllib/files/modules/struct/struct_tree1.html">struct::tree_v1</a></td>
<td class="#doctools_tocright">Create and manipulate tree objects</td>
</tr>
</table></dl>
<dl><dt><a name='tar'>tar</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>



|



|



|



|



|



|



|



|



|



|







3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
<td class="#doctools_tocright">Create and manipulate directed graph objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_list'><a href="tcllib/files/modules/struct/struct_list.html">struct::list</a></td>
<td class="#doctools_tocright">Procedures for manipulating lists</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_map'><a href="tcllib/files/modules/struct/struct_map.html">struct::map</a></td>
<td class="#doctools_tocright">Manage key/value maps</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_matrix'><a href="tcllib/files/modules/struct/matrix.html">struct::matrix</a></td>
<td class="#doctools_tocright">Create and manipulate matrix objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_matrix_v1'><a href="tcllib/files/modules/struct/matrix1.html">struct::matrix_v1</a></td>
<td class="#doctools_tocright">Create and manipulate matrix objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_pool'><a href="tcllib/files/modules/struct/pool.html">struct::pool</a></td>
<td class="#doctools_tocright">Create and manipulate pool objects (of discrete items)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_prioqueue'><a href="tcllib/files/modules/struct/prioqueue.html">struct::prioqueue</a></td>
<td class="#doctools_tocright">Create and manipulate prioqueue objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_queue'><a href="tcllib/files/modules/struct/queue.html">struct::queue</a></td>
<td class="#doctools_tocright">Create and manipulate queue objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_record'><a href="tcllib/files/modules/struct/record.html">struct::record</a></td>
<td class="#doctools_tocright">Define and create records (similar to 'C' structures)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_set'><a href="tcllib/files/modules/struct/struct_set.html">struct::set</a></td>
<td class="#doctools_tocright">Procedures for manipulating sets</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_skiplist'><a href="tcllib/files/modules/struct/skiplist.html">struct::skiplist</a></td>
<td class="#doctools_tocright">Create and manipulate skiplists</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_stack'><a href="tcllib/files/modules/struct/stack.html">struct::stack</a></td>
<td class="#doctools_tocright">Create and manipulate stack objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_tree'><a href="tcllib/files/modules/struct/struct_tree.html">struct::tree</a></td>
<td class="#doctools_tocright">Create and manipulate tree objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_tree_v1'><a href="tcllib/files/modules/struct/struct_tree1.html">struct::tree_v1</a></td>
<td class="#doctools_tocright">Create and manipulate tree objects</td>
</tr>
</table></dl>
<dl><dt><a name='tar'>tar</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
3540
3541
3542
3543
3544
3545
3546




3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
<td class="#doctools_tocright">Procedures to adjust, indent, and undent paragraphs</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_expander'><a href="tcllib/files/modules/textutil/expander.html">textutil::expander</a></td>
<td class="#doctools_tocright">Procedures to process templates and expand text.</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='textutil_repeat'><a href="tcllib/files/modules/textutil/repeat.html">textutil::repeat</a></td>
<td class="#doctools_tocright">Procedures to repeat strings.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_split'><a href="tcllib/files/modules/textutil/textutil_split.html">textutil::split</a></td>
<td class="#doctools_tocright">Procedures to split texts</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_string'><a href="tcllib/files/modules/textutil/textutil_string.html">textutil::string</a></td>
<td class="#doctools_tocright">Procedures to manipulate texts and strings.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_tabify'><a href="tcllib/files/modules/textutil/tabify.html">textutil::tabify</a></td>
<td class="#doctools_tocright">Procedures to (un)tabify strings</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_trim'><a href="tcllib/files/modules/textutil/trim.html">textutil::trim</a></td>
<td class="#doctools_tocright">Procedures to trim strings</td>
</tr>
</table></dl>
<dl><dt><a name='tie'>tie</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>



|



|



|



|







3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
<td class="#doctools_tocright">Procedures to adjust, indent, and undent paragraphs</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_expander'><a href="tcllib/files/modules/textutil/expander.html">textutil::expander</a></td>
<td class="#doctools_tocright">Procedures to process templates and expand text.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_patch'><a href="tcllib/files/modules/textutil/patch.html">textutil::patch</a></td>
<td class="#doctools_tocright">Application of uni-diff patches to directory trees</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_repeat'><a href="tcllib/files/modules/textutil/repeat.html">textutil::repeat</a></td>
<td class="#doctools_tocright">Procedures to repeat strings.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_split'><a href="tcllib/files/modules/textutil/textutil_split.html">textutil::split</a></td>
<td class="#doctools_tocright">Procedures to split texts</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_string'><a href="tcllib/files/modules/textutil/textutil_string.html">textutil::string</a></td>
<td class="#doctools_tocright">Procedures to manipulate texts and strings.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_tabify'><a href="tcllib/files/modules/textutil/tabify.html">textutil::tabify</a></td>
<td class="#doctools_tocright">Procedures to (un)tabify strings</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_trim'><a href="tcllib/files/modules/textutil/trim.html">textutil::trim</a></td>
<td class="#doctools_tocright">Procedures to trim strings</td>
</tr>
</table></dl>
<dl><dt><a name='tie'>tie</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >

Changes to idoc/www/toc0.html.

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
<td class="#doctools_tocright">Package for Principal Component Analysis</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_polynomials'><a href="tcllib/files/modules/math/polynomials.html">math::polynomials</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='math_rationalfunctions'><a href="tcllib/files/modules/math/rational_funcs.html">math::rationalfunctions</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_roman'><a href="tcllib/files/modules/math/roman.html">math::roman</a></td>
<td class="#doctools_tocright">Tools for creating and manipulating roman numerals</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_special'><a href="tcllib/files/modules/math/special.html">math::special</a></td>
<td class="#doctools_tocright">Special mathematical functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_statistics'><a href="tcllib/files/modules/math/statistics.html">math::statistics</a></td>
<td class="#doctools_tocright">Basic statistical functions and procedures</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_trig'><a href="tcllib/files/modules/math/trig.html">math::trig</a></td>
<td class="#doctools_tocright">Trigonometric anf hyperbolic functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='simulation_annealing'><a href="tcllib/files/modules/simulation/annealing.html">simulation::annealing</a></td>
<td class="#doctools_tocright">Simulated annealing</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='simulation_montecarlo'><a href="tcllib/files/modules/simulation/montecarlo.html">simulation::montecarlo</a></td>
<td class="#doctools_tocright">Monte Carlo simulations</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='simulation_random'><a href="tcllib/files/modules/simulation/simulation_random.html">simulation::random</a></td>
<td class="#doctools_tocright">Pseudo-random number generators</td>
</tr>
</table></dl>
<dl><dt><a name='networking'>Networking</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>



|



|



|



|



|



|



|







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
<td class="#doctools_tocright">Package for Principal Component Analysis</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_polynomials'><a href="tcllib/files/modules/math/polynomials.html">math::polynomials</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_quasirandom'><a href="tcllib/files/modules/math/quasirandom.html">math::quasirandom</a></td>
<td class="#doctools_tocright">Quasi-random points for integration and Monte Carlo type methods</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_rationalfunctions'><a href="tcllib/files/modules/math/rational_funcs.html">math::rationalfunctions</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_roman'><a href="tcllib/files/modules/math/roman.html">math::roman</a></td>
<td class="#doctools_tocright">Tools for creating and manipulating roman numerals</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_special'><a href="tcllib/files/modules/math/special.html">math::special</a></td>
<td class="#doctools_tocright">Special mathematical functions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_statistics'><a href="tcllib/files/modules/math/statistics.html">math::statistics</a></td>
<td class="#doctools_tocright">Basic statistical functions and procedures</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_trig'><a href="tcllib/files/modules/math/trig.html">math::trig</a></td>
<td class="#doctools_tocright">Trigonometric anf hyperbolic functions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='simulation_annealing'><a href="tcllib/files/modules/simulation/annealing.html">simulation::annealing</a></td>
<td class="#doctools_tocright">Simulated annealing</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='simulation_montecarlo'><a href="tcllib/files/modules/simulation/montecarlo.html">simulation::montecarlo</a></td>
<td class="#doctools_tocright">Monte Carlo simulations</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='simulation_random'><a href="tcllib/files/modules/simulation/simulation_random.html">simulation::random</a></td>
<td class="#doctools_tocright">Pseudo-random number generators</td>
</tr>
</table></dl>
<dl><dt><a name='networking'>Networking</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
858
859
860
861
862
863
864




865
866
867




868
869
870
871
872
873
874
<td class="#doctools_tocright">Uri handler for ftp urls</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='ftpd'><a href="tcllib/files/modules/ftpd/ftpd.html">ftpd</a></td>
<td class="#doctools_tocright">Tcl FTP server implementation</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='ident'><a href="tcllib/files/modules/ident/ident.html">ident</a></td>
<td class="#doctools_tocright">Ident protocol client</td>
</tr>




<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='irc'><a href="tcllib/files/modules/irc/irc.html">irc</a></td>
<td class="#doctools_tocright">Create IRC connection and interface.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='ldap'><a href="tcllib/files/modules/ldap/ldap.html">ldap</a></td>
<td class="#doctools_tocright">LDAP client</td>







>
>
>
>



>
>
>
>







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
<td class="#doctools_tocright">Uri handler for ftp urls</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='ftpd'><a href="tcllib/files/modules/ftpd/ftpd.html">ftpd</a></td>
<td class="#doctools_tocright">Tcl FTP server implementation</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='httpd'><a href="tcllib/files/modules/httpd/httpd.html">httpd</a></td>
<td class="#doctools_tocright">A TclOO and coroutine based web server</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='ident'><a href="tcllib/files/modules/ident/ident.html">ident</a></td>
<td class="#doctools_tocright">Ident protocol client</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='imap4'><a href="tcllib/files/modules/imap4/imap4.html">imap4</a></td>
<td class="#doctools_tocright">imap client-side tcl implementation of imap protocol</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='irc'><a href="tcllib/files/modules/irc/irc.html">irc</a></td>
<td class="#doctools_tocright">Create IRC connection and interface.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='ldap'><a href="tcllib/files/modules/ldap/ldap.html">ldap</a></td>
<td class="#doctools_tocright">LDAP client</td>
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
<td class="#doctools_tocright">Tcl SMTP server implementation</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcllib_ip'><a href="tcllib/files/modules/dns/tcllib_ip.html">tcllib_ip</a></td>
<td class="#doctools_tocright">IPv4 and IPv6 address manipulation</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tool'><a href="tcllib/files/modules/httpd/httpd.html">tool</a></td>
<td class="#doctools_tocright">A TclOO and coroutine based web server</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='udpcluster'><a href="tcllib/files/modules/udpcluster/udpcluster.html">udpcluster</a></td>
<td class="#doctools_tocright">UDP Peer-to-Peer cluster</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uri'><a href="tcllib/files/modules/uri/uri.html">uri</a></td>
<td class="#doctools_tocright">URI utilities</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uri_urn'><a href="tcllib/files/modules/uri/urn-scheme.html">uri_urn</a></td>
<td class="#doctools_tocright">URI utilities, URN scheme</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='websocket'><a href="tcllib/files/modules/websocket/websocket.html">websocket</a></td>
<td class="#doctools_tocright">Tcl implementation of the websocket protocol</td>
</tr>
</table></dl>
<dl><dt><a name='page_parser_generator'>Page Parser Generator</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







<
<
<
<



|



|



|







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
<td class="#doctools_tocright">Tcl SMTP server implementation</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tcllib_ip'><a href="tcllib/files/modules/dns/tcllib_ip.html">tcllib_ip</a></td>
<td class="#doctools_tocright">IPv4 and IPv6 address manipulation</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='udpcluster'><a href="tcllib/files/modules/udpcluster/udpcluster.html">udpcluster</a></td>
<td class="#doctools_tocright">UDP Peer-to-Peer cluster</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uri'><a href="tcllib/files/modules/uri/uri.html">uri</a></td>
<td class="#doctools_tocright">URI utilities</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uri_urn'><a href="tcllib/files/modules/uri/urn-scheme.html">uri_urn</a></td>
<td class="#doctools_tocright">URI utilities, URN scheme</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='websocket'><a href="tcllib/files/modules/websocket/websocket.html">websocket</a></td>
<td class="#doctools_tocright">Tcl implementation of the websocket protocol</td>
</tr>
</table></dl>
<dl><dt><a name='page_parser_generator'>Page Parser Generator</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
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
<td class="#doctools_tocleft" ><a name='tepam_procedure'><a href="tcllib/files/modules/tepam/tepam_procedure.html">tepam::procedure</a></td>
<td class="#doctools_tocright">TEPAM procedure, reference manual</td>
</tr>
</table></dl>
<dl><dt><a name='programming_tools'>Programming tools</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >




<td class="#doctools_tocleft" ><a name='cmdline'><a href="tcllib/files/modules/cmdline/cmdline.html">cmdline</a></td>
<td class="#doctools_tocright">Procedures to process command lines and options.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='comm'><a href="tcllib/files/modules/comm/comm.html">comm</a></td>
<td class="#doctools_tocright">A remote communication facility for Tcl (8.3 and later)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='comm_wire'><a href="tcllib/files/modules/comm/comm_wire.html">comm_wire</a></td>
<td class="#doctools_tocright">The comm wire protocol</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='control'><a href="tcllib/files/modules/control/control.html">control</a></td>
<td class="#doctools_tocright">Procedures for control flow structures.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='deleg_method'><a href="tcllib/files/modules/interp/deleg_method.html">deleg_method</a></td>
<td class="#doctools_tocright">Creation of comm delegates (snit methods)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='deleg_proc'><a href="tcllib/files/modules/interp/deleg_proc.html">deleg_proc</a></td>
<td class="#doctools_tocright">Creation of comm delegates (procedures)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil'><a href="tcllib/files/modules/fileutil/fileutil.html">fileutil</a></td>
<td class="#doctools_tocright">Procedures implementing some file utilities</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_magic_cfront'><a href="tcllib/files/modules/fumagic/cfront.html">fileutil::magic::cfront</a></td>
<td class="#doctools_tocright">Generator core for compiler of magic(5) files</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_magic_cgen'><a href="tcllib/files/modules/fumagic/cgen.html">fileutil::magic::cgen</a></td>
<td class="#doctools_tocright">Generator core for compiler of magic(5) files</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_magic_filetype'><a href="tcllib/files/modules/fumagic/filetypes.html">fileutil::magic::filetype</a></td>
<td class="#doctools_tocright">Procedures implementing file-type recognition</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_magic_rt'><a href="tcllib/files/modules/fumagic/rtcore.html">fileutil::magic::rt</a></td>
<td class="#doctools_tocright">Runtime core for file type recognition engines written in pure Tcl</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_multi'><a href="tcllib/files/modules/fileutil/multi.html">fileutil::multi</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather, standard object</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_multi_op'><a href="tcllib/files/modules/fileutil/multiop.html">fileutil::multi::op</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_traverse'><a href="tcllib/files/modules/fileutil/traverse.html">fileutil_traverse</a></td>
<td class="#doctools_tocright">Iterative directory traversal</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='hook'><a href="tcllib/files/modules/hook/hook.html">hook</a></td>
<td class="#doctools_tocright">Hooks</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='interp'><a href="tcllib/files/modules/interp/tcllib_interp.html">interp</a></td>
<td class="#doctools_tocright">Interp creation and aliasing</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='log'><a href="tcllib/files/modules/log/log.html">log</a></td>
<td class="#doctools_tocright">Procedures to log messages of libraries and applications.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='logger'><a href="tcllib/files/modules/log/logger.html">logger</a></td>
<td class="#doctools_tocright">System to control logging of events.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='logger_appender'><a href="tcllib/files/modules/log/loggerAppender.html">logger::appender</a></td>
<td class="#doctools_tocright">Collection of predefined appenders for logger</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='logger_utils'><a href="tcllib/files/modules/log/loggerUtils.html">logger::utils</a></td>
<td class="#doctools_tocright">Utilities for logger</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='multiplexer'><a href="tcllib/files/modules/multiplexer/multiplexer.html">multiplexer</a></td>
<td class="#doctools_tocright">One-to-many communication with sockets.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='pluginmgr'><a href="tcllib/files/modules/pluginmgr/pluginmgr.html">pluginmgr</a></td>
<td class="#doctools_tocright">Manage a plugin</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='profiler'><a href="tcllib/files/modules/profiler/profiler.html">profiler</a></td>
<td class="#doctools_tocright">Tcl source code profiler</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='snit'><a href="tcllib/files/modules/snit/snit.html">snit</a></td>
<td class="#doctools_tocright">Snit's Not Incr Tcl</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='snitfaq'><a href="tcllib/files/modules/snit/snitfaq.html">snitfaq</a></td>
<td class="#doctools_tocright">Snit Frequently Asked Questions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='stooop'><a href="tcllib/files/modules/stooop/stooop.html">stooop</a></td>
<td class="#doctools_tocright">Object oriented extension.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='switched'><a href="tcllib/files/modules/stooop/switched.html">switched</a></td>
<td class="#doctools_tocright">switch/option management.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tie'><a href="tcllib/files/modules/tie/tie.html">tie</a></td>
<td class="#doctools_tocright">Array persistence</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tie'><a href="tcllib/files/modules/tie/tie_std.html">tie</a></td>
<td class="#doctools_tocright">Array persistence, standard data sources</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uevent'><a href="tcllib/files/modules/uev/uevent.html">uevent</a></td>
<td class="#doctools_tocright">User events</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='wip'><a href="tcllib/files/modules/wip/wip.html">wip</a></td>
<td class="#doctools_tocright">Word Interpreter</td>
</tr>
</table></dl>
<dl><dt><a name='system'>System</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|



|







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
<td class="#doctools_tocleft" ><a name='tepam_procedure'><a href="tcllib/files/modules/tepam/tepam_procedure.html">tepam::procedure</a></td>
<td class="#doctools_tocright">TEPAM procedure, reference manual</td>
</tr>
</table></dl>
<dl><dt><a name='programming_tools'>Programming tools</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='clay'><a href="tcllib/files/modules/clay/clay.html">clay</a></td>
<td class="#doctools_tocright">A minimalist framework for large scale OO Projects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='cmdline'><a href="tcllib/files/modules/cmdline/cmdline.html">cmdline</a></td>
<td class="#doctools_tocright">Procedures to process command lines and options.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='comm'><a href="tcllib/files/modules/comm/comm.html">comm</a></td>
<td class="#doctools_tocright">A remote communication facility for Tcl (8.3 and later)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='comm_wire'><a href="tcllib/files/modules/comm/comm_wire.html">comm_wire</a></td>
<td class="#doctools_tocright">The comm wire protocol</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='control'><a href="tcllib/files/modules/control/control.html">control</a></td>
<td class="#doctools_tocright">Procedures for control flow structures.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='deleg_method'><a href="tcllib/files/modules/interp/deleg_method.html">deleg_method</a></td>
<td class="#doctools_tocright">Creation of comm delegates (snit methods)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='deleg_proc'><a href="tcllib/files/modules/interp/deleg_proc.html">deleg_proc</a></td>
<td class="#doctools_tocright">Creation of comm delegates (procedures)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil'><a href="tcllib/files/modules/fileutil/fileutil.html">fileutil</a></td>
<td class="#doctools_tocright">Procedures implementing some file utilities</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_magic_cfront'><a href="tcllib/files/modules/fumagic/cfront.html">fileutil::magic::cfront</a></td>
<td class="#doctools_tocright">Generator core for compiler of magic(5) files</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_magic_cgen'><a href="tcllib/files/modules/fumagic/cgen.html">fileutil::magic::cgen</a></td>
<td class="#doctools_tocright">Generator core for compiler of magic(5) files</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_magic_filetype'><a href="tcllib/files/modules/fumagic/filetypes.html">fileutil::magic::filetype</a></td>
<td class="#doctools_tocright">Procedures implementing file-type recognition</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_magic_rt'><a href="tcllib/files/modules/fumagic/rtcore.html">fileutil::magic::rt</a></td>
<td class="#doctools_tocright">Runtime core for file type recognition engines written in pure Tcl</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_multi'><a href="tcllib/files/modules/fileutil/multi.html">fileutil::multi</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather, standard object</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_multi_op'><a href="tcllib/files/modules/fileutil/multiop.html">fileutil::multi::op</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_traverse'><a href="tcllib/files/modules/fileutil/traverse.html">fileutil_traverse</a></td>
<td class="#doctools_tocright">Iterative directory traversal</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='hook'><a href="tcllib/files/modules/hook/hook.html">hook</a></td>
<td class="#doctools_tocright">Hooks</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='interp'><a href="tcllib/files/modules/interp/tcllib_interp.html">interp</a></td>
<td class="#doctools_tocright">Interp creation and aliasing</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='log'><a href="tcllib/files/modules/log/log.html">log</a></td>
<td class="#doctools_tocright">Procedures to log messages of libraries and applications.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='logger'><a href="tcllib/files/modules/log/logger.html">logger</a></td>
<td class="#doctools_tocright">System to control logging of events.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='logger_appender'><a href="tcllib/files/modules/log/loggerAppender.html">logger::appender</a></td>
<td class="#doctools_tocright">Collection of predefined appenders for logger</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='logger_utils'><a href="tcllib/files/modules/log/loggerUtils.html">logger::utils</a></td>
<td class="#doctools_tocright">Utilities for logger</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='multiplexer'><a href="tcllib/files/modules/multiplexer/multiplexer.html">multiplexer</a></td>
<td class="#doctools_tocright">One-to-many communication with sockets.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='pluginmgr'><a href="tcllib/files/modules/pluginmgr/pluginmgr.html">pluginmgr</a></td>
<td class="#doctools_tocright">Manage a plugin</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='profiler'><a href="tcllib/files/modules/profiler/profiler.html">profiler</a></td>
<td class="#doctools_tocright">Tcl source code profiler</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='snit'><a href="tcllib/files/modules/snit/snit.html">snit</a></td>
<td class="#doctools_tocright">Snit's Not Incr Tcl</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='snitfaq'><a href="tcllib/files/modules/snit/snitfaq.html">snitfaq</a></td>
<td class="#doctools_tocright">Snit Frequently Asked Questions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='stooop'><a href="tcllib/files/modules/stooop/stooop.html">stooop</a></td>
<td class="#doctools_tocright">Object oriented extension.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='switched'><a href="tcllib/files/modules/stooop/switched.html">switched</a></td>
<td class="#doctools_tocright">switch/option management.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tie'><a href="tcllib/files/modules/tie/tie.html">tie</a></td>
<td class="#doctools_tocright">Array persistence</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tie'><a href="tcllib/files/modules/tie/tie_std.html">tie</a></td>
<td class="#doctools_tocright">Array persistence, standard data sources</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uevent'><a href="tcllib/files/modules/uev/uevent.html">uevent</a></td>
<td class="#doctools_tocright">User events</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='wip'><a href="tcllib/files/modules/wip/wip.html">wip</a></td>
<td class="#doctools_tocright">Word Interpreter</td>
</tr>
</table></dl>
<dl><dt><a name='system'>System</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
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
<td class="#doctools_tocright">Procedures to manipulate texts and strings.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_adjust'><a href="tcllib/files/modules/textutil/adjust.html">textutil::adjust</a></td>
<td class="#doctools_tocright">Procedures to adjust, indent, and undent paragraphs</td>
</tr>
<tr class="#doctools_toceven" >




<td class="#doctools_tocleft" ><a name='textutil_repeat'><a href="tcllib/files/modules/textutil/repeat.html">textutil::repeat</a></td>
<td class="#doctools_tocright">Procedures to repeat strings.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_split'><a href="tcllib/files/modules/textutil/textutil_split.html">textutil::split</a></td>
<td class="#doctools_tocright">Procedures to split texts</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_string'><a href="tcllib/files/modules/textutil/textutil_string.html">textutil::string</a></td>
<td class="#doctools_tocright">Procedures to manipulate texts and strings.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_tabify'><a href="tcllib/files/modules/textutil/tabify.html">textutil::tabify</a></td>
<td class="#doctools_tocright">Procedures to (un)tabify strings</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_trim'><a href="tcllib/files/modules/textutil/trim.html">textutil::trim</a></td>
<td class="#doctools_tocright">Procedures to trim strings</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uuencode'><a href="tcllib/files/modules/base64/uuencode.html">uuencode</a></td>
<td class="#doctools_tocright">UU-encode/decode binary data</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='xsxp'><a href="tcllib/files/modules/amazon-s3/xsxp.html">xsxp</a></td>
<td class="#doctools_tocright">eXtremely Simple Xml Parser</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='yencode'><a href="tcllib/files/modules/base64/yencode.html">yencode</a></td>
<td class="#doctools_tocright">Y-encode/decode binary data</td>
</tr>
</table></dl>
<dl><dt><a name='transfer_module'>Transfer module</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>



|



|



|



|



|



|



|







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
<td class="#doctools_tocright">Procedures to manipulate texts and strings.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_adjust'><a href="tcllib/files/modules/textutil/adjust.html">textutil::adjust</a></td>
<td class="#doctools_tocright">Procedures to adjust, indent, and undent paragraphs</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_patch'><a href="tcllib/files/modules/textutil/patch.html">textutil::patch</a></td>
<td class="#doctools_tocright">Application of uni-diff patches to directory trees</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_repeat'><a href="tcllib/files/modules/textutil/repeat.html">textutil::repeat</a></td>
<td class="#doctools_tocright">Procedures to repeat strings.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_split'><a href="tcllib/files/modules/textutil/textutil_split.html">textutil::split</a></td>
<td class="#doctools_tocright">Procedures to split texts</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_string'><a href="tcllib/files/modules/textutil/textutil_string.html">textutil::string</a></td>
<td class="#doctools_tocright">Procedures to manipulate texts and strings.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_tabify'><a href="tcllib/files/modules/textutil/tabify.html">textutil::tabify</a></td>
<td class="#doctools_tocright">Procedures to (un)tabify strings</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_trim'><a href="tcllib/files/modules/textutil/trim.html">textutil::trim</a></td>
<td class="#doctools_tocright">Procedures to trim strings</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uuencode'><a href="tcllib/files/modules/base64/uuencode.html">uuencode</a></td>
<td class="#doctools_tocright">UU-encode/decode binary data</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='xsxp'><a href="tcllib/files/modules/amazon-s3/xsxp.html">xsxp</a></td>
<td class="#doctools_tocright">eXtremely Simple Xml Parser</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='yencode'><a href="tcllib/files/modules/base64/yencode.html">yencode</a></td>
<td class="#doctools_tocright">Y-encode/decode binary data</td>
</tr>
</table></dl>
<dl><dt><a name='transfer_module'>Transfer module</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
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
<dl><dt><a name='unfiled'>Unfiled</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='cache_async'><a href="tcllib/files/modules/cache/async.html">cache::async</a></td>
<td class="#doctools_tocright">Asynchronous in-memory cache</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='generator'><a href="tcllib/files/modules/generator/generator.html">generator</a></td>
<td class="#doctools_tocright">Procedures for creating and using generators.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='huddle'><a href="tcllib/files/modules/yaml/huddle.html">huddle</a></td>
<td class="#doctools_tocright">Create and manipulate huddle object</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='imap4'><a href="tcllib/files/modules/imap4/imap4.html">imap4</a></td>
<td class="#doctools_tocright">imap client-side tcl implementation of imap protocol</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='map_geocode_nominatim'><a href="tcllib/files/modules/map/map_geocode_nominatim.html">map::geocode::nominatim</a></td>
<td class="#doctools_tocright">Resolving geographical names with a Nominatim service</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='map_slippy'><a href="tcllib/files/modules/map/map_slippy.html">map::slippy</a></td>
<td class="#doctools_tocright">Common code for slippy based map packages</td>







>
>
>
>



|



<
<
<
<







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
<dl><dt><a name='unfiled'>Unfiled</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='cache_async'><a href="tcllib/files/modules/cache/async.html">cache::async</a></td>
<td class="#doctools_tocright">Asynchronous in-memory cache</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_paths'><a href="tcllib/files/modules/fileutil/paths.html">fileutil::paths</a></td>
<td class="#doctools_tocright">Manage search path pools</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='generator'><a href="tcllib/files/modules/generator/generator.html">generator</a></td>
<td class="#doctools_tocright">Procedures for creating and using generators.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='huddle'><a href="tcllib/files/modules/yaml/huddle.html">huddle</a></td>
<td class="#doctools_tocright">Create and manipulate huddle object</td>
</tr>




<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='map_geocode_nominatim'><a href="tcllib/files/modules/map/map_geocode_nominatim.html">map::geocode::nominatim</a></td>
<td class="#doctools_tocright">Resolving geographical names with a Nominatim service</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='map_slippy'><a href="tcllib/files/modules/map/map_slippy.html">map::slippy</a></td>
<td class="#doctools_tocright">Common code for slippy based map packages</td>
1691
1692
1693
1694
1695
1696
1697




1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
<td class="#doctools_tocright">Implementation of stringprep</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='stringprep_data'><a href="tcllib/files/modules/stringprep/stringprep_data.html">stringprep::data</a></td>
<td class="#doctools_tocright">stringprep data tables, generated, internal</td>
</tr>
<tr class="#doctools_toceven" >




<td class="#doctools_tocleft" ><a name='tclrep_machineparameters'><a href="tcllib/files/modules/math/machineparameters.html">tclrep/machineparameters</a></td>
<td class="#doctools_tocright">Compute double precision machine parameters.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='uevent_onidle'><a href="tcllib/files/modules/uev/uevent_onidle.html">uevent::onidle</a></td>
<td class="#doctools_tocright">Request merging and deferal to idle time</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='unicode'><a href="tcllib/files/modules/stringprep/unicode.html">unicode</a></td>
<td class="#doctools_tocright">Implementation of Unicode normalization</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='unicode_data'><a href="tcllib/files/modules/stringprep/unicode_data.html">unicode::data</a></td>
<td class="#doctools_tocright">unicode data tables, generated, internal</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='units'><a href="tcllib/files/modules/units/units.html">units</a></td>
<td class="#doctools_tocright">unit conversion</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='yaml'><a href="tcllib/files/modules/yaml/yaml.html">yaml</a></td>
<td class="#doctools_tocright">YAML Format Encoder/Decoder</td>
</tr>
</table></dl>
<dl><dt><a name='utilities'>Utilities</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>



|



|



|



|



|







1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
<td class="#doctools_tocright">Implementation of stringprep</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='stringprep_data'><a href="tcllib/files/modules/stringprep/stringprep_data.html">stringprep::data</a></td>
<td class="#doctools_tocright">stringprep data tables, generated, internal</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_map'><a href="tcllib/files/modules/struct/struct_map.html">struct::map</a></td>
<td class="#doctools_tocright">Manage key/value maps</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tclrep_machineparameters'><a href="tcllib/files/modules/math/machineparameters.html">tclrep/machineparameters</a></td>
<td class="#doctools_tocright">Compute double precision machine parameters.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='uevent_onidle'><a href="tcllib/files/modules/uev/uevent_onidle.html">uevent::onidle</a></td>
<td class="#doctools_tocright">Request merging and deferal to idle time</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='unicode'><a href="tcllib/files/modules/stringprep/unicode.html">unicode</a></td>
<td class="#doctools_tocright">Implementation of Unicode normalization</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='unicode_data'><a href="tcllib/files/modules/stringprep/unicode_data.html">unicode::data</a></td>
<td class="#doctools_tocright">unicode data tables, generated, internal</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='units'><a href="tcllib/files/modules/units/units.html">units</a></td>
<td class="#doctools_tocright">unit conversion</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='yaml'><a href="tcllib/files/modules/yaml/yaml.html">yaml</a></td>
<td class="#doctools_tocright">YAML Format Encoder/Decoder</td>
</tr>
</table></dl>
<dl><dt><a name='utilities'>Utilities</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >

Changes to idoc/www/toc1.html.

129
130
131
132
133
134
135







136
137
138
139
140
141
142
</table></dl>
<dl><dt><a name='cache'>cache</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='cache_async'><a href="tcllib/files/modules/cache/async.html">cache::async</a></td>
<td class="#doctools_tocright">Asynchronous in-memory cache</td>
</tr>







</table></dl>
<dl><dt><a name='clock'>clock</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='clock_iso8601'><a href="tcllib/files/modules/clock/iso8601.html">clock_iso8601</a></td>
<td class="#doctools_tocright">Parsing ISO 8601 dates/times</td>
</tr>







>
>
>
>
>
>
>







129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
</table></dl>
<dl><dt><a name='cache'>cache</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='cache_async'><a href="tcllib/files/modules/cache/async.html">cache::async</a></td>
<td class="#doctools_tocright">Asynchronous in-memory cache</td>
</tr>
</table></dl>
<dl><dt><a name='clay'>clay</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='clay'><a href="tcllib/files/modules/clay/clay.html">clay</a></td>
<td class="#doctools_tocright">A minimalist framework for large scale OO Projects</td>
</tr>
</table></dl>
<dl><dt><a name='clock'>clock</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='clock_iso8601'><a href="tcllib/files/modules/clock/iso8601.html">clock_iso8601</a></td>
<td class="#doctools_tocright">Parsing ISO 8601 dates/times</td>
</tr>
577
578
579
580
581
582
583




584
585
586
587
588
589
590
<td class="#doctools_tocright">Multi-file operation, scatter/gather, standard object</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_multi_op'><a href="tcllib/files/modules/fileutil/multiop.html">fileutil::multi::op</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='fileutil_traverse'><a href="tcllib/files/modules/fileutil/traverse.html">fileutil_traverse</a></td>
<td class="#doctools_tocright">Iterative directory traversal</td>
</tr>
</table></dl>
<dl><dt><a name='ftp'>ftp</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>







584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
<td class="#doctools_tocright">Multi-file operation, scatter/gather, standard object</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_multi_op'><a href="tcllib/files/modules/fileutil/multiop.html">fileutil::multi::op</a></td>
<td class="#doctools_tocright">Multi-file operation, scatter/gather</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='fileutil_paths'><a href="tcllib/files/modules/fileutil/paths.html">fileutil::paths</a></td>
<td class="#doctools_tocright">Manage search path pools</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='fileutil_traverse'><a href="tcllib/files/modules/fileutil/traverse.html">fileutil_traverse</a></td>
<td class="#doctools_tocright">Iterative directory traversal</td>
</tr>
</table></dl>
<dl><dt><a name='ftp'>ftp</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
<td class="#doctools_tocleft" ><a name='autoproxy'><a href="tcllib/files/modules/http/autoproxy.html">autoproxy</a></td>
<td class="#doctools_tocright">Automatic HTTP proxy usage and authentication</td>
</tr>
</table></dl>
<dl><dt><a name='httpd'>httpd</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tool'><a href="tcllib/files/modules/httpd/httpd.html">tool</a></td>
<td class="#doctools_tocright">A TclOO and coroutine based web server</td>
</tr>
</table></dl>
<dl><dt><a name='ident'>ident</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='ident'><a href="tcllib/files/modules/ident/ident.html">ident</a></td>







|







746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
<td class="#doctools_tocleft" ><a name='autoproxy'><a href="tcllib/files/modules/http/autoproxy.html">autoproxy</a></td>
<td class="#doctools_tocright">Automatic HTTP proxy usage and authentication</td>
</tr>
</table></dl>
<dl><dt><a name='httpd'>httpd</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='httpd'><a href="tcllib/files/modules/httpd/httpd.html">httpd</a></td>
<td class="#doctools_tocright">A TclOO and coroutine based web server</td>
</tr>
</table></dl>
<dl><dt><a name='ident'>ident</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='ident'><a href="tcllib/files/modules/ident/ident.html">ident</a></td>
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
<td class="#doctools_tocright">Package for Principal Component Analysis</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_polynomials'><a href="tcllib/files/modules/math/polynomials.html">math::polynomials</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_toceven" >




<td class="#doctools_tocleft" ><a name='math_rationalfunctions'><a href="tcllib/files/modules/math/rational_funcs.html">math::rationalfunctions</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_roman'><a href="tcllib/files/modules/math/roman.html">math::roman</a></td>
<td class="#doctools_tocright">Tools for creating and manipulating roman numerals</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_special'><a href="tcllib/files/modules/math/special.html">math::special</a></td>
<td class="#doctools_tocright">Special mathematical functions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_statistics'><a href="tcllib/files/modules/math/statistics.html">math::statistics</a></td>
<td class="#doctools_tocright">Basic statistical functions and procedures</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_trig'><a href="tcllib/files/modules/math/trig.html">math::trig</a></td>
<td class="#doctools_tocright">Trigonometric anf hyperbolic functions</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='tclrep_machineparameters'><a href="tcllib/files/modules/math/machineparameters.html">tclrep/machineparameters</a></td>
<td class="#doctools_tocright">Compute double precision machine parameters.</td>
</tr>
</table></dl>
<dl><dt><a name='md4'>md4</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>



|



|



|



|



|







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
<td class="#doctools_tocright">Package for Principal Component Analysis</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_polynomials'><a href="tcllib/files/modules/math/polynomials.html">math::polynomials</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_quasirandom'><a href="tcllib/files/modules/math/quasirandom.html">math::quasirandom</a></td>
<td class="#doctools_tocright">Quasi-random points for integration and Monte Carlo type methods</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_rationalfunctions'><a href="tcllib/files/modules/math/rational_funcs.html">math::rationalfunctions</a></td>
<td class="#doctools_tocright">Polynomial functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_roman'><a href="tcllib/files/modules/math/roman.html">math::roman</a></td>
<td class="#doctools_tocright">Tools for creating and manipulating roman numerals</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_special'><a href="tcllib/files/modules/math/special.html">math::special</a></td>
<td class="#doctools_tocright">Special mathematical functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='math_statistics'><a href="tcllib/files/modules/math/statistics.html">math::statistics</a></td>
<td class="#doctools_tocright">Basic statistical functions and procedures</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='math_trig'><a href="tcllib/files/modules/math/trig.html">math::trig</a></td>
<td class="#doctools_tocright">Trigonometric anf hyperbolic functions</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='tclrep_machineparameters'><a href="tcllib/files/modules/math/machineparameters.html">tclrep/machineparameters</a></td>
<td class="#doctools_tocright">Compute double precision machine parameters.</td>
</tr>
</table></dl>
<dl><dt><a name='md4'>md4</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
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
<td class="#doctools_tocright">Create and manipulate directed graph objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_list'><a href="tcllib/files/modules/struct/struct_list.html">struct::list</a></td>
<td class="#doctools_tocright">Procedures for manipulating lists</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='struct_matrix'><a href="tcllib/files/modules/struct/matrix.html">struct::matrix</a></td>
<td class="#doctools_tocright">Create and manipulate matrix objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_matrix_v1'><a href="tcllib/files/modules/struct/matrix1.html">struct::matrix_v1</a></td>
<td class="#doctools_tocright">Create and manipulate matrix objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_pool'><a href="tcllib/files/modules/struct/pool.html">struct::pool</a></td>
<td class="#doctools_tocright">Create and manipulate pool objects (of discrete items)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_prioqueue'><a href="tcllib/files/modules/struct/prioqueue.html">struct::prioqueue</a></td>
<td class="#doctools_tocright">Create and manipulate prioqueue objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_queue'><a href="tcllib/files/modules/struct/queue.html">struct::queue</a></td>
<td class="#doctools_tocright">Create and manipulate queue objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_record'><a href="tcllib/files/modules/struct/record.html">struct::record</a></td>
<td class="#doctools_tocright">Define and create records (similar to 'C' structures)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_set'><a href="tcllib/files/modules/struct/struct_set.html">struct::set</a></td>
<td class="#doctools_tocright">Procedures for manipulating sets</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_skiplist'><a href="tcllib/files/modules/struct/skiplist.html">struct::skiplist</a></td>
<td class="#doctools_tocright">Create and manipulate skiplists</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_stack'><a href="tcllib/files/modules/struct/stack.html">struct::stack</a></td>
<td class="#doctools_tocright">Create and manipulate stack objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_tree'><a href="tcllib/files/modules/struct/struct_tree.html">struct::tree</a></td>
<td class="#doctools_tocright">Create and manipulate tree objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_tree_v1'><a href="tcllib/files/modules/struct/struct_tree1.html">struct::tree_v1</a></td>
<td class="#doctools_tocright">Create and manipulate tree objects</td>
</tr>
</table></dl>
<dl><dt><a name='tar'>tar</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>



|



|



|



|



|



|



|



|



|



|







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
<td class="#doctools_tocright">Create and manipulate directed graph objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_list'><a href="tcllib/files/modules/struct/struct_list.html">struct::list</a></td>
<td class="#doctools_tocright">Procedures for manipulating lists</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_map'><a href="tcllib/files/modules/struct/struct_map.html">struct::map</a></td>
<td class="#doctools_tocright">Manage key/value maps</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_matrix'><a href="tcllib/files/modules/struct/matrix.html">struct::matrix</a></td>
<td class="#doctools_tocright">Create and manipulate matrix objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_matrix_v1'><a href="tcllib/files/modules/struct/matrix1.html">struct::matrix_v1</a></td>
<td class="#doctools_tocright">Create and manipulate matrix objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_pool'><a href="tcllib/files/modules/struct/pool.html">struct::pool</a></td>
<td class="#doctools_tocright">Create and manipulate pool objects (of discrete items)</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_prioqueue'><a href="tcllib/files/modules/struct/prioqueue.html">struct::prioqueue</a></td>
<td class="#doctools_tocright">Create and manipulate prioqueue objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_queue'><a href="tcllib/files/modules/struct/queue.html">struct::queue</a></td>
<td class="#doctools_tocright">Create and manipulate queue objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_record'><a href="tcllib/files/modules/struct/record.html">struct::record</a></td>
<td class="#doctools_tocright">Define and create records (similar to 'C' structures)</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_set'><a href="tcllib/files/modules/struct/struct_set.html">struct::set</a></td>
<td class="#doctools_tocright">Procedures for manipulating sets</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_skiplist'><a href="tcllib/files/modules/struct/skiplist.html">struct::skiplist</a></td>
<td class="#doctools_tocright">Create and manipulate skiplists</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_stack'><a href="tcllib/files/modules/struct/stack.html">struct::stack</a></td>
<td class="#doctools_tocright">Create and manipulate stack objects</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='struct_tree'><a href="tcllib/files/modules/struct/struct_tree.html">struct::tree</a></td>
<td class="#doctools_tocright">Create and manipulate tree objects</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='struct_tree_v1'><a href="tcllib/files/modules/struct/struct_tree1.html">struct::tree_v1</a></td>
<td class="#doctools_tocright">Create and manipulate tree objects</td>
</tr>
</table></dl>
<dl><dt><a name='tar'>tar</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >
1706
1707
1708
1709
1710
1711
1712




1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
<td class="#doctools_tocright">Procedures to adjust, indent, and undent paragraphs</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_expander'><a href="tcllib/files/modules/textutil/expander.html">textutil::expander</a></td>
<td class="#doctools_tocright">Procedures to process templates and expand text.</td>
</tr>
<tr class="#doctools_tocodd"  >




<td class="#doctools_tocleft" ><a name='textutil_repeat'><a href="tcllib/files/modules/textutil/repeat.html">textutil::repeat</a></td>
<td class="#doctools_tocright">Procedures to repeat strings.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_split'><a href="tcllib/files/modules/textutil/textutil_split.html">textutil::split</a></td>
<td class="#doctools_tocright">Procedures to split texts</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_string'><a href="tcllib/files/modules/textutil/textutil_string.html">textutil::string</a></td>
<td class="#doctools_tocright">Procedures to manipulate texts and strings.</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_tabify'><a href="tcllib/files/modules/textutil/tabify.html">textutil::tabify</a></td>
<td class="#doctools_tocright">Procedures to (un)tabify strings</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_trim'><a href="tcllib/files/modules/textutil/trim.html">textutil::trim</a></td>
<td class="#doctools_tocright">Procedures to trim strings</td>
</tr>
</table></dl>
<dl><dt><a name='tie'>tie</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >







>
>
>
>



|



|



|



|







1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
<td class="#doctools_tocright">Procedures to adjust, indent, and undent paragraphs</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_expander'><a href="tcllib/files/modules/textutil/expander.html">textutil::expander</a></td>
<td class="#doctools_tocright">Procedures to process templates and expand text.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_patch'><a href="tcllib/files/modules/textutil/patch.html">textutil::patch</a></td>
<td class="#doctools_tocright">Application of uni-diff patches to directory trees</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_repeat'><a href="tcllib/files/modules/textutil/repeat.html">textutil::repeat</a></td>
<td class="#doctools_tocright">Procedures to repeat strings.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_split'><a href="tcllib/files/modules/textutil/textutil_split.html">textutil::split</a></td>
<td class="#doctools_tocright">Procedures to split texts</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_string'><a href="tcllib/files/modules/textutil/textutil_string.html">textutil::string</a></td>
<td class="#doctools_tocright">Procedures to manipulate texts and strings.</td>
</tr>
<tr class="#doctools_tocodd"  >
<td class="#doctools_tocleft" ><a name='textutil_tabify'><a href="tcllib/files/modules/textutil/tabify.html">textutil::tabify</a></td>
<td class="#doctools_tocright">Procedures to (un)tabify strings</td>
</tr>
<tr class="#doctools_toceven" >
<td class="#doctools_tocleft" ><a name='textutil_trim'><a href="tcllib/files/modules/textutil/trim.html">textutil::trim</a></td>
<td class="#doctools_tocright">Procedures to trim strings</td>
</tr>
</table></dl>
<dl><dt><a name='tie'>tie</dt><dd>
<table class="#doctools_toc">
<tr class="#doctools_toceven" >

Changes to installer.tcl.

278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
	# Starpack. No defaults for location.
    } else {
	# Starkit, or unwrapped. Derive defaults location from the
	# location of the executable running the installer, or the
	# location of its library.

	# For a starkit [info library] is inside the running
	# tclkit. Detect this and derive the lcoation from the
	# location of the executable itself for that case.

	if {[string match [info nameofexecutable]* [info library]]} {
	    # Starkit
	    set libdir [file join [file dirname [file dirname [info nameofexecutable]]] lib]
	} else {
	    # Unwrapped.







|







278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
	# Starpack. No defaults for location.
    } else {
	# Starkit, or unwrapped. Derive defaults location from the
	# location of the executable running the installer, or the
	# location of its library.

	# For a starkit [info library] is inside the running
	# tclkit. Detect this and derive the location from the
	# location of the executable itself for that case.

	if {[string match [info nameofexecutable]* [info library]]} {
	    # Starkit
	    set libdir [file join [file dirname [file dirname [info nameofexecutable]]] lib]
	} else {
	    # Unwrapped.

Changes to license.terms.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
This software is copyrighted by Ajuba Solutions and other parties.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

GOVERNMENT USE: If you are acquiring this software on behalf of the
U.S. government, the Government shall have only "Restricted Rights"
in the software and related documentation as defined in the Federal 
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
are acquiring the software on behalf of the Department of Defense, the
software shall be classified as "Commercial Computer Software" and the
Government shall have only "Restricted Rights" as defined in Clause
252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license. 

|
|


|
|
|
|
|
|
|
|








|
|
|
|
|


|
|







|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
This software is copyrighted by Ajuba Solutions and other parties.
The following terms apply to all files associated with the software
unless explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose,
provided that existing copyright notices are retained in all copies
and that this notice is included verbatim in any distributions. No
written agreement, license, or royalty fee is required for any of the
authorized uses.  Modifications to this software may be copyrighted by
their authors and need not follow the licensing terms described here,
provided that the new terms are clearly indicated on the first page of
each file where they apply.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND
THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

GOVERNMENT USE: If you are acquiring this software on behalf of the
U.S. government, the Government shall have only "Restricted Rights" in
the software and related documentation as defined in the Federal
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
are acquiring the software on behalf of the Department of Defense, the
software shall be classified as "Commercial Computer Software" and the
Government shall have only "Restricted Rights" as defined in Clause
252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license.

Added modules/0compatibility/d_config.tcl.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# (c) 2019 Andreas Kupries
# Redirection wrapper for deprecated package
# Deprecated:
# - doctools::config
# Replacement:
# - struct::map

package require Tcl 8.4
package require struct::map

namespace eval ::doctools {}

proc ::doctools::config {args} { uplevel 1 [linsert $args 0 ::struct::map] }

package provide doctools::config 0.1
return

Added modules/0compatibility/d_config.test.

































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# -*- tcl -*-
# config.test:  Testsuite for DEPRECATED package doctools::config
#
# Copyright (c) 2019 by Andreas Kupries <[email protected]>
# All rights reserved.

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2.0

support {
    use snit/snit.tcl  snit
    use struct/map.tcl struct::map
}
testing {
    useLocal d_config.tcl doctools::config
}

# ---------------------------------------------------------------------
# [] constructor
# [] destructor
# [] get
# [] names
# [] set
# [] unset

#----------------------------------------------------------------------
## Constructor, destructor

test doctools-config-1.0 {constructor, wrong args, too many} -body {
    doctools::config M X
} -returnCodes error -result {Error in constructor: wrong # args: should be "::struct::map::I::Snit_constructor type selfns win self"}

test doctools-config-1.1 {instance, bogus method} -setup {
    doctools::config M
} -cleanup {
    M destroy
} -body {
    M bogus
} -returnCodes error -result {"::M bogus" is not defined}

#----------------------------------------------------------------------
## get

test doctools-config-2.0 {get, wrong args, too many} -setup {
    doctools::config M
} -cleanup {
    M destroy
} -body {
    M get X
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodget type selfns win self"}

test doctools-config-2.1 {get, base state, none} -setup {
    doctools::config M
} -cleanup {
    M destroy
} -body {
    M get
} -result {}

#----------------------------------------------------------------------
## names

test doctools-config-3.0 {names, wrong args, too many} -setup {
    doctools::config M
} -cleanup {
    M destroy
} -body {
    M names X
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodnames type selfns win self"}

test doctools-config-3.1 {names, base state, none} -setup {
    doctools::config M
} -cleanup {
    M destroy
} -body {
    M names
} -result {}

#----------------------------------------------------------------------
## set

test doctools-config-4.0 {set, wrong args, not enough} -setup {
    doctools::config M
} -cleanup {
    M destroy
} -body {
    M set
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

test doctools-config-4.1 {set, wrong args, too many} -setup {
    doctools::config M
} -cleanup {
    M destroy
} -body {
    M set K V X
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

test doctools-config-4.2 {set, state change, result} -setup {
    doctools::config M
} -cleanup {
    M destroy
} -body {
    list [M names] [M get] [M set K V] [M names] [M get]
} -result {{} {} V K {K V}}

#----------------------------------------------------------------------
## unset

test doctools-config-5.2 {unset, known key, state change, result} -setup {
    doctools::config M
    M set K V
} -cleanup {
    M destroy
} -body {
    list [M names] [M get] [M unset K] [M names] [M get]
} -result {K {K V} {} {} {}}

test doctools-config-5.3 {unset, missing key, no state change, result} -setup {
    doctools::config M
    M set K V
} -cleanup {
    M destroy
} -body {
    list [M names] [M get] [M unset K'] [M names] [M get]
} -result {K {K V} {} K {K V}}

test doctools-config-5.4 {unset, no pattern, clear, result} -setup {
    doctools::config M
    M set K V
} -cleanup {
    M destroy
} -body {
    list [M names] [M get] [M unset] [M names] [M get]
} -result {K {K V} {} {} {}}

#----------------------------------------------------------------------
testsuiteCleanup
return

Added modules/0compatibility/d_paths.tcl.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# (c) 2019 Andreas Kupries
# Redirection wrapper for deprecated package
# Deprecated:
# - doctools::paths
# Replacement:
# - fileutil::paths

package require Tcl 8.4
package require fileutil::paths

namespace eval ::doctools {}

proc ::doctools::paths {args} { uplevel 1 [linsert $args 0 ::fileutil::paths] }

package provide doctools::paths 0.1
return

Added modules/0compatibility/d_paths.test.

















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# -*- tcl -*-
# paths.test:  Testsuite for DEPRECATED package doctools::paths
#
# Copyright (c) 2019 by Andreas Kupries <[email protected]>
# All rights reserved.

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2.0

support {
    use snit/snit.tcl      snit
    use fileutil/paths.tcl fileutil::paths
}    
testing {
    useLocal d_paths.tcl doctools::paths
}

# ---------------------------------------------------------------------
# [] constructor
# [] destructor
# [] paths
# [] add
# [] remove
# [] clear

#----------------------------------------------------------------------
## Constructor, destructor

test doctools-paths-1.0 {constructor, wrong args, too many} -body {
    doctools::paths P X
} -returnCodes error -result {Error in constructor: wrong # args: should be "::fileutil::paths::Snit_constructor type selfns win self"}

test doctools-paths-1.1 {instance, bogus method} -setup {
    doctools::paths P
} -cleanup {
    P destroy
} -body {
    P bogus
} -returnCodes error -result {"::P bogus" is not defined}

#----------------------------------------------------------------------
## paths

test doctools-paths-2.0 {paths, wrong args, too many} -setup {
    doctools::paths P
} -cleanup {
    P destroy
} -body {
    P paths X
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodpaths type selfns win self"}

test doctools-paths-2.1 {paths, base state, none} -setup {
    doctools::paths P
} -cleanup {
    P destroy
} -body {
    P paths
} -result {}

#----------------------------------------------------------------------
## add

test doctools-paths-3.0 {add, wrong args, not enough} -setup {
    doctools::paths P
} -cleanup {
    P destroy
} -body {
    P add
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodadd type selfns win self path"}

test doctools-paths-3.1 {add, wrong args, too many} -setup {
    doctools::paths P
} -cleanup {
    P destroy
} -body {
    P add F X
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodadd type selfns win self path"}

test doctools-paths-3.2 {add, state change, result} -setup {
    doctools::paths P
} -cleanup {
    P destroy
} -body {
    list [P add F] [P paths]
} -result {{} F}

#----------------------------------------------------------------------
## remove

test doctools-paths-4.0 {remove, wrong args, not enough} -setup {
    doctools::paths P
} -cleanup {
    P destroy
} -body {
    P remove
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodremove type selfns win self path"}

test doctools-paths-4.1 {remove, wrong args, too many} -setup {
    doctools::paths P
} -cleanup {
    P destroy
} -body {
    P remove F X
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodremove type selfns win self path"}

test doctools-paths-4.2 {remove, known path, state change, result} -setup {
    doctools::paths P
    P add F
} -cleanup {
    P destroy
} -body {
    list [P remove F] [P paths]
} -result {{} {}}

test doctools-paths-4.3 {remove, missing path, no state change, result} -setup {
    doctools::paths P
    P add Z
} -cleanup {
    P destroy
} -body {
    list [P remove F] [P paths]
} -result {{} Z}

#----------------------------------------------------------------------
## clear

test doctools-paths-5.0 {clear, wrong args, too many} -setup {
    doctools::paths P
} -cleanup {
    P destroy
} -body {
    P clear X
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodclear type selfns win self"}

test doctools-paths-5.1 {clear, return to base state} -setup {
    doctools::paths P
    P add F
} -cleanup {
    P destroy
} -body {
    list [P clear] [P paths]
} -result {{} {}}

#----------------------------------------------------------------------
testsuiteCleanup
return

Added modules/0compatibility/p_config.tcl.





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# (c) 2019 Andreas Kupries
# Redirection wrapper for deprecated package
# Deprecated:
# - configuration
# Replacement:
# - struct::map

package require Tcl 8.4
package require struct::map

proc ::configuration {args} { uplevel 1 [linsert $args 0 ::struct::map] }

package provide configuration 1
return

Added modules/0compatibility/p_config.test.

































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# -*- tcl -*-
# config.test:  Testsuite for DEPRECATED package configuration
#
# Copyright (c) 2019 by Andreas Kupries <[email protected]>
# All rights reserved.

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2.0

support {
    use snit/snit.tcl  snit
    use struct/map.tcl struct::map
}
testing {
    useLocal p_config.tcl configuration
}

# ---------------------------------------------------------------------
# [] constructor
# [] destructor
# [] get
# [] names
# [] set
# [] unset

#----------------------------------------------------------------------
## Constructor, destructor

test configuration-1.0 {constructor, wrong args, too many} -body {
    configuration M X
} -returnCodes error -result {Error in constructor: wrong # args: should be "::struct::map::I::Snit_constructor type selfns win self"}

test configuration-1.1 {instance, bogus method} -setup {
    configuration M
} -cleanup {
    M destroy
} -body {
    M bogus
} -returnCodes error -result {"::M bogus" is not defined}

#----------------------------------------------------------------------
## get

test configuration-2.0 {get, wrong args, too many} -setup {
    configuration M
} -cleanup {
    M destroy
} -body {
    M get X
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodget type selfns win self"}

test configuration-2.1 {get, base state, none} -setup {
    configuration M
} -cleanup {
    M destroy
} -body {
    M get
} -result {}

#----------------------------------------------------------------------
## names

test configuration-3.0 {names, wrong args, too many} -setup {
    configuration M
} -cleanup {
    M destroy
} -body {
    M names X
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodnames type selfns win self"}

test configuration-3.1 {names, base state, none} -setup {
    configuration M
} -cleanup {
    M destroy
} -body {
    M names
} -result {}

#----------------------------------------------------------------------
## set

test configuration-4.0 {set, wrong args, not enough} -setup {
    configuration M
} -cleanup {
    M destroy
} -body {
    M set
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

test configuration-4.1 {set, wrong args, too many} -setup {
    configuration M
} -cleanup {
    M destroy
} -body {
    M set K V X
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

test configuration-4.2 {set, state change, result} -setup {
    configuration M
} -cleanup {
    M destroy
} -body {
    list [M names] [M get] [M set K V] [M names] [M get]
} -result {{} {} V K {K V}}

#----------------------------------------------------------------------
## unset

test configuration-5.2 {unset, known key, state change, result} -setup {
    configuration M
    M set K V
} -cleanup {
    M destroy
} -body {
    list [M names] [M get] [M unset K] [M names] [M get]
} -result {K {K V} {} {} {}}

test configuration-5.3 {unset, missing key, no state change, result} -setup {
    configuration M
    M set K V
} -cleanup {
    M destroy
} -body {
    list [M names] [M get] [M unset K'] [M names] [M get]
} -result {K {K V} {} K {K V}}

test configuration-5.4 {unset, no pattern, clear, result} -setup {
    configuration M
    M set K V
} -cleanup {
    M destroy
} -body {
    list [M names] [M get] [M unset] [M names] [M get]
} -result {K {K V} {} {} {}}

#----------------------------------------------------------------------
testsuiteCleanup
return

Added modules/0compatibility/p_paths.tcl.





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# (c) 2019 Andreas Kupries
# Redirection wrapper for deprecated package
# Deprecated:
# - paths
# Replacement:
# - fileutil::paths

package require Tcl 8.4
package require fileutil::paths

proc ::paths {args} { uplevel 1 [linsert $args 0 ::fileutil::paths] }

package provide paths 1
return

Added modules/0compatibility/p_paths.test.

















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# -*- tcl -*-
# paths.test:  Testsuite for DEPRECATED package paths (pt)
#
# Copyright (c) 2019 by Andreas Kupries <[email protected]>
# All rights reserved.

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2.0

support {
    use snit/snit.tcl      snit
    use fileutil/paths.tcl fileutil::paths
}    
testing {
    useLocal p_paths.tcl paths
}

# ---------------------------------------------------------------------
# [] constructor
# [] destructor
# [] paths
# [] add
# [] remove
# [] clear

#----------------------------------------------------------------------
## Constructor, destructor

test paths-1.0 {constructor, wrong args, too many} -body {
    paths P X
} -returnCodes error -result {Error in constructor: wrong # args: should be "::fileutil::paths::Snit_constructor type selfns win self"}

test paths-1.1 {instance, bogus method} -setup {
    paths P
} -cleanup {
    P destroy
} -body {
    P bogus
} -returnCodes error -result {"::P bogus" is not defined}

#----------------------------------------------------------------------
## paths

test paths-2.0 {paths, wrong args, too many} -setup {
    paths P
} -cleanup {
    P destroy
} -body {
    P paths X
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodpaths type selfns win self"}

test paths-2.1 {paths, base state, none} -setup {
    paths P
} -cleanup {
    P destroy
} -body {
    P paths
} -result {}

#----------------------------------------------------------------------
## add

test paths-3.0 {add, wrong args, not enough} -setup {
    paths P
} -cleanup {
    P destroy
} -body {
    P add
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodadd type selfns win self path"}

test paths-3.1 {add, wrong args, too many} -setup {
    paths P
} -cleanup {
    P destroy
} -body {
    P add F X
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodadd type selfns win self path"}

test paths-3.2 {add, state change, result} -setup {
    paths P
} -cleanup {
    P destroy
} -body {
    list [P add F] [P paths]
} -result {{} F}

#----------------------------------------------------------------------
## remove

test paths-4.0 {remove, wrong args, not enough} -setup {
    paths P
} -cleanup {
    P destroy
} -body {
    P remove
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodremove type selfns win self path"}

test paths-4.1 {remove, wrong args, too many} -setup {
    paths P
} -cleanup {
    P destroy
} -body {
    P remove F X
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodremove type selfns win self path"}

test paths-4.2 {remove, known path, state change, result} -setup {
    paths P
    P add F
} -cleanup {
    P destroy
} -body {
    list [P remove F] [P paths]
} -result {{} {}}

test paths-4.3 {remove, missing path, no state change, result} -setup {
    paths P
    P add Z
} -cleanup {
    P destroy
} -body {
    list [P remove F] [P paths]
} -result {{} Z}

#----------------------------------------------------------------------
## clear

test paths-5.0 {clear, wrong args, too many} -setup {
    paths P
} -cleanup {
    P destroy
} -body {
    P clear X
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodclear type selfns win self"}

test paths-5.1 {clear, return to base state} -setup {
    paths P
    P add F
} -cleanup {
    P destroy
} -body {
    list [P clear] [P paths]
} -result {{} {}}

#----------------------------------------------------------------------
testsuiteCleanup
return

Added modules/0compatibility/pkgIndex.tcl.



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Compatibility wrapper for deprecated packages.
##
# Stages
# [D1] Next Release   - Noted deprecated, with redirection wrappers
# [D2] Release After  - Wrappers become Boockers, throwing error noting redirection
# [D3] Release Beyond - All removed.
##
# Currently in deprecation
# - D1 doctools::path	(doctools2base)
# - D1 doctools::config	(doctools2base)
# - D1 configuration	(pt)
# - D1 paths		(pt)
#
# :Attention:
# - Original    `doctools::paths`     Tcl 8.4 required
#   Replacement `fileutilutil::paths` Tcl 8.5 required!

if {![package vsatisfies [package provide Tcl] 8.4]} {return}

package ifneeded configuration    1   [list source [file join $dir p_config.tcl]]
package ifneeded doctools::config 0.1 [list source [file join $dir d_config.tcl]]
package ifneeded doctools::paths  0.1 [list source [file join $dir d_paths.tcl]]
package ifneeded paths            1   [list source [file join $dir p_paths.tcl]]

if {![package vsatisfies [package provide Tcl] 8.5]} {return}


if {![package vsatisfies [package provide Tcl] 8.6]} {return}

Changes to modules/aes/aes.man.

160
161
162
163
164
165
166
167
168

[list_end]

[section AUTHORS]
Thorsten Schloermann, Pat Thoyts

[vset CATEGORY aes]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

160
161
162
163
164
165
166
167
168

[list_end]

[section AUTHORS]
Thorsten Schloermann, Pat Thoyts

[vset CATEGORY aes]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/amazon-s3/S3.man.

1442
1443
1444
1445
1446
1447
1448
1449
1450
each moving on to the next unstarted task as it finishes each.
This is still being designed, and it is intended primarily
to be run on Amazon's Elastic Compute Cloud.

[include ../common-text/tls-security-notes.inc]

[vset CATEGORY amazon-s3]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

1442
1443
1444
1445
1446
1447
1448
1449
1450
each moving on to the next unstarted task as it finishes each.
This is still being designed, and it is intended primarily
to be run on Amazon's Elastic Compute Cloud.

[include ../common-text/tls-security-notes.inc]

[vset CATEGORY amazon-s3]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/amazon-s3/S3.test.

17
18
19
20
21
22
23


24
25
26
27
28
29






















30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2.0



if {[catch {package require xml}]} {
    puts "    Aborting the tests found in \"[file tail [info script]]\""
    puts "    Requiring xml package, not found."
    return
}























support {
    # Requires xml (TclXML)
    useLocal xsxp.tcl xsxp
}
testing {
    useLocal S3.tcl S3
}

# -------------------------------------------------------------------------

# I normally leave BucketDeletion false, because Amazon gets cranky
# if you delete a bucket and then try to recreate it any time soon.

# This may clobber files starting with the characers "S3T". Don't
# run it in a directory with such files you want.

# Put your own keys in S3-test.config.

tcltest::customMatch S3err S3ErrorMatch

tcltest::testConstraint BucketDeletion false
tcltest::testConstraint REST true
tcltest::testConstraint BucketIO true
tcltest::testConstraint ItemIO true







>
>






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
|













|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2.0

testsNeed xml ; # aka TclXML, author Steve Ball, of Zveno (Australia)

if {[catch {package require xml}]} {
    puts "    Aborting the tests found in \"[file tail [info script]]\""
    puts "    Requiring xml package, not found."
    return
}

# Put your own keys into test-assets/aws-access-id, aws-secret-access_key
# -------------------------------------------------------------------------

if {![file exists [asset aws-access-id]] ||
    ![file exists [asset aws-secret-access-key]]
} {
    if {[file exists [asset no-aws]]} {
	puts "    Skipping the tests found in \"[file tail [info script]]\""
	puts "    AWS not configured by user choice."

    } else {
	puts "    Aborting the tests found in \"[file tail [info script]]\""
	puts "    AWS configuration required, missing."
	puts "    Place access id and secret key into the files"
	puts "    - [asset aws-access-id], and"
	puts "    - [asset aws-secret-access-key]"
    }
    return
}

# -------------------------------------------------------------------------

support {

    useLocal xsxp.tcl xsxp ;# Here we need (tcl)xml
}
testing {
    useLocal S3.tcl S3
}

# -------------------------------------------------------------------------

# I normally leave BucketDeletion false, because Amazon gets cranky
# if you delete a bucket and then try to recreate it any time soon.

# This may clobber files starting with the characers "S3T". Don't
# run it in a directory with such files you want.

# Put your own keys in test-assets/test-S3.config.

tcltest::customMatch S3err S3ErrorMatch

tcltest::testConstraint BucketDeletion false
tcltest::testConstraint REST true
tcltest::testConstraint BucketIO true
tcltest::testConstraint ItemIO true
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
}

proc bgerror {args} {set ::S3::afterResult [list "BGERROR" $args $::errorInfo]}

# Allow easy incorporation of user's AccessID and SecretKey

proc S3loadKeys {} {
    source test-S3.config
}

namespace import ::tcltest::test

proc CleanUpBuckets {{buckets 0}} {
    S3loadKeys
    set bucket [S3::SuggestBucket TclTestS3b]







|







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
}

proc bgerror {args} {set ::S3::afterResult [list "BGERROR" $args $::errorInfo]}

# Allow easy incorporation of user's AccessID and SecretKey

proc S3loadKeys {} {
    source [asset test-S3.config]
}

namespace import ::tcltest::test

proc CleanUpBuckets {{buckets 0}} {
    S3loadKeys
    set bucket [S3::SuggestBucket TclTestS3b]

Deleted modules/amazon-s3/test-S3.config.

1
2
S3::Configure -accesskeyid use-yours \
-secretaccesskey put-yours-here
<
<




Added modules/amazon-s3/test-assets/test-S3.config.





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# -*- tcl -*-
# Scope: proc S3loadkeys
    
set i [open [asset aws-access-id]         r]
set k [open [asset aws-secret-access-key] r]

set id [read $i] ; close $i
set ky [read $k] ; close $k

S3::Configure -accesskeyid $id -secretaccesskey $ky

# Memoize
proc S3loadKeys {} \
    [list S3::Configure -accesskeyid $id -secretaccesskey $ky]

Changes to modules/amazon-s3/xsxp.man.

129
130
131
132
133
134
135
136
137
[call [cmd xsxp::prettyprint] [arg pxml] [opt [arg chan]]]
This outputs to [arg chan] (default stdout) a pretty-printed
version of [arg pxml].

[list_end]

[vset CATEGORY amazon-s3]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

129
130
131
132
133
134
135
136
137
[call [cmd xsxp::prettyprint] [arg pxml] [opt [arg chan]]]
This outputs to [arg chan] (default stdout) a pretty-printed
version of [arg pxml].

[list_end]

[vset CATEGORY amazon-s3]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/asn/asn.man.

456
457
458
459
460
461
462
463
464

[section EXAMPLES]

Examples for the usage of this package can be found in the
implementation of package [package ldap].

[vset CATEGORY asn]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

456
457
458
459
460
461
462
463
464

[section EXAMPLES]

Examples for the usage of this package can be found in the
implementation of package [package ldap].

[vset CATEGORY asn]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/base32/base32.man.

67
68
69
70
71
72
73
74
75
	5 F   14 O   23 X
	6 G   15 P   24 Y
	7 H   16 Q   25 Z
	8 I   17 R   26 2
}]

[vset CATEGORY base32]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

67
68
69
70
71
72
73
74
75
	5 F   14 O   23 X
	6 G   15 P   24 Y
	7 H   16 Q   25 Z
	8 I   17 R   26 2
}]

[vset CATEGORY base32]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/base32/base32core.man.

58
59
60
61
62
63
64
65
66
[enum] The length of the input is not a multiple of eight,
[enum] The padding appears not at the end of input, but in the middle,
[enum] The padding has not of length six, four, three, or one characters,
[list_end]
[list_end]

[vset CATEGORY base32]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

58
59
60
61
62
63
64
65
66
[enum] The length of the input is not a multiple of eight,
[enum] The padding appears not at the end of input, but in the middle,
[enum] The padding has not of length six, four, three, or one characters,
[list_end]
[list_end]

[vset CATEGORY base32]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/base32/base32hex.man.

70
71
72
73
74
75
76
77
78
	5 5   14 E        23 N
	6 6   15 F        24 O
	7 7        16 G   25 P
	8 8        17 H   26 Q
}]

[vset CATEGORY base32]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

70
71
72
73
74
75
76
77
78
	5 5   14 E        23 N
	6 6   15 F        24 O
	7 7        16 G   25 P
	8 8        17 H   26 Q
}]

[vset CATEGORY base32]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/base64/ascii85.man.

67
68
69
70
71
72
73
74
75
[list_begin enum]
[enum] [uri http://en.wikipedia.org/wiki/Ascii85]
[enum] Postscript Language Reference Manual, 3rd Edition, page 131.
       [uri http://www.adobe.com/devnet/postscript/pdfs/PLRM.pdf]
[list_end]

[vset CATEGORY base64]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

67
68
69
70
71
72
73
74
75
[list_begin enum]
[enum] [uri http://en.wikipedia.org/wiki/Ascii85]
[enum] Postscript Language Reference Manual, 3rd Edition, page 131.
       [uri http://www.adobe.com/devnet/postscript/pdfs/PLRM.pdf]
[list_end]

[vset CATEGORY base64]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/base64/base64.man.

62
63
64
65
66
67
68
69
70
% set chemical [encoding convertto utf-8 "C\u2088H\u2081\u2080N\u2084O\u2082"]
% set encoded [base64::encode $chemical]
Q+KCiEjigoHigoBO4oKET+KCgg==
% set caffeine [encoding convertfrom utf-8 [base64::decode $encoded]]
}]

[vset CATEGORY base64]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

62
63
64
65
66
67
68
69
70
% set chemical [encoding convertto utf-8 "C\u2088H\u2081\u2080N\u2084O\u2082"]
% set encoded [base64::encode $chemical]
Q+KCiEjigoHigoBO4oKET+KCgg==
% set caffeine [encoding convertfrom utf-8 [base64::decode $encoded]]
}]

[vset CATEGORY base64]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/base64/uuencode.man.

89
90
91
92
93
94
95
96
97
[para]
[example {
% uuencode::uudecode $d
{hello.txt 644 {Hello World}}
}]

[vset CATEGORY base64]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

89
90
91
92
93
94
95
96
97
[para]
[example {
% uuencode::uudecode $d
{hello.txt 644 {Hello World}}
}]

[vset CATEGORY base64]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/base64/yencode.man.

88
89
90
91
92
93
94
95
96
[section References]

[list_begin enum]
[enum] [uri http://www.yenc.org/yenc-draft.1.3.txt]
[list_end]

[vset CATEGORY base64]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

88
89
90
91
92
93
94
95
96
[section References]

[list_begin enum]
[enum] [uri http://www.yenc.org/yenc-draft.1.3.txt]
[list_end]

[vset CATEGORY base64]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/bee/bee.man.

335
336
337
338
339
340
341
342
343
By wrapping an integer number into [const i]...[const e] the format
makes sure that they are different from strings, which all begin with
a digit.

[section EXAMPLES]

[vset CATEGORY bee]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

335
336
337
338
339
340
341
342
343
By wrapping an integer number into [const i]...[const e] the format
makes sure that they are different from strings, which all begin with
a digit.

[section EXAMPLES]

[vset CATEGORY bee]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/bee/bee.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# -*- tcl -*-
# bee.test:  tests for the bee encoding.
#
# Copyright (c) 2004 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: bee.test,v 1.9 2006/10/09 21:41:39 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]




|

<
<







1
2
3
4
5


6
7
8
9
10
11
12
# -*- tcl -*-
# bee.test:  tests for the bee encoding.
#
# Copyright (c) 2004,2018 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
}


test bee-12.0 {decoder, torrent file} {
    set end 0

    # tcltest::viewFile does not do binary :(
    set f [open  [file join $::tcltest::testsDirectory example.torrent] r]
    fconfigure $f -translation binary
    set d [read $f]
    close $f

    set data [bee::decode $d end]

    # Cut the binary stuff out of the result, to much, display problems







|







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
}


test bee-12.0 {decoder, torrent file} {
    set end 0

    # tcltest::viewFile does not do binary :(
    set f [open  [asset example.torrent] r]
    fconfigure $f -translation binary
    set d [read $f]
    close $f

    set data [bee::decode $d end]

    # Cut the binary stuff out of the result, to much, display problems
378
379
380
381
382
383
384

	removeFile bee16.$n
	set res
    } [lrange $result 0 1] ; # {}
}

# ....... ............................................................
testsuiteCleanup








>
376
377
378
379
380
381
382
383
	removeFile bee16.$n
	set res
    } [lrange $result 0 1] ; # {}
}

# ....... ............................................................
testsuiteCleanup
return

Deleted modules/bee/example.torrent.

cannot compute difference between binary files

Added modules/bee/test-assets/example.torrent.

cannot compute difference between binary files

Changes to modules/bench/bench.man.

288
289
290
291
292
293
294
295
296
The benchmark could be executed, however the result from its body did
not match the declared expectations.

[list_end]
[list_end]

[vset CATEGORY bench]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

288
289
290
291
292
293
294
295
296
The benchmark could be executed, however the result from its body did
not match the declared expectations.

[list_end]
[list_end]

[vset CATEGORY bench]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/bench/bench_intro.man.

83
84
85
86
87
88
89
90
91
[section {HISTORICAL NOTES}]

This module and package have been derived from Jeff Hobbs'
[syscmd tclbench] application for the benchmarking of the Tcl core and
its ancestor [file runbench.tcl].

[vset CATEGORY bench]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

83
84
85
86
87
88
89
90
91
[section {HISTORICAL NOTES}]

This module and package have been derived from Jeff Hobbs'
[syscmd tclbench] application for the benchmarking of the Tcl core and
its ancestor [file runbench.tcl].

[vset CATEGORY bench]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/bench/bench_lang_intro.man.

145
146
147
148
149
150
151
152
153
to understand the formal [term {bench language specfication}]. It will
also serve as the detailed specification and cheat sheet for all
available commands and their syntax.

[para]

[vset CATEGORY bench]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

145
146
147
148
149
150
151
152
153
to understand the formal [term {bench language specfication}]. It will
also serve as the detailed specification and cheat sheet for all
available commands and their syntax.

[para]

[vset CATEGORY bench]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/bench/bench_lang_spec.man.

124
125
126
127
128
129
130
131
132
responsibility is to create whatever resources are needed by the body
to run without failing.

[list_end]
[list_end]

[vset CATEGORY bench]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

124
125
126
127
128
129
130
131
132
responsibility is to create whatever resources are needed by the body
to run without failing.

[list_end]
[list_end]

[vset CATEGORY bench]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/bench/bench_read.man.

57
58
59
60
61
62
63
64
65
[para]

and automatically detects which format is used by the input file.

[list_end]

[vset CATEGORY bench]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

57
58
59
60
61
62
63
64
65
[para]

and automatically detects which format is used by the input file.

[list_end]

[vset CATEGORY bench]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/bench/bench_wcsv.man.

46
47
48
49
50
51
52
53
54
For other formatting styles see the packages [package bench] and
[package bench::out::text] which provide commands to format benchmark
results in raw form, or for human consumption, respectively.

[list_end]

[vset CATEGORY bench]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

46
47
48
49
50
51
52
53
54
For other formatting styles see the packages [package bench] and
[package bench::out::text] which provide commands to format benchmark
results in raw form, or for human consumption, respectively.

[list_end]

[vset CATEGORY bench]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/bench/bench_wtext.man.

47
48
49
50
51
52
53
54
55
For other formatting styles see the packages [package bench] and
[package bench::out::csv] which provide commands to format benchmark
results in raw form, or as importable CSV data, respectively.

[list_end]

[vset CATEGORY bench]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

47
48
49
50
51
52
53
54
55
For other formatting styles see the packages [package bench] and
[package bench::out::csv] which provide commands to format benchmark
results in raw form, or as importable CSV data, respectively.

[list_end]

[vset CATEGORY bench]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/bibtex/bibtex.man.

172
173
174
175
176
177
178
179
180
replacement strings. This command has the correct signature for use as
a [option -stringcommand] callback in an invokation of the command
[cmd ::bibtex::parse].

[list_end]

[vset CATEGORY bibtex]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

172
173
174
175
176
177
178
179
180
replacement strings. This command has the correct signature for use as
a [option -stringcommand] callback in an invokation of the command
[cmd ::bibtex::parse].

[list_end]

[vset CATEGORY bibtex]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/bibtex/bibtex.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# -*- tcl -*-
# bibtex.test:  tests for the bibtex parser.
#
# Copyright (c) 2005 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: bibtex.test,v 1.7 2006/10/09 21:41:40 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]






<
<







1
2
3
4
5


6
7
8
9
10
11
12
# -*- tcl -*-
# bibtex.test:  tests for the bibtex parser.
#
# Copyright (c) 2005 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

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
	year      1990 \
	pages     471--478 \
	address   {Boston, MA} \
	]]]


test bibtex-2.0 {Parse string, direct result} {
    set str [viewFile [file join [file dirname [info script]] bytecode.bib]]
    bibtex::parse $str
} $bytecode

test bibtex-2.1 {Parse string, sax mode} {
    set track {}
    set str [viewFile [file join [file dirname [info script]] bytecode.bib]]
    set t [bibtex::parse \
	    -progresscommand {track progress} \
	    -commentcommand  {track comment_} \
	    -stringcommand   {track string__} \
	    -preamblecommand {track preamble} \
	    -recordcommand   {track record__} \
	    $str]
    bibtex::destroy $t
    list $t $track
} [list bibtex2 [list \
	{progress bibtex2 100} \
	[linsert [lindex $bytecode 0] 0 record__ bibtex2]
]]

test bibtex-2.2 {Parse channel, direct result} {
    # The contents of penn_sub.bib have been taken out of
    # ftp://ftp.cis.upenn.edu/pub/anoop/bib/pennbib.bib

    set chan    [open [file join [file dirname [info script]] penn_sub.bib] r]
    set records [bibtex::parse -channel $chan]
    close $chan
    set records
} $pennfull

test bibtex-2.3 {Parse channel, sax mode} {
    set track {}
    set chan [open [file join [file dirname [info script]] penn_sub.bib] r]

    set t [bibtex::parse \
	    -progresscommand {track progress} \
	    -commentcommand  {track comment_} \
	    -stringcommand   {track string__} \
	    -preamblecommand {track preamble} \
	    -recordcommand   {track record__} \







|





|


















|







|







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
	year      1990 \
	pages     471--478 \
	address   {Boston, MA} \
	]]]


test bibtex-2.0 {Parse string, direct result} {
    set str [viewFile [asset bytecode.bib]]
    bibtex::parse $str
} $bytecode

test bibtex-2.1 {Parse string, sax mode} {
    set track {}
    set str [viewFile [asset bytecode.bib]]
    set t [bibtex::parse \
	    -progresscommand {track progress} \
	    -commentcommand  {track comment_} \
	    -stringcommand   {track string__} \
	    -preamblecommand {track preamble} \
	    -recordcommand   {track record__} \
	    $str]
    bibtex::destroy $t
    list $t $track
} [list bibtex2 [list \
	{progress bibtex2 100} \
	[linsert [lindex $bytecode 0] 0 record__ bibtex2]
]]

test bibtex-2.2 {Parse channel, direct result} {
    # The contents of penn_sub.bib have been taken out of
    # ftp://ftp.cis.upenn.edu/pub/anoop/bib/pennbib.bib

    set chan    [open [asset penn_sub.bib] r]
    set records [bibtex::parse -channel $chan]
    close $chan
    set records
} $pennfull

test bibtex-2.3 {Parse channel, sax mode} {
    set track {}
    set chan [open [asset penn_sub.bib] r]

    set t [bibtex::parse \
	    -progresscommand {track progress} \
	    -commentcommand  {track comment_} \
	    -stringcommand   {track string__} \
	    -preamblecommand {track preamble} \
	    -recordcommand   {track record__} \
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
	{string__ bibtex4 {aaai90 {Proc. National Conference on Artificial Intelligence, Boston}}} \
	{progress bibtex4 100} \
	[linsert [lindex $penn 0] 0 record__ bibtex4] \
	]

test bibtex-2.4 {Parse channel, sax mode 2} {
    set track {}
    set chan [open [file join [file dirname [info script]] penn_sub.bib] r]

    set t [bibtex::parse \
	    -progresscommand {track progress} \
	    -commentcommand  {track comment_} \
	    -stringcommand   addstr \
	    -preamblecommand {track preamble} \
	    -recordcommand   {track record__} \







|







162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
	{string__ bibtex4 {aaai90 {Proc. National Conference on Artificial Intelligence, Boston}}} \
	{progress bibtex4 100} \
	[linsert [lindex $penn 0] 0 record__ bibtex4] \
	]

test bibtex-2.4 {Parse channel, sax mode 2} {
    set track {}
    set chan [open [asset penn_sub.bib] r]

    set t [bibtex::parse \
	    -progresscommand {track progress} \
	    -commentcommand  {track comment_} \
	    -stringcommand   addstr \
	    -preamblecommand {track preamble} \
	    -recordcommand   {track record__} \
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
	[linsert [lindex $pennfull 0] 0 record__ bibtex5] \
	]

test bibtex-2.5 {Parse channel, async} {
    # The contents of penn_sub.bib have been taken out of
    # ftp://ftp.cis.upenn.edu/pub/anoop/bib/pennbib.bib

    set chan [open [file join [file dirname [info script]] penn_sub.bib] r]
    proc done {args} {global done ; set done $args ; return}

    set done ""
    set t [bibtex::parse -command done -channel $chan]
    vwait ::done
    bibtex::destroy $t
    close $chan







|







186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
	[linsert [lindex $pennfull 0] 0 record__ bibtex5] \
	]

test bibtex-2.5 {Parse channel, async} {
    # The contents of penn_sub.bib have been taken out of
    # ftp://ftp.cis.upenn.edu/pub/anoop/bib/pennbib.bib

    set chan [open [asset penn_sub.bib] r]
    proc done {args} {global done ; set done $args ; return}

    set done ""
    set t [bibtex::parse -command done -channel $chan]
    vwait ::done
    bibtex::destroy $t
    close $chan
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
test bibtex-3.2 {Destroying a parser} {
    set code [catch {::bibtex::destroy foo} msg]
    list $code $msg
} {1 {Illegal bibtex parser "foo"}}

test bibtex-4.0 {Destroying a parser} {

    set chan [open [file join [file dirname [info script]] bytecode.bib] r]
    proc done {args} {global done ; set done $args ; return}

    set done ""
    set t [bibtex::parse -command done -channel $chan]
    bibtex::destroy $t
    close $chan
} {}

# ... Tests of addStrings ...
#     (Requires introspection of parser state)

testsuiteCleanup







|












215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
test bibtex-3.2 {Destroying a parser} {
    set code [catch {::bibtex::destroy foo} msg]
    list $code $msg
} {1 {Illegal bibtex parser "foo"}}

test bibtex-4.0 {Destroying a parser} {

    set chan [open [asset bytecode.bib] r]
    proc done {args} {global done ; set done $args ; return}

    set done ""
    set t [bibtex::parse -command done -channel $chan]
    bibtex::destroy $t
    close $chan
} {}

# ... Tests of addStrings ...
#     (Requires introspection of parser state)

testsuiteCleanup

Deleted modules/bibtex/bytecode.bib.

1
2
3
4
5
6
@Book{krasner83,
  title = 	 "Smalltalk-80: Bits of History, Words of Advice",
  publisher = 	 "Addison-Wesley",
  year = 	 1983,
  editor =	 "Glen Krasner"
}
<
<
<
<
<
<












Deleted modules/bibtex/penn_sub.bib.

1
2
3
4
5
6
7
8
9
10
11
@String{aaai90 = "Proc. National Conference on Artificial Intelligence,
                 Boston"}
@InProceedings{Carberry90,
  author =       "Sandra Carberry",
  title =        "Incorporating default inferences into plan
                 recognition",
  booktitle =    "aaai90",
  year =         "1990",
  pages =        "471--478",
  address =      "Boston, MA",
}
<
<
<
<
<
<
<
<
<
<
<






















Added modules/bibtex/test-assets/bytecode.bib.













>
>
>
>
>
>
1
2
3
4
5
6
@Book{krasner83,
  title = 	 "Smalltalk-80: Bits of History, Words of Advice",
  publisher = 	 "Addison-Wesley",
  year = 	 1983,
  editor =	 "Glen Krasner"
}

Added modules/bibtex/test-assets/penn_sub.bib.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
@String{aaai90 = "Proc. National Conference on Artificial Intelligence,
                 Boston"}
@InProceedings{Carberry90,
  author =       "Sandra Carberry",
  title =        "Incorporating default inferences into plan
                 recognition",
  booktitle =    "aaai90",
  year =         "1990",
  pages =        "471--478",
  address =      "Boston, MA",
}

Changes to modules/blowfish/blowfish.man.

156
157
158
159
160
161
162
163
164

[list_end]

[section AUTHORS]
Frank Pilhofer, Pat Thoyts

[vset CATEGORY blowfish]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

156
157
158
159
160
161
162
163
164

[list_end]

[section AUTHORS]
Frank Pilhofer, Pat Thoyts

[vset CATEGORY blowfish]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/cache/async.man.

136
137
138
139
140
141
142
143
144
This method resets the state of either the specified [arg key] or of
all keys known to the cache, making it unkown. This forces future
[method get]-requests to reload the information from the provider.

[list_end]

[vset CATEGORY cache]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

136
137
138
139
140
141
142
143
144
This method resets the state of either the specified [arg key] or of
all keys known to the cache, making it unkown. This forces future
[method get]-requests to reload the information from the provider.

[list_end]

[vset CATEGORY cache]
[include ../common-text/feedback.inc]
[manpage_end]

Added modules/clay/build/build.tcl.







































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
set srcdir [file dirname [file normalize [file join [pwd] [info script]]]]
set moddir [file dirname $srcdir]

set version 0.8.6
set module clay
set filename clay
if {[file exists [file join $moddir .. .. scripts practcl.tcl]]} {
  source [file join $moddir .. .. scripts practcl.tcl]
} elseif {[file exists [file join $moddir .. practcl build doctool.tcl]]} {
  source [file join $moddir .. practcl build doctool.tcl]
} else {
  package require practcl 0.14
}
::practcl::doctool create AutoDoc

set fout [open [file join $moddir ${filename}.tcl] w]
dict set modmap %module% $module
dict set modmap %version% $version
dict set modmap %license% BSD
dict set modmap %filename% $filename

set authors {{Sean Woods} {<[email protected]>}}

puts $fout [string map $modmap {###
# %filename%.tcl
#
# Copyright (c) 2018 Sean Woods
#
# BSD License
###
# @@ Meta Begin
# Package %module% %version%
# Meta platform     tcl
# Meta summary      A minimalist framework for complex TclOO development
# Meta description  This package introduces the method "clay" to both oo::object
# Meta description  and oo::class which facilitate complex interactions between objects
# Meta description  and their ancestor and mixed in classes.
# Meta category     TclOO
# Meta subject      framework
# Meta require      {Tcl 8.6}}]
foreach {name email} $authors {
  puts $fout   "# Meta author       $name"
}
puts $fout [string map $modmap {# Meta license      %license%
# @@ Meta End
}]

puts $fout [string map $modmap {###
# Amalgamated package for %module%
# Do not edit directly, tweak the source in build/ and rerun
# build.tcl
###
package provide %module% %version%
namespace eval ::%module% {}
}]


# Track what files we have included so far
set loaded {}
lappend loaded build.tcl test.tcl

foreach file {
  procs.tcl
  core.tcl uuid.tcl
  dict.tcl list.tcl dictargs.tcl
  dialect.tcl
  metaclass.tcl
  ensemble.tcl
  class.tcl
  object.tcl
} {
  lappend loaded $file
  set content [::practcl::cat [file join $srcdir {*}$file]]
  AutoDoc scan_text $content
  puts $fout "###\n# START: [file tail $file]\n###"
  puts $fout [::practcl::docstrip $content]
  puts $fout "###\n# END: [file tail $file]\n###"
}
# These files can be loaded in any order
foreach file [lsort -dictionary [glob [file join $srcdir *.tcl]]] {
  if {[file tail $file] in $loaded} continue
  lappend loaded $file
  set content [::practcl::cat [file join $srcdir {*}$file]]
  AutoDoc scan_text $content
  puts $fout "###\n# START: [file tail $file]\n###"
  puts $fout [::practcl::docstrip $content]
  puts $fout "###\n# END: [file tail $file]\n###"
}

# Provide some cleanup and our final package provide
puts $fout [string map $modmap {
namespace eval ::%module% {
  namespace export *
}
}]
close $fout

###
# Build our pkgIndex.tcl file
###
set fout [open [file join $moddir pkgIndex.tcl] w]
puts $fout [string map $modmap {# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.6]} {return}
}]
puts $fout [string map $modmap {
package ifneeded %module% %version% [list source [file join $dir %module%.tcl]]
}]

close $fout

###
# Generate the test script
###
namespace eval ::clay {}
source [file join $srcdir procs.tcl]
set fout [open [file join $moddir $filename.test] w]
puts $fout {
namespace eval ::oo::dialect {}
set ::oo::dialect::has(tip470) 0
}
puts $fout [source [file join $srcdir test.tcl]]
puts $fout {

if {![package vsatisfies [package provide Tcl] 8.7]} {return}
puts "Repeating tests with 8.7 features"
namespace eval ::oo::dialect {}
set ::oo::dialect::has(tip470) 1
}
puts $fout [source [file join $srcdir test.tcl]]
close $fout
set manout [open [file join $moddir $filename.man] w]
puts $manout [AutoDoc manpage map $modmap \
  header [::practcl::cat [file join $srcdir manual.txt]] \
  authors $authors \
  footer [::practcl::cat [file join $srcdir footer.txt]] \
]
close $manout

Added modules/clay/build/class.tcl.





































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
::oo::define ::clay::class {

  ###
  # description:
  # The [method clay] method allows a class object access
  # to a combination of its own clay data as
  # well as to that of its ancestors
  # ensemble:
  # ancestors {
  #   argspec {}
  #   description {Return this class and all ancestors in search order.}
  # }
  # dump {
  #   argspec {}
  #   description {Return a complete dump of this object's clay data, but only this object's clay data.}
  # }
  # find {
  #   argspec {path {mandatory 1 positional 1 repeating 1}}
  #   description {
  #     Pull a chunk of data from the clay system. If the last element of [emph path] is a branch,
  #     returns a recursive merge of all data from this object and it's constituent classes of the data in that branch.
  #     If the last element is a leaf, search this object for a matching leaf, or search all  constituent classes for a matching
  #     leaf and return the first value found.
  #     If no value is found, returns an empty string.
  #     If a branch is returned the topmost . entry is omitted.
  #   }
  # }
  # get {
  #   argspec {path {mandatory 1 positional 1 repeating 1}}
  #   description {
  #     Pull a chunk of data from the class's clay system.
  #     If no value is found, returns an empty string.
  #     If a branch is returned the topmost . entry is omitted.
  #   }
  # }
  # GET {
  #   argspec {path {mandatory 1 positional 1 repeating 1}}
  #   description {
  #     Pull a chunk of data from the class's clay system.
  #     If no value is found, returns an empty string.
  #   }
  #}
  # merge {
  #   argspec {dict {mandatory 1 positional 1 repeating 1}}
  #   description {Recursively merge the dictionaries given into the object's local clay storage.}
  # }
  # replace {
  #   argspec {dictionary {mandatory 1 positional 1}}
  #   description {Replace the contents of the internal clay storage with the dictionary given.}
  # }
  # search {
  #   argspec {path {mandatory 1 positional 1 repeating 1}}
  #   description {Return the first matching value for the path in either this class's clay data or one of its ancestors}
  # }
  # set {
  #   argspec {path {mandatory 1 positional 1 repeating 1} value {mandatory 1 postional 1}}
  #   description {Merge the conents of [const value] with the object's clay storage at [const path].}
  # }
  ###
  method clay {submethod args} {
    my variable clay
    if {![info exists clay]} {
      set clay {}
    }
    switch $submethod {
      ancestors {
        tailcall ::clay::ancestors [self]
      }
      branch {
        set path [::clay::tree::storage $args]
        if {![dict exists $clay {*}$path .]} {
          dict set clay {*}$path . {}
        }
      }
      exists {
        if {![info exists clay]} {
          return 0
        }
        set path [::clay::tree::storage $args]
        if {[dict exists $clay {*}$path]} {
          return 1
        }
        if {[dict exists $clay {*}[lrange $path 0 end-1] [lindex $path end]:]} {
          return 1
        }
        return 0
      }
      dump {
        return $clay
      }
      dget {
         if {![info exists clay]} {
          return {}
        }
        set path [::clay::tree::storage $args]
        if {[dict exists $clay {*}$path]} {
          return [dict get $clay {*}$path]
        }
        if {[dict exists $clay {*}[lrange $path 0 end-1] [lindex $path end]:]} {
          return [dict get $clay {*}[lrange $path 0 end-1] [lindex $path end]:]
        }
        return {}
      }
      is_branch {
        set path [::clay::tree::storage $args]
        return [dict exists $clay {*}$path .]
      }
      getnull -
      get {
        if {![info exists clay]} {
          return {}
        }
        set path [::clay::tree::storage $args]
        if {[llength $path]==0} {
          return $clay
        }
        if {[dict exists $clay {*}$path .]} {
          return [::clay::tree::sanitize [dict get $clay {*}$path]]
        }
        if {[dict exists $clay {*}$path]} {
          return [dict get $clay {*}$path]
        }
        if {[dict exists $clay {*}[lrange $path 0 end-1] [lindex $path end]:]} {
          return [dict get $clay {*}[lrange $path 0 end-1] [lindex $path end]:]
        }
        return {}
      }
      find {
        set path [::clay::tree::storage $args]
        if {![info exists clay]} {
          set clay {}
        }
        set clayorder [::clay::ancestors [self]]
        set found 0
        if {[llength $path]==0} {
          set result [dict create . {}]
          foreach class $clayorder {
            ::clay::tree::dictmerge result [$class clay dump]
          }
          return [::clay::tree::sanitize $result]
        }
        foreach class $clayorder {
          if {[$class clay exists {*}$path .]} {
            # Found a branch break
            set found 1
            break
          }
          if {[$class clay exists {*}$path]} {
            # Found a leaf. Return that value immediately
            return [$class clay get {*}$path]
          }
          if {[dict exists $clay {*}[lrange $path 0 end-1] [lindex $path end]:]} {
            return [dict get $clay {*}[lrange $path 0 end-1] [lindex $path end]:]
          }
        }
        if {!$found} {
          return {}
        }
        set result {}
        # Leaf searches return one data field at a time
        # Search in our local dict
        # Search in the in our list of classes for an answer
        foreach class [lreverse $clayorder] {
          ::clay::tree::dictmerge result [$class clay dget {*}$path]
        }
        return [::clay::tree::sanitize $result]
      }
      merge {
        foreach arg $args {
          ::clay::tree::dictmerge clay {*}$arg
        }
      }
      noop {
        # Do nothing. Used as a sign of clay savviness
      }
      search {
        foreach aclass [::clay::ancestors [self]] {
          if {[$aclass clay exists {*}$args]} {
            return [$aclass clay get {*}$args]
          }
        }
      }
      set {
        ::clay::tree::dictset clay {*}$args
      }
      unset {
        dict unset clay {*}$args
      }
      default {
        dict $submethod clay {*}$args
      }
    }
  }
}

Added modules/clay/build/core.tcl.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package require Tcl 8.6 ;# try in pipeline.tcl. Possibly other things.
if {[info commands irmmd5] eq {}} {
  if {[catch {package require odielibc}]} {
    package require md5 2
  }
}
::namespace eval ::clay {}
::namespace eval ::clay::classes {}
::namespace eval ::clay::define {}
::namespace eval ::clay::tree {}
::namespace eval ::clay::dict {}
::namespace eval ::clay::list {}
::namespace eval ::clay::uuid {}

if {![info exists ::clay::idle_destroy]} {
  set ::clay::idle_destroy {}
}

Added modules/clay/build/dialect.tcl.























































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
###
# Adapted from Tcllib's oo::dialect
#
# Copyright (c) 2015-2018 Sean Woods
# Copyright (c) 2015 Donald K Fellows
#
# BSD License
###
# @@ Meta Begin
# Package clay::dialect 0.4
# Meta platform     tcl
# Meta summary      A utility for defining a domain specific language for TclOO systems
# Meta description  This package allows developers to generate
# Meta description  domain specific languages to describe TclOO
# Meta description  classes and objects.
# Meta category     TclOO
# Meta subject      oodialect
# Meta require      {Tcl 8.6}
# Meta author       Sean Woods
# Meta author       Donald K. Fellows
# Meta license      BSD
# @@ Meta End
namespace eval ::clay::dialect {
  namespace export create
  # Allow test rigs to overwrite the flags before invoking this script
  foreach {flag test} {
    tip470 {package vsatisfies [package provide Tcl] 8.7}
  } {
    if {![info exists ::clay::dialect::has($flag)]} {
      set ::clay::dialect::has($flag) [eval $test]
    }
  }
}


proc ::clay::dialect::Push {class} {
  ::variable class_stack
  lappend class_stack $class
}
proc ::clay::dialect::Peek {} {
  ::variable class_stack
  return [lindex $class_stack end]
}
proc ::clay::dialect::Pop {} {
  ::variable class_stack
  set class_stack [lrange $class_stack 0 end-1]
}

if {$::clay::dialect::has(tip470)} {
proc ::clay::dialect::current_class {} {
  return [uplevel 1 self]
}
} else {
proc ::clay::dialect::current_class {} {
  tailcall Peek
}
}

###
# This proc will generate a namespace, a "mother of all classes", and a
# rudimentary set of policies for this dialect.
###
proc ::clay::dialect::create {name {parent ""}} {
  variable has
  set NSPACE [NSNormalize [uplevel 1 {namespace current}] $name]
  ::namespace eval $NSPACE {::namespace eval define {}}
  ###
  # Build the "define" namespace
  ###

  if {$parent eq ""} {
    ###
    # With no "parent" language, begin with all of the keywords in
    # oo::define
    ###
    foreach command [info commands ::oo::define::*] {
      set procname [namespace tail $command]
      interp alias {} ${NSPACE}::define::$procname {} \
        ::clay::dialect::DefineThunk $procname
    }
    # Create an empty dynamic_methods proc
    proc ${NSPACE}::dynamic_methods {class} {}
    namespace eval $NSPACE {
      ::namespace export dynamic_methods
      ::namespace eval define {::namespace export *}
    }
    set ANCESTORS {}
  } else {
    ###
    # If we have a parent language, that language already has the
    # [oo::define] keywords as well as additional keywords and behaviors.
    # We should begin with that
    ###
    set pnspace [NSNormalize [uplevel 1 {namespace current}] $parent]
    apply [list parent {
      ::namespace export dynamic_methods
      ::namespace import -force ${parent}::dynamic_methods
    } $NSPACE] $pnspace

    apply [list parent {
      ::namespace import -force ${parent}::define::*
      ::namespace export *
    } ${NSPACE}::define] $pnspace
      set ANCESTORS [list ${pnspace}::object]
  }
  ###
  # Build our dialect template functions
  ###
  proc ${NSPACE}::define {oclass args} [string map [list %NSPACE% $NSPACE] {
  ###
  # To facilitate library reloading, allow
  # a dialect to create a class from DEFINE
  ###
  set class [::clay::dialect::NSNormalize [uplevel 1 {namespace current}] $oclass]
    if {[info commands $class] eq {}} {
      %NSPACE%::class create $class {*}${args}
    } else {
      ::clay::dialect::Define %NSPACE% $class {*}${args}
    }
}]
  interp alias {} ${NSPACE}::define::current_class {} \
    ::clay::dialect::current_class
  interp alias {} ${NSPACE}::define::aliases {} \
    ::clay::dialect::Aliases $NSPACE
  interp alias {} ${NSPACE}::define::superclass {} \
    ::clay::dialect::SuperClass $NSPACE

  if {[info command ${NSPACE}::class] ne {}} {
    ::rename ${NSPACE}::class {}
  }
  ###
  # Build the metaclass for our language
  ###
  ::oo::class create ${NSPACE}::class {
    superclass ::clay::dialect::MotherOfAllMetaClasses
  }
  # Wire up the create method to add in the extra argument we need; the
  # MotherOfAllMetaClasses will know what to do with it.
  ::oo::objdefine ${NSPACE}::class \
    method create {name {definitionScript ""}} \
      "next \$name [list ${NSPACE}::define] \$definitionScript"

  ###
  # Build the mother of all classes. Note that $ANCESTORS is already
  # guaranteed to be a list in canonical form.
  ###
  uplevel #0 [string map [list %NSPACE% [list $NSPACE] %name% [list $name] %ANCESTORS% $ANCESTORS] {
    %NSPACE%::class create %NSPACE%::object {
     superclass %ANCESTORS%
      # Put MOACish stuff in here
    }
  }]
  if { "${NSPACE}::class" ni $::clay::dialect::core_classes } {
    lappend ::clay::dialect::core_classes "${NSPACE}::class"
  }
  if { "${NSPACE}::object" ni $::clay::dialect::core_classes } {
    lappend ::clay::dialect::core_classes "${NSPACE}::object"
  }
}

# Support commands; not intended to be called directly.
proc ::clay::dialect::NSNormalize {namespace qualname} {
  if {![string match ::* $qualname]} {
    set qualname ${namespace}::$qualname
  }
  regsub -all {::+} $qualname "::"
}

proc ::clay::dialect::DefineThunk {target args} {
  tailcall ::oo::define [Peek] $target {*}$args
}

proc ::clay::dialect::Canonical {namespace NSpace class} {
  namespace upvar $namespace cname cname
  #if {[string match ::* $class]} {
  #  return $class
  #}
  if {[info exists cname($class)]} {
    return $cname($class)
  }
  if {[info exists ::clay::dialect::cname($class)]} {
    return $::clay::dialect::cname($class)
  }
  if {[info exists ::clay::dialect::cname(${NSpace}::${class})]} {
    return $::clay::dialect::cname(${NSpace}::${class})
  }
  foreach item [list "${NSpace}::$class" "::$class"] {
    if {[info commands $item] ne {}} {
      return $item
    }
  }
  return ${NSpace}::$class
}

###
# Implementation of the languages' define command
###
proc ::clay::dialect::Define {namespace class args} {
  Push $class
  try {
  	if {[llength $args]==1} {
      namespace eval ${namespace}::define [lindex $args 0]
    } else {
      ${namespace}::define::[lindex $args 0] {*}[lrange $args 1 end]
    }
  	${namespace}::dynamic_methods $class
  } finally {
    Pop
  }
}

###
# Implementation of how we specify the other names that this class will answer
# to
###

proc ::clay::dialect::Aliases {namespace args} {
  set class [Peek]
  namespace upvar $namespace cname cname
  set NSpace [join [lrange [split $class ::] 1 end-2] ::]
  set cname($class) $class
  foreach name $args {
    set cname($name) $class
    #set alias $name
    set alias [NSNormalize $NSpace $name]
    # Add a local metaclass reference
    if {![info exists ::clay::dialect::cname($alias)]} {
      lappend ::clay::dialect::aliases($class) $alias
      ##
      # Add a global reference, first come, first served
      ##
      set ::clay::dialect::cname($alias) $class
    }
  }
}

###
# Implementation of a superclass keyword which will enforce the inheritance of
# our language's mother of all classes
###

proc ::clay::dialect::SuperClass {namespace args} {
  set class [Peek]
  namespace upvar $namespace class_info class_info
  dict set class_info($class) superclass 1
  set ::clay::dialect::cname($class) $class
  set NSpace [join [lrange [split $class ::] 1 end-2] ::]
  set unique {}
  foreach item $args {
    set Item [Canonical $namespace $NSpace $item]
    dict set unique $Item $item
  }
  set root ${namespace}::object
  if {$class ne $root} {
    dict set unique $root $root
  }
  tailcall ::oo::define $class superclass {*}[dict keys $unique]
}

###
# Implementation of the common portions of the the metaclass for our
# languages.
###
if {[info command ::clay::dialect::MotherOfAllMetaClasses] eq {}} {
::oo::class create ::clay::dialect::MotherOfAllMetaClasses {
  superclass ::oo::class
  constructor {define definitionScript} {
    $define [self] {
      superclass
    }
    $define [self] $definitionScript
  }
  method aliases {} {
    if {[info exists ::clay::dialect::aliases([self])]} {
      return $::clay::dialect::aliases([self])
    }
  }
}
}

namespace eval ::clay::dialect {
  variable core_classes {::oo::class ::oo::object}
}

Added modules/clay/build/dict.tcl.



































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
###
# If the path (given by the list of elements) exists, return that value.
# Otherwise return an empty string. Designed to replace [example {
# if {[dict exists $dictionary {*}$args]} {
#   return [dict get $dictionary {*}$args]
# } else {
#   return {}
# }
# }]
# example:
# set value [dict getnull $arglist $option]
# arglist:
# dictionary {mandatory 1 positional 1}
# element {mandatory 0 positional 1 repeating 1}
###
::clay::PROC ::tcl::dict::getnull {dictionary args} {
  if {[exists $dictionary {*}$args]} {
    get $dictionary {*}$args
  }
} {
  namespace ensemble configure dict -map [dict replace\
      [namespace ensemble configure dict -map] getnull ::tcl::dict::getnull]
}


###
# Test if value is a dict.
# [para]
# This command is added to the [fun dict] ensemble as [fun {dict is_dict}]
###
::clay::PROC ::tcl::dict::is_dict { d } {
  # is it a dict, or can it be treated like one?
  if {[catch {dict size $d} err]} {
    #::set ::errorInfo {}
    return 0
  }
  return 1
} {
  namespace ensemble configure dict -map [dict replace\
      [namespace ensemble configure dict -map] is_dict ::tcl::dict::is_dict]
}

###
# A routine to recursively dig through dicts and merge
# adapted from http://stevehavelka.com/tcl-dict-operation-nested-merge/
###
::clay::PROC ::tcl::dict::rmerge {args} {
  ::set result [dict create . {}]
  # Merge b into a, and handle nested dicts appropriately
  ::foreach b $args {
    for { k v } $b {
      ::set field [string trim $k :/]
      if {![::clay::tree::is_branch $b $k]} {
        # Element names that end in ":" are assumed to be literals
        set result $k $v
      } elseif { [exists $result $k] } {
        # key exists in a and b?  let's see if both values are dicts
        # both are dicts, so merge the dicts
        if { [is_dict [get $result $k]] && [is_dict $v] } {
          set result $k [rmerge [get $result $k] $v]
        } else {
          set result $k $v
        }
      } else {
        set result $k $v
      }
    }
  }
  return $result
} {
  namespace ensemble configure dict -map [dict replace\
      [namespace ensemble configure dict -map] rmerge ::tcl::dict::rmerge]
}

###
# Return true if the element [variable path] with the value [variable dict]
# is a dict. [variable path] is given as a list to descend into sub-dicts of
# the current dict.
# The rules are as follows:
# [list_begin enumerated]
# [enum]
# If the last character of the last element of [variable path] is a colon (:)
# return false
# [enum]
# If the last character of the last element of [variable path] is a slash (/)
# return true
# [enum]
# If a sub-element if [variable path] named [const .info] is present return true
# [list_end]
# [para]
# [para]
# This command is added to the [fun dict] ensemble as [fun {clay::tree::is_branch}]
# example:
# > set mydict {sub/ {sub/ {field {A block of text}}}
# > clay::tree::is_branch $mydict sub/
# 1
# > clay::tree::is_branch $mydict {sub/ sub/}
# 1
# > clay::tree::is_branch $mydict {sub/ sub/ field}
# 0
###
::clay::PROC ::clay::tree::is_branch { dict path } {
  set field [lindex $path end]
  if {[string index $field end] eq ":"} {
    return 0
  }
  if {[string index $field 0] eq "."} {
    return 0
  }
  if {[string index $field end] eq "/"} {
    return 1
  }
  return [dict exists $dict {*}$path .]
}

###
# Output a dictionary as an indented stream of
# data suitable for output to the screen. The system uses
# the rules for [fun {clay::tree::is_branch}] to determine if
# an value in a dictionary is a leaf or a branch.
# example:
# > set mydict {sub/ {sub/ {field {A block of text}}}
# > clay::tree::print $mydict
# sub/ {
#   sub/ {
#     field {A block of text}
#   }
# }
###
::clay::PROC ::clay::tree::print {dict} {
  ::set result {}
  ::set level -1
  ::clay::tree::_dictputb $level result $dict
  return $result
}

###
# Helper function for ::clay::tree::print
# Formats the string representation for a dictionary element within
# a human readable stream of lines, and determines if it needs to call itself
# with further indentation to express a sub-branch
###
::clay::PROC ::clay::tree::_dictputb {level varname dict} {
  upvar 1 $varname result
  incr level
  dict for {field value} $dict {
    if {$field eq "."} continue
    if {[clay::tree::is_branch $dict $field]} {
      putb result "[string repeat "  " $level]$field \{"
      _dictputb $level result $value
      putb result "[string repeat "  " $level]\}"
    } else {
      putb result "[string repeat "  " $level][list $field $value]"
    }
  }
}

###
# Output a dictionary removing any . entries added by [fun {clay::tree::merge}]
###
proc ::clay::tree::sanitize {dict} {
  ::set result {}
  ::set level -1
  ::clay::tree::_sanitizeb {} result $dict
  return $result
}

###
# Helper function for ::clay::tree::sanitize
# Formats the string representation for a dictionary element within
# a human readable stream of lines, and determines if it needs to call itself
# with further indentation to express a sub-branch
###
proc ::clay::tree::_sanitizeb {path varname dict} {
  upvar 1 $varname result
  dict for {field value} $dict {
    if {$field eq "."} continue
    if {[clay::tree::is_branch $dict $field]} {
      _sanitizeb [list {*}$path $field] result $value
    } else {
      dict set result {*}$path $field $value
    }
  }
}

###
# Return the path as a storage path for clay::tree
# with all branch terminators removed.
# This command will also break arguments up if they
# contain /.
# example:
# > clay::tree::storage {foo bar baz bang}
# foo bar baz bang
# > clay::tree::storage {foo bar baz bang/}
# foo bar baz bang
# > clay::tree::storage {foo bar baz bang:}
# foo bar baz bang:
# > clay::tree::storage {foo/bar/baz bang:}
# foo bar baz bang:
# > clay::tree::storage {foo/bar/baz/bang}
# foo bar baz bang
###
proc ::clay::tree::storage {rawpath} {
  set isleafvar 0
  set path {}
  set tail [string index $rawpath end]
  foreach element $rawpath {
    set items [split [string trim $element /] /]
    foreach item $items {
      if {$item eq {}} continue
      lappend path $item
    }
  }
  return $path
}

###
# Set an element with a recursive dictionary,
# marking all branches on the way down to the
# final element.
# If the value does not exists in the nested dictionary
# it is added as a leaf. If the value already exists as a branch
# the value given is merged if the value is a valid dict. If the
# incoming value is not a valid dict, the value overrides the value
# stored, and the value is treated as a leaf from then on.
# example:
# > set r {}
# > ::clay::tree::dictset r option color default Green
# . {} option {. {} color {. {} default Green}}
# > ::clay::tree::dictset r option {Something not dictlike}
# . {} option {Something not dictlike}
# # Note that if the value is not a dict, and you try to force it to be
# # an error with be thrown on the merge
# > ::clay::tree::dictset r option color default Blue
# missing value to go with key
###
proc ::clay::tree::dictset {varname args} {
  upvar 1 $varname result
  if {[llength $args] < 2} {
    error "Usage: ?path...? path value"
  } elseif {[llength $args]==2} {
    set rawpath [lindex $args 0]
  } else {
    set rawpath  [lrange $args 0 end-1]
  }
  set value [lindex $args end]
  set path [storage $rawpath]
  set dot .
  set one {}
  dict set result $dot $one
  set dpath {}
  foreach item [lrange $path 0 end-1] {
    set field $item
    lappend dpath [string trim $item /]
    dict set result {*}$dpath $dot $one
  }
  set field [lindex $rawpath end]
  set ext   [string index $field end]
  if {$ext eq {:} || ![dict is_dict $value]} {
    dict set result {*}$path $value
    return
  }
  if {$ext eq {/} && ![dict exists $result {*}$path $dot]} {
    dict set result {*}$path $dot $one
  }
  if {[dict exists $result {*}$path $dot]} {
    dict set result {*}$path [::clay::tree::merge [dict get $result {*}$path] $value]
    return
  }
  dict set result {*}$path $value
}

###
# A recursive form of dict merge, intended for modifying variables in place.
# example:
# > set mydict {sub/ {sub/ {description {a block of text}}}}
# > ::clay::tree::dictmerge mydict {sub/ {sub/ {field {another block of text}}}}]
# > clay::tree::print $mydict
# sub/ {
#   sub/ {
#     description {a block of text}
#     field {another block of text}
#   }
# }
###
proc ::clay::tree::dictmerge {varname args} {
  upvar 1 $varname result
  set dot .
  set one {}
  dict set result $dot $one
  foreach dict $args {
    dict for {f v} $dict {
      set field [string trim $f /]
      set bbranch [clay::tree::is_branch $dict $f]
      if {![dict exists $result $field]} {
        dict set result $field $v
        if {$bbranch} {
          dict set result $field [clay::tree::merge $v]
        } else {
          dict set result $field $v
        }
      } elseif {[dict exists $result $field $dot]} {
        if {$bbranch} {
          dict set result $field [clay::tree::merge [dict get $result $field] $v]
        } else {
          dict set result $field $v
        }
      }
    }
  }
  return $result
}



###
# A recursive form of dict merge
# [para]
# A routine to recursively dig through dicts and merge
# adapted from http://stevehavelka.com/tcl-dict-operation-nested-merge/
# example:
# > set mydict {sub/ {sub/ {description {a block of text}}}}
# > set odict [clay::tree::merge $mydict {sub/ {sub/ {field {another block of text}}}}]
# > clay::tree::print $odict
# sub/ {
#   sub/ {
#     description {a block of text}
#     field {another block of text}
#   }
# }
###
proc ::clay::tree::merge {args} {
  ###
  # The result of a merge is always a dict with branches
  ###
  set dot .
  set one {}
  dict set result $dot $one
  set argument 0
  foreach b $args {
    # Merge b into a, and handle nested dicts appropriately
    if {![dict is_dict $b]} {
      error "Element $b is not a dictionary"
    }
    dict for { k v } $b {
      if {$k eq $dot} {
        dict set result $dot $one
        continue
      }
      set bbranch [is_branch $b $k]
      set field [string trim $k /]
      if { ![dict exists $result $field] } {
        if {$bbranch} {
          dict set result $field [merge $v]
        } else {
          dict set result $field $v
        }
      } else {
        set abranch [dict exists $result $field $dot]
        if {$abranch && $bbranch} {
          dict set result $field [merge [dict get $result $field] $v]
        } else {
          dict set result $field $v
          if {$bbranch} {
            dict set result $field $dot $one
          }
        }
      }
    }
  }
  return $result
}
###
# Returns true if the path specified by args either does not exist,
# if exists and contains an empty string or the value of NULL or null.
# [para]
# This function is added to the global dict ensemble as [fun {dict isnull}]
###
::clay::PROC ::tcl::dict::isnull {dictionary args} {
  if {![exists $dictionary {*}$args]} {return 1}
  return [expr {[get $dictionary {*}$args] in {{} NULL null}}]
} {
  namespace ensemble configure dict -map [dict replace\
      [namespace ensemble configure dict -map] isnull ::tcl::dict::isnull]
}

Added modules/clay/build/dictargs.tcl.





















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
namespace eval ::dictargs {}
if {[info commands ::dictargs::parse] eq {}} {
  proc ::dictargs::parse {argdef argdict} {
    set result {}
    dict for {field info} $argdef {
      if {![string is alnum [string index $field 0]]} {
        error "$field is not a simple variable name"
      }
      upvar 1 $field _var
      set aliases {}
      if {[dict exists $argdict $field]} {
        set _var [dict get $argdict $field]
        continue
      }
      if {[dict exists $info aliases:]} {
        set found 0
        foreach {name} [dict get $info aliases:] {
          if {[dict exists $argdict $name]} {
            set _var [dict get $argdict $name]
            set found 1
            break
          }
        }
        if {$found} continue
      }
      if {[dict exists $info default:]} {
        set _var [dict get $info default:]
        continue
      }
      set mandatory 1
      if {[dict exists $info mandatory:]} {
        set mandatory [dict get $info mandatory:]
      }
      if {$mandatory} {
        error "$field is required"
      }
    }
  }
}

###
# Named Procedures as new command
###
proc ::dictargs::proc {name argspec body} {
  set result {}
  append result "::dictargs::parse \{$argspec\} \$args" \;
  append result $body
  uplevel 1 [list ::proc $name [list [list args [list dictargs $argspec]]] $result]
}

proc ::dictargs::method {name argspec body} {
  set class [lindex [::info level -1] 1]
  set result {}
  append result "::dictargs::parse \{$argspec\} \$args" \;
  append result $body
  oo::define $class method $name [list [list args [list dictargs $argspec]]] $result
}

Added modules/clay/build/ensemble.tcl.

















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
::namespace eval ::clay::define {}

###
# Produce the body of an ensemble's public dispatch method
# ensemble is the name of the the ensemble.
# einfo is a dictionary of methods for the ensemble, and each value is a script
# to execute on dispatch
# example:
# ::clay::ensemble_methodbody foo {
#   bar {tailcall my Foo_bar {*}$args}
#   baz {tailcall my Foo_baz {*}$args}
#   clock {return [clock seconds]}
#   default {puts "You gave me $method"}
# }
###
proc ::clay::ensemble_methodbody {ensemble einfo} {
  set default standard
  set preamble {}
  set eswitch {}
  set Ensemble [string totitle $ensemble]
  if {$Ensemble eq "."} continue
  foreach {msubmethod minfo} [lsort -dictionary -stride 2 $einfo] {
    if {$msubmethod eq "."} continue
    if {![dict exists $minfo body:]} {
      continue
    }
    set submethod [string trim $msubmethod :/-]
    if {$submethod eq "default"} {
      set default [dict get $minfo body:]
    } else {
      dict set eswitch $submethod [dict get $minfo body:]
    }
    if {[dict exists $submethod aliases:]} {
      foreach alias [dict get $minfo aliases:] {
        if {![dict exists $eswitch $alias]} {
          dict set eswitch $alias [dict get $minfo body:]
        }
      }
    }
  }
  set methodlist [lsort -dictionary [dict keys $eswitch]]
  if {![dict exists $eswitch <list>]} {
    dict set eswitch <list> {return $methodlist}
  }
  if {$default eq "standard"} {
    set default "error \"unknown method $ensemble \$method. Valid: \$methodlist\""
  }
  dict set eswitch default $default
  set mbody {}
  append mbody \n [list set methodlist $methodlist]
  append mbody \n "switch -- \$method \{$eswitch\}" \n
  return $mbody
}

::proc ::clay::define::Ensemble {rawmethod args} {
  if {[llength $args]==2} {
    lassign $args argspec body
    set argstyle tcl
  } elseif {[llength $args]==3} {
    lassign $args argstyle argspec body
  } else {
    error "Usage: Ensemble name ?argstyle? argspec body"
  }
  set class [current_class]
  #if {$::clay::trace>2} {
  #  puts [list $class Ensemble $rawmethod $argspec $body]
  #}
  set mlist [split $rawmethod "::"]
  set ensemble [string trim [lindex $mlist 0] :/]
  set method   [string trim [lindex $mlist 2] :/]
  if {[string index $method 0] eq "_"} {
    $class clay set method_ensemble $ensemble $method $body
    return
  }
  set realmethod  [string totitle $ensemble]_${method}
  set realbody {}
  if {$argstyle eq "dictargs"} {
    append realbody "::dictargs::parse \{$argspec\} \$args" \n
  }
  if {[$class clay exists method_ensemble $ensemble _preamble]} {
    append realbody [$class clay get method_ensemble $ensemble _preamble] \n
  }
  append realbody $body
  if {$method eq "default"} {
    $class clay set method_ensemble $ensemble $method: "tailcall my $realmethod \$method {*}\$args"
    if {$argstyle eq "dictargs"} {
      oo::define $class method $realmethod [list method [list args $argspec]] $realbody
    } else {
      oo::define $class method $realmethod [list method {*}$argspec] $realbody
    }
  } else {
    $class clay set method_ensemble $ensemble $method: "tailcall my $realmethod {*}\$args"
    if {$argstyle eq "dictargs"} {
      oo::define $class method $realmethod [list [list args $argspec]] $realbody
    } else {
      oo::define $class method $realmethod $argspec $realbody
    }
  }
  if {$::clay::trace>2} {
    puts [list $class clay set method_ensemble/ $ensemble [string trim $method :/]  ...]
  }
}


Added modules/clay/build/event.tcl.































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
if {[info commands ::cron::object_destroy] eq {}} {
  # Provide a noop if we aren't running with the cron scheduler
  namespace eval ::cron {}
  proc ::cron::object_destroy args {}
}
::namespace eval ::clay::event {}

###
# Process the queue of objects to be destroyed
###
proc ::clay::cleanup {} {
  if {![info exists ::clay::idle_destroy]} return
  foreach obj $::clay::idle_destroy {
    if {[info commands $obj] ne {}} {
      catch {$obj destroy}
    }
  }
  set ::clay::idle_destroy {}
}

proc ::clay::object_create {objname {class {}}} {
  #if {$::clay::trace>0} {
  #  puts [list $objname CREATE]
  #}
}

proc ::clay::object_rename {object newname} {
  if {$::clay::trace>0} {
    puts [list $object RENAME -> $newname]
  }
}

###
# Mark an objects for destruction on the next cleanup
###
proc ::clay::object_destroy args {
  if {![info exists ::clay::idle_destroy]} {
    set ::clay::idle_destroy {}
  }
  foreach objname $args {
    if {$::clay::trace>0} {
      puts [list $objname DESTROY]
    }
    ::cron::object_destroy $objname
    if {$objname in $::clay::idle_destroy} continue
    lappend ::clay::idle_destroy $objname
  }
}

###
# description: Cancel a scheduled event
###
proc ::clay::event::cancel {self {task *}} {
  variable timer_event
  variable timer_script

  foreach {id event} [array get timer_event $self:$task] {
    ::after cancel $event
    set timer_event($id) {}
    set timer_script($id) {}
  }
}

###
# description:
#    Generate an event
#    Adds a subscription mechanism for objects
#    to see who has recieved this event and prevent
#    spamming or infinite recursion
###
proc ::clay::event::generate {self event args} {
  set wholist [Notification_list $self $event]
  if {$wholist eq {}} return
  set dictargs [::oo::meta::args_to_options {*}$args]
  set info $dictargs
  set strict 0
  set debug 0
  set sender $self
  dict with dictargs {}
  dict set info id     [::clay::event::nextid]
  dict set info origin $self
  dict set info sender $sender
  dict set info rcpt   {}
  foreach who $wholist {
    catch {::clay::event::notify $who $self $event $info}
  }
}

###
# title: Return a unique event handle
###
proc ::clay::event::nextid {} {
  return "event#[format %0.8x [incr ::clay::event_count]]"
}

###
# description:
#    Called recursively to produce a list of
#    who recieves notifications
###
proc ::clay::event::Notification_list {self event {stackvar {}}} {
  set notify_list {}
  foreach {obj patternlist} [array get ::clay::object_subscribe] {
    if {$obj eq $self} continue
    if {$obj in $notify_list} continue
    set match 0
    foreach {objpat eventlist} $patternlist {
      if {![string match $objpat $self]} continue
      foreach eventpat $eventlist {
        if {![string match $eventpat $event]} continue
        set match 1
        break
      }
      if {$match} {
        break
      }
    }
    if {$match} {
      lappend notify_list $obj
    }
  }
  return $notify_list
}

###
# Final delivery to intended recipient object
###
proc ::clay::event::notify {rcpt sender event eventinfo} {
  if {[info commands $rcpt] eq {}} return
  if {$::clay::trace} {
    puts [list event notify rcpt $rcpt sender $sender event $event info $eventinfo]
  }
  $rcpt notify $event $sender $eventinfo
}

###
# Evaluate an event script in the global namespace
###
proc ::clay::event::process {self handle script} {
  variable timer_event
  variable timer_script

  array unset timer_event $self:$handle
  array unset timer_script $self:$handle

  set err [catch {uplevel #0 $script} result errdat]
  if $err {
    puts "BGError: $self $handle $script
ERR: $result
[dict get $errdat -errorinfo]
***"
  }
}

###
# description: Schedule an event to occur later
###
proc ::clay::event::schedule {self handle interval script} {
  variable timer_event
  variable timer_script
  if {$::clay::trace} {
    puts [list $self schedule $handle $interval]
  }
  if {[info exists timer_event($self:$handle)]} {
    if {$script eq $timer_script($self:$handle)} {
      return
    }
    ::after cancel $timer_event($self:$handle)
  }
  set timer_script($self:$handle) $script
  set timer_event($self:$handle) [::after $interval [list ::clay::event::process $self $handle $script]]
}

###
# Subscribe an object to an event pattern
###
proc ::clay::event::subscribe {self who event} {
  upvar #0 ::clay::object_subscribe($self) subscriptions
  if {![info exists subscriptions]} {
    set subscriptions {}
  }
  set match 0
  foreach {objpat eventlist} $subscriptions {
    if {![string match $objpat $who]} continue
    foreach eventpat $eventlist {
      if {[string match $eventpat $event]} {
        # This rule already exists
        return
      }
    }
  }
  dict lappend subscriptions $who $event
}

###
# Unsubscribe an object from an event pattern
###
proc ::clay::event::unsubscribe {self args} {
  upvar #0 ::clay::object_subscribe($self) subscriptions
  if {![info exists subscriptions]} {
    return
  }
  switch [llength $args] {
    1 {
      set event [lindex $args 0]
      if {$event eq "*"} {
        # Shortcut, if the
        set subscriptions {}
      } else {
        set newlist {}
        foreach {objpat eventlist} $subscriptions {
          foreach eventpat $eventlist {
            if {[string match $event $eventpat]} continue
            dict lappend newlist $objpat $eventpat
          }
        }
        set subscriptions $newlist
      }
    }
    2 {
      set who [lindex $args 0]
      set event [lindex $args 1]
      if {$who eq "*" && $event eq "*"} {
        set subscriptions {}
      } else {
        set newlist {}
        foreach {objpat eventlist} $subscriptions {
          if {[string match $who $objpat]} {
            foreach eventpat $eventlist {
              if {[string match $event $eventpat]} continue
              dict lappend newlist $objpat $eventpat
            }
          }
        }
        set subscriptions $newlist
      }
    }
  }
}

Added modules/clay/build/footer.txt.





>
>
1
2
[vset CATEGORY oo]
[include ../common-text/feedback.inc]

Added modules/clay/build/list.tcl.

























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
###
# Add elements to a list if that are not already present in the list.
# As a side effect, if variable [variable varname] does not exists,
# create it as an empty list.
# arglist:
# varname {positional 1 mandatory 1}
# element {positional 1 mandatory 0 repeating 1}
# example:
# ladd contents foo bar
# puts $contents
# > foo bar
# ladd contents foo bar baz bang
# puts $contents
# > foo bar baz bang
###
::clay::PROC ::clay::ladd {varname args} {
  upvar 1 $varname var
  if ![info exists var] {
      set var {}
  }
  foreach item $args {
    if {$item in $var} continue
    lappend var $item
  }
  return $var
}

###
# Delete all instances of the elements given from a list contained in [variable varname].
# If the variable does exist this is a noop.
# arglist:
# varname {positional 1 mandatory 1}
# element {positional 1 mandatory 0 repeating 1}
# example:
# set contents {foo bar baz bang foo foo foo}
# ldelete contents foo
# puts $contents
# > bar baz bang
###
::clay::PROC ::clay::ldelete {varname args} {
  upvar 1 $varname var
  if ![info exists var] {
      return
  }
  foreach item [lsort -unique $args] {
    while {[set i [lsearch $var $item]]>=0} {
      set var [lreplace $var $i $i]
    }
  }
  return $var
}

###
# Return a random element from [variable list]
###
::clay::PROC ::clay::lrandom list {
  set len [llength $list]
  set idx [expr int(rand()*$len)]
  return [lindex $list $idx]
}

Added modules/clay/build/manual.txt.















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
[keywords oo]
[copyright {2018 Sean Woods <[email protected]>}]
[moddesc   {Clay Framework}]
[titledesc {A minimalist framework for large scale OO Projects}]
[category  {Programming tools}]
[keywords TclOO]
[require Tcl 8.6]
[require uuid]
[require oo::dialect]
[description]
Clay introduces a method ensemble to both [class oo::class] and [class oo::object] called
clay. This ensemble handles all of the high level interactions within the framework.
Clay stores structured data. Clan manages method delegation. Clay has facilities to
manage the complex interactions that come about with mixins.
[para]
The central concept is that inside of every object and class
(which are actually objects too) is a dict called clay. What is stored in that dict is
left to the imagination. But because this dict is exposed via a public method, we can
share structured data between object, classes, and mixins.
[para]
[subsection {Structured Data}]
Clay uses a standardized set of method interactions and introspection that TclOO already provides to perform on-the-fly searches. On-the-fly searches mean that the data is never stale, and we avoid many of the sorts of collisions that would arise when objects start mixing in other classes during operation.
[para]
The [method clay] methods for both classes and objects have a get and a set method. For objects, get will search through the local clay dict. If the requested leaf is not found, or the query is for a branch, the system will then begin to poll the clay methods of all of the class that implements the object, all of that classes’ ancestors, as well as all of the classes that have been mixed into this object, and all of their ancestors.
[para]
Intended branches on a tree end with a directory slash (/). Intended leaves are left unadorned. This is a guide for the tool that builds the search
results to know what parts of a dict are intended to be branches and which are intended to be leaves.
For simple cases, branch marking can be ignored:
[example {
::oo::class create ::foo { }
::foo clay set property/ color blue
::foo clay set property/ shape round

set A [::foo new]
$A clay get property/
{color blue shape round}

$A clay set property/ shape square
$A clay get property/
{color blue shape square}
}]
[para]
But when you start storing blocks of text, guessing what field is a dict and what isn’t gets messy:
[example {
::foo clay set description {A generic thing of designated color and shape}

$A clay get description
{A generic thing of designated color and shape}

Without a convention for discerning branches for leaves what should have been a value can be accidentally parsed as a dictionary, and merged with all of the other values that were never intended to be merge. Here is an example of it all going wrong:
::oo::class create ::foo { }
# Add description as a leaf
::foo clay set description \
  {A generic thing of designated color and shape}
# Add description as a branch
::foo clay set description/ \
  {A generic thing of designated color and shape}

::oo::class create ::bar {
  superclass foo
}
# Add description as a leaf
::bar clay set description \
  {A drinking establishment of designated color and shape and size}
# Add description as a branch
::bar clay set description/ \
  {A drinking establishment of designated color and shape and size}

set B [::bar new]
# As a leaf we get the value verbatim from he nearest ancestor
$B clay get description
  {A drinking establishment of designated color and shape and size}
# As a branch we get a recursive merge
$B clay get description/
{A drinking establishment of designated color and size thing of}
}]
[subsection {Clay Dialect}]
Clay is built using the oo::dialect module from Tcllib. oo::dialect allows you to either add keywords directly to clay, or to create your own
metaclass and keyword set using Clay as a foundation. For details on the keywords and what they do, consult the functions in the ::clay::define namespace.
[subsection {Method Delegation}]
Method Delegation
It is sometimes useful to have an external object that can be invoked as if it were a method of the object. Clay provides a delegate ensemble method to perform that delegation, as well as introspect which methods are delegated in that manner. All delegated methods are marked with html-like tag markings (< >) around them.
[example {
::clay::define counter {
  Variable counter 0
  method incr {{howmuch 1}} {
    my variable counter
    incr counter $howmuch
  }
  method value {} {
    my variable counter
    return $counter
  }
  method reset {} {
    my variable counter
    set counter 0
  }
}
::clay::define example {
  variable buffer
  constructor {} {
    # Build a counter object
    set obj [namespace current]::counter
    ::counter create $obj
    # Delegate the counter
    my delegate <counter> $obj
  }
  method line {text} {
    my <counter> incr
    append buffer $text
  }
}

set A [example new]
$A line {Who’s line is it anyway?}
$A <counter> value
1
}]

Added modules/clay/build/metaclass.tcl.









































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
#-------------------------------------------------------------------------
# TITLE:
#    clay.tcl
#
# PROJECT:
#    clay: TclOO Helper Library
#
# DESCRIPTION:
#    clay(n): Implementation File
#
#-------------------------------------------------------------------------
::clay::dialect::create ::clay


proc ::clay::dynamic_methods class {
  foreach command [info commands [namespace current]::dynamic_methods_*] {
    $command $class
  }
}

proc ::clay::dynamic_methods_class {thisclass} {
  set methods {}
  set mdata [$thisclass clay find class_typemethod]
  foreach {method info} $mdata {
    if {$method eq {.}} continue
    set method [string trimright $method :/-]
    if {$method in $methods} continue
    lappend methods $method
    set arglist [dict getnull $info arglist]
    set body    [dict getnull $info body]
    ::oo::objdefine $thisclass method $method $arglist $body
  }
}

###
# New OO Keywords for clay
###
proc ::clay::define::Array {name {values {}}} {
  set class [current_class]
  set name [string trim $name :/]
  $class clay branch array $name
  dict for {var val} $values {
    $class clay set array/ $name $var $val
  }
}

###
# An annotation that objects of this class interact with delegated
# methods. The annotation is intended to be a dictionary, and the
# only reserved key is [emph {description}], a human readable description.
###
proc ::clay::define::Delegate {name info} {
  set class [current_class]
  foreach {field value} $info {
    $class clay set component/ [string trim $name :/]/ $field $value
  }
}

###
# topic: 2cfc44a49f067124fda228458f77f177
# title: Specify the constructor for a class
###
proc ::clay::define::constructor {arglist rawbody} {
  set body {
my variable DestroyEvent
set DestroyEvent 0
::clay::object_create [self] [info object class [self]]
# Initialize public variables and options
my InitializePublic
  }
  append body $rawbody
  set class [current_class]
  ::oo::define $class constructor $arglist $body
}

###
# Specify the a method for the class object itself, instead of for objects of the class
###
proc ::clay::define::Class_Method {name arglist body} {
  set class [current_class]
  $class clay set class_typemethod/ [string trim $name :/] [dict create arglist $arglist body $body]
}

###
# And alias to the new Class_Method keyword
###
proc ::clay::define::class_method {name arglist body} {
  set class [current_class]
  $class clay set class_typemethod/ [string trim $name :/] [dict create arglist $arglist body $body]
}

proc ::clay::define::clay {args} {
  set class [current_class]
  if {[lindex $args 0] in "cget set branch"} {
    $class clay {*}$args
  } else {
    $class clay set {*}$args
  }
}

###
# topic: 4cb3696bf06d1e372107795de7fe1545
# title: Specify the destructor for a class
###
proc ::clay::define::destructor rawbody {
  set body {
# Run the destructor once and only once
set self [self]
my variable DestroyEvent
if {$DestroyEvent} return
set DestroyEvent 1
}
  append body $rawbody
  ::oo::define [current_class] destructor $body
}

proc ::clay::define::Dict {name {values {}}} {
  set class [current_class]
  set name [string trim $name :/]
  $class clay branch dict $name
  foreach {var val} $values {
    $class clay set dict/ $name/ $var $val
  }
}

###
# Define an option for the class
###
proc ::clay::define::Option {name args} {
  set class [current_class]
  set dictargs {default {}}
  foreach {var val} [::clay::args_to_dict {*}$args] {
    dict set dictargs [string trim $var -:/] $val
  }
  set name [string trimleft $name -]

  ###
  # Option Class handling
  ###
  set optclass [dict getnull $dictargs class]
  if {$optclass ne {}} {
    foreach {f v} [$class clay find option_class $optclass] {
      if {![dict exists $dictargs $f]} {
        dict set dictargs $f $v
      }
    }
    if {$optclass eq "variable"} {
      variable $name [dict getnull $dictargs default]
    }
  }
  foreach {f v} $dictargs {
    $class clay set option $name $f $v
  }
}

proc ::clay::define::Method {name argstyle argspec body} {
  set class [current_class]
  set result {}
  switch $argstyle {
    dictargs {
      append result "::dictargs::parse \{$argspec\} \$args" \;
    }
  }
  append result $body
  oo::define $class method $name [list [list args [list dictargs $argspec]]] $result
}

###
# Define a class of options
# All field / value pairs will be be inherited by an option that
# specify [emph name] as it class field.
###
proc ::clay::define::Option_Class {name args} {
  set class [current_class]
  set dictargs {default {}}
  set name [string trimleft $name -:]
  foreach {f v} [::clay::args_to_dict {*}$args] {
    $class clay set option_class $name [string trim $f -/:] $v
  }
}

###
# topic: 615b7c43b863b0d8d1f9107a8d126b21
# title: Specify a variable which should be initialized in the constructor
# description:
#    This keyword can also be expressed:
#    [example {property variable NAME {default DEFAULT}}]
#    [para]
#    Variables registered in the variable property are also initialized
#    (if missing) when the object changes class via the [emph morph] method.
###
proc ::clay::define::Variable {name {default {}}} {
  set class [current_class]
  set name [string trimright $name :/]
  $class clay set variable/ $name $default
}

Added modules/clay/build/object.tcl.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# clay::object
#
# This class is inherited by all classes that have options.
#
::oo::define ::clay::object {

  ###
  # description:
  # The [method clay] method allows an object access
  # to a combination of its own clay data as
  # well as to that of its class
  # ensemble:
  # ancestors {
  #   argspec {}
  #   description {Return the class this object belongs to, all classes mixed into this object, and all ancestors of those classes in search order.}
  # }
  # cache {
  #   argspec {path {mandatory 1 positional 1} value {mandatory 1 positional 1}}
  #   description {Store VALUE in such a way that request in SEARCH for PATH will always return it until the cache is flushed}
  # }
  # cget {
  #   argspec {field {mandatory 1 positional 1}}
  #   description {
  # Pull a value from either the object's clay structure or one of its constituent classes that matches the field name.
  # The order of search us:
  # [para] 1. The as a value in local dict variable config
  # [para] 2. The as a value in local dict variable clay
  # [para] 3. As a leaf in any ancestor as a root of the clay tree
  # [para] 4. As a leaf in any ancestor as [const const] [emph field]
  # [para] 5. As a leaf in any ancestor as [const option] [emph field] [const default]
  #   }
  # }
  # delegate {
  #   argspec {stub {mandatory 0 positional 1} object {mandatory 0 positional 1}}
  #   description {
  # Introspect or control method delegation. With no arguments, the method will return a
  # key/value list of stubs and objects. With just the [arg stub] argument, the method will
  # return the object (if any) attached to the stub. With a [arg stub] and an [arg object]
  # this command will forward all calls to the method [arg stub] to the [arg object].
  # }
  # }
  # dump { argspec {} description {Return a complete dump of this object's clay data, as well as the data from all constituent classes recursively blended in.}}
  # ensemble_map {argspec {} description {Return a dictionary describing the method ensembles to be assembled for this object}}
  # eval {argspec {script {mandatory 1 positional 1}} description {Evaluated a script in the namespace of this object}}
  # evolve {argspec {} description {Trigger the [method InitializePublic] private method}}
  # exists {argspec {path {mandatory 1 positional 1 repeating 1}} description {Returns 1 if [emph path] exists in either the object's clay data. Values greater than one indicate the element exists in one of the object's constituent classes. A value of zero indicates the path could not be found.}}
  # flush {argspec {} description {Wipe any caches built by the clay implementation}}
  # forward {argspec {method {positional 1 mandatory 1} object {positional 1 mandatory 1}} description {A convenience wrapper for
  # [example {oo::objdefine [self] forward {*}$args}]
  # }
  # }
  # get {argspec {path {mandatory 1 positional 1 repeating 1}}
  #   description {Pull a chunk of data from the clay system. If the last element of [emph path] is a branch (ends in a slash /),
  #   returns a recursive merge of all data from this object and it's constituent classes of the data in that branch.
  #   If the last element is a leaf, search this object for a matching leaf, or search all  constituent classes for a matching
  #   leaf and return the first value found.
  #   If no value is found, returns an empty string.
  # }
  # }
  # leaf {argspec {path {mandatory 1 positional 1 repeating 1}} description {A modified get which is tailored to pull only leaf elements}}
  # merge {argspec {dict {mandatory 1 positional 1 repeating 1}} description {Recursively merge the dictionaries given into the object's local clay storage.}}
  # mixin {argspec {class {mandatory 1 positional 1 repeating 1}} description {
  # Perform [lb]oo::objdefine [lb]self[rb] mixin[rb] on this object, with a few additional rules:
  #   Prior to the call, for any class was previously mixed in, but not in the new result, execute the script registered to mixin/ unmap-script (if given.)
  #   For all new classes, that were not present prior to this call, after the native TclOO mixin is invoked, execute the script registered to mixin/ map-script (if given.)
  #   Fall all classes that are now present and “mixed in”, execute the script registered to mixin/ react-script (if given.)
  # }}
  # mixinmap {
  #   argspec {stub {mandatory 0 positional 1} classes {mandatory 0 positional 1}}
  #   description {With no arguments returns the map of stubs and classes mixed into the current object. When only stub is given,
  #  returns the classes mixed in on that stub. When stub and classlist given, replace the classes currently on that stub with the given
  #  classes and invoke clay mixin on the new matrix of mixed in classes.
  # }
  # }
  # provenance {argspec {path {mandatory 1 positional 1 repeating 1}} description {Return either [const self] if that path exists in the current object, or return the first class (if any) along the clay search path which contains that element.}}
  # replace {argspec {dictionary {mandatory 1 positional 1}} description {Replace the contents of the internal clay storage with the dictionary given.}}
  # search {
  #   argspec {path {mandatory 1 positional 1} valuevar {mandatory 1 positional 1} isleafvar {mandatory 1 positional 1}}
  #   description {Return true, and set valuevar to the value and isleafar to true for false if PATH was found in the cache.}
  #}
  # source {argspec {filename {mandatory 1 positional 1}} description {Source the given filename within the object's namespace}}
  # set {argspec {path {mandatory 1 positional 1 repeating 1} value {mandatory 1 postional 1}} description {Merge the conents of [const value] with the object's clay storage at [const path].}}
  ###
  method clay {submethod args} {
    my variable clay claycache clayorder config option_canonical
    if {![info exists clay]} {set clay {}}
    if {![info exists claycache]} {set claycache {}}
    if {![info exists config]} {set config {}}
    if {![info exists clayorder] || [llength $clayorder]==0} {
      set clayorder {}
      if {[dict exists $clay cascade]} {
        dict for {f v} [dict get $clay cascade] {
          if {$f eq "."} continue
          if {[info commands $v] ne {}} {
            lappend clayorder $v
          }
        }
      }
      lappend clayorder {*}[::clay::ancestors [info object class [self]] {*}[lreverse [info object mixins [self]]]]
    }
    switch $submethod {
      ancestors {
        return $clayorder
      }
      branch {
        set path [::clay::tree::storage $args]
        if {![dict exists $clay {*}$path .]} {
          dict set clay {*}$path . {}
        }
      }
      busy {
        my variable clay_busy
        if {[llength $args]} {
          set clay_busy [string is true [lindex $args 0]]
          set claycache {}
        }
        if {![info exists clay_busy]} {
          set clay_busy 0
        }
        return $clay_busy
      }
      cache {
        set path [lindex $args 0]
        set value [lindex $args 1]
        dict set claycache $path $value
      }
      cget {
        # Leaf searches return one data field at a time
        # Search in our local dict
        if {[llength $args]==1} {
          set field [string trim [lindex $args 0] -:/]
          if {[info exists option_canonical($field)]} {
            set field $option_canonical($field)
          }
          if {[dict exists $config $field]} {
            return [dict get $config $field]
          }
        }
        set path [::clay::tree::storage $args]
        if {[dict exists $clay {*}$path]} {
          return [dict get $clay {*}$path]
        }
        # Search in our local cache
        if {[dict exists $claycache {*}$path]} {
          if {[dict exists $claycache {*}$path .]} {
            return [dict remove [dict get $claycache {*}$path] .]
          } else {
            return [dict get $claycache {*}$path]
          }
        }
        # Search in the in our list of classes for an answer
        foreach class $clayorder {
          if {[$class clay exists {*}$path]} {
            set value [$class clay get {*}$path]
            dict set claycache {*}$path $value
            return $value
          }
          if {[$class clay exists const {*}$path]} {
            set value [$class clay get const {*}$path]
            dict set claycache {*}$path $value
            return $value
          }
          if {[$class clay exists option {*}$path default]} {
            set value [$class clay get option {*}$path default]
            dict set claycache {*}$path $value
            return $value
          }
        }
        return {}
      }
      delegate {
        if {![dict exists $clay .delegate <class>]} {
          dict set clay .delegate <class> [info object class [self]]
        }
        if {[llength $args]==0} {
          return [dict get $clay .delegate]
        }
        if {[llength $args]==1} {
          set stub <[string trim [lindex $args 0] <>]>
          if {![dict exists $clay .delegate $stub]} {
            return {}
          }
          return [dict get $clay .delegate $stub]
        }
        if {([llength $args] % 2)} {
          error "Usage: delegate
    OR
    delegate stub
    OR
    delegate stub OBJECT ?stub OBJECT? ..."
        }
        foreach {stub object} $args {
          set stub <[string trim $stub <>]>
          dict set clay .delegate $stub $object
          oo::objdefine [self] forward ${stub} $object
          oo::objdefine [self] export ${stub}
        }
      }
      dump {
        # Do a full dump of clay data
        set result {}
        # Search in the in our list of classes for an answer
        foreach class $clayorder {
          ::clay::tree::dictmerge result [$class clay dump]
        }
        ::clay::tree::dictmerge result $clay
        return $result
      }
      ensemble_map {
        set path [::clay::tree::storage method_ensemble]
        if {[dict exists $claycache {*}$path]} {
          return [dict get $claycache {*}$path]
        }
        set emap {}
        foreach class $clayorder {
          if {![$class clay exists {*}$path .]} continue
          dict for {ensemble einfo} [$class clay dget {*}$path] {
            if {$ensemble eq "."} continue
            dict for {method body} $einfo {
              if {$method eq "."} continue
              dict set emap $ensemble $method class: $class
              dict set emap $ensemble $method body: $body
            }
          }
        }
        if {[dict exists $clay {*}$path]} {
          dict for {ensemble einfo} [dict get $clay {*}$path] {
            dict for {method body} $einfo {
              if {$method eq "."} continue
              dict set emap $ensemble $method class: $class
              dict set emap $ensemble $method body: $body
            }
          }
        }
        dict set claycache {*}$path $emap
        return $emap
      }
      eval {
        set script [lindex $args 0]
        set buffer {}
        set thisline {}
        foreach line [split $script \n] {
          append thisline $line
          if {![info complete $thisline]} {
            append thisline \n
            continue
          }
          set thisline [string trim $thisline]
          if {[string index $thisline 0] eq "#"} continue
          if {[string length $thisline]==0} continue
          if {[lindex $thisline 0] eq "my"} {
            # Line already calls out "my", accept verbatim
            append buffer $thisline \n
          } elseif {[string range $thisline 0 2] eq "::"} {
            # Fully qualified commands accepted verbatim
            append buffer $thisline \n
          } elseif {
            append buffer "my $thisline" \n
          }
          set thisline {}
        }
        eval $buffer
      }
      evolve -
      initialize {
        my InitializePublic
      }
      exists {
        # Leaf searches return one data field at a time
        # Search in our local dict
        set path [::clay::tree::storage $args]
        if {[dict exists $clay {*}$path]} {
          return 1
        }
        # Search in our local cache
        if {[dict exists $claycache {*}$path]} {
          return 2
        }
        set count 2
        # Search in the in our list of classes for an answer
        foreach class $clayorder {
          incr count
          if {[$class clay exists {*}$path]} {
            return $count
          }
        }
        return 0
      }
      flush {
        set claycache {}
        set clayorder [::clay::ancestors [info object class [self]] {*}[lreverse [info object mixins [self]]]]
      }
      forward {
        oo::objdefine [self] forward {*}$args
      }
      dget {
        set path [::clay::tree::storage $args]
        if {[llength $path]==0} {
          # Do a full dump of clay data
          set result {}
          # Search in the in our list of classes for an answer
          foreach class $clayorder {
            ::clay::tree::dictmerge result [$class clay dump]
          }
          ::clay::tree::dictmerge result $clay
          return $result
        }
        if {[dict exists $clay {*}$path] && ![dict exists $clay {*}$path .]} {
          # Path is a leaf
          return [dict get $clay {*}$path]
        }
        # Search in our local cache
        if {[my clay search $path value isleaf]} {
          return $value
        }

        set found 0
        set branch [dict exists $clay {*}$path .]
        foreach class $clayorder {
          if {[$class clay exists {*}$path .]} {
            set found 1
            break
          }
          if {!$branch && [$class clay exists {*}$path]} {
            set result [$class clay dget {*}$path]
            my clay cache $path $result
            return $result
          }
        }
        # Path is a branch
        set result [dict getnull $clay {*}$path]
        foreach class $clayorder {
          if {![$class clay exists {*}$path .]} continue
          ::clay::tree::dictmerge result [$class clay dget {*}$path]
        }
        #if {[dict exists $clay {*}$path .]} {
        #  ::clay::tree::dictmerge result
        #}
        my clay cache $path $result
        return $result
      }
      getnull -
      get {
        set path [::clay::tree::storage $args]
        if {[llength $path]==0} {
          # Do a full dump of clay data
          set result {}
          # Search in the in our list of classes for an answer
          foreach class $clayorder {
            ::clay::tree::dictmerge result [$class clay dump]
          }
          ::clay::tree::dictmerge result $clay
          return [::clay::tree::sanitize $result]
        }
        if {[dict exists $clay {*}$path] && ![dict exists $clay {*}$path .]} {
          # Path is a leaf
          return [dict get $clay {*}$path]
        }
        # Search in our local cache
        if {[my clay search $path value isleaf]} {
          if {!$isleaf} {
            return [clay::tree::sanitize $value]
          } else {
            return $value
          }
        }
        set found 0
        set branch [dict exists $clay {*}$path .]
        foreach class $clayorder {
          if {[$class clay exists {*}$path .]} {
            set found 1
            break
          }
          if {!$branch && [$class clay exists {*}$path]} {
            set result [$class clay dget {*}$path]
            my clay cache $path $result
            return $result
          }
        }
        # Path is a branch
        set result [dict getnull $clay {*}$path]
        #foreach class [lreverse $clayorder] {
        #  if {![$class clay exists {*}$path .]} continue
        #  ::clay::tree::dictmerge result [$class clay dget {*}$path]
        #}
        foreach class $clayorder {
          if {![$class clay exists {*}$path .]} continue
          ::clay::tree::dictmerge result [$class clay dget {*}$path]
        }
        #if {[dict exists $clay {*}$path .]} {
        #  ::clay::tree::dictmerge result [dict get $clay {*}$path]
        #}
        my clay cache $path $result
        return [clay::tree::sanitize $result]
      }
      leaf {
        # Leaf searches return one data field at a time
        # Search in our local dict
        set path [::clay::tree::storage $args]
        if {[dict exists $clay {*}$path .]} {
          return [clay::tree::sanitize [dict get $clay {*}$path]]
        }
        if {[dict exists $clay {*}$path]} {
          return [dict get $clay {*}$path]
        }
        # Search in our local cache
        if {[my clay search $path value isleaf]} {
          if {!$isleaf} {
            return [clay::tree::sanitize $value]
          } else {
            return $value
          }
        }
        # Search in the in our list of classes for an answer
        foreach class $clayorder {
          if {[$class clay exists {*}$path]} {
            set value [$class clay get {*}$path]
            my clay cache $path $value
            return $value
          }
        }
      }
      merge {
        foreach arg $args {
          ::clay::tree::dictmerge clay {*}$arg
        }
      }
      mixin {
        ###
        # Mix in the class
        ###
        my clay flush
        set prior  [info object mixins [self]]
        set newmixin {}
        foreach item $args {
          lappend newmixin ::[string trimleft $item :]
        }
        set newmap $args
        foreach class $prior {
          if {$class ni $newmixin} {
            set script [$class clay search mixin/ unmap-script]
            if {[string length $script]} {
              if {[catch $script err errdat]} {
                puts stderr "[self] MIXIN ERROR POPPING $class:\n[dict get $errdat -errorinfo]"
              }
            }
          }
        }
        ::oo::objdefine [self] mixin {*}$args
        ###
        # Build a compsite map of all ensembles defined by the object's current
        # class as well as all of the classes being mixed in
        ###
        my InitializePublic
        foreach class $newmixin {
          if {$class ni $prior} {
            set script [$class clay search mixin/ map-script]
            if {[string length $script]} {
              if {[catch $script err errdat]} {
                puts stderr "[self] MIXIN ERROR PUSHING $class:\n[dict get $errdat -errorinfo]"
              }
            }
          }
        }
        foreach class $newmixin {
          set script [$class clay search mixin/ react-script]
          if {[string length $script]} {
            if {[catch $script err errdat]} {
              puts stderr "[self] MIXIN ERROR PEEKING $class:\n[dict get $errdat -errorinfo]"
            }
            break
          }
        }
      }
      mixinmap {
        if {![dict exists $clay .mixin]} {
          dict set clay .mixin {}
        }
        if {[llength $args]==0} {
          return [dict get $clay .mixin]
        } elseif {[llength $args]==1} {
          return [dict getnull $clay .mixin [lindex $args 0]]
        } else {
          dict for {slot classes} $args {
            dict set clay .mixin $slot $classes
          }
          set classlist {}
          dict for {item class} [dict get $clay .mixin] {
            if {$class ne {}} {
              lappend classlist $class
            }
          }
          my clay mixin {*}[lreverse $classlist]
        }
      }
      provenance {
        if {[dict exists $clay {*}$args]} {
          return self
        }
        foreach class $clayorder {
          if {[$class clay exists {*}$args]} {
            return $class
          }
        }
        return {}
      }
      refcount {
        my variable refcount
        if {![info exists refcount]} {
          return 0
        }
        return $refcount
      }
      refcount_incr {
        my variable refcount
        incr refcount
      }
      refcount_decr {
        my variable refcount
        incr refcount -1
        if {$refcount <= 0} {
          ::clay::object_destroy [self]
        }
      }
      replace {
        set clay [lindex $args 0]
      }
      search {
        set path [lindex $args 0]
        upvar 1 [lindex $args 1] value [lindex $args 2] isleaf
        set isleaf [expr {![dict exists $claycache $path .]}]
        if {[dict exists $claycache $path]} {
          set value [dict get $claycache $path]
          return 1
        }
        return 0
      }
      source {
        source [lindex $args 0]
      }
      set {
        #puts [list [self] clay SET {*}$args]
        ::clay::tree::dictset clay {*}$args
      }
      default {
        dict $submethod clay {*}$args
      }
    }
  }

  ###
  # Instantiate variables. Called on object creation and during clay mixin.
  ###
  method InitializePublic {} {
    my variable clayorder clay claycache config option_canonical clay_busy
    if {[info exists clay_busy] && $clay_busy} {
      # Avoid repeated calls to InitializePublic if we know that someone is
      # going to invoke it at the end of whatever process is going on
      return
    }
    set claycache {}
    set clayorder [::clay::ancestors [info object class [self]] {*}[lreverse [info object mixins [self]]]]
    if {![info exists clay]} {
      set clay {}
    }
    if {![info exists config]} {
      set config {}
    }
    dict for {var value} [my clay get variable] {
      if { $var in {. clay} } continue
      set var [string trim $var :/]
      my variable $var
      if {![info exists $var]} {
        if {$::clay::trace>2} {puts [list initialize variable $var $value]}
        set $var $value
      }
    }
    dict for {var value} [my clay get dict/] {
      if { $var in {. clay} } continue
      set var [string trim $var :/]
      my variable $var
      if {![info exists $var]} {
        set $var {}
      }
      foreach {f v} $value {
        if {$f eq "."} continue
        if {![dict exists ${var} $f]} {
          if {$::clay::trace>2} {puts [list initialize dict $var $f $v]}
          dict set ${var} $f $v
        }
      }
    }
    foreach {var value} [my clay get array/] {
      if { $var in {. clay} } continue
      set var [string trim $var :/]
      if { $var eq {clay} } continue
      my variable $var
      if {![info exists $var]} { array set $var {} }
      foreach {f v} $value {
        if {![array exists ${var}($f)]} {
          if {$f eq "."} continue
          if {$::clay::trace>2} {puts [list initialize array $var\($f\) $v]}
          set ${var}($f) $v
        }
      }
    }
    foreach {field info} [my clay get option/] {
      if { $field in {. clay} } continue
      set field [string trim $field -/:]
      foreach alias [dict getnull $info aliases] {
        set option_canonical($alias) $field
      }
      if {[dict exists $config $field]} continue
      set getcmd [dict getnull $info default-command]
      if {$getcmd ne {}} {
        set value [{*}[string map [list %field% $field %self% [namespace which my]] $getcmd]]
      } else {
        set value [dict getnull $info default]
      }
      dict set config $field $value
      set setcmd [dict getnull $info set-command]
      if {$setcmd ne {}} {
        {*}[string map [list %field% [list $field] %value% [list $value] %self% [namespace which my]] $setcmd]
      }
    }

    foreach {ensemble einfo} [my clay ensemble_map] {
      #if {[dict exists $einfo _body]} continue
      if {$ensemble eq "."} continue
      set body [::clay::ensemble_methodbody $ensemble $einfo]
      if {$::clay::trace>2} {
        set rawbody $body
        set body {puts [list [self] <object> [self method]]}
        append body \n $rawbody
      }
      oo::objdefine [self] method $ensemble {{method default} args} $body
    }
  }
}

::clay::object clay branch array
::clay::object clay branch mixin
::clay::object clay branch option
::clay::object clay branch dict clay
::clay::object clay set variable DestroyEvent 0


Added modules/clay/build/procs.tcl.



















































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
namespace eval ::clay {}
set ::clay::trace 0

if {[info commands ::cron::object_destroy] eq {}} {
  # Provide a noop if we aren't running with the cron scheduler
  namespace eval ::cron {}
  proc ::cron::object_destroy args {}
}

###
# Because many features in this package may be added as
# commands to future tcl cores, or be provided in binary
# form by packages, I need a declaritive way of saying
# [emph {Create this command if there isn't one already}].
# The [emph ninja] argument is a script to execute if the
# command is created by this mechanism.
###
proc ::clay::PROC {name arglist body {ninja {}}} {
  if {[info commands $name] ne {}} return
  proc $name $arglist $body
  eval $ninja
}
if {[info commands ::PROC] eq {}} {
  namespace eval ::clay { namespace export PROC }
  namespace eval :: { namespace import ::clay::PROC }
}

proc ::clay::_ancestors {resultvar class} {
  upvar 1 $resultvar result
  if {$class in $result} {
    return
  }
  lappend result $class
  foreach aclass [::info class superclasses $class] {
    _ancestors result $aclass
  }
}

proc ::clay::ancestors {args} {
  set result {}
  set queue  {}
  set metaclasses {}

  foreach class $args {
    set ancestors($class) {}
    _ancestors ancestors($class) $class
  }
  foreach class [lreverse $args] {
    foreach aclass $ancestors($class) {
      if {$aclass in $result} continue
      set skip 0
      foreach bclass $args {
        if {$class eq $bclass} continue
        if {$aclass in $ancestors($bclass)} {
          set skip 1
          break
        }
      }
      if {$skip} continue
      lappend result $aclass
    }
  }
  foreach class [lreverse $args] {
    foreach aclass $ancestors($class) {
      if {$aclass in $result} continue
      lappend result $aclass
    }
  }
  ###
  # Screen out classes that do not participate in clay
  # interactions
  ###
  set output {}
  foreach {item} $result {
    if {[catch {$item clay noop} err]} {
      continue
    }
    lappend output $item
  }
  return $output
}

proc ::clay::args_to_dict args {
  if {[llength $args]==1} {
    return [lindex $args 0]
  }
  return $args
}

proc ::clay::args_to_options args {
  set result {}
  foreach {var val} [args_to_dict {*}$args] {
    lappend result [string trim $var -:] $val
  }
  return $result
}

###
# topic: 4969d897a83d91a230a17f166dbcaede
###
proc ::clay::dynamic_arguments {ensemble method arglist args} {
  set idx 0
  set len [llength $args]
  if {$len > [llength $arglist]} {
    ###
    # Catch if the user supplies too many arguments
    ###
    set dargs 0
    if {[lindex $arglist end] ni {args dictargs}} {
      return -code error -level 2 "Usage: $ensemble $method [string trim [dynamic_wrongargs_message $arglist]]"
    }
  }
  foreach argdef $arglist {
    if {$argdef eq "args"} {
      ###
      # Perform args processing in the style of tcl
      ###
      uplevel 1 [list set args [lrange $args $idx end]]
      break
    }
    if {$argdef eq "dictargs"} {
      ###
      # Perform args processing in the style of tcl
      ###
      uplevel 1 [list set args [lrange $args $idx end]]
      ###
      # Perform args processing in the style of clay
      ###
      set dictargs [::clay::args_to_options {*}[lrange $args $idx end]]
      uplevel 1 [list set dictargs $dictargs]
      break
    }
    if {$idx > $len} {
      ###
      # Catch if the user supplies too few arguments
      ###
      if {[llength $argdef]==1} {
        return -code error -level 2 "Usage: $ensemble $method [string trim [dynamic_wrongargs_message $arglist]]"
      } else {
        uplevel 1 [list set [lindex $argdef 0] [lindex $argdef 1]]
      }
    } else {
      uplevel 1 [list set [lindex $argdef 0] [lindex $args $idx]]
    }
    incr idx
  }
}

###
# topic: 53ab28ac5c6ee601fe1fe07b073be88e
###
proc ::clay::dynamic_wrongargs_message {arglist} {
  set result ""
  set dargs 0
  foreach argdef $arglist {
    if {$argdef in {args dictargs}} {
      set dargs 1
      break
    }
    if {[llength $argdef]==1} {
      append result " $argdef"
    } else {
      append result " ?[lindex $argdef 0]?"
    }
  }
  if { $dargs } {
    append result " ?option value?..."
  }
  return $result
}

proc ::clay::is_dict { d } {
  # is it a dict, or can it be treated like one?
  if {[catch {::dict size $d} err]} {
    #::set ::errorInfo {}
    return 0
  }
  return 1
}

proc ::clay::is_null value {
  return [expr {$value in {{} NULL}}]
}

proc ::clay::leaf args {
  set marker [string index [lindex $args end] end]
  set result [path {*}${args}]
  if {$marker eq "/"} {
    return $result
  }
  return [list {*}[lrange $result 0 end-1] [string trim [string trim [lindex $result end]] /]]
}

proc ::clay::K {a b} {set a}
if {[info commands ::K] eq {}} {
  namespace eval ::clay { namespace export K }
  namespace eval :: { namespace import ::clay::K }
}

###
# Perform a noop. Useful in prototyping for commenting out blocks
# of code without actually having to comment them out. It also makes
# a handy default for method delegation if a delegate has not been
# assigned yet.
proc ::clay::noop args {}
if {[info commands ::noop] eq {}} {
  namespace eval ::clay { namespace export noop }
  namespace eval :: { namespace import ::clay::noop }
}


###
# Process the queue of objects to be destroyed
###
proc ::clay::cleanup {} {
  set count 0
  if {![info exists ::clay::idle_destroy]} return
  set objlist $::clay::idle_destroy
  set ::clay::idle_destroy {}
  foreach obj $objlist {
    if {![catch {$obj destroy}]} {
      incr count
    }
  }
  return $count
}

proc ::clay::object_create {objname {class {}}} {
  #if {$::clay::trace>0} {
  #  puts [list $objname CREATE]
  #}
}

proc ::clay::object_rename {object newname} {
  if {$::clay::trace>0} {
    puts [list $object RENAME -> $newname]
  }
}

###
# Mark an objects for destruction on the next cleanup
###
proc ::clay::object_destroy args {
  if {![info exists ::clay::idle_destroy]} {
    set ::clay::idle_destroy {}
  }
  foreach objname $args {
    if {$::clay::trace>0} {
      puts [list $objname DESTROY]
    }
    ::cron::object_destroy $objname
    if {$objname in $::clay::idle_destroy} continue
    lappend ::clay::idle_destroy $objname
  }
}


proc ::clay::path args {
  set result {}
  foreach item $args {
    set item [string trim $item :./]
    foreach subitem [split $item /] {
      lappend result [string trim ${subitem}]/
    }
  }
  return $result
}

###
# Append a line of text to a variable. Optionally apply a string mapping.
# arglist:
#   map {mandatory 0 positional 1}
#   text {mandatory 1 positional 1}
###
proc ::clay::putb {buffername args} {
  upvar 1 $buffername buffer
  switch [llength $args] {
    1 {
      append buffer [lindex $args 0] \n
    }
    2 {
      append buffer [string map {*}$args] \n
    }
    default {
      error "usage: putb buffername ?map? string"
    }
  }
}
if {[info command ::putb] eq {}} {
  namespace eval ::clay { namespace export putb }
  namespace eval :: { namespace import ::clay::putb }
}

proc ::clay::script_path {} {
  set path [file dirname [file join [pwd] [info script]]]
  return $path
}

proc ::clay::NSNormalize qualname {
  if {![string match ::* $qualname]} {
    set qualname ::clay::classes::$qualname
  }
  regsub -all {::+} $qualname "::"
}

proc ::clay::uuid_generate args {
  return [uuid generate]
}

namespace eval ::clay {
  variable option_class {}
  variable core_classes {::oo::class ::oo::object}
}

Added modules/clay/build/singleton.tcl.

















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
###
# An object which is intended to be it's own class.
# arglist:
#   name    {mandatory 1 positional 1 description {the fully qualified name of the object}}
#   script  {mandatory 1 positional 1 description {
# A script that will be executed in the object's namespace.
# The command [bold clay] is provided, and will allow the script to exercise the object's own
# clay method. The command [bold method] is provided, and will define or modify a per-instance
# version of the object's method. The command [bold Ensemble] is provided, and will define or
# modify an ensemble method (though customized for this object)
# }}
###
proc ::clay::singleton {name script} {
  if {[info commands $name] eq {}} {
    ::clay::object create $name
  }
  oo::objdefine $name {
method SingletonProcs {} {
proc class class {
  uplevel 1 "oo::objdefine \[self\] class $class"
  my clay delegate class $class
}
proc clay args {
  my clay {*}$args
}
proc Ensemble {rawmethod args} {
  if {[llength $args]==2} {
    lassign $args argspec body
    set argstyle tcl
  } elseif {[llength $args]==3} {
    lassign $args argstyle argspec body
  } else {
    error "Usage: Ensemble name ?argstyle? argspec body"
  }
  set class [uplevel 1 self]
  #if {$::clay::trace>2} {
  #  puts [list $class Ensemble $rawmethod $argspec $body]
  #}
  set mlist [split $rawmethod "::"]
  set ensemble [string trim [lindex $mlist 0] :/]
  set method   [string trim [lindex $mlist 2] :/]
  if {[string index $method 0] eq "_"} {
    $class clay set method_ensemble $ensemble $method $body
    return
  }
  set realmethod  [string totitle $ensemble]_${method}
  set realbody {}
  if {$argstyle eq "dictargs"} {
    append realbody "::dictargs::parse \{$argspec\} \$args" \n
  }
  if {[$class clay exists method_ensemble $ensemble _preamble]} {
    append realbody [$class clay get method_ensemble $ensemble _preamble] \n
  }
  append realbody $body
  if {$method eq "default"} {
    $class clay set method_ensemble $ensemble $method: "tailcall my $realmethod \$method {*}\$args"
    if {$argstyle eq "dictargs"} {
      oo::objdefine $class method $realmethod [list method [list args $argspec]] $realbody
    } else {
      oo::objdefine $class method $realmethod [list method {*}$argspec] $realbody
    }
  } else {
    $class clay set method_ensemble $ensemble $method: "tailcall my $realmethod {*}\$args"
    if {$argstyle eq "dictargs"} {
      oo::objdefine $class method $realmethod [list [list args $argspec]] $realbody
    } else {
      oo::objdefine $class method $realmethod $argspec $realbody
    }
  }
  if {$::clay::trace>2} {
    puts [list $class clay set method_ensemble/ $ensemble [string trim $method :/]  ...]
  }
}
proc method args {
  uplevel 1 "oo::objdefine \[self\] method {*}$args"
}
}
method script script {
  my clay busy 1
  my SingletonProcs
  eval $script
  my clay busy 0
  my InitializePublic
}
}
  $name script $script
  return $name
}

Added modules/clay/build/test.tcl.







































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
###
# Test script build functions
###

set result {}
putb result {# clay.test - Copyright (c) 2018 Sean Woods
# -------------------------------------------------------------------------

set MODDIR [file dirname [file dirname [file join [pwd] [info script]]]]
if {[file exists [file join $MODDIR devtools testutilities.tcl]]} {
  # Running inside tcllib
  set TCLLIBMOD $MODDIR
} else {
  set TCLLIBMOD [file join $MODDIR .. .. tcllib modules]
}
source [file join $TCLLIBMOD devtools testutilities.tcl]

testsNeedTcl     8.6
testsNeedTcltest 2
testsNeed        TclOO 1

support {}
testing {
    useLocal clay.tcl clay
}
}

putb result {
set ::clay::trace 0
}

###
# UUID test
###
putb result {

# -------------------------------------------------------------------------
# Handle multiple implementation testing
#

array set preserve [array get ::clay::uuid::accel]

proc implementations {} {
    variable ::clay::uuid::accel
    foreach {a v} [array get accel] {if {$v} {lappend r $a}}
    lappend r tcl; set r
}

proc select_implementation {impl} {
    variable ::clay::uuid::accel
    foreach e [array names accel] { set accel($e) 0 }
    if {[string compare "tcl" $impl] != 0} {
        set accel($impl) 1
    }
}

proc reset_implementation {} {
    variable ::clay::uuid::accel
    array set accel [array get ::preserve]
}

# -------------------------------------------------------------------------
# Setup any constraints
#

# -------------------------------------------------------------------------
# Now the package specific tests....
# -------------------------------------------------------------------------

# -------------------------------------------------------------------------

foreach impl [implementations] {
    select_implementation $impl

    test uuid-1.0-$impl "uuid requires args" {
        list [catch {clay::uuid} msg]
    } {1}

    test uuid-1.1-$impl "uuid generate should create a 36 char string uuid" {
        list [catch {string length [clay::uuid generate]} msg] $msg
    } {0 36}

    test uuid-1.2-$impl "uuid comparison of uuid with self should be true" {
        list [catch {
            set a [clay::uuid generate]
            clay::uuid equal $a $a
        } msg] $msg
    } {0 1}

    test uuid-1.3-$impl "uuid comparison of two different\
        uuids should be false" {
        list [catch {
            set a [clay::uuid generate]
            set b [clay::uuid generate]
            clay::uuid equal $a $b
        } msg] $msg
    } {0 0}

    reset_implementation
}
}


putb result {
# Modification History:
###
# Modification 2018-10-30
# Fixed an error in our ancestry mapping and developed tests to
# ensure we are actually following in the order TclOO follows methods
###
# Modification 2018-10-21
# The clay metaclass no longer exports the clay method
# to oo::class and oo::object, and clay::ancestors no
# longer returns any class that lacks the clay method
###
# Modification 2018-10-10
# clay::ancestors now rigged to descend into all classes depth-first
# and then place metaclasses at the end of the search
###
# -------------------------------------------------------------------------

# -------------------------------------------------------------------------
# Test Helpers
###
proc dict_compare {a b} {
  set result {}
  set A {}
  dict for {f v} $a {
    set f [string trim $f :/]
    if {$f eq {.}} continue
    dict set A $f $v
  }
  set B {}
  dict for {f v} $b {
    set f [string trim $f :/]
    if {$f eq {.}} continue
    dict set B $f $v
  }
  dict for {f v} $A {
    if {[dict exists $B $f]} {
      if {[dict get $B $f] ne $v} {
        lappend result [list B $f [dict get $B $f] [list != $v]]
      }
    } else {
      lappend result [list B $f $v missing]
    }
  }
  dict for {f v} $B {
    if {![dict exists $A $f]} {
      lappend result [list A $f $v missing]
    }
  }
  return $result
}

test dict-compare-001 {Test our testing method} {
  dict_compare {} {}
} {}

test dict-compare-002 {Test our testing method} {
  dict_compare {a 1} {}
} {{B a 1 missing}}

test dict-compare-003 {Test our testing method} {
  dict_compare {a 1 b 2} {a 1 b 2}
} {}

test dict-compare-003.a {Test our testing method} {
  dict_compare {a 1 b 2} {b 2 a 1 }
} {}

test dict-compare-003.b {Test our testing method} {
  dict_compare {b 2 a 1} {a 1 b 2}
} {}


test dict-compare-004 {Test our testing method} {
  dict_compare {a: 1 b: 2} {a 1 b 2}
} {}

test dict-compare-005 {Test our testing method} {
  dict_compare {a 1 b 3} {a 1 b 2}
} {{B b 2 {!= 3}}}
}


###
# Tests for clay::tree
###

putb result {
###
# Test canonical mapping
###
}
set test 0
  foreach {pattern canonical storage} {
    {foo bar baz}       {foo/ bar/ baz}         {foo bar baz}
    {foo bar baz/}      {foo/ bar/ baz/}        {foo bar baz}
    {foo bar .}         {foo/ bar}              {foo bar .}
    {foo/ bar/ .}       {foo/ bar}              {foo bar .}
    {foo . bar . baz .} {foo/ bar/ baz}         {foo . bar . baz .}
    {foo bar baz bat:}  {foo/ bar/ baz/ bat:}   {foo bar baz bat:}
    {foo:}              {foo:}                  {foo:}
    {foo/bar/baz/bat:}  {foo/ bar/ baz/ bat:}   {foo bar baz bat:}
} {
    dict set map %pattern% $pattern
    dict set map %canonical% $canonical
    dict set map %storage% $storage
    incr test

    dict set map %test% [format "test-storage-%04d" $test]
    putb result $map {
test {%test%} {Test ::clay::tree::storage with %pattern%} {
  clay::tree::storage {%pattern%}
} {%storage%}
}
}

putb result {
dict set r foo/ bar/ baz 1
dict set s foo/ bar/ baz 0
set t [clay::tree::merge $r $s]

test rmerge-0001 {Test that the root is marked as a branch} {
  dict get $t foo bar baz
} 0

set r [dict create]
clay::tree::dictmerge r {
  foo/ {
    bar/ {
      baz 1
      bing: 2
      bang { bim 3 boom 4 }
      womp: {a 1 b 2}
    }
  }
}

test dictmerge-0001 {Test that the root is marked as a branch} {
  dict exists $r .
} 1
test dictmerge-0002 {Test that branch foo is marked correctly} {
  dict exists $r foo .
} 1
test dictmerge-0003 {Test that branch bar is marked correctly} {
  dict exists $r foo bar .
} 1
test dictmerge-0004 {Test that leaf foo/bar/bang is not marked as branch despite being a dict} {
  dict exists $r foo bar bang .
} 0
test dictmerge-0004 {Test that leaf foo/bar/bang/bim exists} {
  dict exists $r foo bar bang bim
} 1
test dictmerge-0005 {Test that leaf foo/bar/bang/boom exists} {
  dict exists $r foo bar bang boom
} 1

###
# Replace bang with bang/
###
clay::tree::dictmerge r {
  foo/ {
    bar/ {
      bang/ {
        whoop 1
      }
    }
  }
}

test dictmerge-0006 {Test that leaf foo/bar/bang/bim ceases to exist} {
  dict exists $r foo bar bang bim
} 0
test dictmerge-0007 {Test that leaf foo/bar/bang/boom exists} {
  dict exists $r foo bar bang boom
} 0

test dictmerge-0008 {Test that leaf foo/bar/bang is now a branch} {
  dict exists $r foo bar bang .
} 1

test branch-0001 {Test that foo/ is a branch} {
  clay::tree::is_branch $r foo/
} 1
test branch-0002 {Test that foo is a branch} {
  clay::tree::is_branch $r foo
} 1
test branch-0003 {Test that foo/bar/ is a branch} {
  clay::tree::is_branch $r {foo/ bar/}
} 1
test branch-0004 {Test that foo bar is not branch} {
  clay::tree::is_branch $r {foo bar}
} 1
test branch-0004 {Test that foo/ bar is not branch} {
  clay::tree::is_branch $r {foo/ bar}
} 0
}

set test 0
foreach {path isbranch} {
  foo 1
  {foo bar} 1
  {foo bar baz} 0
  {foo bar bing} 0
  {foo bar bang} 1
  {foo bar bang whoop} 0
} {
  set mpath [lrange $path 0 end-1]
  set item  [lindex $path end]
  set tests [list {} {} $isbranch {} : 0 {} / 1 . {} 0]
  dict set map %mpath% $mpath
  dict set map %item% $item
  foreach {head tail isbranch} $tests {
    dict set map %head% $head
    dict set map %tail% $tail
    dict set map %isbranch% $isbranch
    dict set map %test% [format "test-branch-%04d" [incr test]]
    putb result $map {
test {%test%} {Test that %mpath% %head%%item%%tail% is_branch = %isbranch%} {
  clay::tree::is_branch $r {%mpath% %head%%item%%tail%}
} %isbranch%
}
  }
}

putb result {
# -------------------------------------------------------------------------
# dictmerge Testing - oometa
unset -nocomplain foo
clay::tree::dictmerge foo {
  option/ {
    color/ {
      label Color
      default green
    }
  }
}
clay::tree::dictmerge foo {
  option/ {
    color/ {
      default purple
    }
  }
}

test oometa-0001 {Invoking dictmerge with empty args on a non existent variable create an empty variable} {
  dict get $foo option color default
} purple
test oometa-0002 {Invoking dictmerge with empty args on a non existent variable create an empty variable} {
  dict get $foo option color label
} Color

unset -nocomplain foo
set foo {. {}}
::clay::tree::dictmerge foo {. {} color {. {} default green label Color}}
::clay::tree::dictmerge foo {. {} color {. {} default purple}}
test oometa-0003 {Recursive merge problem from oometa/clay find} {
  dict get $foo color default
} purple
test oometa-0004 {Recursive merge problem from oometa/clay find} {
  dict get $foo color label
} Color

unset -nocomplain foo
set foo {. {}}
::clay::tree::dictmerge foo {. {} color {. {} default purple}}
::clay::tree::dictmerge foo {. {} color {. {} default green label Color}}
test oometa-0005 {Recursive merge problem from oometa/clay find} {
  dict get $foo color default
} green
test oometa-0006 {Recursive merge problem from oometa/clay find} {
  dict get $foo color label
} Color

test oometa-0008 {Un-Sanitized output} {
  set foo
} {. {} color {. {} default green label Color}}

test oometa-0009 {Sanitize} {
  clay::tree::sanitize $foo
} {color {default green label Color}}
}


putb result {
# -------------------------------------------------------------------------
# dictmerge Testing - clay
unset -nocomplain foo
test clay-0001 {Invoking dictmerge with empty args on a non existent variable create an empty variable} {
  ::clay::tree::dictmerge foo
  set foo
} {. {}}

unset -nocomplain foo
::clay::tree::dictset foo bar/ baz/ bell bang

test clay-0002 {For new entries dictmerge is essentially a set} {
  dict get $foo bar baz bell
} {bang}
::clay::tree::dictset foo bar/ baz/ boom/ bang
test clay-0003 {For entries that do exist a zipper merge is performed} {
  dict get $foo bar baz bell
} {bang}
test clay-0004 {For entries that do exist a zipper merge is performed} {
  dict get $foo bar baz boom
} {bang}

::clay::tree::dictset foo bar/ baz/ bop {color green flavor strawberry}

test clay-0005 {Leaves are replaced even if they look like a dict} {
  dict get $foo bar baz bop
} {color green flavor strawberry}

::clay::tree::dictset foo bar/ baz/ bop {color yellow}
test clay-0006 {Leaves are replaced even if they look like a dict} {
  dict get $foo bar baz bop
} {color yellow}

::clay::tree::dictset foo bar/ baz/ bang/ {color green flavor strawberry}
test clay-0007a {Branches are merged} {
  dict get $foo bar baz bang
} {. {} color green flavor strawberry}

::clay::tree::dictset foo bar/ baz/ bang/ color yellow
test clay-0007b {Branches are merged}  {
  dict get $foo bar baz bang
} {. {} color yellow flavor strawberry}

::clay::tree::dictset foo bar/ baz/ bang/ {color blue}
test clay-0007c {Branches are merged}  {
  dict get $foo bar baz bang
} {. {} color blue flavor strawberry}

::clay::tree::dictset foo bar/ baz/ bang/ shape: {Sort of round}
test clay-0007d {Branches are merged} {
  dict get $foo bar baz bang
} {. {} color blue flavor strawberry shape: {Sort of round}}

::clay::tree::dictset foo bar/ baz/ bang/ color yellow
test clay-0007e {Branches are merged}  {
  dict get $foo bar baz bang
} {. {} color yellow flavor strawberry shape: {Sort of round}}

::clay::tree::dictset foo bar/ baz/ bang/ {color blue}
test clay-0007f {Branches are merged}  {
  dict get $foo bar baz bang
} {. {} color blue flavor strawberry shape: {Sort of round}}

::clay::tree::dictset foo dict my_var 10
::clay::tree::dictset foo dict my_other_var 9

test clay-0007g {Branches are merged}  {
  dict get $foo dict
} {. {} my_var 10 my_other_var 9}

::clay::tree::dictset foo dict/ my_other_other_var 8
test clay-0007h {Branches are merged}  {
  dict get $foo dict
} {. {} my_var 10 my_other_var 9 my_other_other_var 8}


::clay::tree::dictmerge foo {option/ {color {type color} flavor {sense taste}}}
::clay::tree::dictmerge foo {option/ {format {default ascii}}}

test clay-0008 {Whole dicts are merged}  {
  dict get $foo option color
} {type color}
test clay-0009 {Whole dicts are merged}  {
  dict get $foo option flavor
} {sense taste}
test clay-0010 {Whole dicts are merged}  {
  dict get $foo option format
} {default ascii}

###
# Tests for the httpd module
###
test clay-0010 {Test that leaves are merged properly}
set bar {}
::clay::tree::dictmerge bar {
   proxy/ {port 10101 host myhost.localhost}
}
::clay::tree::dictmerge bar {
   mimetxt {Host: localhost
Content_Type: text/plain
Content-Length: 15
}
   http {HTTP_HOST {} CONTENT_LENGTH 15 HOST localhost CONTENT_TYPE text/plain UUID 3a7b4cdc-28d7-49b7-b18d-9d7d18382b9e REMOTE_ADDR 127.0.0.1 REMOTE_HOST 127.0.0.1 REQUEST_METHOD POST REQUEST_URI /echo REQUEST_PATH echo REQUEST_VERSION 1.0 DOCUMENT_ROOT {} QUERY_STRING {} REQUEST_RAW {POST /echo HTTP/1.0} SERVER_PORT 10001 SERVER_NAME 127.0.0.1 SERVER_PROTOCOL HTTP/1.1 SERVER_SOFTWARE {TclHttpd 4.2.0} LOCALHOST 0} UUID 3a7b4cdc-28d7-49b7-b18d-9d7d18382b9e uriinfo {fragment {} port {} path echo scheme http host {} query {} pbare 0 pwd {} user {}}
   mixin {reply ::test::content.echo}
   prefix /echo
   proxy_port 10010
   proxy/ {host localhost}
}

test clay-0011 {Whole dicts are merged}  {
  dict get $bar proxy_port
} {10010}

test clay-0012 {Whole dicts are merged}  {
  dict get $bar http CONTENT_LENGTH
} 15
test clay-0013 {Whole dicts are merged}  {
  dict get $bar proxy host
} localhost
test clay-0014 {Whole dicts are merged}  {
  dict get $bar proxy port
} 10101
}

putb result {
###
# Dialect Testing
###
::clay::dialect::create ::alpha

proc ::alpha::define::is_alpha {} {
  dict set ::testinfo([current_class]) is_alpha 1
}

::alpha::define ::alpha::object {
  is_alpha
}

::clay::dialect::create ::bravo ::alpha

proc ::bravo::define::is_bravo {} {
  dict set ::testinfo([current_class]) is_bravo 1
}

::bravo::define ::bravo::object {
  is_bravo
}

::clay::dialect::create ::charlie ::bravo

proc ::charlie::define::is_charlie {} {
  dict set ::testinfo([current_class]) is_charlie 1
}

::charlie::define ::charlie::object {
  is_charlie
}

::clay::dialect::create ::delta ::charlie

proc ::delta::define::is_delta {} {
  dict set ::testinfo([current_class]) is_delta 1
}

::delta::define ::delta::object {
  is_delta
}

::delta::class create adam {
  is_alpha
  is_bravo
  is_charlie
  is_delta
}

test oodialect-keyword-001 {Testing keyword application} {
  set ::testinfo(::adam)
} {is_alpha 1 is_bravo 1 is_charlie 1 is_delta 1}

test oodialect-keyword-002 {Testing keyword application} {
  set ::testinfo(::alpha::object)
} {is_alpha 1}

test oodialect-keyword-003 {Testing keyword application} {
  set ::testinfo(::bravo::object)
} {is_bravo 1}

test oodialect-keyword-004 {Testing keyword application} {
  set ::testinfo(::charlie::object)
} {is_charlie 1}

test oodialect-keyword-005 {Testing keyword application} {
  set ::testinfo(::delta::object)
} {is_delta 1}

###
# Declare an object from a namespace
###
namespace eval ::test1 {
  ::alpha::class create a {
    aliases A
    is_alpha
  }
  ::alpha::define b {
    aliases B BEE
    is_alpha
  }
  ::alpha::class create ::c {
    aliases C
    is_alpha
  }
  ::alpha::define ::d {
    aliases D
    is_alpha
  }
}

test oodialect-naming-001 {Testing keyword application} {
  set ::testinfo(::test1::a)
} {is_alpha 1}

test oodialect-naming-002 {Testing keyword application} {
  set ::testinfo(::test1::b)
} {is_alpha 1}

test oodialect-naming-003 {Testing keyword application} {
  set ::testinfo(::c)
} {is_alpha 1}

test oodialect-naming-004 {Testing keyword application} {
  set ::testinfo(::d)
} {is_alpha 1}

test oodialect-aliasing-001 {Testing keyword application} {
namespace eval ::test1 {
    ::alpha::define e {
       superclass A
    }
}
} ::test1::e

test oodialect-aliasing-002 {Testing keyword application} {
namespace eval ::test1 {
    ::bravo::define f {
       superclass A
    }
}
} ::test1::f


test oodialect-aliasing-003 {Testing aliase method on class} {
  ::test1::a aliases
} {::test1::A}

###
# Test modified 2018-10-21
###
test oodialect-ancestry-003 {Testing heritage} {
  ::clay::ancestors ::test1::f
} {}

###
# Test modified 2018-10-21
###
test oodialect-ancestry-004 {Testing heritage} {
  ::clay::ancestors ::alpha::object
} {}

###
# Test modified 2018-10-21
###
test oodialect-ancestry-005 {Testing heritage} {
  ::clay::ancestors ::delta::object
} {}

}

putb result {
# -------------------------------------------------------------------------
# clay submodule testing
# -------------------------------------------------------------------------

}
putb result {
# Test canonical path building
set path {const/ foo/ bar/ baz/}
}
set testnum 0
foreach {pattern} {
  {const foo bar baz}
  {const/ foo/ bar/ baz}
  {const/foo/bar/baz}
  {const/foo bar/baz}
  {const/foo/bar baz}
  {const foo/bar/baz}
  {const foo bar/baz}
  {const/foo bar baz}
} {
  putb result [list %pattern% $pattern %testnum% [format %04d [incr testnum]]] {
test oo-clay-path-%testnum% "Test path: %pattern%" {
  ::clay::path %pattern%
} $path
}
}
putb result {set path {const/ foo/ bar/ baz/ bing}}
set testnum 0
foreach {pattern} {
  {const foo bar baz bing}
  {const/ foo/ bar/ baz/ bing}
  {const/foo/bar/baz/bing}
  {const/foo bar/baz/bing:}
  {const/foo/bar baz bing}
  {const/foo/bar baz bing:}
  {const foo/bar/baz/bing}
  {const foo bar/baz/bing}
  {const/foo bar baz bing}
} {
  putb result [list %pattern% $pattern %testnum% [format %04d [incr testnum]]] {
test oo-clay-leaf-%testnum% "Test leaf: %pattern%" {
  ::clay::leaf %pattern%
} $path
}
}

putb result {namespace eval ::foo {}}

set class-a ::foo::classa
set commands-a {
  clay set const color  blue
  clay set const/flavor strawberry
  clay set {const/ sound} zoink
  clay set info/ {
    animal no
    building no
    subelement {pedantic yes}
  }

  # Provide a method that returns a constant so we can compare clay's inheritance to
  # TclOO
  method color {} {
    return blue
  }
  method flavor {} {
    return strawberry
  }
  method sound {} {
    return zoink
  }
}
set claydict-a {
  const/ {color blue flavor strawberry sound zoink}
  info/  {
    animal no
    building no
    subelement {pedantic yes}
  }
}

putb result [list %class% ${class-a} %commands% ${commands-a}] {
clay::define %class% {
%commands%
}
}

set testnum 0
foreach {top children} ${claydict-a} {
  foreach {child value} $children {
    set map {}
    dict set map %class% ${class-a}
    dict set map %top% $top
    dict set map %child% $child
    dict set map %value% $value
    dict set map %testnum% [format %04d [incr testnum]]
    putb result $map {
test oo-class-clay-method-%testnum% "Test %class% %top% %child% exists" {
  %class% clay exists %top% %child%
} 1
}
    dict set map %test% [format %04d [incr testnum]]
    putb result $map {
test oo-class-clay-method-%testnum% "Test %class% %top% %child% value" {
  %class% clay get %top% %child%
} {%value%}
}
  }
}


set class-b ::foo::classb
set claydict-b {
  const/ {color black flavor vanilla feeling dread}
  info/  {subelement {spoon yes}}
}
set commands-b {}
foreach {top children} ${claydict-b} {
  foreach {child value} $children {
    putb commands-b "  [list clay set $top $child $value]"
    putb commands-b "  [list method $child {} [list return $value]]"
  }
}
putb result [list %class% ${class-b} %commands% ${commands-b}] {
clay::define %class% {
%commands%
}
}

foreach {top children} ${claydict-b} {
  foreach {child value} $children {
    set map {}
    dict set map %class% ${class-b}
    dict set map %top% $top
    dict set map %child% $child
    dict set map %value% $value
    dict set map %testnum% [format %04d [incr testnum]]
    putb result $map {
test oo-class-clay-method-%testnum% "Test %class% %top% %child% exists" {
  %class% clay exists %top% %child%
} 1
}
    dict set map %test% [format %04d [incr testnum]]
    putb result $map {
test oo-class-clay-method-%testnum% "Test %class% %top% %child% value" {
  %class% clay get %top% %child%
} {%value%}
}
  }
}

set commands-c {superclass ::foo::classb ::foo::classa}
set class-c ::foo::class.ab
putb result [list %class% ${class-c} %commands% ${commands-c}] {
clay::define %class% {
%commands%
}
}
set commands-d {superclass ::foo::classa ::foo::classb}
set class-d ::foo::class.ba
putb result [list %class% ${class-d} %commands% ${commands-d}] {
clay::define %class% {
%commands%
}
}

###
# Tests for objects
###

putb result {# -------------------------------------------------------------------------
# Singleton
::clay::define ::test::singletonbehavior {
  method bar {} {
    return CLASS
  }
  method booze {} {
    return CLASS
  }
  Ensemble foo::bang {} {
    return CLASS
  }
  Ensemble foo::both {} {
    return CLASS
  }
  Ensemble foo::mixin {} {
    return CLASS
  }
  Ensemble foo::sloppy {} {
    return CLASS
  }
}
::clay::define ::test::flavor.strawberry {
  clay define property flavor strawbery
  method bar {} {
    return STRAWBERRY
  }
  Ensemble foo::bing {} {
    return STRAWBERRY
  }
  Ensemble foo::both {} {
    return STRAWBERRY
  }
  Ensemble foo::mixin {} {
    return STRAWBERRY
  }
  Ensemble foo::sloppy {} {
    return STRAWBERRY
  }
}
::clay::singleton ::TEST {
  class ::test::singletonbehavior
  clay mixinmap flavor ::test::flavor.strawberry
  clay set property color green
  method bar {} {
    return OBJECT
  }
  method booze {} {
    return OBJECT
  }
  method baz {} {
    return OBJECT
  }
  Ensemble foo::bar {} {
    return OBJECT
  }
  Ensemble foo::both {} {
    return OBJECT
  }
}

test oo-object-singleton-001 {Test singleton superclass keyword} {
  ::TEST clay delegate class
} {::test::singletonbehavior}

test oo-object-singleton-002 {Test singleton ensemble 1} {
  ::TEST foo <list>
} {bang bar bing both mixin sloppy}

test oo-object-singleton-003 {Test singleton ensemble from script} {
  ::TEST foo bar
} {OBJECT}
test oo-object-singleton-004 {Test singleton ensemble from mixin} {
  ::TEST foo bing
} {STRAWBERRY}
test oo-object-singleton-005 {Test singleton ensemble from class} {
  ::TEST foo bang
} {CLASS}
# Test note: the behavior from TclOO is unexpected
# Intuitively, a local method should override a mixin
# but this is not the case
test oo-object-singleton-006 {Test singleton ensemble from conflict, should resolve to object} {
  ::TEST foo both
} {STRAWBERRY}
test oo-object-singleton-007 {Test singleton ensemble from conflict, should resolve to mixin} {
  ::TEST foo sloppy
} {STRAWBERRY}
###
# Test note:
# This should work but does not
###
#test oo-object-singleton-009 {Test property from mixin/class} {
#  ::TEST clay get property flavor
#} {strawberry}
test oo-object-singleton-008 {Test property from script} {
  ::TEST clay get property color
} {green}


# Test note: the behavior from TclOO is unexpected
# Intuitively, a local method should override a mixin
# but this is not the case
test oo-object-singleton-010 {Test method declared in script} {
  ::TEST bar
} {STRAWBERRY}

test oo-object-singleton-011 {Test method declared in script} {
  ::TEST booze
} {OBJECT}
TEST destroy

# OBJECT of ::foo::classa
set OBJECTA [::foo::classa new]

###
# Test object degation
###
proc ::foo::fakeobject {a b} {
  return [expr {$a + $b}]
}

::clay::object create TEST
TEST clay delegate funct ::foo::fakeobject
test oo-object-delegate-001 {Test object delegation} {
  ::TEST clay delegate
} {<class> ::clay::object <funct> ::foo::fakeobject}

test oo-object-delegate-002 {Test object delegation} {
  ::TEST clay delegate funct
} {::foo::fakeobject}

test oo-object-delegate-002a {Test object delegation} {
  ::TEST clay delegate <funct>
} {::foo::fakeobject}

test oo-object-delegate-003 {Test object delegation} {
  ::TEST <funct> 1 1
} {2}
test oo-object-delegate-004 {Test object delegation} {
  ::TEST <funct> 10 -7
} {3}

# Replace the function out from under
proc ::foo::fakeobject {a b} {
  return [expr {$a * $b}]
}
test oo-object-delegate-005 {Test object delegation} {
  ::TEST <funct> 10 -7
} {-70}

# Object with ::foo::classa mixed in
set MIXINA  [::oo::object new]
oo::objdefine $MIXINA mixin ::foo::classa
}
set matrix ${claydict-a}
set testnum 0
foreach {top children} $matrix {
  foreach {child value} $children {
    set map {}
    dict set map %object1% OBJECTA
    dict set map %object2% MIXINA

    dict set map %top% $top
    dict set map %child% $child
    dict set map %value% $value
    dict set map %testnum% [format %04d [incr testnum]]
    putb result $map {
test oo-object-clay-method-native-%testnum% {Test native object gets the property %top%/%child%} {
  $%object1% clay get %top% %child%
} {%value%}
test oo-object-clay-method-mixin-%testnum% {Test mixin object gets the property %top%/%child%} {
  $%object2% clay get %top% %child%
} {%value%}
}
    if {$top eq "const/"} {
      putb result $map {
test oo-object-clay-method-native-methodcheck-%testnum% {Test that %top%/%child% would mimic method interheritance for a native class} {
  $%object1% %child%
} {%value%}
test oo-object-clay-method-mixin-%testnum% {Test that %top%/%child% would mimic method interheritance for a mixed in class} {
  $%object2% %child%
} {%value%}
    }
    }
  }
}

putb result {# -------------------------------------------------------------------------
# OBJECT of ::foo::classb
set OBJECTB [::foo::classb new]
# Object with ::foo::classb mixed in
set MIXINB  [::oo::object new]
oo::objdefine $MIXINB mixin ::foo::classb
}
set matrix ${claydict-b}
#set testnum 0
foreach {top children} $matrix {
  foreach {child value} $children {
    set map {}
    dict set map %object1% OBJECTB
    dict set map %object2% MIXINB

    dict set map %top% $top
    dict set map %child% $child
    dict set map %value% $value
    dict set map %testnum% [format %04d [incr testnum]]
    putb result $map {
test oo-object-clay-method-native-%testnum% {Test native object gets the property %top%/%child%} {
  $%object1% clay get %top% %child%
} {%value%}
test oo-object-clay-method-mixin-%testnum% {Test mixin object gets the property %top%/%child%} {
  $%object2% clay get %top% %child%
} {%value%}
}
    if {$top eq "const/"} {
      putb result $map {
test oo-object-clay-method-native-methodcheck-%testnum% {Test that %top%/%child% would mimic method interheritance for a native class} {
  $%object1% %child%
} {%value%}
test oo-object-clay-method-mixin-%testnum% {Test that %top%/%child% would mimic method interheritance for a mixed in class} {
  $%object2% %child%
} {%value%}
    }
    }
  }
}

putb result {# -------------------------------------------------------------------------
# OBJECT descended from ::foo::classa ::foo::classb
set OBJECTAB [::foo::class.ab new]
# Object where classes were mixed in ::foo::classa ::foo::classb
set MIXINAB  [::oo::object new]
# Test modified 2018-10-30, mixin order was wrong before
oo::objdefine $MIXINAB mixin ::foo::classb ::foo::classa
}
set matrix ${claydict-b}
foreach {top children} ${claydict-a} {
  foreach {child value} $children {
    if {![dict exists $matrix $top $child]} {
      dict set matrix $top $child $value
    }
  }
}
#set testnum 0
foreach {top children} $matrix {
  foreach {child value} $children {
    set map {}
    dict set map %object1% OBJECTAB
    dict set map %object2% MIXINAB

    dict set map %top% $top
    dict set map %child% $child
    dict set map %value% $value
    dict set map %testnum% [format %04d [incr testnum]]
    putb result $map {
test oo-object-clay-method-native-%testnum% {Test native object gets the property %top%/%child%} {
  $%object1% clay get %top% %child%
} {%value%}
test oo-object-clay-method-mixin-%testnum% {Test mixin object gets the property %top%/%child%} {
  $%object2% clay get %top% %child%
} {%value%}
}
    if {$top eq "const/"} {
      putb result $map {
test oo-object-clay-method-native-methodcheck-%testnum% {Test that %top%/%child% would mimic method interheritance for a native class} {
  $%object1% %child%
} {%value%}
test oo-object-clay-method-mixin-%testnum% {Test that %top%/%child% would mimic method interheritance for a mixed in class} {
  $%object2% %child%
} {%value%}
    }
    }
  }
}

putb result {# -------------------------------------------------------------------------
# OBJECT descended from ::foo::classb ::foo::classa
set OBJECTBA [::foo::class.ba new]
# Object where classes were mixed in ::foo::classb ::foo::classa
set MIXINBA  [::oo::object new]
# Test modified 2018-10-30, mixin order was wrong before
oo::objdefine $MIXINBA mixin ::foo::classa ::foo::classb
}
set matrix ${claydict-a}
foreach {top children} ${claydict-b} {
  foreach {child value} $children {
    if {![dict exists $matrix $top $child]} {
      dict set matrix $top $child $value
    }
  }
}
#set testnum 0
foreach {top children} $matrix {
  foreach {child value} $children {
    set map {}
    dict set map %object1% OBJECTBA
    dict set map %object2% MIXINBA

    dict set map %top% $top
    dict set map %child% $child
    dict set map %value% $value
    dict set map %testnum% [format %04d [incr testnum]]
    putb result $map {
test oo-object-clay-method-native-%testnum% {Test native object gets the property} {
  $%object1% clay get %top% %child%
} {%value%}
test oo-object-clay-method-mixin-%testnum% {Test mixin object gets the property} {
  $%object2% clay get %top% %child%
} {%value%}
}

    if {$top eq "const/"} {
      putb result $map {
test oo-object-clay-method-native-methodcheck-%testnum% {Test that %top%/%child% would mimic method interheritance for a native class} {
  $%object1% %child%
} {%value%}
test oo-object-clay-method-mixin-%testnum% {Test that %top%/%child% would mimic method interheritance for a mixed in class} {
  $%object2% %child%
} {%value%}
    }
    }
  }
}

putb resut {
###
# Test local setting if clay data in an object
###
set OBJECT [::foo::classa new]
test oo-object-clay-method-local-0001 {Test native object gets the property} {
  $OBJECT clay get const/ color
} {blue}
test oo-object-clay-method-local-0002 {Test that local settings override the inherited properties} {
  $OBJECT clay set const/ color black
  $OBJECT clay set const/
} {black}

test oo-object-clay-method-local-0003 {Test native object gets an empty property} {
  $OBJECT clay get color
} {}
test oo-object-clay-method-local-0004 {Test that local settings override the empty property} {
  $OBJECT clay set color orange
  $OBJECT clay get color
} {orange}

}

putb result {
###
# put a do-nothing constructor on the books
###
::clay::define ::clay::object {
  constructor args {}
}

oo::objdefine ::clay::object method foo args { return bar }

test clay-core-method-0001 {Test that adding methods to the core ::clay::object class works} {
  ::clay::object foo
} {bar}

namespace eval ::TEST {}
::clay::define ::TEST::myclass {
  clay color red
  clay flavor strawberry

}

###
# Test adding a clay property
###
test clay-class-clay-0001 {Test that a clay statement is recorded in the object of the class} {
  ::TEST::myclass clay get color
} red
test clay-class-clay-0002 {Test that a clay statement is recorded in the object of the class} {
  ::TEST::myclass clay get flavor
} strawberry

###
# Test that objects of the class get the same properties
###
set OBJ [::clay::object new {}]
set OBJ2 [::TEST::myclass new {}]

test clay-object-clay-a-0001 {Test that objects not thee class do not get properties} {
  $OBJ clay get color
} {}
test clay-object-clay-a-0002 {Test that objects not thee class do not get properties} {
  $OBJ clay get flavor
} {}
test clay-object-clay-a-0003 {Test that objects of the class get properties} {
  $OBJ2 clay get color
} red
test clay-object-clay-a-0004 {Test that objects of the class get properties} {
  $OBJ2 clay get flavor
} strawberry

###
# Test modified 2018-10-21
###
test clay-object-clay-a-0005 {Test the clay ancestors function} {
  $OBJ clay ancestors
} {::clay::object}

###
# Test modified 2018-10-21
###
test clay-object-clay-a-0006 {Test the clay ancestors function} {
  $OBJ2 clay ancestors
} {::TEST::myclass ::clay::object}

test clay-object-clay-a-0007 {Test the clay provenance  function} {
  $OBJ2 clay provenance  flavor
} ::TEST::myclass

###
# Test that object local setting override the class
###
test clay-object-clay-a-0008 {Test that object local setting override the class} {
  $OBJ2 clay set color purple
  $OBJ2 clay get color
} purple
test clay-object-clay-a-0009 {Test that object local setting override the class} {
  $OBJ2 clay provenance  color
} self

::clay::define ::TEST::myclasse {
  superclass ::TEST::myclass

  clay color blue
  method do args {
    return "I did $args"
  }

  Ensemble which::color {} {
    return [my clay get color]
  }
  clay set method_ensemble which farbe: {tailcall my Which_color {*}$args}
}

###
# Test clay information is passed town to subclasses
###
test clay-class-clay-0003 {Test that a clay statement is recorded in the object of the class} {
  ::TEST::myclasse clay get color
} blue
test clay-class-clay-0004 {Test that clay statements from the ancestors of this class are not present (we handle them seperately in objects)} {
  ::TEST::myclasse clay get flavor
} {}
test clay-class-clay-0005 {Test that clay statements from the ancestors of this class are found with the FIND method} {
  ::TEST::myclasse clay find flavor
} {strawberry}

###
# Test that properties reach objects
###
set OBJ3 [::TEST::myclasse new {}]
test clay-object-clay-b-0001 {Test that objects of the class get properties} {
  $OBJ3 clay get color
} blue
test clay-object-clay-b-0002 {Test the clay provenance  function} {
  $OBJ3 clay provenance  color
} ::TEST::myclasse
test clay-object-clay-b-0003 {Test that objects of the class get properties} {
  $OBJ3 clay get flavor
} strawberry
test clay-object-clay-b-0004 {Test the clay provenance  function} {
  $OBJ3 clay provenance  flavor
} ::TEST::myclass

###
# Test modified 2018-10-21
###
test clay-object-clay-b-0005 {Test the clay provenance  function} {
  $OBJ3 clay ancestors
} {::TEST::myclasse ::TEST::myclass ::clay::object}

###
# Test defining a standard method
###
test clay-object-method-0001 {Test and standard method} {
  $OBJ3 do this really cool thing
} {I did this really cool thing}

test clay-object-method-0003 {Test an ensemble} {
  $OBJ3 which color
} blue
# Test setting properties
test clay-object-method-0004 {Test an ensemble} {
  $OBJ3 clay set color black
  $OBJ3 which color
} black

# Test setting properties
test clay-object-method-0004 {Test an ensemble alias} {
  $OBJ3 which farbe
} black


###
# Added 2019-06-24
# Test that grabbing a leaf does not pollute the cache
###
::clay::define ::TEST::class_with_deep_tree {
  clay set tree deep has depth 1
  clay set tree shallow has depth 0
}

$OBJ3 clay mixinmap deep ::TEST::class_with_deep_tree

test clay-deep-nested-0001 {Test that a leaf query does not pollute the cache} {
  $OBJ3 clay get tree shallow has depth
} 0
test clay-deep-nested-0001 {Test that a leaf query does not pollute the cache} {
  $OBJ3 clay get tree
} {deep {has {depth 1}} shallow {has {depth 0}}}



###
# Test that if you try to replace a global command you get an error
###
test clay-nspace-0001 {Test that if you try to replace a global command you get an error} -body {
::clay::define open {
  method bar {} { return foo }

}
}  -returnCodes {error} -result "::open does not refer to an object"

::clay::define fubar {
  method bar {} { return foo }
}
test clay-nspace-0002 {Test a non qualified class ends up in the current namespace} {
  info commands ::fubar
} {::fubar}

namespace eval ::cluster {
::clay::define fubar {
  method bar {} { return foo }
}

::clay::define ::clay::pot {
  method bar {} { return foo }
}

}
test clay-nspace-0003 {Test a non qualified class ends up in the current namespace} {
  info commands ::cluster::fubar
} {::cluster::fubar}
test clay-nspace-0003 {Test a fully qualified class ends up in the proper namespace} {
  info commands ::clay::pot
} {::clay::pot}

#set ::clay::trace 3

###
# New test - Added 2019-09-15
# Test that the "method" variable is exposed to a default method
###

::clay::define ::ensembleWithDefault {
  Ensemble foo::bar {} { return A }
  Ensemble foo::baz {} { return B }
  Ensemble foo::bang {} { return C }

  Ensemble foo::default {} { return $method }
}


set OBJ [::ensembleWithDefault new]
test clay-ensemble-default-0001 {Test a normal ensemble method} {
  $OBJ foo bar
} {A}
test clay-ensemble-default-0002 {Test a normal ensemble method} {
  $OBJ foo baz
} {B}
test clay-ensemble-default-0003 {Test a normal ensemble method} {
  $OBJ foo <list>
} [lsort -dictionary {bar baz bang}]

test clay-ensemble-default-0004 {Test a normal ensemble method} {
  $OBJ foo bing
} {bing}
test clay-ensemble-default-0005 {Test a normal ensemble method} {
  $OBJ foo bong
} {bong}
###
# Mixin tests
###

###
# Define a core class
###
::clay::define ::TEST::thing {

  method do args {
    return "I did $args"
  }
}


::clay::define ::TEST::vegetable {

  clay color unknown
  clay flavor unknown

  Ensemble which::flavor {} {
    return [my clay get flavor]
  }
  Ensemble which::color {} {
    return [my clay get color]
  }

}

::clay::define ::TEST::animal {

  clay color unknown
  clay sound unknown

  Ensemble which::sound {} {
    return [my clay get sound]
  }
  Ensemble which::color {} {
    return [my clay get color]
  }
  method sound {} {
    return unknown
  }
}

::clay::define ::TEST::species.cat {
  superclass ::TEST::animal
  clay sound meow
  method sound {} {
    return meow
  }
}

::clay::define ::TEST::coloring.calico {
  clay color calico

}

::clay::define ::TEST::condition.dark {
  Ensemble which::color {} {
    return grey
  }
}

::clay::define ::TEST::mood.happy {
  Ensemble which::sound {} {
    return purr
  }
  method sound {} {
    return purr
  }
}
test clay-object-0001 {Test than an object is created when clay::define is invoked} {
  info commands ::TEST::mood.happy
} ::TEST::mood.happy

set OBJ [::TEST::thing new]
test clay-mixin-a-0001 {Test that prior to a mixin an ensemble doesn't exist} -body {
  $OBJ which color
} -returnCodes error -result {unknown method "which": must be clay, destroy or do}

test clay-mixin-a-0002 {Test and standard method from an ancestor} {
  $OBJ do this really cool thing
} {I did this really cool thing}

$OBJ clay mixinmap species ::TEST::animal
test clay-mixin-b-0001 {Test that an ensemble is created during a mixin} {
  $OBJ which color
} {unknown}

test clay-mixin-b-0002 {Test that an ensemble is created during a mixin} {
  $OBJ which sound
} {unknown}

test clay-mixin-b-0003 {Test that an ensemble is created during a mixin} \
  -body {$OBJ which flavor} -returnCodes {error} \
  -result {unknown method which flavor. Valid: color sound}

###
# Test Modified: 2018-10-21
###
test clay-mixin-b-0004 {Test that mixins resolve in the correct order} {
  $OBJ clay ancestors
} {::TEST::animal ::TEST::thing ::clay::object}

###
# Replacing a mixin replaces the behaviors
###
$OBJ clay mixinmap species ::TEST::vegetable
test clay-mixin-c-0001 {Test that an ensemble is created during a mixin} {
  $OBJ which color
} {unknown}
test clay-mixin-c-0002 {Test that an ensemble is created during a mixin} \
  -body {$OBJ which sound} \
  -returnCodes {error} \
  -result {unknown method which sound. Valid: color flavor}
test clay-mixin-c-0003 {Test that an ensemble is created during a mixin} {
  $OBJ which flavor
} {unknown}
###
# Test Modified: 2018-10-21
###
test clay-mixin-c-0004 {Test that mixins resolve in the correct order} {
  $OBJ clay ancestors
} {::TEST::vegetable ::TEST::thing ::clay::object}

###
# Replacing a mixin
$OBJ clay mixinmap species ::TEST::species.cat
test clay-mixin-e-0001 {Test that an ensemble is created during a mixin} {
  $OBJ which color
} {unknown}
test clay-mixin-e-0002a {Test that an ensemble is created during a mixin} {
  $OBJ sound
} {meow}
test clay-mixin-e-0002b {Test that an ensemble is created during a mixin} {
  $OBJ clay get sound
} {meow}
test clay-mixin-e-0002 {Test that an ensemble is created during a mixin} {
  $OBJ which sound
} {meow}
test clay-mixin-e-0003 {Test that an ensemble is created during a mixin} \
  -body {$OBJ which flavor} -returnCodes {error} \
  -result {unknown method which flavor. Valid: color sound}
###
# Test Modified: 2018-10-30, 2018-10-21, 2018-10-10
###
test clay-mixin-e-0004 {Test that clay data follows the rules of inheritence and order of mixin} {
  $OBJ clay ancestors
} {::TEST::species.cat ::TEST::animal ::TEST::thing ::clay::object}

$OBJ clay mixinmap coloring ::TEST::coloring.calico
test clay-mixin-f-0001 {Test that an ensemble is created during a mixin} {
  $OBJ which color
} {calico}
test clay-mixin-f-0002 {Test that an ensemble is created during a mixin} {
  $OBJ which sound
} {meow}
test clay-mixin-f-0003 {Test that an ensemble is created during a mixin} \
  -body {$OBJ which flavor} -returnCodes {error} \
  -result {unknown method which flavor. Valid: color sound}

###
# Test modified 2018-10-30, 2018-10-21, 2018-10-10
###
test clay-mixin-f-0004 {Test that clay data follows the rules of inheritence and order of mixin} {
  $OBJ clay ancestors
} {::TEST::coloring.calico ::TEST::species.cat ::TEST::animal ::TEST::thing ::clay::object}

test clay-mixin-f-0005 {Test that clay data from a mixin works} {
  $OBJ clay provenance  color
} {::TEST::coloring.calico}

###
# Test variable initialization
###
::clay::define ::TEST::has_var {
  Variable my_variable 10

  method get_my_variable {} {
    my variable my_variable
    return $my_variable
  }
}

set OBJ [::TEST::has_var new]
test clay-class-variable-0001 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay get variable/ my_variable
} {10}

# Modified 2018-10-30 (order is different)
test clay-class-variable-0002 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay get variable
} {my_variable 10 DestroyEvent 0}

# Modified 2018-10-30 (order is different)
test clay-class-variable-0003 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay dget variable
} {. {} my_variable 10 DestroyEvent 0}

test clay-class-variable-0004 {Test that variables declared in the class definition are initialized} {
  $OBJ get_my_variable
} 10

###
# Test array initialization
###
::clay::define ::TEST::has_array {
  Array my_array {timeout 10}

  method get_my_array {field} {
    my variable my_array
    return $my_array($field)
  }
}

set OBJ [::TEST::has_array new]
test clay-class-array-0001 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay get array
} {my_array {timeout 10}}

test clay-class-array-0002 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay dget array
} {. {} my_array {. {} timeout 10}}

test clay-class-array-0003 {Test that variables declared in the class definition are initialized} {
  $OBJ get_my_array timeout
} 10

::clay::define ::TEST::has_more_array {
  superclass ::TEST::has_array
  Array my_array {color blue}
}
test clay-class-array-0008 {Test that the parser injected the right value in the right place for clay to catch it} {
  ::TEST::has_more_array clay get array
} {my_array {color blue}}

test clay-class-array-0009 {Test that the parser injected the right value in the right place for clay to catch it} {
  ::TEST::has_more_array clay find array
} {my_array {timeout 10 color blue}}

# Modified 2018-10-30 (order is different)
set BOBJ [::TEST::has_more_array new]
test clay-class-array-0004 {Test that the parser injected the right value in the right place for clay to catch it} {
  $BOBJ clay get array
} {my_array {color blue timeout 10}}

# Modified 2018-10-30 (order is different)
test clay-class-array-0005 {Test that the parser injected the right value in the right place for clay to catch it} {
  $BOBJ clay dget array
} {. {} my_array {. {} color blue timeout 10}}

test clay-class-arrau-0006 {Test that variables declared in the class definition are initialized} {
  $BOBJ get_my_array timeout
} 10
test clay-class-arrau-0007 {Test that variables declared in the class definition are initialized} {
  $BOBJ get_my_array color
} blue

::clay::define ::TEST::has_empty_array {
  Array my_array {}

  method my_array_exists {} {
    my variable my_array
    return [info exists my_array]
  }
  method get {field} {
    my variable my_array
    return $my_array($field)
  }
  method set {field value} {
    my variable my_array
    set my_array($field) $value
  }
}

test clay-class-array-0008 {Test that an declaration of an array with no values produces and empty array} {
  set COBJ [::TEST::has_empty_array new]
  $COBJ my_array_exists
} 1

test clay-class-array-0009 {Test that an declaration of an array with no values produces and empty array} {
  $COBJ set test "A random value"
  $COBJ get test
} {A random value}
###
# Test dict initialization
###
::clay::define ::TEST::has_dict {
  Dict my_dict {timeout 10}

  method get_my_dict {args} {
    my variable my_dict
    if {[llength $args]==0} {
      return $my_dict
    }
    return [dict get $my_dict {*}$args]
  }

}

set OBJ [::TEST::has_dict new]
test clay-class-dict-0001 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay get dict
} {my_dict {timeout 10}}

test clay-class-dict-0002 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay dget dict
} {. {} my_dict {. {} timeout 10}}

test clay-class-dict-0003 {Test that variables declared in the class definition are initialized} {
  $OBJ get_my_dict timeout
} 10

test clay-class-dict-0004 {Test that an empty dict is annotated} {
  $OBJ clay get dict
} {my_dict {timeout 10}}


::clay::define ::TEST::has_more_dict {
  superclass ::TEST::has_dict
  Dict my_dict {color blue}
}
set BOBJ [::TEST::has_more_dict new]

# Modified 2018-10-30
test clay-class-dict-0004 {Test that the parser injected the right value in the right place for clay to catch it} {
  $BOBJ clay get dict
} {my_dict {color blue timeout 10}}

# Modified 2018-10-30
test clay-class-dict-0005 {Test that the parser injected the right value in the right place for clay to catch it} {
  $BOBJ clay dget dict
} {. {} my_dict {. {} color blue timeout 10}}

test clay-class-dict-0006 {Test that variables declared in the class definition are initialized} {
  $BOBJ get_my_dict timeout
} 10

test clay-class-dict-0007 {Test that variables declared in the class definition are initialized} {
  $BOBJ get_my_dict color
} blue

::clay::define ::TEST::has_empty_dict {
  Dict my_empty_dict {}

  method get_my_empty_dict {args} {
    my variable my_empty_dict
    if {[llength $args]==0} {
      return $my_empty_dict
    }
    return [dict get $my_empty_dict {*}$args]
  }
}

set COBJ [::TEST::has_empty_dict new]

test clay-class-dict-0008 {Test that the parser injected the right value in the right place for clay to catch it} {
  $COBJ clay dget dict
} {my_empty_dict {. {}}}

test clay-class-dict-0009 {Test that an empty dict is initialized} {
  $COBJ get_my_empty_dict
} {}

###
# Test object delegation
###
::clay::define ::TEST::organelle {
  method add args {
    set total 0
    foreach item $args {
      set total [expr {$total+$item}]
    }
    return $total
  }
}
::clay::define ::TEST::master {
  constructor {} {
    set mysub [namespace current]::sub
    ::TEST::organelle create $mysub
    my clay delegate sub $mysub
  }
}

set OBJ [::TEST::master new]
###
# Test that delegation is working
###
test clay-delegation-0001 {Test an array driven ensemble} {
  $OBJ <sub> add 5 5
} 10


###
# Test the Ensemble keyword
###
::clay::define ::TEST::with_ensemble {

  Ensemble myensemble {pattern args} {
    set ensemble [self method]
    set emap [my clay ensemble_map $ensemble]
    set mlist [dict keys $emap [string tolower $pattern]]
    if {[llength $mlist] != 1} {
      error "Couldn't figure out what to do with $pattern"
    }
    set method [lindex $mlist 0]
    set argspec [dict get $emap $method argspec]
    set body    [dict get $emap $method body]
    if {$argspec ni {args {}}} {
      ::clay::dynamic_arguments $ensemble $method [list $argspec] {*}$args
    }
    eval $body
  }

  Ensemble myensemble::go args {
    return 1
  }
}

::clay::define ::TEST::with_ensemble.dance {
  Ensemble myensemble::dance args {
    return 1
  }
}
::clay::define ::TEST::with_ensemble.cannot_dance {
  Ensemble myensemble::dance args {
    return 0
  }
}

set OBJA [::clay::object new]
set OBJB [::clay::object new]

$OBJA clay mixinmap \
  core ::TEST::with_ensemble \
  friends ::TEST::with_ensemble.dance

$OBJB clay mixinmap \
  core ::TEST::with_ensemble \
  friends ::TEST::with_ensemble.cannot_dance
}

set testnum 0

set matrix {
  go {
    OBJA 1
    OBJB 1
  }
  dance {
    OBJA 1
    OBJB 0
  }
}
foreach {action output} $matrix {
  putb result "# Test $action"
  foreach {object value} $output {
    set map [dict create %object% $object %action% $action %value% $value]
    dict set map %testnum% [format %04d [incr testnum]]
    putb result $map {test clay-dynamic-ensemble-%testnum% {Test ensemble with static method} {
  $%object% myensemble %action%
} {%value%}}
  }
}

putb result {

###
# Class method testing
###

clay::class create WidgetClass {
  Class_Method working {} {
    return {Works}
  }

  Class_Method unknown args {
    set tkpath [lindex $args 0]
    if {[string index $tkpath 0] eq "."} {
      set obj [my new $tkpath {*}[lrange $args 1 end]]
      $obj tkalias $tkpath
      return $tkpath
    }
    next {*}$args
  }

  constructor {TkPath args} {
    my variable hull
    set hull $TkPath
    my clay delegate hull $TkPath
  }

  method tkalias tkname {
    set oldname $tkname
    my variable tkalias
    set tkalias $tkname
    set self [self]
    set hullwidget [::info object namespace $self]::tkwidget
    my clay delegate tkwidget $hullwidget
    #rename ::$tkalias $hullwidget
    my clay delegate hullwidget $hullwidget
    #::tool::object_rename [self] ::$tkalias
    rename [self] ::$tkalias
    #my Hull_Bind $tkname
    return $hullwidget
  }
}

test tool-class-method-000 {Test that class methods actually work...} {
  WidgetClass working
} {Works}

test tool-class-method-001 {Test Tk style creator} {
  WidgetClass .foo
  .foo clay delegate hull
} {.foo}

::clay::define WidgetNewClass {
  superclass WidgetClass
}

test tool-class-method-002 {Test Tk style creator inherited by morph} {
  WidgetNewClass .bar
  .bar clay delegate hull
} {.bar}



###
# Test ensemble inheritence
###
clay::define NestedClassA {
  Ensemble do::family {} {
    return NestedClassA
  }
  Ensemble do::something {} {
    return A
  }
  Ensemble do::whop {} {
    return A
  }
}
clay::define NestedClassB {
  superclass NestedClassA
  Ensemble do::family {} {
    set r [next family]
    lappend r NestedClassB
    return $r
  }
  Ensemble do::whop {} {
    return B
  }
}
clay::define NestedClassC {
  superclass NestedClassB

  Ensemble do::somethingelse {} {
    return C
  }
}
clay::define NestedClassD {
  superclass NestedClassB

  Ensemble do::somethingelse {} {
    return D
  }
}

clay::define NestedClassE {
  superclass NestedClassD NestedClassC
}

clay::define NestedClassF {
  superclass NestedClassC NestedClassD
}

NestedClassC create NestedObjectC

###
# These tests no longer work because method ensembles are now dynamically
# generated by object, that are not attached to the class anymore
#
####
#test tool-ensemble-001 {Test that an ensemble can access [next] even if no object of the ancestor class have been instantiated} {
#  NestedObjectC do family
#} {::NestedClassA ::NestedClassB ::NestedClassC}

test tool-ensemble-002 {Test that a later ensemble definition trumps a more primitive one} {
  NestedObjectC do whop
} {B}
test tool-ensemble-003 {Test that an ensemble definitions in an ancestor carry over} {
  NestedObjectC do something
} {A}

NestedClassE create NestedObjectE
NestedClassF create NestedObjectF


test tool-ensemble-004 {Test that ensembles follow the same rules for inheritance as methods} {
  NestedObjectE do somethingelse
} {D}

test tool-ensemble-005 {Test that ensembles follow the same rules for inheritance as methods} {
  NestedObjectF do somethingelse
} {C}

###
# Set of tests to exercise the mixinmap system
###
clay::define MixinMainClass {
  Variable mainvar unchanged

  Ensemble test::which {} {
    my variable mainvar
    return $mainvar
  }

  Ensemble test::main args {
    puts [list this is main $method $args]
  }

}

set mixoutscript {my test untool $class}
set mixinscript {my test tool $class}
clay::define MixinTool {
  Variable toolvar unchanged.mixin
  clay set mixin/ unmap-script $mixoutscript
  clay set mixin/ map-script $mixinscript
  clay set mixin/ name {Generic Tool}

  Ensemble test::untool class {
    my variable toolvar mainvar
    set mainvar {}
    set toolvar {}
  }

  Ensemble test::tool class {
    my variable toolvar mainvar
    set mainvar [$class clay get mixin name]
    set toolvar [$class clay get mixin name]
  }
}

clay::define MixinToolA {
  superclass MixinTool

  clay set mixin/ name {Tool A}
}

clay::define MixinToolB {
  superclass MixinTool

  clay set mixin/ name {Tool B}

  method test_newfunc {} {
    return "B"
  }
}

test tool-mixinspec-001 {Test application of mixin specs} {
  MixinTool clay get mixin map-script
} $mixinscript

test tool-mixinspec-002 {Test application of mixin specs} {
  MixinToolA clay get mixin map-script
} {}

test tool-mixinspec-003 {Test application of mixin specs} {
  MixinToolA clay find mixin map-script
} $mixinscript

test tool-mixinspec-004 {Test application of mixin specs} {
  MixinToolB clay find mixin map-script
} $mixinscript


MixinMainClass create mixintest

test tool-mixinmap-001 {Test object prior to mixins} {
  mixintest test which
} {unchanged}

mixintest clay mixinmap tool MixinToolA
test tool-mixinmap-002 {Test mixin map script ran} {
  mixintest test which
} {Tool A}

mixintest clay mixinmap tool MixinToolB

test tool-mixinmap-003 {Test mixin map script ran} {
  mixintest test which
} {Tool B}

test tool-mixinmap-003 {Test mixin map script ran} {
  mixintest test_newfunc
} {B}

mixintest clay mixinmap tool {}
test tool-mixinmap-004 {Test object prior to mixins} {
  mixintest test which
} {}
}

###
# Test clay mixinslots
###
putb result {

clay::define ::clay::object {
  method path {} {
    return [self class]
  }
}


clay::define ::MixinRoot {
  clay set opts core   root
  clay set opts option unset
  clay set opts color  unset

  Ensemble info::root {} {
    return MixinRoot
  }
  Ensemble info::shade {} {
    return avacodo
  }
  Ensemble info::default {} {
    return Undefined
  }

  method did {} {
    return MixinRoot
  }

  method path {} {
    return [list [self class] {*}[next]]
  }
}

clay::define ::MixinOption1 {
  clay set opts option option1

  Ensemble info::option {} {
    return MixinOption1
  }
  Ensemble info::other {} {
    return MixinOption1
  }

  method did {} {
    return MixinOption1
  }

  method path {} {
    return [list [self class] {*}[next]]
  }
}

clay::define ::MixinOption2 {
  superclass ::MixinOption1

  clay set opts option option2

  Ensemble info::option {} {
    return MixinOption2
  }

  method did {} {
    return MixinOption2
  }

  method path {} {
    return [list [self class] {*}[next]]
  }
}


clay::define ::MixinColor1 {
  clay set opts color blue

  Ensemble info::color {} {
    return MixinColor1
  }
  Ensemble info::shade {} {
    return blue
  }

  method did {} {
    return MixinColor1
  }

  method path {} {
    return [list [self class] {*}[next]]
  }
}

clay::define ::MixinColor2 {
  clay set opts color green

  Ensemble info::color {} {
    return MixinColor2
  }
  Ensemble info::shade {} {
    return green
  }

  method did {} {
    return MixinColor2
  }

  method path {} {
    return [list [self class] {*}[next]]
  }
}

set obj [clay::object new]

$obj clay mixinmap root ::MixinRoot
}
set testnum 0
set batnum  0

set obj {$obj}
set template {
test tool-prototype-%battery%-%test% {%comment%} {
  %obj% %method%
} {%answer%}
}
set map {}

dict set map %obj% {$obj}
dict set map %battery% [format %04d [incr batnum]]
dict set map %comment% {Mixin core}

foreach {method answer} {
  {info root} {MixinRoot}
  {info option} {Undefined}
  {info color} {Undefined}
  {info other} {Undefined}
  {info shade} {avacodo}
  {did} {MixinRoot}
  {path} {::MixinRoot ::clay::object}
  {clay get opts} {core root option unset color unset}
  {clay get opts core} root
  {clay get opts option} unset
  {clay get opts color} unset
  {clay ancestors} {::MixinRoot ::clay::object}
} {
  set testid [format %04d [incr testnum]]
  dict set map %test% $testid
  dict set map %method% $method
  dict set map %answer% $answer
  putb result $map $template
}

set testnum 0
putb result {$obj clay mixinmap option ::MixinOption1}
dict set map %battery% [format %04d [incr batnum]]
dict set map %comment% {Mixin option1}
foreach {method answer} {
  {info root} {MixinRoot}
  {info option} {MixinOption1}
  {info color} {Undefined}
  {info other} {MixinOption1}
  {info shade} {avacodo}
  {did} {MixinOption1}
  {path} {::MixinOption1 ::MixinRoot ::clay::object}
  {clay get opts} {option option1 core root color unset}
  {clay get opts core} root
  {clay get opts option} option1
  {clay get opts color} unset
  {clay ancestors} {::MixinOption1 ::MixinRoot ::clay::object}
} {
  set testid [format %04d [incr testnum]]
  dict set map %test% $testid
  dict set map %method% $method
  dict set map %answer% $answer
  putb result $map $template
}

set testnum 0
putb result {
set obj2 [clay::object new]
$obj2 clay mixinmap root ::MixinRoot option ::MixinOption1
}
putb result {$obj clay mixinmap option ::MixinOption1}
dict set map %obj% {$obj2}
dict set map %battery% [format %04d [incr batnum]]
dict set map %comment% {Mixin option1 - clean object}
foreach {method answer} {
  {info root} {MixinRoot}
  {info option} {MixinOption1}
  {info color} {Undefined}
  {info other} {MixinOption1}
  {info shade} {avacodo}
  {did} {MixinOption1}
  {path} {::MixinOption1 ::MixinRoot ::clay::object}
  {clay get opts} {option option1 core root color unset}
  {clay get opts core} root
  {clay get opts option} option1
  {clay get opts color} unset
  {clay ancestors} {::MixinOption1 ::MixinRoot ::clay::object}
} {
  set testid [format %04d [incr testnum]]
  dict set map %test% $testid
  dict set map %method% $method
  dict set map %answer% $answer
  putb result $map $template
}

set testnum 0
putb result {$obj clay mixinmap option ::MixinOption2}
dict set map %battery% [format %04d [incr batnum]]
dict set map %comment% {Mixin option2}
dict set map %obj% {$obj}
foreach {method answer} {
  {info root} {MixinRoot}
  {info option} {MixinOption2}
  {info color} {Undefined}
  {info other} {MixinOption1}
  {info shade} {avacodo}
  {did} {MixinOption2}
  {path} {::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object}
  {clay get opts} {option option2 core root color unset}
  {clay get opts core} root
  {clay get opts option} option2
  {clay get opts color} unset
  {clay ancestors} {::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object}
} {
  set testid [format %04d [incr testnum]]
  dict set map %test% $testid
  dict set map %method% $method
  dict set map %answer% $answer
  putb result $map $template
}

set testnum 0
putb result {$obj clay mixinmap color MixinColor1}
dict set map %battery% [format %04d [incr batnum]]
dict set map %comment% {Mixin color1}
foreach {method answer} {
  {info root} {MixinRoot}
  {info option} {MixinOption2}
  {info color} {MixinColor1}
  {info other} {MixinOption1}
  {info shade} {blue}
  {did} {MixinColor1}
  {path} {::MixinColor1 ::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object}
  {clay get opts} {color blue option option2 core root}
  {clay get opts core} root
  {clay get opts option} option2
  {clay get opts color} blue
  {clay ancestors} {::MixinColor1 ::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object}
} {
  set testid [format %04d [incr testnum]]
  dict set map %test% $testid
  dict set map %method% $method
  dict set map %answer% $answer
  putb result $map $template
}
set testnum 0
putb result {$obj clay mixinmap color MixinColor2}
dict set map %battery% [format %04d [incr batnum]]
dict set map %comment% {Mixin color2}
foreach {method answer} {
  {info root} {MixinRoot}
  {info option} {MixinOption2}
  {info color} {MixinColor2}
  {info other} {MixinOption1}
  {info shade} {green}
  {clay get opts} {color green option option2 core root}
  {clay get opts core} root
  {clay get opts option} option2
  {clay get opts color} green
  {clay ancestors} {::MixinColor2 ::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object}
} {
  set testid [format %04d [incr testnum]]
  dict set map %test% $testid
  dict set map %method% $method
  dict set map %answer% $answer
  putb result $map $template
}

set testnum 0
putb result {$obj clay mixinmap option MixinOption1}
dict set map %battery% [format %04d [incr batnum]]
dict set map %comment% {Mixin color2 + Option1}
foreach {method answer} {
  {info root} {MixinRoot}
  {info option} {MixinOption1}
  {info color} {MixinColor2}
  {info other} {MixinOption1}
  {info shade} {green}
  {clay get opts} {color green option option1 core root}
  {clay get opts core} root
  {clay get opts option} option1
  {clay get opts color} green
  {clay ancestors} {::MixinColor2 ::MixinOption1 ::MixinRoot ::clay::object}
} {
  set testid [format %04d [incr testnum]]
  dict set map %test% $testid
  dict set map %method% $method
  dict set map %answer% $answer
  putb result $map $template
}

set testnum 0
putb result {$obj clay mixinmap option {}}
dict set map %battery% [format %04d [incr batnum]]
dict set map %comment% {Mixin color2 + no option}
foreach {method answer} {
  {info root} {MixinRoot}
  {info option} {Undefined}
  {info color} {MixinColor2}
  {info other} {Undefined}
  {info shade} {green}
  {clay get opts} {color green core root option unset}
  {clay get opts core} root
  {clay get opts option} unset
  {clay get opts color} green
  {clay ancestors} {::MixinColor2 ::MixinRoot ::clay::object}
} {
  set testid [format %04d [incr testnum]]
  dict set map %test% $testid
  dict set map %method% $method
  dict set map %answer% $answer
  putb result $map $template
}

set testnum 0
putb result {$obj clay mixinmap color {}}
dict set map %battery% [format %04d [incr batnum]]
dict set map %comment% {Mixin core (return to normal)}
foreach {method answer} {
  {info root} {MixinRoot}
  {info option} {Undefined}
  {info color} {Undefined}
  {info other} {Undefined}
  {info shade} {avacodo}
  {clay get opts} {core root option unset color unset}
  {clay get opts core} root
  {clay get opts option} unset
  {clay get opts color} unset
  {clay ancestors} {::MixinRoot ::clay::object}
} {
  set testid [format %04d [incr testnum]]
  dict set map %test% $testid
  dict set map %method% $method
  dict set map %answer% $answer
  putb result $map $template
}

putb result {
###
# Tip479 Tests
###
clay::define tip479class {

  Method newitem dictargs {
    id {type: number}
    color {default: green}
    shape {options: {round square}}
    flavor {default: grape}
  } {
    my variable items
    foreach {f v} $args {
      dict set items $id $f $v
    }
    if {"color" ni [dict keys $args]} {
      dict set items $id color $color
    }
    return [dict get $items $id]
  }

  method itemget {id field} {
    my variable items
    return [dict get $id $field]
  }
}

set obj [tip479class new]
test tip479-001 {Test that a later ensemble definition trumps a more primitive one} {
  $obj newitem id 1 color orange shape round
} {id 1 color orange shape round}

# Fail because we left off a mandatory argument
test tip479-002 {Test that a later ensemble definition trumps a more primitive one} \
  -errorCode NONE -body {
  $obj newitem id 2
} -result {shape is required}

###
# Leave off a value that has a default
# note: Method had special handling for color, but not flavor
###
test tip479-003 {Test that a later ensemble definition trumps a more primitive one} {
  $obj newitem id 3 shape round
} {id 3 shape round color green}

###
# Add extra arguments
###
test tip479-004 {Test that a later ensemble definition trumps a more primitive one} {
  $obj newitem id 4 shape round trim leather
} {id 4 shape round trim leather color green}

clay::define tip479classE {

  Ensemble item::new dictargs {
    id {type: number}
    color {default: green}
    shape {options: {round square}}
    flavor {default: grape}
  } {
    my variable items
    foreach {f v} $args {
      dict set items $id $f $v
    }
    if {"color" ni [dict keys $args]} {
      dict set items $id color $color
    }
    return [dict get $items $id]
  }

  Ensemble item::get {id field} {
    my variable items
    return [dict get $id $field]
  }
}


set obj [tip479classE new]
test tip479-001 {Test that a later ensemble definition trumps a more primitive one} {
  $obj item new id 1 color orange shape round
} {id 1 color orange shape round}

# Fail because we left off a mandatory argument
test tip479-002 {Test that a later ensemble definition trumps a more primitive one} \
  -errorCode NONE -body {
  $obj item new id 2
} -result {shape is required}

###
# Leave off a value that has a default
# note: Method had special handling for color, but not flavor
###
test tip479-003 {Test that a later ensemble definition trumps a more primitive one} {
  $obj item new id 3 shape round
} {id 3 shape round color green}

###
# Add extra arguments
###
test tip479-004 {Test that a later ensemble definition trumps a more primitive one} {
  $obj item new id 4 shape round trim leather
} {id 4 shape round trim leather color green}

}

###
# TESTS NEEDED:
# destructor
###

putb result {
testsuiteCleanup

# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End:
}
return $result

Added modules/clay/build/uuid.tcl.













































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
###
# Adapted from tcllib module
#
# uuid.tcl - Copyright (C) 2004 Pat Thoyts <[email protected]>
#
# UUIDs are 128 bit values that attempt to be unique in time and space.
#
# Reference:
#   http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
#
# uuid: scheme:
# http://www.globecom.net/ietf/draft/draft-kindel-uuid-uri-00.html
#
# Usage: clay::uuid generate
#        clay::uuid equal $idA $idB
namespace eval ::clay::uuid {
    namespace export uuid
}

###
# Optimization
# Caches machine info after the first pass
###

proc ::clay::uuid::generate_tcl_machinfo {} {
  variable machinfo
  if {[info exists machinfo]} {
    return $machinfo
  }
  lappend machinfo [clock seconds]; # timestamp
  lappend machinfo [clock clicks];  # system incrementing counter
  lappend machinfo [info hostname]; # spatial unique id (poor)
  lappend machinfo [pid];           # additional entropy
  lappend machinfo [array get ::tcl_platform]

  ###
  # If we have /dev/urandom just stream 128 bits from that
  ###
  if {[file exists /dev/urandom]} {
    set fin [open /dev/urandom r]
    binary scan [read $fin 128] H* machinfo
    close $fin
  } elseif {[catch {package require nettool}]} {
    # More spatial information -- better than hostname.
    # bug 1150714: opening a server socket may raise a warning messagebox
    #   with WinXP firewall, using ipconfig will return all IP addresses
    #   including ipv6 ones if available. ipconfig is OK on win98+
    if {[string equal $::tcl_platform(platform) "windows"]} {
      catch {exec ipconfig} config
      lappend machinfo $config
    } else {
      catch {
          set s [socket -server void -myaddr [info hostname] 0]
          ::clay::K [fconfigure $s -sockname] [close $s]
      } r
      lappend machinfo $r
    }

    if {[package provide Tk] != {}} {
      lappend machinfo [winfo pointerxy .]
      lappend machinfo [winfo id .]
    }
  } else {
    ###
    # If the nettool package works on this platform
    # use the stream of hardware ids from it
    ###
    lappend machinfo {*}[::nettool::hwid_list]
  }
  return $machinfo
}

# Generates a binary UUID as per the draft spec. We generate a pseudo-random
# type uuid (type 4). See section 3.4
#
if {[info commands irmmd5] ne {}} {
proc ::clay::uuid::generate {{type {}}} {
    variable nextuuid
    set s [irmmd5 "$type [incr nextuuid(type)] [generate_tcl_machinfo]"]
    foreach {a b} {0 7 8 11 12 15 16 19 20 31} {
         append r [string range $s $a $b] -
     }
     return [string tolower [string trimright $r -]]
}
proc ::clay::uuid::short {{type {}}} {
  variable nextuuid
  set r [irmmd5 "$type [incr nextuuid(type)] [generate_tcl_machinfo]"]
  return [string range $r 0 16]
}

} else {
package require md5 2
proc ::clay::uuid::raw {{type {}}} {
    variable nextuuid
    set tok [md5::MD5Init]
    md5::MD5Update $tok "$type [incr nextuuid($type)] [generate_tcl_machinfo]"
    set r [md5::MD5Final $tok]
    return $r
    #return [::clay::uuid::tostring $r]
}
proc ::clay::uuid::generate {{type {}}} {
    return [::clay::uuid::tostring [::clay::uuid::raw  $type]]
}
proc ::clay::uuid::short {{type {}}} {
  set r [::clay::uuid::raw $type]
  binary scan $r H* s
  return [string range $s 0 16]
}
}
proc ::clay::uuid::tostring {uuid} {
    binary scan $uuid H* s
    foreach {a b} {0 7 8 11 12 15 16 19 20 31} {
        append r [string range $s $a $b] -
    }
    return [string tolower [string trimright $r -]]
}
# Convert a string representation of a uuid into its binary format.
#
proc ::clay::uuid::fromstring {uuid} {
    return [binary format H* [string map {- {}} $uuid]]
}

# Compare two uuids for equality.
#
proc ::clay::uuid::equal {left right} {
    set l [fromstring $left]
    set r [fromstring $right]
    return [string equal $l $r]
}

# uuid generate -> string rep of a new uuid
# uuid equal uuid1 uuid2
#
proc ::clay::uuid {cmd args} {
    switch -exact -- $cmd {
        generate {
           return [::clay::uuid::generate {*}$args]
        }
        short {
          set uuid [::clay::uuid::short {*}$args]
        }
        equal {
            tailcall ::clay::uuid::equal {*}$args
        }
        default {
            return -code error "bad option \"$cmd\":\
                must be generate or equal"
        }
    }
}

Added modules/clay/clay.man.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
[comment {-*- tcl -*- doctools manpage}]
[vset PACKAGE_VERSION 0.8.6]
[manpage_begin clay n [vset PACKAGE_VERSION]]
[keywords oo]
[copyright {2018 Sean Woods <[email protected]>}]
[moddesc   {Clay Framework}]
[titledesc {A minimalist framework for large scale OO Projects}]
[category  {Programming tools}]
[keywords TclOO]
[require Tcl 8.6]
[require uuid]
[require oo::dialect]
[description]
Clay introduces a method ensemble to both [class oo::class] and [class oo::object] called
clay. This ensemble handles all of the high level interactions within the framework.
Clay stores structured data. Clan manages method delegation. Clay has facilities to
manage the complex interactions that come about with mixins.
[para]
The central concept is that inside of every object and class
(which are actually objects too) is a dict called clay. What is stored in that dict is
left to the imagination. But because this dict is exposed via a public method, we can
share structured data between object, classes, and mixins.
[para]
[subsection {Structured Data}]
Clay uses a standardized set of method interactions and introspection that TclOO already provides to perform on-the-fly searches. On-the-fly searches mean that the data is never stale, and we avoid many of the sorts of collisions that would arise when objects start mixing in other classes during operation.
[para]
The [method clay] methods for both classes and objects have a get and a set method. For objects, get will search through the local clay dict. If the requested leaf is not found, or the query is for a branch, the system will then begin to poll the clay methods of all of the class that implements the object, all of that classes’ ancestors, as well as all of the classes that have been mixed into this object, and all of their ancestors.
[para]
Intended branches on a tree end with a directory slash (/). Intended leaves are left unadorned. This is a guide for the tool that builds the search
results to know what parts of a dict are intended to be branches and which are intended to be leaves.
For simple cases, branch marking can be ignored:
[example {
::oo::class create ::foo { }
::foo clay set property/ color blue
::foo clay set property/ shape round

set A [::foo new]
$A clay get property/
{color blue shape round}

$A clay set property/ shape square
$A clay get property/
{color blue shape square}
}]
[para]
But when you start storing blocks of text, guessing what field is a dict and what isn’t gets messy:
[example {
::foo clay set description {A generic thing of designated color and shape}

$A clay get description
{A generic thing of designated color and shape}

Without a convention for discerning branches for leaves what should have been a value can be accidentally parsed as a dictionary, and merged with all of the other values that were never intended to be merge. Here is an example of it all going wrong:
::oo::class create ::foo { }
# Add description as a leaf
::foo clay set description \
  {A generic thing of designated color and shape}
# Add description as a branch
::foo clay set description/ \
  {A generic thing of designated color and shape}

::oo::class create ::bar {
  superclass foo
}
# Add description as a leaf
::bar clay set description \
  {A drinking establishment of designated color and shape and size}
# Add description as a branch
::bar clay set description/ \
  {A drinking establishment of designated color and shape and size}

set B [::bar new]
# As a leaf we get the value verbatim from he nearest ancestor
$B clay get description
  {A drinking establishment of designated color and shape and size}
# As a branch we get a recursive merge
$B clay get description/
{A drinking establishment of designated color and size thing of}
}]
[subsection {Clay Dialect}]
Clay is built using the oo::dialect module from Tcllib. oo::dialect allows you to either add keywords directly to clay, or to create your own
metaclass and keyword set using Clay as a foundation. For details on the keywords and what they do, consult the functions in the ::clay::define namespace.
[subsection {Method Delegation}]
Method Delegation
It is sometimes useful to have an external object that can be invoked as if it were a method of the object. Clay provides a delegate ensemble method to perform that delegation, as well as introspect which methods are delegated in that manner. All delegated methods are marked with html-like tag markings (< >) around them.
[example {
::clay::define counter {
  Variable counter 0
  method incr {{howmuch 1}} {
    my variable counter
    incr counter $howmuch
  }
  method value {} {
    my variable counter
    return $counter
  }
  method reset {} {
    my variable counter
    set counter 0
  }
}
::clay::define example {
  variable buffer
  constructor {} {
    # Build a counter object
    set obj [namespace current]::counter
    ::counter create $obj
    # Delegate the counter
    my delegate <counter> $obj
  }
  method line {text} {
    my <counter> incr
    append buffer $text
  }
}

set A [example new]
$A line {Who’s line is it anyway?}
$A <counter> value
1
}]


[section {Commands}]
[list_begin definitions]
[call proc [cmd clay::PROC] [arg name] [arg arglist] [arg body] [opt "[arg ninja] [const ""]"]]

 Because many features in this package may be added as
 commands to future tcl cores, or be provided in binary
 form by packages, I need a declaritive way of saying
 [emph {Create this command if there isn't one already}].
 The [emph ninja] argument is a script to execute if the
 command is created by this mechanism.




[call proc [cmd clay::_ancestors] [arg resultvar] [arg class]]


[call proc [cmd clay::ancestors] [opt "[arg args]"]]


[call proc [cmd clay::args_to_dict] [opt "[arg args]"]]


[call proc [cmd clay::args_to_options] [opt "[arg args]"]]


[call proc [cmd clay::dynamic_arguments] [arg ensemble] [arg method] [arg arglist] [opt "[arg args]"]]



[call proc [cmd clay::dynamic_wrongargs_message] [arg arglist]]



[call proc [cmd clay::is_dict] [arg d]]


[call proc [cmd clay::is_null] [arg value]]


[call proc [cmd clay::leaf] [opt "[arg args]"]]


[call proc [cmd clay::K] [arg a] [arg b]]


[call proc [cmd clay::noop] [opt "[arg args]"]]

 Perform a noop. Useful in prototyping for commenting out blocks
 of code without actually having to comment them out. It also makes
 a handy default for method delegation if a delegate has not been
 assigned yet.



[call proc [cmd clay::cleanup]]

 Process the queue of objects to be destroyed




[call proc [cmd clay::object_create] [arg objname] [opt "[arg class] [const ""]"]]


[call proc [cmd clay::object_rename] [arg object] [arg newname]]


[call proc [cmd clay::object_destroy] [opt "[arg args]"]]

 Mark an objects for destruction on the next cleanup




[call proc [cmd clay::path] [opt "[arg args]"]]


[call proc [cmd clay::putb] [opt "[arg map]"] [arg text]]

 Append a line of text to a variable. Optionally apply a string mapping.


[call proc [cmd clay::script_path]]


[call proc [cmd clay::NSNormalize] [arg qualname]]


[call proc [cmd clay::uuid_generate] [opt "[arg args]"]]


[call proc [cmd clay::uuid::generate_tcl_machinfo]]


[call proc [cmd clay::uuid::tostring] [arg uuid]]


[call proc [cmd clay::uuid::fromstring] [arg uuid]]
 Convert a string representation of a uuid into its binary format.




[call proc [cmd clay::uuid::equal] [arg left] [arg right]]
 Compare two uuids for equality.




[call proc [cmd clay::uuid] [arg cmd] [opt "[arg args]"]]
 uuid generate -> string rep of a new uuid
 uuid equal uuid1 uuid2




[call proc [cmd clay::tree::sanitize] [arg dict]]

 Output a dictionary removing any . entries added by [fun {clay::tree::merge}]




[call proc [cmd clay::tree::_sanitizeb] [arg path] [arg varname] [arg dict]]

 Helper function for ::clay::tree::sanitize
 Formats the string representation for a dictionary element within
 a human readable stream of lines, and determines if it needs to call itself
 with further indentation to express a sub-branch




[call proc [cmd clay::tree::storage] [arg rawpath]]

 Return the path as a storage path for clay::tree
 with all branch terminators removed.
 This command will also break arguments up if they
 contain /.

[para]Example: [example { > clay::tree::storage {foo bar baz bang}
 foo bar baz bang
 > clay::tree::storage {foo bar baz bang/}
 foo bar baz bang
 > clay::tree::storage {foo bar baz bang:}
 foo bar baz bang:
 > clay::tree::storage {foo/bar/baz bang:}
 foo bar baz bang:
 > clay::tree::storage {foo/bar/baz/bang}
 foo bar baz bang


}]

[call proc [cmd clay::tree::dictset] [arg varname] [opt "[arg args]"]]

 Set an element with a recursive dictionary,
 marking all branches on the way down to the
 final element.
 If the value does not exists in the nested dictionary
 it is added as a leaf. If the value already exists as a branch
 the value given is merged if the value is a valid dict. If the
 incoming value is not a valid dict, the value overrides the value
 stored, and the value is treated as a leaf from then on.

[para]Example: [example { > set r {}
 > ::clay::tree::dictset r option color default Green
 . {} option {. {} color {. {} default Green}}
 > ::clay::tree::dictset r option {Something not dictlike}
 . {} option {Something not dictlike}
 # Note that if the value is not a dict, and you try to force it to be
 # an error with be thrown on the merge
 > ::clay::tree::dictset r option color default Blue
 missing value to go with key


}]

[call proc [cmd clay::tree::dictmerge] [arg varname] [opt "[arg args]"]]

 A recursive form of dict merge, intended for modifying variables in place.

[para]Example: [example { > set mydict {sub/ {sub/ {description {a block of text}}}}
 > ::clay::tree::dictmerge mydict {sub/ {sub/ {field {another block of text}}}}]
 > clay::tree::print $mydict
 sub/ {
   sub/ {
     description {a block of text}
     field {another block of text}
   }
 }


}]

[call proc [cmd clay::tree::merge] [opt "[arg args]"]]

 A recursive form of dict merge
 [para]
 A routine to recursively dig through dicts and merge
 adapted from http://stevehavelka.com/tcl-dict-operation-nested-merge/

[para]Example: [example { > set mydict {sub/ {sub/ {description {a block of text}}}}
 > set odict [clay::tree::merge $mydict {sub/ {sub/ {field {another block of text}}}}]
 > clay::tree::print $odict
 sub/ {
   sub/ {
     description {a block of text}
     field {another block of text}
   }
 }


}]

[call proc [cmd dictargs::proc] [arg name] [arg argspec] [arg body]]

 Named Procedures as new command




[call proc [cmd dictargs::method] [arg name] [arg argspec] [arg body]]


[call proc [cmd clay::dialect::Push] [arg class]]


[call proc [cmd clay::dialect::Peek]]


[call proc [cmd clay::dialect::Pop]]


[call proc [cmd clay::dialect::create] [arg name] [opt "[arg parent] [const ""]"]]

 This proc will generate a namespace, a "mother of all classes", and a
 rudimentary set of policies for this dialect.




[call proc [cmd clay::dialect::NSNormalize] [arg namespace] [arg qualname]]
 Support commands; not intended to be called directly.



[call proc [cmd clay::dialect::DefineThunk] [arg target] [opt "[arg args]"]]


[call proc [cmd clay::dialect::Canonical] [arg namespace] [arg NSpace] [arg class]]


[call proc [cmd clay::dialect::Define] [arg namespace] [arg class] [opt "[arg args]"]]

 Implementation of the languages' define command




[call proc [cmd clay::dialect::Aliases] [arg namespace] [opt "[arg args]"]]


[call proc [cmd clay::dialect::SuperClass] [arg namespace] [opt "[arg args]"]]


[call proc [cmd clay::dynamic_methods] [arg class]]


[call proc [cmd clay::dynamic_methods_class] [arg thisclass]]


[call proc [cmd clay::define::Array] [arg name] [opt "[arg values] [const ""]"]]

 New OO Keywords for clay




[call proc [cmd clay::define::Delegate] [arg name] [arg info]]

 An annotation that objects of this class interact with delegated
 methods. The annotation is intended to be a dictionary, and the
 only reserved key is [emph {description}], a human readable description.




[call proc [cmd clay::define::constructor] [arg arglist] [arg rawbody]]



[call proc [cmd clay::define::Class_Method] [arg name] [arg arglist] [arg body]]

 Specify the a method for the class object itself, instead of for objects of the class




[call proc [cmd clay::define::class_method] [arg name] [arg arglist] [arg body]]

 And alias to the new Class_Method keyword




[call proc [cmd clay::define::clay] [opt "[arg args]"]]


[call proc [cmd clay::define::destructor] [arg rawbody]]



[call proc [cmd clay::define::Dict] [arg name] [opt "[arg values] [const ""]"]]


[call proc [cmd clay::define::Option] [arg name] [opt "[arg args]"]]

 Define an option for the class




[call proc [cmd clay::define::Method] [arg name] [arg argstyle] [arg argspec] [arg body]]


[call proc [cmd clay::define::Option_Class] [arg name] [opt "[arg args]"]]

 Define a class of options
 All field / value pairs will be be inherited by an option that
 specify [emph name] as it class field.




[call proc [cmd clay::define::Variable] [arg name] [opt "[arg default] [const ""]"]]

    This keyword can also be expressed:
    [example {property variable NAME {default DEFAULT}}]
    [para]
    Variables registered in the variable property are also initialized
    (if missing) when the object changes class via the [emph morph] method.




[call proc [cmd clay::ensemble_methodbody] [arg ensemble] [arg einfo]]

 Produce the body of an ensemble's public dispatch method
 ensemble is the name of the the ensemble.
 einfo is a dictionary of methods for the ensemble, and each value is a script
 to execute on dispatch

[para]Example: [example { ::clay::ensemble_methodbody foo {
   bar {tailcall my Foo_bar {*}$args}
   baz {tailcall my Foo_baz {*}$args}
   clock {return [clock seconds]}
   default {puts "You gave me $method"}
 }


}]

[call proc [cmd clay::define::Ensemble] [arg rawmethod] [opt "[arg args]"]]


[call proc [cmd clay::event::cancel] [arg self] [opt "[arg task] [const "*"]"]]

Cancel a scheduled event




[call proc [cmd clay::event::generate] [arg self] [arg event] [opt "[arg args]"]]

    Generate an event
    Adds a subscription mechanism for objects
    to see who has recieved this event and prevent
    spamming or infinite recursion




[call proc [cmd clay::event::nextid]]



[call proc [cmd clay::event::Notification_list] [arg self] [arg event] [opt "[arg stackvar] [const ""]"]]

    Called recursively to produce a list of
    who recieves notifications




[call proc [cmd clay::event::notify] [arg rcpt] [arg sender] [arg event] [arg eventinfo]]

 Final delivery to intended recipient object




[call proc [cmd clay::event::process] [arg self] [arg handle] [arg script]]

 Evaluate an event script in the global namespace




[call proc [cmd clay::event::schedule] [arg self] [arg handle] [arg interval] [arg script]]

Schedule an event to occur later




[call proc [cmd clay::event::subscribe] [arg self] [arg who] [arg event]]

 Subscribe an object to an event pattern




[call proc [cmd clay::event::unsubscribe] [arg self] [opt "[arg args]"]]

 Unsubscribe an object from an event pattern




[call proc [cmd clay::singleton] [arg name] [arg script]]

 An object which is intended to be it's own class.


[list_end]

[section Classes]
[subsection {Class  clay::class}]

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "clay ancestors"]]
Return this class and all ancestors in search order.

[call method [cmd "clay dump"]]
Return a complete dump of this object's clay data, but only this object's clay data.

[call method [cmd "clay find"] [arg path] [opt [option "path..."]]]

     Pull a chunk of data from the clay system. If the last element of [emph path] is a branch,
     returns a recursive merge of all data from this object and it's constituent classes of the data in that branch.
     If the last element is a leaf, search this object for a matching leaf, or search all  constituent classes for a matching
     leaf and return the first value found.
     If no value is found, returns an empty string.
     If a branch is returned the topmost . entry is omitted.
   

[call method [cmd "clay get"] [arg path] [opt [option "path..."]]]

     Pull a chunk of data from the class's clay system.
     If no value is found, returns an empty string.
     If a branch is returned the topmost . entry is omitted.
   

[call method [cmd "clay GET"] [arg path] [opt [option "path..."]]]

     Pull a chunk of data from the class's clay system.
     If no value is found, returns an empty string.
   

[call method [cmd "clay merge"] [arg dict] [opt [option "dict..."]]]
Recursively merge the dictionaries given into the object's local clay storage.

[call method [cmd "clay replace"] [arg dictionary]]
Replace the contents of the internal clay storage with the dictionary given.

[call method [cmd "clay search"] [arg path] [opt [option "path..."]]]
Return the first matching value for the path in either this class's clay data or one of its ancestors

[call method [cmd "clay set"] [arg path] [opt [option "path..."]] [arg value]]
Merge the conents of [const value] with the object's clay storage at [const path].

[list_end]
[para]

[subsection {Class  clay::object}]
 clay::object

 This class is inherited by all classes that have options.



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "clay ancestors"]]
Return the class this object belongs to, all classes mixed into this object, and all ancestors of those classes in search order.

[call method [cmd "clay cache"] [arg path] [arg value]]
Store VALUE in such a way that request in SEARCH for PATH will always return it until the cache is flushed

[call method [cmd "clay cget"] [arg field]]

 Pull a value from either the object's clay structure or one of its constituent classes that matches the field name.
 The order of search us:
 [para] 1. The as a value in local dict variable config
 [para] 2. The as a value in local dict variable clay
 [para] 3. As a leaf in any ancestor as a root of the clay tree
 [para] 4. As a leaf in any ancestor as [const const] [emph field]
 [para] 5. As a leaf in any ancestor as [const option] [emph field] [const default]
   

[call method [cmd "clay delegate"] [opt "[arg stub]"] [opt "[arg object]"]]

 Introspect or control method delegation. With no arguments, the method will return a
 key/value list of stubs and objects. With just the [arg stub] argument, the method will
 return the object (if any) attached to the stub. With a [arg stub] and an [arg object]
 this command will forward all calls to the method [arg stub] to the [arg object].
 

[call method [cmd "clay dump"]]
Return a complete dump of this object's clay data, as well as the data from all constituent classes recursively blended in.

[call method [cmd "clay ensemble_map"]]
Return a dictionary describing the method ensembles to be assembled for this object

[call method [cmd "clay eval"] [arg script]]
Evaluated a script in the namespace of this object

[call method [cmd "clay evolve"]]
Trigger the [method InitializePublic] private method

[call method [cmd "clay exists"] [arg path] [opt [option "path..."]]]
Returns 1 if [emph path] exists in either the object's clay data. Values greater than one indicate the element exists in one of the object's constituent classes. A value of zero indicates the path could not be found.

[call method [cmd "clay flush"]]
Wipe any caches built by the clay implementation

[call method [cmd "clay forward"] [arg method] [arg object]]
A convenience wrapper for
 [example {oo::objdefine [self] forward {*}$args}]
 

[call method [cmd "clay get"] [arg path] [opt [option "path..."]]]
Pull a chunk of data from the clay system. If the last element of [emph path] is a branch (ends in a slash /),
   returns a recursive merge of all data from this object and it's constituent classes of the data in that branch.
   If the last element is a leaf, search this object for a matching leaf, or search all  constituent classes for a matching
   leaf and return the first value found.
   If no value is found, returns an empty string.
 

[call method [cmd "clay leaf"] [arg path] [opt [option "path..."]]]
A modified get which is tailored to pull only leaf elements

[call method [cmd "clay merge"] [arg dict] [opt [option "dict..."]]]
Recursively merge the dictionaries given into the object's local clay storage.

[call method [cmd "clay mixin"] [arg class] [opt [option "class..."]]]

 Perform [lb]oo::objdefine [lb]self[rb] mixin[rb] on this object, with a few additional rules:
   Prior to the call, for any class was previously mixed in, but not in the new result, execute the script registered to mixin/ unmap-script (if given.)
   For all new classes, that were not present prior to this call, after the native TclOO mixin is invoked, execute the script registered to mixin/ map-script (if given.)
   Fall all classes that are now present and “mixed in”, execute the script registered to mixin/ react-script (if given.)
 

[call method [cmd "clay mixinmap"] [opt "[arg stub]"] [opt "[arg classes]"]]
With no arguments returns the map of stubs and classes mixed into the current object. When only stub is given,
  returns the classes mixed in on that stub. When stub and classlist given, replace the classes currently on that stub with the given
  classes and invoke clay mixin on the new matrix of mixed in classes.
 

[call method [cmd "clay provenance"] [arg path] [opt [option "path..."]]]
Return either [const self] if that path exists in the current object, or return the first class (if any) along the clay search path which contains that element.

[call method [cmd "clay replace"] [arg dictionary]]
Replace the contents of the internal clay storage with the dictionary given.

[call method [cmd "clay search"] [arg path] [arg valuevar] [arg isleafvar]]
Return true, and set valuevar to the value and isleafar to true for false if PATH was found in the cache.

[call method [cmd "clay source"] [arg filename]]
Source the given filename within the object's namespace

[call method [cmd "clay set"] [arg path] [opt [option "path..."]] [arg value]]
Merge the conents of [const value] with the object's clay storage at [const path].

[call method [cmd "InitializePublic"]]

 Instantiate variables. Called on object creation and during clay mixin.




[list_end]
[para]

[section AUTHORS]
Sean Woods [uri mailto:<[email protected]>][para]
[vset CATEGORY oo]
[include ../common-text/feedback.inc]

[manpage_end]

Added modules/clay/clay.tcl.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
###
# clay.tcl
#
# Copyright (c) 2018 Sean Woods
#
# BSD License
###
# @@ Meta Begin
# Package clay 0.8.6
# Meta platform     tcl
# Meta summary      A minimalist framework for complex TclOO development
# Meta description  This package introduces the method "clay" to both oo::object
# Meta description  and oo::class which facilitate complex interactions between objects
# Meta description  and their ancestor and mixed in classes.
# Meta category     TclOO
# Meta subject      framework
# Meta require      {Tcl 8.6}
# Meta author       Sean Woods
# Meta license      BSD
# @@ Meta End

###
# Amalgamated package for clay
# Do not edit directly, tweak the source in build/ and rerun
# build.tcl
###
package provide clay 0.8.6
namespace eval ::clay {}

###
# START: procs.tcl
###
namespace eval ::clay {
}
set ::clay::trace 0
if {[info commands ::cron::object_destroy] eq {}} {
  # Provide a noop if we aren't running with the cron scheduler
  namespace eval ::cron {}
  proc ::cron::object_destroy args {}
}
proc ::clay::PROC {name arglist body {ninja {}}} {
  if {[info commands $name] ne {}} return
  proc $name $arglist $body
  eval $ninja
}
if {[info commands ::PROC] eq {}} {
  namespace eval ::clay { namespace export PROC }
  namespace eval :: { namespace import ::clay::PROC }
}
proc ::clay::_ancestors {resultvar class} {
  upvar 1 $resultvar result
  if {$class in $result} {
    return
  }
  lappend result $class
  foreach aclass [::info class superclasses $class] {
    _ancestors result $aclass
  }
}
proc ::clay::ancestors {args} {
  set result {}
  set queue  {}
  set metaclasses {}

  foreach class $args {
    set ancestors($class) {}
    _ancestors ancestors($class) $class
  }
  foreach class [lreverse $args] {
    foreach aclass $ancestors($class) {
      if {$aclass in $result} continue
      set skip 0
      foreach bclass $args {
        if {$class eq $bclass} continue
        if {$aclass in $ancestors($bclass)} {
          set skip 1
          break
        }
      }
      if {$skip} continue
      lappend result $aclass
    }
  }
  foreach class [lreverse $args] {
    foreach aclass $ancestors($class) {
      if {$aclass in $result} continue
      lappend result $aclass
    }
  }
  ###
  # Screen out classes that do not participate in clay
  # interactions
  ###
  set output {}
  foreach {item} $result {
    if {[catch {$item clay noop} err]} {
      continue
    }
    lappend output $item
  }
  return $output
}
proc ::clay::args_to_dict args {
  if {[llength $args]==1} {
    return [lindex $args 0]
  }
  return $args
}
proc ::clay::args_to_options args {
  set result {}
  foreach {var val} [args_to_dict {*}$args] {
    lappend result [string trim $var -:] $val
  }
  return $result
}
proc ::clay::dynamic_arguments {ensemble method arglist args} {
  set idx 0
  set len [llength $args]
  if {$len > [llength $arglist]} {
    ###
    # Catch if the user supplies too many arguments
    ###
    set dargs 0
    if {[lindex $arglist end] ni {args dictargs}} {
      return -code error -level 2 "Usage: $ensemble $method [string trim [dynamic_wrongargs_message $arglist]]"
    }
  }
  foreach argdef $arglist {
    if {$argdef eq "args"} {
      ###
      # Perform args processing in the style of tcl
      ###
      uplevel 1 [list set args [lrange $args $idx end]]
      break
    }
    if {$argdef eq "dictargs"} {
      ###
      # Perform args processing in the style of tcl
      ###
      uplevel 1 [list set args [lrange $args $idx end]]
      ###
      # Perform args processing in the style of clay
      ###
      set dictargs [::clay::args_to_options {*}[lrange $args $idx end]]
      uplevel 1 [list set dictargs $dictargs]
      break
    }
    if {$idx > $len} {
      ###
      # Catch if the user supplies too few arguments
      ###
      if {[llength $argdef]==1} {
        return -code error -level 2 "Usage: $ensemble $method [string trim [dynamic_wrongargs_message $arglist]]"
      } else {
        uplevel 1 [list set [lindex $argdef 0] [lindex $argdef 1]]
      }
    } else {
      uplevel 1 [list set [lindex $argdef 0] [lindex $args $idx]]
    }
    incr idx
  }
}
proc ::clay::dynamic_wrongargs_message {arglist} {
  set result ""
  set dargs 0
  foreach argdef $arglist {
    if {$argdef in {args dictargs}} {
      set dargs 1
      break
    }
    if {[llength $argdef]==1} {
      append result " $argdef"
    } else {
      append result " ?[lindex $argdef 0]?"
    }
  }
  if { $dargs } {
    append result " ?option value?..."
  }
  return $result
}
proc ::clay::is_dict { d } {
  # is it a dict, or can it be treated like one?
  if {[catch {::dict size $d} err]} {
    #::set ::errorInfo {}
    return 0
  }
  return 1
}
proc ::clay::is_null value {
  return [expr {$value in {{} NULL}}]
}
proc ::clay::leaf args {
  set marker [string index [lindex $args end] end]
  set result [path {*}${args}]
  if {$marker eq "/"} {
    return $result
  }
  return [list {*}[lrange $result 0 end-1] [string trim [string trim [lindex $result end]] /]]
}
proc ::clay::K {a b} {set a}
if {[info commands ::K] eq {}} {
  namespace eval ::clay { namespace export K }
  namespace eval :: { namespace import ::clay::K }
}
proc ::clay::noop args {}
if {[info commands ::noop] eq {}} {
  namespace eval ::clay { namespace export noop }
  namespace eval :: { namespace import ::clay::noop }
}
proc ::clay::cleanup {} {
  set count 0
  if {![info exists ::clay::idle_destroy]} return
  set objlist $::clay::idle_destroy
  set ::clay::idle_destroy {}
  foreach obj $objlist {
    if {![catch {$obj destroy}]} {
      incr count
    }
  }
  return $count
}
proc ::clay::object_create {objname {class {}}} {
  #if {$::clay::trace>0} {
  #  puts [list $objname CREATE]
  #}
}
proc ::clay::object_rename {object newname} {
  if {$::clay::trace>0} {
    puts [list $object RENAME -> $newname]
  }
}
proc ::clay::object_destroy args {
  if {![info exists ::clay::idle_destroy]} {
    set ::clay::idle_destroy {}
  }
  foreach objname $args {
    if {$::clay::trace>0} {
      puts [list $objname DESTROY]
    }
    ::cron::object_destroy $objname
    if {$objname in $::clay::idle_destroy} continue
    lappend ::clay::idle_destroy $objname
  }
}
proc ::clay::path args {
  set result {}
  foreach item $args {
    set item [string trim $item :./]
    foreach subitem [split $item /] {
      lappend result [string trim ${subitem}]/
    }
  }
  return $result
}
proc ::clay::putb {buffername args} {
  upvar 1 $buffername buffer
  switch [llength $args] {
    1 {
      append buffer [lindex $args 0] \n
    }
    2 {
      append buffer [string map {*}$args] \n
    }
    default {
      error "usage: putb buffername ?map? string"
    }
  }
}
if {[info command ::putb] eq {}} {
  namespace eval ::clay { namespace export putb }
  namespace eval :: { namespace import ::clay::putb }
}
proc ::clay::script_path {} {
  set path [file dirname [file join [pwd] [info script]]]
  return $path
}
proc ::clay::NSNormalize qualname {
  if {![string match ::* $qualname]} {
    set qualname ::clay::classes::$qualname
  }
  regsub -all {::+} $qualname "::"
}
proc ::clay::uuid_generate args {
  return [uuid generate]
}
namespace eval ::clay {
  variable option_class {}
  variable core_classes {::oo::class ::oo::object}
}

###
# END: procs.tcl
###
###
# START: core.tcl
###
package require Tcl 8.6 ;# try in pipeline.tcl. Possibly other things.
if {[info commands irmmd5] eq {}} {
  if {[catch {package require odielibc}]} {
    package require md5 2
  }
}
::namespace eval ::clay {
}
::namespace eval ::clay::classes {
}
::namespace eval ::clay::define {
}
::namespace eval ::clay::tree {
}
::namespace eval ::clay::dict {
}
::namespace eval ::clay::list {
}
::namespace eval ::clay::uuid {
}
if {![info exists ::clay::idle_destroy]} {
  set ::clay::idle_destroy {}
}

###
# END: core.tcl
###
###
# START: uuid.tcl
###
namespace eval ::clay::uuid {
    namespace export uuid
}
proc ::clay::uuid::generate_tcl_machinfo {} {
  variable machinfo
  if {[info exists machinfo]} {
    return $machinfo
  }
  lappend machinfo [clock seconds]; # timestamp
  lappend machinfo [clock clicks];  # system incrementing counter
  lappend machinfo [info hostname]; # spatial unique id (poor)
  lappend machinfo [pid];           # additional entropy
  lappend machinfo [array get ::tcl_platform]

  ###
  # If we have /dev/urandom just stream 128 bits from that
  ###
  if {[file exists /dev/urandom]} {
    set fin [open /dev/urandom r]
    binary scan [read $fin 128] H* machinfo
    close $fin
  } elseif {[catch {package require nettool}]} {
    # More spatial information -- better than hostname.
    # bug 1150714: opening a server socket may raise a warning messagebox
    #   with WinXP firewall, using ipconfig will return all IP addresses
    #   including ipv6 ones if available. ipconfig is OK on win98+
    if {[string equal $::tcl_platform(platform) "windows"]} {
      catch {exec ipconfig} config
      lappend machinfo $config
    } else {
      catch {
          set s [socket -server void -myaddr [info hostname] 0]
          ::clay::K [fconfigure $s -sockname] [close $s]
      } r
      lappend machinfo $r
    }

    if {[package provide Tk] != {}} {
      lappend machinfo [winfo pointerxy .]
      lappend machinfo [winfo id .]
    }
  } else {
    ###
    # If the nettool package works on this platform
    # use the stream of hardware ids from it
    ###
    lappend machinfo {*}[::nettool::hwid_list]
  }
  return $machinfo
}
if {[info commands irmmd5] ne {}} {
proc ::clay::uuid::generate {{type {}}} {
    variable nextuuid
    set s [irmmd5 "$type [incr nextuuid(type)] [generate_tcl_machinfo]"]
    foreach {a b} {0 7 8 11 12 15 16 19 20 31} {
         append r [string range $s $a $b] -
     }
     return [string tolower [string trimright $r -]]
}
proc ::clay::uuid::short {{type {}}} {
  variable nextuuid
  set r [irmmd5 "$type [incr nextuuid(type)] [generate_tcl_machinfo]"]
  return [string range $r 0 16]
}

} else {
package require md5 2
proc ::clay::uuid::raw {{type {}}} {
    variable nextuuid
    set tok [md5::MD5Init]
    md5::MD5Update $tok "$type [incr nextuuid($type)] [generate_tcl_machinfo]"
    set r [md5::MD5Final $tok]
    return $r
    #return [::clay::uuid::tostring $r]
}
proc ::clay::uuid::generate {{type {}}} {
    return [::clay::uuid::tostring [::clay::uuid::raw  $type]]
}
proc ::clay::uuid::short {{type {}}} {
  set r [::clay::uuid::raw $type]
  binary scan $r H* s
  return [string range $s 0 16]
}
}
proc ::clay::uuid::tostring {uuid} {
    binary scan $uuid H* s
    foreach {a b} {0 7 8 11 12 15 16 19 20 31} {
        append r [string range $s $a $b] -
    }
    return [string tolower [string trimright $r -]]
}
proc ::clay::uuid::fromstring {uuid} {
    return [binary format H* [string map {- {}} $uuid]]
}
proc ::clay::uuid::equal {left right} {
    set l [fromstring $left]
    set r [fromstring $right]
    return [string equal $l $r]
}
proc ::clay::uuid {cmd args} {
    switch -exact -- $cmd {
        generate {
           return [::clay::uuid::generate {*}$args]
        }
        short {
          set uuid [::clay::uuid::short {*}$args]
        }
        equal {
            tailcall ::clay::uuid::equal {*}$args
        }
        default {
            return -code error "bad option \"$cmd\":\
                must be generate or equal"
        }
    }
}

###
# END: uuid.tcl
###
###
# START: dict.tcl
###
::clay::PROC ::tcl::dict::getnull {dictionary args} {
  if {[exists $dictionary {*}$args]} {
    get $dictionary {*}$args
  }
} {
  namespace ensemble configure dict -map [dict replace\
      [namespace ensemble configure dict -map] getnull ::tcl::dict::getnull]
}
::clay::PROC ::tcl::dict::is_dict { d } {
  # is it a dict, or can it be treated like one?
  if {[catch {dict size $d} err]} {
    #::set ::errorInfo {}
    return 0
  }
  return 1
} {
  namespace ensemble configure dict -map [dict replace\
      [namespace ensemble configure dict -map] is_dict ::tcl::dict::is_dict]
}
::clay::PROC ::tcl::dict::rmerge {args} {
  ::set result [dict create . {}]
  # Merge b into a, and handle nested dicts appropriately
  ::foreach b $args {
    for { k v } $b {
      ::set field [string trim $k :/]
      if {![::clay::tree::is_branch $b $k]} {
        # Element names that end in ":" are assumed to be literals
        set result $k $v
      } elseif { [exists $result $k] } {
        # key exists in a and b?  let's see if both values are dicts
        # both are dicts, so merge the dicts
        if { [is_dict [get $result $k]] && [is_dict $v] } {
          set result $k [rmerge [get $result $k] $v]
        } else {
          set result $k $v
        }
      } else {
        set result $k $v
      }
    }
  }
  return $result
} {
  namespace ensemble configure dict -map [dict replace\
      [namespace ensemble configure dict -map] rmerge ::tcl::dict::rmerge]
}
::clay::PROC ::clay::tree::is_branch { dict path } {
  set field [lindex $path end]
  if {[string index $field end] eq ":"} {
    return 0
  }
  if {[string index $field 0] eq "."} {
    return 0
  }
  if {[string index $field end] eq "/"} {
    return 1
  }
  return [dict exists $dict {*}$path .]
}
::clay::PROC ::clay::tree::print {dict} {
  ::set result {}
  ::set level -1
  ::clay::tree::_dictputb $level result $dict
  return $result
}
::clay::PROC ::clay::tree::_dictputb {level varname dict} {
  upvar 1 $varname result
  incr level
  dict for {field value} $dict {
    if {$field eq "."} continue
    if {[clay::tree::is_branch $dict $field]} {
      putb result "[string repeat "  " $level]$field \{"
      _dictputb $level result $value
      putb result "[string repeat "  " $level]\}"
    } else {
      putb result "[string repeat "  " $level][list $field $value]"
    }
  }
}
proc ::clay::tree::sanitize {dict} {
  ::set result {}
  ::set level -1
  ::clay::tree::_sanitizeb {} result $dict
  return $result
}
proc ::clay::tree::_sanitizeb {path varname dict} {
  upvar 1 $varname result
  dict for {field value} $dict {
    if {$field eq "."} continue
    if {[clay::tree::is_branch $dict $field]} {
      _sanitizeb [list {*}$path $field] result $value
    } else {
      dict set result {*}$path $field $value
    }
  }
}
proc ::clay::tree::storage {rawpath} {
  set isleafvar 0
  set path {}
  set tail [string index $rawpath end]
  foreach element $rawpath {
    set items [split [string trim $element /] /]
    foreach item $items {
      if {$item eq {}} continue
      lappend path $item
    }
  }
  return $path
}
proc ::clay::tree::dictset {varname args} {
  upvar 1 $varname result
  if {[llength $args] < 2} {
    error "Usage: ?path...? path value"
  } elseif {[llength $args]==2} {
    set rawpath [lindex $args 0]
  } else {
    set rawpath  [lrange $args 0 end-1]
  }
  set value [lindex $args end]
  set path [storage $rawpath]
  set dot .
  set one {}
  dict set result $dot $one
  set dpath {}
  foreach item [lrange $path 0 end-1] {
    set field $item
    lappend dpath [string trim $item /]
    dict set result {*}$dpath $dot $one
  }
  set field [lindex $rawpath end]
  set ext   [string index $field end]
  if {$ext eq {:} || ![dict is_dict $value]} {
    dict set result {*}$path $value
    return
  }
  if {$ext eq {/} && ![dict exists $result {*}$path $dot]} {
    dict set result {*}$path $dot $one
  }
  if {[dict exists $result {*}$path $dot]} {
    dict set result {*}$path [::clay::tree::merge [dict get $result {*}$path] $value]
    return
  }
  dict set result {*}$path $value
}
proc ::clay::tree::dictmerge {varname args} {
  upvar 1 $varname result
  set dot .
  set one {}
  dict set result $dot $one
  foreach dict $args {
    dict for {f v} $dict {
      set field [string trim $f /]
      set bbranch [clay::tree::is_branch $dict $f]
      if {![dict exists $result $field]} {
        dict set result $field $v
        if {$bbranch} {
          dict set result $field [clay::tree::merge $v]
        } else {
          dict set result $field $v
        }
      } elseif {[dict exists $result $field $dot]} {
        if {$bbranch} {
          dict set result $field [clay::tree::merge [dict get $result $field] $v]
        } else {
          dict set result $field $v
        }
      }
    }
  }
  return $result
}
proc ::clay::tree::merge {args} {
  ###
  # The result of a merge is always a dict with branches
  ###
  set dot .
  set one {}
  dict set result $dot $one
  set argument 0
  foreach b $args {
    # Merge b into a, and handle nested dicts appropriately
    if {![dict is_dict $b]} {
      error "Element $b is not a dictionary"
    }
    dict for { k v } $b {
      if {$k eq $dot} {
        dict set result $dot $one
        continue
      }
      set bbranch [is_branch $b $k]
      set field [string trim $k /]
      if { ![dict exists $result $field] } {
        if {$bbranch} {
          dict set result $field [merge $v]
        } else {
          dict set result $field $v
        }
      } else {
        set abranch [dict exists $result $field $dot]
        if {$abranch && $bbranch} {
          dict set result $field [merge [dict get $result $field] $v]
        } else {
          dict set result $field $v
          if {$bbranch} {
            dict set result $field $dot $one
          }
        }
      }
    }
  }
  return $result
}
::clay::PROC ::tcl::dict::isnull {dictionary args} {
  if {![exists $dictionary {*}$args]} {return 1}
  return [expr {[get $dictionary {*}$args] in {{} NULL null}}]
} {
  namespace ensemble configure dict -map [dict replace\
      [namespace ensemble configure dict -map] isnull ::tcl::dict::isnull]
}

###
# END: dict.tcl
###
###
# START: list.tcl
###
::clay::PROC ::clay::ladd {varname args} {
  upvar 1 $varname var
  if ![info exists var] {
      set var {}
  }
  foreach item $args {
    if {$item in $var} continue
    lappend var $item
  }
  return $var
}
::clay::PROC ::clay::ldelete {varname args} {
  upvar 1 $varname var
  if ![info exists var] {
      return
  }
  foreach item [lsort -unique $args] {
    while {[set i [lsearch $var $item]]>=0} {
      set var [lreplace $var $i $i]
    }
  }
  return $var
}
::clay::PROC ::clay::lrandom list {
  set len [llength $list]
  set idx [expr int(rand()*$len)]
  return [lindex $list $idx]
}

###
# END: list.tcl
###
###
# START: dictargs.tcl
###
namespace eval ::dictargs {
}
if {[info commands ::dictargs::parse] eq {}} {
  proc ::dictargs::parse {argdef argdict} {
    set result {}
    dict for {field info} $argdef {
      if {![string is alnum [string index $field 0]]} {
        error "$field is not a simple variable name"
      }
      upvar 1 $field _var
      set aliases {}
      if {[dict exists $argdict $field]} {
        set _var [dict get $argdict $field]
        continue
      }
      if {[dict exists $info aliases:]} {
        set found 0
        foreach {name} [dict get $info aliases:] {
          if {[dict exists $argdict $name]} {
            set _var [dict get $argdict $name]
            set found 1
            break
          }
        }
        if {$found} continue
      }
      if {[dict exists $info default:]} {
        set _var [dict get $info default:]
        continue
      }
      set mandatory 1
      if {[dict exists $info mandatory:]} {
        set mandatory [dict get $info mandatory:]
      }
      if {$mandatory} {
        error "$field is required"
      }
    }
  }
}
proc ::dictargs::proc {name argspec body} {
  set result {}
  append result "::dictargs::parse \{$argspec\} \$args" \;
  append result $body
  uplevel 1 [list ::proc $name [list [list args [list dictargs $argspec]]] $result]
}
proc ::dictargs::method {name argspec body} {
  set class [lindex [::info level -1] 1]
  set result {}
  append result "::dictargs::parse \{$argspec\} \$args" \;
  append result $body
  oo::define $class method $name [list [list args [list dictargs $argspec]]] $result
}

###
# END: dictargs.tcl
###
###
# START: dialect.tcl
###
namespace eval ::clay::dialect {
  namespace export create
  foreach {flag test} {
    tip470 {package vsatisfies [package provide Tcl] 8.7}
  } {
    if {![info exists ::clay::dialect::has($flag)]} {
      set ::clay::dialect::has($flag) [eval $test]
    }
  }
}
proc ::clay::dialect::Push {class} {
  ::variable class_stack
  lappend class_stack $class
}
proc ::clay::dialect::Peek {} {
  ::variable class_stack
  return [lindex $class_stack end]
}
proc ::clay::dialect::Pop {} {
  ::variable class_stack
  set class_stack [lrange $class_stack 0 end-1]
}
if {$::clay::dialect::has(tip470)} {
proc ::clay::dialect::current_class {} {
  return [uplevel 1 self]
}
} else {
proc ::clay::dialect::current_class {} {
  tailcall Peek
}
}
proc ::clay::dialect::create {name {parent ""}} {
  variable has
  set NSPACE [NSNormalize [uplevel 1 {namespace current}] $name]
  ::namespace eval $NSPACE {::namespace eval define {}}
  ###
  # Build the "define" namespace
  ###

  if {$parent eq ""} {
    ###
    # With no "parent" language, begin with all of the keywords in
    # oo::define
    ###
    foreach command [info commands ::oo::define::*] {
      set procname [namespace tail $command]
      interp alias {} ${NSPACE}::define::$procname {} \
        ::clay::dialect::DefineThunk $procname
    }
    # Create an empty dynamic_methods proc
    proc ${NSPACE}::dynamic_methods {class} {}
    namespace eval $NSPACE {
      ::namespace export dynamic_methods
      ::namespace eval define {::namespace export *}
    }
    set ANCESTORS {}
  } else {
    ###
    # If we have a parent language, that language already has the
    # [oo::define] keywords as well as additional keywords and behaviors.
    # We should begin with that
    ###
    set pnspace [NSNormalize [uplevel 1 {namespace current}] $parent]
    apply [list parent {
      ::namespace export dynamic_methods
      ::namespace import -force ${parent}::dynamic_methods
    } $NSPACE] $pnspace

    apply [list parent {
      ::namespace import -force ${parent}::define::*
      ::namespace export *
    } ${NSPACE}::define] $pnspace
      set ANCESTORS [list ${pnspace}::object]
  }
  ###
  # Build our dialect template functions
  ###
  proc ${NSPACE}::define {oclass args} [string map [list %NSPACE% $NSPACE] {
  ###
  # To facilitate library reloading, allow
  # a dialect to create a class from DEFINE
  ###
  set class [::clay::dialect::NSNormalize [uplevel 1 {namespace current}] $oclass]
    if {[info commands $class] eq {}} {
      %NSPACE%::class create $class {*}${args}
    } else {
      ::clay::dialect::Define %NSPACE% $class {*}${args}
    }
}]
  interp alias {} ${NSPACE}::define::current_class {} \
    ::clay::dialect::current_class
  interp alias {} ${NSPACE}::define::aliases {} \
    ::clay::dialect::Aliases $NSPACE
  interp alias {} ${NSPACE}::define::superclass {} \
    ::clay::dialect::SuperClass $NSPACE

  if {[info command ${NSPACE}::class] ne {}} {
    ::rename ${NSPACE}::class {}
  }
  ###
  # Build the metaclass for our language
  ###
  ::oo::class create ${NSPACE}::class {
    superclass ::clay::dialect::MotherOfAllMetaClasses
  }
  # Wire up the create method to add in the extra argument we need; the
  # MotherOfAllMetaClasses will know what to do with it.
  ::oo::objdefine ${NSPACE}::class \
    method create {name {definitionScript ""}} \
      "next \$name [list ${NSPACE}::define] \$definitionScript"

  ###
  # Build the mother of all classes. Note that $ANCESTORS is already
  # guaranteed to be a list in canonical form.
  ###
  uplevel #0 [string map [list %NSPACE% [list $NSPACE] %name% [list $name] %ANCESTORS% $ANCESTORS] {
    %NSPACE%::class create %NSPACE%::object {
     superclass %ANCESTORS%
      # Put MOACish stuff in here
    }
  }]
  if { "${NSPACE}::class" ni $::clay::dialect::core_classes } {
    lappend ::clay::dialect::core_classes "${NSPACE}::class"
  }
  if { "${NSPACE}::object" ni $::clay::dialect::core_classes } {
    lappend ::clay::dialect::core_classes "${NSPACE}::object"
  }
}
proc ::clay::dialect::NSNormalize {namespace qualname} {
  if {![string match ::* $qualname]} {
    set qualname ${namespace}::$qualname
  }
  regsub -all {::+} $qualname "::"
}
proc ::clay::dialect::DefineThunk {target args} {
  tailcall ::oo::define [Peek] $target {*}$args
}
proc ::clay::dialect::Canonical {namespace NSpace class} {
  namespace upvar $namespace cname cname
  #if {[string match ::* $class]} {
  #  return $class
  #}
  if {[info exists cname($class)]} {
    return $cname($class)
  }
  if {[info exists ::clay::dialect::cname($class)]} {
    return $::clay::dialect::cname($class)
  }
  if {[info exists ::clay::dialect::cname(${NSpace}::${class})]} {
    return $::clay::dialect::cname(${NSpace}::${class})
  }
  foreach item [list "${NSpace}::$class" "::$class"] {
    if {[info commands $item] ne {}} {
      return $item
    }
  }
  return ${NSpace}::$class
}
proc ::clay::dialect::Define {namespace class args} {
  Push $class
  try {
  	if {[llength $args]==1} {
      namespace eval ${namespace}::define [lindex $args 0]
    } else {
      ${namespace}::define::[lindex $args 0] {*}[lrange $args 1 end]
    }
  	${namespace}::dynamic_methods $class
  } finally {
    Pop
  }
}
proc ::clay::dialect::Aliases {namespace args} {
  set class [Peek]
  namespace upvar $namespace cname cname
  set NSpace [join [lrange [split $class ::] 1 end-2] ::]
  set cname($class) $class
  foreach name $args {
    set cname($name) $class
    #set alias $name
    set alias [NSNormalize $NSpace $name]
    # Add a local metaclass reference
    if {![info exists ::clay::dialect::cname($alias)]} {
      lappend ::clay::dialect::aliases($class) $alias
      ##
      # Add a global reference, first come, first served
      ##
      set ::clay::dialect::cname($alias) $class
    }
  }
}
proc ::clay::dialect::SuperClass {namespace args} {
  set class [Peek]
  namespace upvar $namespace class_info class_info
  dict set class_info($class) superclass 1
  set ::clay::dialect::cname($class) $class
  set NSpace [join [lrange [split $class ::] 1 end-2] ::]
  set unique {}
  foreach item $args {
    set Item [Canonical $namespace $NSpace $item]
    dict set unique $Item $item
  }
  set root ${namespace}::object
  if {$class ne $root} {
    dict set unique $root $root
  }
  tailcall ::oo::define $class superclass {*}[dict keys $unique]
}
if {[info command ::clay::dialect::MotherOfAllMetaClasses] eq {}} {
::oo::class create ::clay::dialect::MotherOfAllMetaClasses {
  superclass ::oo::class
  constructor {define definitionScript} {
    $define [self] {
      superclass
    }
    $define [self] $definitionScript
  }
  method aliases {} {
    if {[info exists ::clay::dialect::aliases([self])]} {
      return $::clay::dialect::aliases([self])
    }
  }
}
}
namespace eval ::clay::dialect {
  variable core_classes {::oo::class ::oo::object}
}

###
# END: dialect.tcl
###
###
# START: metaclass.tcl
###
::clay::dialect::create ::clay
proc ::clay::dynamic_methods class {
  foreach command [info commands [namespace current]::dynamic_methods_*] {
    $command $class
  }
}
proc ::clay::dynamic_methods_class {thisclass} {
  set methods {}
  set mdata [$thisclass clay find class_typemethod]
  foreach {method info} $mdata {
    if {$method eq {.}} continue
    set method [string trimright $method :/-]
    if {$method in $methods} continue
    lappend methods $method
    set arglist [dict getnull $info arglist]
    set body    [dict getnull $info body]
    ::oo::objdefine $thisclass method $method $arglist $body
  }
}
proc ::clay::define::Array {name {values {}}} {
  set class [current_class]
  set name [string trim $name :/]
  $class clay branch array $name
  dict for {var val} $values {
    $class clay set array/ $name $var $val
  }
}
proc ::clay::define::Delegate {name info} {
  set class [current_class]
  foreach {field value} $info {
    $class clay set component/ [string trim $name :/]/ $field $value
  }
}
proc ::clay::define::constructor {arglist rawbody} {
  set body {
my variable DestroyEvent
set DestroyEvent 0
::clay::object_create [self] [info object class [self]]
# Initialize public variables and options
my InitializePublic
  }
  append body $rawbody
  set class [current_class]
  ::oo::define $class constructor $arglist $body
}
proc ::clay::define::Class_Method {name arglist body} {
  set class [current_class]
  $class clay set class_typemethod/ [string trim $name :/] [dict create arglist $arglist body $body]
}
proc ::clay::define::class_method {name arglist body} {
  set class [current_class]
  $class clay set class_typemethod/ [string trim $name :/] [dict create arglist $arglist body $body]
}
proc ::clay::define::clay {args} {
  set class [current_class]
  if {[lindex $args 0] in "cget set branch"} {
    $class clay {*}$args
  } else {
    $class clay set {*}$args
  }
}
proc ::clay::define::destructor rawbody {
  set body {
# Run the destructor once and only once
set self [self]
my variable DestroyEvent
if {$DestroyEvent} return
set DestroyEvent 1
}
  append body $rawbody
  ::oo::define [current_class] destructor $body
}
proc ::clay::define::Dict {name {values {}}} {
  set class [current_class]
  set name [string trim $name :/]
  $class clay branch dict $name
  foreach {var val} $values {
    $class clay set dict/ $name/ $var $val
  }
}
proc ::clay::define::Option {name args} {
  set class [current_class]
  set dictargs {default {}}
  foreach {var val} [::clay::args_to_dict {*}$args] {
    dict set dictargs [string trim $var -:/] $val
  }
  set name [string trimleft $name -]

  ###
  # Option Class handling
  ###
  set optclass [dict getnull $dictargs class]
  if {$optclass ne {}} {
    foreach {f v} [$class clay find option_class $optclass] {
      if {![dict exists $dictargs $f]} {
        dict set dictargs $f $v
      }
    }
    if {$optclass eq "variable"} {
      variable $name [dict getnull $dictargs default]
    }
  }
  foreach {f v} $dictargs {
    $class clay set option $name $f $v
  }
}
proc ::clay::define::Method {name argstyle argspec body} {
  set class [current_class]
  set result {}
  switch $argstyle {
    dictargs {
      append result "::dictargs::parse \{$argspec\} \$args" \;
    }
  }
  append result $body
  oo::define $class method $name [list [list args [list dictargs $argspec]]] $result
}
proc ::clay::define::Option_Class {name args} {
  set class [current_class]
  set dictargs {default {}}
  set name [string trimleft $name -:]
  foreach {f v} [::clay::args_to_dict {*}$args] {
    $class clay set option_class $name [string trim $f -/:] $v
  }
}
proc ::clay::define::Variable {name {default {}}} {
  set class [current_class]
  set name [string trimright $name :/]
  $class clay set variable/ $name $default
}

###
# END: metaclass.tcl
###
###
# START: ensemble.tcl
###
::namespace eval ::clay::define {
}
proc ::clay::ensemble_methodbody {ensemble einfo} {
  set default standard
  set preamble {}
  set eswitch {}
  set Ensemble [string totitle $ensemble]
  if {$Ensemble eq "."} continue
  foreach {msubmethod minfo} [lsort -dictionary -stride 2 $einfo] {
    if {$msubmethod eq "."} continue
    if {![dict exists $minfo body:]} {
      continue
    }
    set submethod [string trim $msubmethod :/-]
    if {$submethod eq "default"} {
      set default [dict get $minfo body:]
    } else {
      dict set eswitch $submethod [dict get $minfo body:]
    }
    if {[dict exists $submethod aliases:]} {
      foreach alias [dict get $minfo aliases:] {
        if {![dict exists $eswitch $alias]} {
          dict set eswitch $alias [dict get $minfo body:]
        }
      }
    }
  }
  set methodlist [lsort -dictionary [dict keys $eswitch]]
  if {![dict exists $eswitch <list>]} {
    dict set eswitch <list> {return $methodlist}
  }
  if {$default eq "standard"} {
    set default "error \"unknown method $ensemble \$method. Valid: \$methodlist\""
  }
  dict set eswitch default $default
  set mbody {}
  append mbody \n [list set methodlist $methodlist]
  append mbody \n "switch -- \$method \{$eswitch\}" \n
  return $mbody
}
::proc ::clay::define::Ensemble {rawmethod args} {
  if {[llength $args]==2} {
    lassign $args argspec body
    set argstyle tcl
  } elseif {[llength $args]==3} {
    lassign $args argstyle argspec body
  } else {
    error "Usage: Ensemble name ?argstyle? argspec body"
  }
  set class [current_class]
  #if {$::clay::trace>2} {
  #  puts [list $class Ensemble $rawmethod $argspec $body]
  #}
  set mlist [split $rawmethod "::"]
  set ensemble [string trim [lindex $mlist 0] :/]
  set method   [string trim [lindex $mlist 2] :/]
  if {[string index $method 0] eq "_"} {
    $class clay set method_ensemble $ensemble $method $body
    return
  }
  set realmethod  [string totitle $ensemble]_${method}
  set realbody {}
  if {$argstyle eq "dictargs"} {
    append realbody "::dictargs::parse \{$argspec\} \$args" \n
  }
  if {[$class clay exists method_ensemble $ensemble _preamble]} {
    append realbody [$class clay get method_ensemble $ensemble _preamble] \n
  }
  append realbody $body
  if {$method eq "default"} {
    $class clay set method_ensemble $ensemble $method: "tailcall my $realmethod \$method {*}\$args"
    if {$argstyle eq "dictargs"} {
      oo::define $class method $realmethod [list method [list args $argspec]] $realbody
    } else {
      oo::define $class method $realmethod [list method {*}$argspec] $realbody
    }
  } else {
    $class clay set method_ensemble $ensemble $method: "tailcall my $realmethod {*}\$args"
    if {$argstyle eq "dictargs"} {
      oo::define $class method $realmethod [list [list args $argspec]] $realbody
    } else {
      oo::define $class method $realmethod $argspec $realbody
    }
  }
  if {$::clay::trace>2} {
    puts [list $class clay set method_ensemble/ $ensemble [string trim $method :/]  ...]
  }
}

###
# END: ensemble.tcl
###
###
# START: class.tcl
###
::oo::define ::clay::class {
  method clay {submethod args} {
    my variable clay
    if {![info exists clay]} {
      set clay {}
    }
    switch $submethod {
      ancestors {
        tailcall ::clay::ancestors [self]
      }
      branch {
        set path [::clay::tree::storage $args]
        if {![dict exists $clay {*}$path .]} {
          dict set clay {*}$path . {}
        }
      }
      exists {
        if {![info exists clay]} {
          return 0
        }
        set path [::clay::tree::storage $args]
        if {[dict exists $clay {*}$path]} {
          return 1
        }
        if {[dict exists $clay {*}[lrange $path 0 end-1] [lindex $path end]:]} {
          return 1
        }
        return 0
      }
      dump {
        return $clay
      }
      dget {
         if {![info exists clay]} {
          return {}
        }
        set path [::clay::tree::storage $args]
        if {[dict exists $clay {*}$path]} {
          return [dict get $clay {*}$path]
        }
        if {[dict exists $clay {*}[lrange $path 0 end-1] [lindex $path end]:]} {
          return [dict get $clay {*}[lrange $path 0 end-1] [lindex $path end]:]
        }
        return {}
      }
      is_branch {
        set path [::clay::tree::storage $args]
        return [dict exists $clay {*}$path .]
      }
      getnull -
      get {
        if {![info exists clay]} {
          return {}
        }
        set path [::clay::tree::storage $args]
        if {[llength $path]==0} {
          return $clay
        }
        if {[dict exists $clay {*}$path .]} {
          return [::clay::tree::sanitize [dict get $clay {*}$path]]
        }
        if {[dict exists $clay {*}$path]} {
          return [dict get $clay {*}$path]
        }
        if {[dict exists $clay {*}[lrange $path 0 end-1] [lindex $path end]:]} {
          return [dict get $clay {*}[lrange $path 0 end-1] [lindex $path end]:]
        }
        return {}
      }
      find {
        set path [::clay::tree::storage $args]
        if {![info exists clay]} {
          set clay {}
        }
        set clayorder [::clay::ancestors [self]]
        set found 0
        if {[llength $path]==0} {
          set result [dict create . {}]
          foreach class $clayorder {
            ::clay::tree::dictmerge result [$class clay dump]
          }
          return [::clay::tree::sanitize $result]
        }
        foreach class $clayorder {
          if {[$class clay exists {*}$path .]} {
            # Found a branch break
            set found 1
            break
          }
          if {[$class clay exists {*}$path]} {
            # Found a leaf. Return that value immediately
            return [$class clay get {*}$path]
          }
          if {[dict exists $clay {*}[lrange $path 0 end-1] [lindex $path end]:]} {
            return [dict get $clay {*}[lrange $path 0 end-1] [lindex $path end]:]
          }
        }
        if {!$found} {
          return {}
        }
        set result {}
        # Leaf searches return one data field at a time
        # Search in our local dict
        # Search in the in our list of classes for an answer
        foreach class [lreverse $clayorder] {
          ::clay::tree::dictmerge result [$class clay dget {*}$path]
        }
        return [::clay::tree::sanitize $result]
      }
      merge {
        foreach arg $args {
          ::clay::tree::dictmerge clay {*}$arg
        }
      }
      noop {
        # Do nothing. Used as a sign of clay savviness
      }
      search {
        foreach aclass [::clay::ancestors [self]] {
          if {[$aclass clay exists {*}$args]} {
            return [$aclass clay get {*}$args]
          }
        }
      }
      set {
        ::clay::tree::dictset clay {*}$args
      }
      unset {
        dict unset clay {*}$args
      }
      default {
        dict $submethod clay {*}$args
      }
    }
  }
}

###
# END: class.tcl
###
###
# START: object.tcl
###
::oo::define ::clay::object {
  method clay {submethod args} {
    my variable clay claycache clayorder config option_canonical
    if {![info exists clay]} {set clay {}}
    if {![info exists claycache]} {set claycache {}}
    if {![info exists config]} {set config {}}
    if {![info exists clayorder] || [llength $clayorder]==0} {
      set clayorder {}
      if {[dict exists $clay cascade]} {
        dict for {f v} [dict get $clay cascade] {
          if {$f eq "."} continue
          if {[info commands $v] ne {}} {
            lappend clayorder $v
          }
        }
      }
      lappend clayorder {*}[::clay::ancestors [info object class [self]] {*}[lreverse [info object mixins [self]]]]
    }
    switch $submethod {
      ancestors {
        return $clayorder
      }
      branch {
        set path [::clay::tree::storage $args]
        if {![dict exists $clay {*}$path .]} {
          dict set clay {*}$path . {}
        }
      }
      busy {
        my variable clay_busy
        if {[llength $args]} {
          set clay_busy [string is true [lindex $args 0]]
          set claycache {}
        }
        if {![info exists clay_busy]} {
          set clay_busy 0
        }
        return $clay_busy
      }
      cache {
        set path [lindex $args 0]
        set value [lindex $args 1]
        dict set claycache $path $value
      }
      cget {
        # Leaf searches return one data field at a time
        # Search in our local dict
        if {[llength $args]==1} {
          set field [string trim [lindex $args 0] -:/]
          if {[info exists option_canonical($field)]} {
            set field $option_canonical($field)
          }
          if {[dict exists $config $field]} {
            return [dict get $config $field]
          }
        }
        set path [::clay::tree::storage $args]
        if {[dict exists $clay {*}$path]} {
          return [dict get $clay {*}$path]
        }
        # Search in our local cache
        if {[dict exists $claycache {*}$path]} {
          if {[dict exists $claycache {*}$path .]} {
            return [dict remove [dict get $claycache {*}$path] .]
          } else {
            return [dict get $claycache {*}$path]
          }
        }
        # Search in the in our list of classes for an answer
        foreach class $clayorder {
          if {[$class clay exists {*}$path]} {
            set value [$class clay get {*}$path]
            dict set claycache {*}$path $value
            return $value
          }
          if {[$class clay exists const {*}$path]} {
            set value [$class clay get const {*}$path]
            dict set claycache {*}$path $value
            return $value
          }
          if {[$class clay exists option {*}$path default]} {
            set value [$class clay get option {*}$path default]
            dict set claycache {*}$path $value
            return $value
          }
        }
        return {}
      }
      delegate {
        if {![dict exists $clay .delegate <class>]} {
          dict set clay .delegate <class> [info object class [self]]
        }
        if {[llength $args]==0} {
          return [dict get $clay .delegate]
        }
        if {[llength $args]==1} {
          set stub <[string trim [lindex $args 0] <>]>
          if {![dict exists $clay .delegate $stub]} {
            return {}
          }
          return [dict get $clay .delegate $stub]
        }
        if {([llength $args] % 2)} {
          error "Usage: delegate
    OR
    delegate stub
    OR
    delegate stub OBJECT ?stub OBJECT? ..."
        }
        foreach {stub object} $args {
          set stub <[string trim $stub <>]>
          dict set clay .delegate $stub $object
          oo::objdefine [self] forward ${stub} $object
          oo::objdefine [self] export ${stub}
        }
      }
      dump {
        # Do a full dump of clay data
        set result {}
        # Search in the in our list of classes for an answer
        foreach class $clayorder {
          ::clay::tree::dictmerge result [$class clay dump]
        }
        ::clay::tree::dictmerge result $clay
        return $result
      }
      ensemble_map {
        set path [::clay::tree::storage method_ensemble]
        if {[dict exists $claycache {*}$path]} {
          return [dict get $claycache {*}$path]
        }
        set emap {}
        foreach class $clayorder {
          if {![$class clay exists {*}$path .]} continue
          dict for {ensemble einfo} [$class clay dget {*}$path] {
            if {$ensemble eq "."} continue
            dict for {method body} $einfo {
              if {$method eq "."} continue
              dict set emap $ensemble $method class: $class
              dict set emap $ensemble $method body: $body
            }
          }
        }
        if {[dict exists $clay {*}$path]} {
          dict for {ensemble einfo} [dict get $clay {*}$path] {
            dict for {method body} $einfo {
              if {$method eq "."} continue
              dict set emap $ensemble $method class: $class
              dict set emap $ensemble $method body: $body
            }
          }
        }
        dict set claycache {*}$path $emap
        return $emap
      }
      eval {
        set script [lindex $args 0]
        set buffer {}
        set thisline {}
        foreach line [split $script \n] {
          append thisline $line
          if {![info complete $thisline]} {
            append thisline \n
            continue
          }
          set thisline [string trim $thisline]
          if {[string index $thisline 0] eq "#"} continue
          if {[string length $thisline]==0} continue
          if {[lindex $thisline 0] eq "my"} {
            # Line already calls out "my", accept verbatim
            append buffer $thisline \n
          } elseif {[string range $thisline 0 2] eq "::"} {
            # Fully qualified commands accepted verbatim
            append buffer $thisline \n
          } elseif {
            append buffer "my $thisline" \n
          }
          set thisline {}
        }
        eval $buffer
      }
      evolve -
      initialize {
        my InitializePublic
      }
      exists {
        # Leaf searches return one data field at a time
        # Search in our local dict
        set path [::clay::tree::storage $args]
        if {[dict exists $clay {*}$path]} {
          return 1
        }
        # Search in our local cache
        if {[dict exists $claycache {*}$path]} {
          return 2
        }
        set count 2
        # Search in the in our list of classes for an answer
        foreach class $clayorder {
          incr count
          if {[$class clay exists {*}$path]} {
            return $count
          }
        }
        return 0
      }
      flush {
        set claycache {}
        set clayorder [::clay::ancestors [info object class [self]] {*}[lreverse [info object mixins [self]]]]
      }
      forward {
        oo::objdefine [self] forward {*}$args
      }
      dget {
        set path [::clay::tree::storage $args]
        if {[llength $path]==0} {
          # Do a full dump of clay data
          set result {}
          # Search in the in our list of classes for an answer
          foreach class $clayorder {
            ::clay::tree::dictmerge result [$class clay dump]
          }
          ::clay::tree::dictmerge result $clay
          return $result
        }
        if {[dict exists $clay {*}$path] && ![dict exists $clay {*}$path .]} {
          # Path is a leaf
          return [dict get $clay {*}$path]
        }
        # Search in our local cache
        if {[my clay search $path value isleaf]} {
          return $value
        }

        set found 0
        set branch [dict exists $clay {*}$path .]
        foreach class $clayorder {
          if {[$class clay exists {*}$path .]} {
            set found 1
            break
          }
          if {!$branch && [$class clay exists {*}$path]} {
            set result [$class clay dget {*}$path]
            my clay cache $path $result
            return $result
          }
        }
        # Path is a branch
        set result [dict getnull $clay {*}$path]
        foreach class $clayorder {
          if {![$class clay exists {*}$path .]} continue
          ::clay::tree::dictmerge result [$class clay dget {*}$path]
        }
        #if {[dict exists $clay {*}$path .]} {
        #  ::clay::tree::dictmerge result
        #}
        my clay cache $path $result
        return $result
      }
      getnull -
      get {
        set path [::clay::tree::storage $args]
        if {[llength $path]==0} {
          # Do a full dump of clay data
          set result {}
          # Search in the in our list of classes for an answer
          foreach class $clayorder {
            ::clay::tree::dictmerge result [$class clay dump]
          }
          ::clay::tree::dictmerge result $clay
          return [::clay::tree::sanitize $result]
        }
        if {[dict exists $clay {*}$path] && ![dict exists $clay {*}$path .]} {
          # Path is a leaf
          return [dict get $clay {*}$path]
        }
        # Search in our local cache
        if {[my clay search $path value isleaf]} {
          if {!$isleaf} {
            return [clay::tree::sanitize $value]
          } else {
            return $value
          }
        }
        set found 0
        set branch [dict exists $clay {*}$path .]
        foreach class $clayorder {
          if {[$class clay exists {*}$path .]} {
            set found 1
            break
          }
          if {!$branch && [$class clay exists {*}$path]} {
            set result [$class clay dget {*}$path]
            my clay cache $path $result
            return $result
          }
        }
        # Path is a branch
        set result [dict getnull $clay {*}$path]
        #foreach class [lreverse $clayorder] {
        #  if {![$class clay exists {*}$path .]} continue
        #  ::clay::tree::dictmerge result [$class clay dget {*}$path]
        #}
        foreach class $clayorder {
          if {![$class clay exists {*}$path .]} continue
          ::clay::tree::dictmerge result [$class clay dget {*}$path]
        }
        #if {[dict exists $clay {*}$path .]} {
        #  ::clay::tree::dictmerge result [dict get $clay {*}$path]
        #}
        my clay cache $path $result
        return [clay::tree::sanitize $result]
      }
      leaf {
        # Leaf searches return one data field at a time
        # Search in our local dict
        set path [::clay::tree::storage $args]
        if {[dict exists $clay {*}$path .]} {
          return [clay::tree::sanitize [dict get $clay {*}$path]]
        }
        if {[dict exists $clay {*}$path]} {
          return [dict get $clay {*}$path]
        }
        # Search in our local cache
        if {[my clay search $path value isleaf]} {
          if {!$isleaf} {
            return [clay::tree::sanitize $value]
          } else {
            return $value
          }
        }
        # Search in the in our list of classes for an answer
        foreach class $clayorder {
          if {[$class clay exists {*}$path]} {
            set value [$class clay get {*}$path]
            my clay cache $path $value
            return $value
          }
        }
      }
      merge {
        foreach arg $args {
          ::clay::tree::dictmerge clay {*}$arg
        }
      }
      mixin {
        ###
        # Mix in the class
        ###
        my clay flush
        set prior  [info object mixins [self]]
        set newmixin {}
        foreach item $args {
          lappend newmixin ::[string trimleft $item :]
        }
        set newmap $args
        foreach class $prior {
          if {$class ni $newmixin} {
            set script [$class clay search mixin/ unmap-script]
            if {[string length $script]} {
              if {[catch $script err errdat]} {
                puts stderr "[self] MIXIN ERROR POPPING $class:\n[dict get $errdat -errorinfo]"
              }
            }
          }
        }
        ::oo::objdefine [self] mixin {*}$args
        ###
        # Build a compsite map of all ensembles defined by the object's current
        # class as well as all of the classes being mixed in
        ###
        my InitializePublic
        foreach class $newmixin {
          if {$class ni $prior} {
            set script [$class clay search mixin/ map-script]
            if {[string length $script]} {
              if {[catch $script err errdat]} {
                puts stderr "[self] MIXIN ERROR PUSHING $class:\n[dict get $errdat -errorinfo]"
              }
            }
          }
        }
        foreach class $newmixin {
          set script [$class clay search mixin/ react-script]
          if {[string length $script]} {
            if {[catch $script err errdat]} {
              puts stderr "[self] MIXIN ERROR PEEKING $class:\n[dict get $errdat -errorinfo]"
            }
            break
          }
        }
      }
      mixinmap {
        if {![dict exists $clay .mixin]} {
          dict set clay .mixin {}
        }
        if {[llength $args]==0} {
          return [dict get $clay .mixin]
        } elseif {[llength $args]==1} {
          return [dict getnull $clay .mixin [lindex $args 0]]
        } else {
          dict for {slot classes} $args {
            dict set clay .mixin $slot $classes
          }
          set classlist {}
          dict for {item class} [dict get $clay .mixin] {
            if {$class ne {}} {
              lappend classlist $class
            }
          }
          my clay mixin {*}[lreverse $classlist]
        }
      }
      provenance {
        if {[dict exists $clay {*}$args]} {
          return self
        }
        foreach class $clayorder {
          if {[$class clay exists {*}$args]} {
            return $class
          }
        }
        return {}
      }
      refcount {
        my variable refcount
        if {![info exists refcount]} {
          return 0
        }
        return $refcount
      }
      refcount_incr {
        my variable refcount
        incr refcount
      }
      refcount_decr {
        my variable refcount
        incr refcount -1
        if {$refcount <= 0} {
          ::clay::object_destroy [self]
        }
      }
      replace {
        set clay [lindex $args 0]
      }
      search {
        set path [lindex $args 0]
        upvar 1 [lindex $args 1] value [lindex $args 2] isleaf
        set isleaf [expr {![dict exists $claycache $path .]}]
        if {[dict exists $claycache $path]} {
          set value [dict get $claycache $path]
          return 1
        }
        return 0
      }
      source {
        source [lindex $args 0]
      }
      set {
        #puts [list [self] clay SET {*}$args]
        ::clay::tree::dictset clay {*}$args
      }
      default {
        dict $submethod clay {*}$args
      }
    }
  }
  method InitializePublic {} {
    my variable clayorder clay claycache config option_canonical clay_busy
    if {[info exists clay_busy] && $clay_busy} {
      # Avoid repeated calls to InitializePublic if we know that someone is
      # going to invoke it at the end of whatever process is going on
      return
    }
    set claycache {}
    set clayorder [::clay::ancestors [info object class [self]] {*}[lreverse [info object mixins [self]]]]
    if {![info exists clay]} {
      set clay {}
    }
    if {![info exists config]} {
      set config {}
    }
    dict for {var value} [my clay get variable] {
      if { $var in {. clay} } continue
      set var [string trim $var :/]
      my variable $var
      if {![info exists $var]} {
        if {$::clay::trace>2} {puts [list initialize variable $var $value]}
        set $var $value
      }
    }
    dict for {var value} [my clay get dict/] {
      if { $var in {. clay} } continue
      set var [string trim $var :/]
      my variable $var
      if {![info exists $var]} {
        set $var {}
      }
      foreach {f v} $value {
        if {$f eq "."} continue
        if {![dict exists ${var} $f]} {
          if {$::clay::trace>2} {puts [list initialize dict $var $f $v]}
          dict set ${var} $f $v
        }
      }
    }
    foreach {var value} [my clay get array/] {
      if { $var in {. clay} } continue
      set var [string trim $var :/]
      if { $var eq {clay} } continue
      my variable $var
      if {![info exists $var]} { array set $var {} }
      foreach {f v} $value {
        if {![array exists ${var}($f)]} {
          if {$f eq "."} continue
          if {$::clay::trace>2} {puts [list initialize array $var\($f\) $v]}
          set ${var}($f) $v
        }
      }
    }
    foreach {field info} [my clay get option/] {
      if { $field in {. clay} } continue
      set field [string trim $field -/:]
      foreach alias [dict getnull $info aliases] {
        set option_canonical($alias) $field
      }
      if {[dict exists $config $field]} continue
      set getcmd [dict getnull $info default-command]
      if {$getcmd ne {}} {
        set value [{*}[string map [list %field% $field %self% [namespace which my]] $getcmd]]
      } else {
        set value [dict getnull $info default]
      }
      dict set config $field $value
      set setcmd [dict getnull $info set-command]
      if {$setcmd ne {}} {
        {*}[string map [list %field% [list $field] %value% [list $value] %self% [namespace which my]] $setcmd]
      }
    }

    foreach {ensemble einfo} [my clay ensemble_map] {
      #if {[dict exists $einfo _body]} continue
      if {$ensemble eq "."} continue
      set body [::clay::ensemble_methodbody $ensemble $einfo]
      if {$::clay::trace>2} {
        set rawbody $body
        set body {puts [list [self] <object> [self method]]}
        append body \n $rawbody
      }
      oo::objdefine [self] method $ensemble {{method default} args} $body
    }
  }
}
::clay::object clay branch array
::clay::object clay branch mixin
::clay::object clay branch option
::clay::object clay branch dict clay
::clay::object clay set variable DestroyEvent 0

###
# END: object.tcl
###
###
# START: event.tcl
###
if {[info commands ::cron::object_destroy] eq {}} {
  # Provide a noop if we aren't running with the cron scheduler
  namespace eval ::cron {}
  proc ::cron::object_destroy args {}
}
::namespace eval ::clay::event {
}
proc ::clay::cleanup {} {
  if {![info exists ::clay::idle_destroy]} return
  foreach obj $::clay::idle_destroy {
    if {[info commands $obj] ne {}} {
      catch {$obj destroy}
    }
  }
  set ::clay::idle_destroy {}
}
proc ::clay::object_create {objname {class {}}} {
  #if {$::clay::trace>0} {
  #  puts [list $objname CREATE]
  #}
}
proc ::clay::object_rename {object newname} {
  if {$::clay::trace>0} {
    puts [list $object RENAME -> $newname]
  }
}
proc ::clay::object_destroy args {
  if {![info exists ::clay::idle_destroy]} {
    set ::clay::idle_destroy {}
  }
  foreach objname $args {
    if {$::clay::trace>0} {
      puts [list $objname DESTROY]
    }
    ::cron::object_destroy $objname
    if {$objname in $::clay::idle_destroy} continue
    lappend ::clay::idle_destroy $objname
  }
}
proc ::clay::event::cancel {self {task *}} {
  variable timer_event
  variable timer_script

  foreach {id event} [array get timer_event $self:$task] {
    ::after cancel $event
    set timer_event($id) {}
    set timer_script($id) {}
  }
}
proc ::clay::event::generate {self event args} {
  set wholist [Notification_list $self $event]
  if {$wholist eq {}} return
  set dictargs [::oo::meta::args_to_options {*}$args]
  set info $dictargs
  set strict 0
  set debug 0
  set sender $self
  dict with dictargs {}
  dict set info id     [::clay::event::nextid]
  dict set info origin $self
  dict set info sender $sender
  dict set info rcpt   {}
  foreach who $wholist {
    catch {::clay::event::notify $who $self $event $info}
  }
}
proc ::clay::event::nextid {} {
  return "event#[format %0.8x [incr ::clay::event_count]]"
}
proc ::clay::event::Notification_list {self event {stackvar {}}} {
  set notify_list {}
  foreach {obj patternlist} [array get ::clay::object_subscribe] {
    if {$obj eq $self} continue
    if {$obj in $notify_list} continue
    set match 0
    foreach {objpat eventlist} $patternlist {
      if {![string match $objpat $self]} continue
      foreach eventpat $eventlist {
        if {![string match $eventpat $event]} continue
        set match 1
        break
      }
      if {$match} {
        break
      }
    }
    if {$match} {
      lappend notify_list $obj
    }
  }
  return $notify_list
}
proc ::clay::event::notify {rcpt sender event eventinfo} {
  if {[info commands $rcpt] eq {}} return
  if {$::clay::trace} {
    puts [list event notify rcpt $rcpt sender $sender event $event info $eventinfo]
  }
  $rcpt notify $event $sender $eventinfo
}
proc ::clay::event::process {self handle script} {
  variable timer_event
  variable timer_script

  array unset timer_event $self:$handle
  array unset timer_script $self:$handle

  set err [catch {uplevel #0 $script} result errdat]
  if $err {
    puts "BGError: $self $handle $script
ERR: $result
[dict get $errdat -errorinfo]
***"
  }
}
proc ::clay::event::schedule {self handle interval script} {
  variable timer_event
  variable timer_script
  if {$::clay::trace} {
    puts [list $self schedule $handle $interval]
  }
  if {[info exists timer_event($self:$handle)]} {
    if {$script eq $timer_script($self:$handle)} {
      return
    }
    ::after cancel $timer_event($self:$handle)
  }
  set timer_script($self:$handle) $script
  set timer_event($self:$handle) [::after $interval [list ::clay::event::process $self $handle $script]]
}
proc ::clay::event::subscribe {self who event} {
  upvar #0 ::clay::object_subscribe($self) subscriptions
  if {![info exists subscriptions]} {
    set subscriptions {}
  }
  set match 0
  foreach {objpat eventlist} $subscriptions {
    if {![string match $objpat $who]} continue
    foreach eventpat $eventlist {
      if {[string match $eventpat $event]} {
        # This rule already exists
        return
      }
    }
  }
  dict lappend subscriptions $who $event
}
proc ::clay::event::unsubscribe {self args} {
  upvar #0 ::clay::object_subscribe($self) subscriptions
  if {![info exists subscriptions]} {
    return
  }
  switch [llength $args] {
    1 {
      set event [lindex $args 0]
      if {$event eq "*"} {
        # Shortcut, if the
        set subscriptions {}
      } else {
        set newlist {}
        foreach {objpat eventlist} $subscriptions {
          foreach eventpat $eventlist {
            if {[string match $event $eventpat]} continue
            dict lappend newlist $objpat $eventpat
          }
        }
        set subscriptions $newlist
      }
    }
    2 {
      set who [lindex $args 0]
      set event [lindex $args 1]
      if {$who eq "*" && $event eq "*"} {
        set subscriptions {}
      } else {
        set newlist {}
        foreach {objpat eventlist} $subscriptions {
          if {[string match $who $objpat]} {
            foreach eventpat $eventlist {
              if {[string match $event $eventpat]} continue
              dict lappend newlist $objpat $eventpat
            }
          }
        }
        set subscriptions $newlist
      }
    }
  }
}

###
# END: event.tcl
###
###
# START: singleton.tcl
###
proc ::clay::singleton {name script} {
  if {[info commands $name] eq {}} {
    ::clay::object create $name
  }
  oo::objdefine $name {
method SingletonProcs {} {
proc class class {
  uplevel 1 "oo::objdefine \[self\] class $class"
  my clay delegate class $class
}
proc clay args {
  my clay {*}$args
}
proc Ensemble {rawmethod args} {
  if {[llength $args]==2} {
    lassign $args argspec body
    set argstyle tcl
  } elseif {[llength $args]==3} {
    lassign $args argstyle argspec body
  } else {
    error "Usage: Ensemble name ?argstyle? argspec body"
  }
  set class [uplevel 1 self]
  #if {$::clay::trace>2} {
  #  puts [list $class Ensemble $rawmethod $argspec $body]
  #}
  set mlist [split $rawmethod "::"]
  set ensemble [string trim [lindex $mlist 0] :/]
  set method   [string trim [lindex $mlist 2] :/]
  if {[string index $method 0] eq "_"} {
    $class clay set method_ensemble $ensemble $method $body
    return
  }
  set realmethod  [string totitle $ensemble]_${method}
  set realbody {}
  if {$argstyle eq "dictargs"} {
    append realbody "::dictargs::parse \{$argspec\} \$args" \n
  }
  if {[$class clay exists method_ensemble $ensemble _preamble]} {
    append realbody [$class clay get method_ensemble $ensemble _preamble] \n
  }
  append realbody $body
  if {$method eq "default"} {
    $class clay set method_ensemble $ensemble $method: "tailcall my $realmethod \$method {*}\$args"
    if {$argstyle eq "dictargs"} {
      oo::objdefine $class method $realmethod [list method [list args $argspec]] $realbody
    } else {
      oo::objdefine $class method $realmethod [list method {*}$argspec] $realbody
    }
  } else {
    $class clay set method_ensemble $ensemble $method: "tailcall my $realmethod {*}\$args"
    if {$argstyle eq "dictargs"} {
      oo::objdefine $class method $realmethod [list [list args $argspec]] $realbody
    } else {
      oo::objdefine $class method $realmethod $argspec $realbody
    }
  }
  if {$::clay::trace>2} {
    puts [list $class clay set method_ensemble/ $ensemble [string trim $method :/]  ...]
  }
}
proc method args {
  uplevel 1 "oo::objdefine \[self\] method {*}$args"
}
}
method script script {
  my clay busy 1
  my SingletonProcs
  eval $script
  my clay busy 0
  my InitializePublic
}
}
  $name script $script
  return $name
}

###
# END: singleton.tcl
###

namespace eval ::clay {
  namespace export *
}

Added modules/clay/clay.test.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279

namespace eval ::oo::dialect {}
set ::oo::dialect::has(tip470) 0

# clay.test - Copyright (c) 2018 Sean Woods
# -------------------------------------------------------------------------

set MODDIR [file dirname [file dirname [file join [pwd] [info script]]]]
if {[file exists [file join $MODDIR devtools testutilities.tcl]]} {
  # Running inside tcllib
  set TCLLIBMOD $MODDIR
} else {
  set TCLLIBMOD [file join $MODDIR .. .. tcllib modules]
}
source [file join $TCLLIBMOD devtools testutilities.tcl]

testsNeedTcl     8.6
testsNeedTcltest 2
testsNeed        TclOO 1

support {}
testing {
    useLocal clay.tcl clay
}


set ::clay::trace 0



# -------------------------------------------------------------------------
# Handle multiple implementation testing
#

array set preserve [array get ::clay::uuid::accel]

proc implementations {} {
    variable ::clay::uuid::accel
    foreach {a v} [array get accel] {if {$v} {lappend r $a}}
    lappend r tcl; set r
}

proc select_implementation {impl} {
    variable ::clay::uuid::accel
    foreach e [array names accel] { set accel($e) 0 }
    if {[string compare "tcl" $impl] != 0} {
        set accel($impl) 1
    }
}

proc reset_implementation {} {
    variable ::clay::uuid::accel
    array set accel [array get ::preserve]
}

# -------------------------------------------------------------------------
# Setup any constraints
#

# -------------------------------------------------------------------------
# Now the package specific tests....
# -------------------------------------------------------------------------

# -------------------------------------------------------------------------

foreach impl [implementations] {
    select_implementation $impl

    test uuid-1.0-$impl "uuid requires args" {
        list [catch {clay::uuid} msg]
    } {1}

    test uuid-1.1-$impl "uuid generate should create a 36 char string uuid" {
        list [catch {string length [clay::uuid generate]} msg] $msg
    } {0 36}

    test uuid-1.2-$impl "uuid comparison of uuid with self should be true" {
        list [catch {
            set a [clay::uuid generate]
            clay::uuid equal $a $a
        } msg] $msg
    } {0 1}

    test uuid-1.3-$impl "uuid comparison of two different uuids should be false" {
        list [catch {
            set a [clay::uuid generate]
            set b [clay::uuid generate]
            clay::uuid equal $a $b
        } msg] $msg
    } {0 0}

    reset_implementation
}


# Modification History:
###
# Modification 2018-10-30
# Fixed an error in our ancestry mapping and developed tests to
# ensure we are actually following in the order TclOO follows methods
###
# Modification 2018-10-21
# The clay metaclass no longer exports the clay method
# to oo::class and oo::object, and clay::ancestors no
# longer returns any class that lacks the clay method
###
# Modification 2018-10-10
# clay::ancestors now rigged to descend into all classes depth-first
# and then place metaclasses at the end of the search
###
# -------------------------------------------------------------------------

# -------------------------------------------------------------------------
# Test Helpers
###
proc dict_compare {a b} {
  set result {}
  set A {}
  dict for {f v} $a {
    set f [string trim $f :/]
    if {$f eq {.}} continue
    dict set A $f $v
  }
  set B {}
  dict for {f v} $b {
    set f [string trim $f :/]
    if {$f eq {.}} continue
    dict set B $f $v
  }
  dict for {f v} $A {
    if {[dict exists $B $f]} {
      if {[dict get $B $f] ne $v} {
        lappend result [list B $f [dict get $B $f] [list != $v]]
      }
    } else {
      lappend result [list B $f $v missing]
    }
  }
  dict for {f v} $B {
    if {![dict exists $A $f]} {
      lappend result [list A $f $v missing]
    }
  }
  return $result
}

test dict-compare-001 {Test our testing method} {
  dict_compare {} {}
} {}

test dict-compare-002 {Test our testing method} {
  dict_compare {a 1} {}
} {{B a 1 missing}}

test dict-compare-003 {Test our testing method} {
  dict_compare {a 1 b 2} {a 1 b 2}
} {}

test dict-compare-003.a {Test our testing method} {
  dict_compare {a 1 b 2} {b 2 a 1 }
} {}

test dict-compare-003.b {Test our testing method} {
  dict_compare {b 2 a 1} {a 1 b 2}
} {}


test dict-compare-004 {Test our testing method} {
  dict_compare {a: 1 b: 2} {a 1 b 2}
} {}

test dict-compare-005 {Test our testing method} {
  dict_compare {a 1 b 3} {a 1 b 2}
} {{B b 2 {!= 3}}}


###
# Test canonical mapping
###


test {test-storage-0001} {Test ::clay::tree::storage with foo bar baz} {
  clay::tree::storage {foo bar baz}
} {foo bar baz}


test {test-storage-0002} {Test ::clay::tree::storage with foo bar baz/} {
  clay::tree::storage {foo bar baz/}
} {foo bar baz}


test {test-storage-0003} {Test ::clay::tree::storage with foo bar .} {
  clay::tree::storage {foo bar .}
} {foo bar .}


test {test-storage-0004} {Test ::clay::tree::storage with foo/ bar/ .} {
  clay::tree::storage {foo/ bar/ .}
} {foo bar .}


test {test-storage-0005} {Test ::clay::tree::storage with foo . bar . baz .} {
  clay::tree::storage {foo . bar . baz .}
} {foo . bar . baz .}


test {test-storage-0006} {Test ::clay::tree::storage with foo bar baz bat:} {
  clay::tree::storage {foo bar baz bat:}
} {foo bar baz bat:}


test {test-storage-0007} {Test ::clay::tree::storage with foo:} {
  clay::tree::storage {foo:}
} {foo:}


test {test-storage-0008} {Test ::clay::tree::storage with foo/bar/baz/bat:} {
  clay::tree::storage {foo/bar/baz/bat:}
} {foo bar baz bat:}


dict set r foo/ bar/ baz 1
dict set s foo/ bar/ baz 0
set t [clay::tree::merge $r $s]

test rmerge-0001 {Test that the root is marked as a branch} {
  dict get $t foo bar baz
} 0

set r [dict create]
clay::tree::dictmerge r {
  foo/ {
    bar/ {
      baz 1
      bing: 2
      bang { bim 3 boom 4 }
      womp: {a 1 b 2}
    }
  }
}

test dictmerge-0001 {Test that the root is marked as a branch} {
  dict exists $r .
} 1
test dictmerge-0002 {Test that branch foo is marked correctly} {
  dict exists $r foo .
} 1
test dictmerge-0003 {Test that branch bar is marked correctly} {
  dict exists $r foo bar .
} 1
test dictmerge-0004 {Test that leaf foo/bar/bang is not marked as branch despite being a dict} {
  dict exists $r foo bar bang .
} 0
test dictmerge-0004 {Test that leaf foo/bar/bang/bim exists} {
  dict exists $r foo bar bang bim
} 1
test dictmerge-0005 {Test that leaf foo/bar/bang/boom exists} {
  dict exists $r foo bar bang boom
} 1

###
# Replace bang with bang/
###
clay::tree::dictmerge r {
  foo/ {
    bar/ {
      bang/ {
        whoop 1
      }
    }
  }
}

test dictmerge-0006 {Test that leaf foo/bar/bang/bim ceases to exist} {
  dict exists $r foo bar bang bim
} 0
test dictmerge-0007 {Test that leaf foo/bar/bang/boom exists} {
  dict exists $r foo bar bang boom
} 0

test dictmerge-0008 {Test that leaf foo/bar/bang is now a branch} {
  dict exists $r foo bar bang .
} 1

test branch-0001 {Test that foo/ is a branch} {
  clay::tree::is_branch $r foo/
} 1
test branch-0002 {Test that foo is a branch} {
  clay::tree::is_branch $r foo
} 1
test branch-0003 {Test that foo/bar/ is a branch} {
  clay::tree::is_branch $r {foo/ bar/}
} 1
test branch-0004 {Test that foo bar is not branch} {
  clay::tree::is_branch $r {foo bar}
} 1
test branch-0004 {Test that foo/ bar is not branch} {
  clay::tree::is_branch $r {foo/ bar}
} 0


test {test-branch-0001} {Test that  foo is_branch = 1} {
  clay::tree::is_branch $r { foo}
} 1


test {test-branch-0002} {Test that  foo: is_branch = 0} {
  clay::tree::is_branch $r { foo:}
} 0


test {test-branch-0003} {Test that  foo/ is_branch = 1} {
  clay::tree::is_branch $r { foo/}
} 1


test {test-branch-0004} {Test that  .foo is_branch = 0} {
  clay::tree::is_branch $r { .foo}
} 0


test {test-branch-0005} {Test that foo bar is_branch = 1} {
  clay::tree::is_branch $r {foo bar}
} 1


test {test-branch-0006} {Test that foo bar: is_branch = 0} {
  clay::tree::is_branch $r {foo bar:}
} 0


test {test-branch-0007} {Test that foo bar/ is_branch = 1} {
  clay::tree::is_branch $r {foo bar/}
} 1


test {test-branch-0008} {Test that foo .bar is_branch = 0} {
  clay::tree::is_branch $r {foo .bar}
} 0


test {test-branch-0009} {Test that foo bar baz is_branch = 0} {
  clay::tree::is_branch $r {foo bar baz}
} 0


test {test-branch-0010} {Test that foo bar baz: is_branch = 0} {
  clay::tree::is_branch $r {foo bar baz:}
} 0


test {test-branch-0011} {Test that foo bar baz/ is_branch = 1} {
  clay::tree::is_branch $r {foo bar baz/}
} 1


test {test-branch-0012} {Test that foo bar .baz is_branch = 0} {
  clay::tree::is_branch $r {foo bar .baz}
} 0


test {test-branch-0013} {Test that foo bar bing is_branch = 0} {
  clay::tree::is_branch $r {foo bar bing}
} 0


test {test-branch-0014} {Test that foo bar bing: is_branch = 0} {
  clay::tree::is_branch $r {foo bar bing:}
} 0


test {test-branch-0015} {Test that foo bar bing/ is_branch = 1} {
  clay::tree::is_branch $r {foo bar bing/}
} 1


test {test-branch-0016} {Test that foo bar .bing is_branch = 0} {
  clay::tree::is_branch $r {foo bar .bing}
} 0


test {test-branch-0017} {Test that foo bar bang is_branch = 1} {
  clay::tree::is_branch $r {foo bar bang}
} 1


test {test-branch-0018} {Test that foo bar bang: is_branch = 0} {
  clay::tree::is_branch $r {foo bar bang:}
} 0


test {test-branch-0019} {Test that foo bar bang/ is_branch = 1} {
  clay::tree::is_branch $r {foo bar bang/}
} 1


test {test-branch-0020} {Test that foo bar .bang is_branch = 0} {
  clay::tree::is_branch $r {foo bar .bang}
} 0


test {test-branch-0021} {Test that foo bar bang whoop is_branch = 0} {
  clay::tree::is_branch $r {foo bar bang whoop}
} 0


test {test-branch-0022} {Test that foo bar bang whoop: is_branch = 0} {
  clay::tree::is_branch $r {foo bar bang whoop:}
} 0


test {test-branch-0023} {Test that foo bar bang whoop/ is_branch = 1} {
  clay::tree::is_branch $r {foo bar bang whoop/}
} 1


test {test-branch-0024} {Test that foo bar bang .whoop is_branch = 0} {
  clay::tree::is_branch $r {foo bar bang .whoop}
} 0


# -------------------------------------------------------------------------
# dictmerge Testing - oometa
unset -nocomplain foo
clay::tree::dictmerge foo {
  option/ {
    color/ {
      label Color
      default green
    }
  }
}
clay::tree::dictmerge foo {
  option/ {
    color/ {
      default purple
    }
  }
}

test oometa-0001 {Invoking dictmerge with empty args on a non existent variable create an empty variable} {
  dict get $foo option color default
} purple
test oometa-0002 {Invoking dictmerge with empty args on a non existent variable create an empty variable} {
  dict get $foo option color label
} Color

unset -nocomplain foo
set foo {. {}}
::clay::tree::dictmerge foo {. {} color {. {} default green label Color}}
::clay::tree::dictmerge foo {. {} color {. {} default purple}}
test oometa-0003 {Recursive merge problem from oometa/clay find} {
  dict get $foo color default
} purple
test oometa-0004 {Recursive merge problem from oometa/clay find} {
  dict get $foo color label
} Color

unset -nocomplain foo
set foo {. {}}
::clay::tree::dictmerge foo {. {} color {. {} default purple}}
::clay::tree::dictmerge foo {. {} color {. {} default green label Color}}
test oometa-0005 {Recursive merge problem from oometa/clay find} {
  dict get $foo color default
} green
test oometa-0006 {Recursive merge problem from oometa/clay find} {
  dict get $foo color label
} Color

test oometa-0008 {Un-Sanitized output} {
  set foo
} {. {} color {. {} default green label Color}}

test oometa-0009 {Sanitize} {
  clay::tree::sanitize $foo
} {color {default green label Color}}


# -------------------------------------------------------------------------
# dictmerge Testing - clay
unset -nocomplain foo
test clay-0001 {Invoking dictmerge with empty args on a non existent variable create an empty variable} {
  ::clay::tree::dictmerge foo
  set foo
} {. {}}

unset -nocomplain foo
::clay::tree::dictset foo bar/ baz/ bell bang

test clay-0002 {For new entries dictmerge is essentially a set} {
  dict get $foo bar baz bell
} {bang}
::clay::tree::dictset foo bar/ baz/ boom/ bang
test clay-0003 {For entries that do exist a zipper merge is performed} {
  dict get $foo bar baz bell
} {bang}
test clay-0004 {For entries that do exist a zipper merge is performed} {
  dict get $foo bar baz boom
} {bang}

::clay::tree::dictset foo bar/ baz/ bop {color green flavor strawberry}

test clay-0005 {Leaves are replaced even if they look like a dict} {
  dict get $foo bar baz bop
} {color green flavor strawberry}

::clay::tree::dictset foo bar/ baz/ bop {color yellow}
test clay-0006 {Leaves are replaced even if they look like a dict} {
  dict get $foo bar baz bop
} {color yellow}

::clay::tree::dictset foo bar/ baz/ bang/ {color green flavor strawberry}
test clay-0007a {Branches are merged} {
  dict get $foo bar baz bang
} {. {} color green flavor strawberry}

::clay::tree::dictset foo bar/ baz/ bang/ color yellow
test clay-0007b {Branches are merged}  {
  dict get $foo bar baz bang
} {. {} color yellow flavor strawberry}

::clay::tree::dictset foo bar/ baz/ bang/ {color blue}
test clay-0007c {Branches are merged}  {
  dict get $foo bar baz bang
} {. {} color blue flavor strawberry}

::clay::tree::dictset foo bar/ baz/ bang/ shape: {Sort of round}
test clay-0007d {Branches are merged} {
  dict get $foo bar baz bang
} {. {} color blue flavor strawberry shape: {Sort of round}}

::clay::tree::dictset foo bar/ baz/ bang/ color yellow
test clay-0007e {Branches are merged}  {
  dict get $foo bar baz bang
} {. {} color yellow flavor strawberry shape: {Sort of round}}

::clay::tree::dictset foo bar/ baz/ bang/ {color blue}
test clay-0007f {Branches are merged}  {
  dict get $foo bar baz bang
} {. {} color blue flavor strawberry shape: {Sort of round}}

::clay::tree::dictset foo dict my_var 10
::clay::tree::dictset foo dict my_other_var 9

test clay-0007g {Branches are merged}  {
  dict get $foo dict
} {. {} my_var 10 my_other_var 9}

::clay::tree::dictset foo dict/ my_other_other_var 8
test clay-0007h {Branches are merged}  {
  dict get $foo dict
} {. {} my_var 10 my_other_var 9 my_other_other_var 8}


::clay::tree::dictmerge foo {option/ {color {type color} flavor {sense taste}}}
::clay::tree::dictmerge foo {option/ {format {default ascii}}}

test clay-0008 {Whole dicts are merged}  {
  dict get $foo option color
} {type color}
test clay-0009 {Whole dicts are merged}  {
  dict get $foo option flavor
} {sense taste}
test clay-0010 {Whole dicts are merged}  {
  dict get $foo option format
} {default ascii}

###
# Tests for the httpd module
###
test clay-0010 {Test that leaves are merged properly}
set bar {}
::clay::tree::dictmerge bar {
   proxy/ {port 10101 host myhost.localhost}
}
::clay::tree::dictmerge bar {
   mimetxt {Host: localhost
Content_Type: text/plain
Content-Length: 15
}
   http {HTTP_HOST {} CONTENT_LENGTH 15 HOST localhost CONTENT_TYPE text/plain UUID 3a7b4cdc-28d7-49b7-b18d-9d7d18382b9e REMOTE_ADDR 127.0.0.1 REMOTE_HOST 127.0.0.1 REQUEST_METHOD POST REQUEST_URI /echo REQUEST_PATH echo REQUEST_VERSION 1.0 DOCUMENT_ROOT {} QUERY_STRING {} REQUEST_RAW {POST /echo HTTP/1.0} SERVER_PORT 10001 SERVER_NAME 127.0.0.1 SERVER_PROTOCOL HTTP/1.1 SERVER_SOFTWARE {TclHttpd 4.2.0} LOCALHOST 0} UUID 3a7b4cdc-28d7-49b7-b18d-9d7d18382b9e uriinfo {fragment {} port {} path echo scheme http host {} query {} pbare 0 pwd {} user {}}
   mixin {reply ::test::content.echo}
   prefix /echo
   proxy_port 10010
   proxy/ {host localhost}
}

test clay-0011 {Whole dicts are merged}  {
  dict get $bar proxy_port
} {10010}

test clay-0012 {Whole dicts are merged}  {
  dict get $bar http CONTENT_LENGTH
} 15
test clay-0013 {Whole dicts are merged}  {
  dict get $bar proxy host
} localhost
test clay-0014 {Whole dicts are merged}  {
  dict get $bar proxy port
} 10101


###
# Dialect Testing
###
::clay::dialect::create ::alpha

proc ::alpha::define::is_alpha {} {
  dict set ::testinfo([current_class]) is_alpha 1
}

::alpha::define ::alpha::object {
  is_alpha
}

::clay::dialect::create ::bravo ::alpha

proc ::bravo::define::is_bravo {} {
  dict set ::testinfo([current_class]) is_bravo 1
}

::bravo::define ::bravo::object {
  is_bravo
}

::clay::dialect::create ::charlie ::bravo

proc ::charlie::define::is_charlie {} {
  dict set ::testinfo([current_class]) is_charlie 1
}

::charlie::define ::charlie::object {
  is_charlie
}

::clay::dialect::create ::delta ::charlie

proc ::delta::define::is_delta {} {
  dict set ::testinfo([current_class]) is_delta 1
}

::delta::define ::delta::object {
  is_delta
}

::delta::class create adam {
  is_alpha
  is_bravo
  is_charlie
  is_delta
}

test oodialect-keyword-001 {Testing keyword application} {
  set ::testinfo(::adam)
} {is_alpha 1 is_bravo 1 is_charlie 1 is_delta 1}

test oodialect-keyword-002 {Testing keyword application} {
  set ::testinfo(::alpha::object)
} {is_alpha 1}

test oodialect-keyword-003 {Testing keyword application} {
  set ::testinfo(::bravo::object)
} {is_bravo 1}

test oodialect-keyword-004 {Testing keyword application} {
  set ::testinfo(::charlie::object)
} {is_charlie 1}

test oodialect-keyword-005 {Testing keyword application} {
  set ::testinfo(::delta::object)
} {is_delta 1}

###
# Declare an object from a namespace
###
namespace eval ::test1 {
  ::alpha::class create a {
    aliases A
    is_alpha
  }
  ::alpha::define b {
    aliases B BEE
    is_alpha
  }
  ::alpha::class create ::c {
    aliases C
    is_alpha
  }
  ::alpha::define ::d {
    aliases D
    is_alpha
  }
}

test oodialect-naming-001 {Testing keyword application} {
  set ::testinfo(::test1::a)
} {is_alpha 1}

test oodialect-naming-002 {Testing keyword application} {
  set ::testinfo(::test1::b)
} {is_alpha 1}

test oodialect-naming-003 {Testing keyword application} {
  set ::testinfo(::c)
} {is_alpha 1}

test oodialect-naming-004 {Testing keyword application} {
  set ::testinfo(::d)
} {is_alpha 1}

test oodialect-aliasing-001 {Testing keyword application} {
namespace eval ::test1 {
    ::alpha::define e {
       superclass A
    }
}
} ::test1::e

test oodialect-aliasing-002 {Testing keyword application} {
namespace eval ::test1 {
    ::bravo::define f {
       superclass A
    }
}
} ::test1::f


test oodialect-aliasing-003 {Testing aliase method on class} {
  ::test1::a aliases
} {::test1::A}

###
# Test modified 2018-10-21
###
test oodialect-ancestry-003 {Testing heritage} {
  ::clay::ancestors ::test1::f
} {}

###
# Test modified 2018-10-21
###
test oodialect-ancestry-004 {Testing heritage} {
  ::clay::ancestors ::alpha::object
} {}

###
# Test modified 2018-10-21
###
test oodialect-ancestry-005 {Testing heritage} {
  ::clay::ancestors ::delta::object
} {}



# -------------------------------------------------------------------------
# clay submodule testing
# -------------------------------------------------------------------------



# Test canonical path building
set path {const/ foo/ bar/ baz/}


test oo-clay-path-0001 "Test path: const foo bar baz" {
  ::clay::path const foo bar baz
} $path


test oo-clay-path-0002 "Test path: const/ foo/ bar/ baz" {
  ::clay::path const/ foo/ bar/ baz
} $path


test oo-clay-path-0003 "Test path: const/foo/bar/baz" {
  ::clay::path const/foo/bar/baz
} $path


test oo-clay-path-0004 "Test path: const/foo bar/baz" {
  ::clay::path const/foo bar/baz
} $path


test oo-clay-path-0005 "Test path: const/foo/bar baz" {
  ::clay::path const/foo/bar baz
} $path


test oo-clay-path-0006 "Test path: const foo/bar/baz" {
  ::clay::path const foo/bar/baz
} $path


test oo-clay-path-0007 "Test path: const foo bar/baz" {
  ::clay::path const foo bar/baz
} $path


test oo-clay-path-0008 "Test path: const/foo bar baz" {
  ::clay::path const/foo bar baz
} $path

set path {const/ foo/ bar/ baz/ bing}

test oo-clay-leaf-0001 "Test leaf: const foo bar baz bing" {
  ::clay::leaf const foo bar baz bing
} $path


test oo-clay-leaf-0002 "Test leaf: const/ foo/ bar/ baz/ bing" {
  ::clay::leaf const/ foo/ bar/ baz/ bing
} $path


test oo-clay-leaf-0003 "Test leaf: const/foo/bar/baz/bing" {
  ::clay::leaf const/foo/bar/baz/bing
} $path


test oo-clay-leaf-0004 "Test leaf: const/foo bar/baz/bing:" {
  ::clay::leaf const/foo bar/baz/bing:
} $path


test oo-clay-leaf-0005 "Test leaf: const/foo/bar baz bing" {
  ::clay::leaf const/foo/bar baz bing
} $path


test oo-clay-leaf-0006 "Test leaf: const/foo/bar baz bing:" {
  ::clay::leaf const/foo/bar baz bing:
} $path


test oo-clay-leaf-0007 "Test leaf: const foo/bar/baz/bing" {
  ::clay::leaf const foo/bar/baz/bing
} $path


test oo-clay-leaf-0008 "Test leaf: const foo bar/baz/bing" {
  ::clay::leaf const foo bar/baz/bing
} $path


test oo-clay-leaf-0009 "Test leaf: const/foo bar baz bing" {
  ::clay::leaf const/foo bar baz bing
} $path

namespace eval ::foo {}

clay::define ::foo::classa {

  clay set const color  blue
  clay set const/flavor strawberry
  clay set {const/ sound} zoink
  clay set info/ {
    animal no
    building no
    subelement {pedantic yes}
  }

  # Provide a method that returns a constant so we can compare clay's inheritance to
  # TclOO
  method color {} {
    return blue
  }
  method flavor {} {
    return strawberry
  }
  method sound {} {
    return zoink
  }

}


test oo-class-clay-method-0001 "Test ::foo::classa const/ color exists" {
  ::foo::classa clay exists const/ color
} 1


test oo-class-clay-method-0001 "Test ::foo::classa const/ color value" {
  ::foo::classa clay get const/ color
} {blue}


test oo-class-clay-method-0003 "Test ::foo::classa const/ flavor exists" {
  ::foo::classa clay exists const/ flavor
} 1


test oo-class-clay-method-0003 "Test ::foo::classa const/ flavor value" {
  ::foo::classa clay get const/ flavor
} {strawberry}


test oo-class-clay-method-0005 "Test ::foo::classa const/ sound exists" {
  ::foo::classa clay exists const/ sound
} 1


test oo-class-clay-method-0005 "Test ::foo::classa const/ sound value" {
  ::foo::classa clay get const/ sound
} {zoink}


test oo-class-clay-method-0007 "Test ::foo::classa info/ animal exists" {
  ::foo::classa clay exists info/ animal
} 1


test oo-class-clay-method-0007 "Test ::foo::classa info/ animal value" {
  ::foo::classa clay get info/ animal
} {no}


test oo-class-clay-method-0009 "Test ::foo::classa info/ building exists" {
  ::foo::classa clay exists info/ building
} 1


test oo-class-clay-method-0009 "Test ::foo::classa info/ building value" {
  ::foo::classa clay get info/ building
} {no}


test oo-class-clay-method-0011 "Test ::foo::classa info/ subelement exists" {
  ::foo::classa clay exists info/ subelement
} 1


test oo-class-clay-method-0011 "Test ::foo::classa info/ subelement value" {
  ::foo::classa clay get info/ subelement
} {pedantic yes}


clay::define ::foo::classb {
  clay set const/ color black
  method color {} {return black}
  clay set const/ flavor vanilla
  method flavor {} {return vanilla}
  clay set const/ feeling dread
  method feeling {} {return dread}
  clay set info/ subelement {spoon yes}
  method subelement {} {return {spoon yes}}

}


test oo-class-clay-method-0013 "Test ::foo::classb const/ color exists" {
  ::foo::classb clay exists const/ color
} 1


test oo-class-clay-method-0013 "Test ::foo::classb const/ color value" {
  ::foo::classb clay get const/ color
} {black}


test oo-class-clay-method-0015 "Test ::foo::classb const/ flavor exists" {
  ::foo::classb clay exists const/ flavor
} 1


test oo-class-clay-method-0015 "Test ::foo::classb const/ flavor value" {
  ::foo::classb clay get const/ flavor
} {vanilla}


test oo-class-clay-method-0017 "Test ::foo::classb const/ feeling exists" {
  ::foo::classb clay exists const/ feeling
} 1


test oo-class-clay-method-0017 "Test ::foo::classb const/ feeling value" {
  ::foo::classb clay get const/ feeling
} {dread}


test oo-class-clay-method-0019 "Test ::foo::classb info/ subelement exists" {
  ::foo::classb clay exists info/ subelement
} 1


test oo-class-clay-method-0019 "Test ::foo::classb info/ subelement value" {
  ::foo::classb clay get info/ subelement
} {spoon yes}


clay::define ::foo::class.ab {
superclass ::foo::classb ::foo::classa
}


clay::define ::foo::class.ba {
superclass ::foo::classa ::foo::classb
}

# -------------------------------------------------------------------------
# Singleton
::clay::define ::test::singletonbehavior {
  method bar {} {
    return CLASS
  }
  method booze {} {
    return CLASS
  }
  Ensemble foo::bang {} {
    return CLASS
  }
  Ensemble foo::both {} {
    return CLASS
  }
  Ensemble foo::mixin {} {
    return CLASS
  }
  Ensemble foo::sloppy {} {
    return CLASS
  }
}
::clay::define ::test::flavor.strawberry {
  clay define property flavor strawbery
  method bar {} {
    return STRAWBERRY
  }
  Ensemble foo::bing {} {
    return STRAWBERRY
  }
  Ensemble foo::both {} {
    return STRAWBERRY
  }
  Ensemble foo::mixin {} {
    return STRAWBERRY
  }
  Ensemble foo::sloppy {} {
    return STRAWBERRY
  }
}
::clay::singleton ::TEST {
  class ::test::singletonbehavior
  clay mixinmap flavor ::test::flavor.strawberry
  clay set property color green
  method bar {} {
    return OBJECT
  }
  method booze {} {
    return OBJECT
  }
  method baz {} {
    return OBJECT
  }
  Ensemble foo::bar {} {
    return OBJECT
  }
  Ensemble foo::both {} {
    return OBJECT
  }
}

test oo-object-singleton-001 {Test singleton superclass keyword} {
  ::TEST clay delegate class
} {::test::singletonbehavior}

test oo-object-singleton-002 {Test singleton ensemble 1} {
  ::TEST foo <list>
} {bang bar bing both mixin sloppy}

test oo-object-singleton-003 {Test singleton ensemble from script} {
  ::TEST foo bar
} {OBJECT}
test oo-object-singleton-004 {Test singleton ensemble from mixin} {
  ::TEST foo bing
} {STRAWBERRY}
test oo-object-singleton-005 {Test singleton ensemble from class} {
  ::TEST foo bang
} {CLASS}
# Test note: the behavior from TclOO is unexpected
# Intuitively, a local method should override a mixin
# but this is not the case
test oo-object-singleton-006 {Test singleton ensemble from conflict, should resolve to object} {
  ::TEST foo both
} {STRAWBERRY}
test oo-object-singleton-007 {Test singleton ensemble from conflict, should resolve to mixin} {
  ::TEST foo sloppy
} {STRAWBERRY}
###
# Test note:
# This should work but does not
###
#test oo-object-singleton-009 {Test property from mixin/class} {
#  ::TEST clay get property flavor
#} {strawberry}
test oo-object-singleton-008 {Test property from script} {
  ::TEST clay get property color
} {green}


# Test note: the behavior from TclOO is unexpected
# Intuitively, a local method should override a mixin
# but this is not the case
test oo-object-singleton-010 {Test method declared in script} {
  ::TEST bar
} {STRAWBERRY}

test oo-object-singleton-011 {Test method declared in script} {
  ::TEST booze
} {OBJECT}
TEST destroy

# OBJECT of ::foo::classa
set OBJECTA [::foo::classa new]

###
# Test object degation
###
proc ::foo::fakeobject {a b} {
  return [expr {$a + $b}]
}

::clay::object create TEST
TEST clay delegate funct ::foo::fakeobject
test oo-object-delegate-001 {Test object delegation} {
  ::TEST clay delegate
} {<class> ::clay::object <funct> ::foo::fakeobject}

test oo-object-delegate-002 {Test object delegation} {
  ::TEST clay delegate funct
} {::foo::fakeobject}

test oo-object-delegate-002a {Test object delegation} {
  ::TEST clay delegate <funct>
} {::foo::fakeobject}

test oo-object-delegate-003 {Test object delegation} {
  ::TEST <funct> 1 1
} {2}
test oo-object-delegate-004 {Test object delegation} {
  ::TEST <funct> 10 -7
} {3}

# Replace the function out from under
proc ::foo::fakeobject {a b} {
  return [expr {$a * $b}]
}
test oo-object-delegate-005 {Test object delegation} {
  ::TEST <funct> 10 -7
} {-70}

# Object with ::foo::classa mixed in
set MIXINA  [::oo::object new]
oo::objdefine $MIXINA mixin ::foo::classa


test oo-object-clay-method-native-0001 {Test native object gets the property const//color} {
  $OBJECTA clay get const/ color
} {blue}
test oo-object-clay-method-mixin-0001 {Test mixin object gets the property const//color} {
  $MIXINA clay get const/ color
} {blue}


test oo-object-clay-method-native-methodcheck-0001 {Test that const//color would mimic method interheritance for a native class} {
  $OBJECTA color
} {blue}
test oo-object-clay-method-mixin-0001 {Test that const//color would mimic method interheritance for a mixed in class} {
  $MIXINA color
} {blue}
    

test oo-object-clay-method-native-0002 {Test native object gets the property const//flavor} {
  $OBJECTA clay get const/ flavor
} {strawberry}
test oo-object-clay-method-mixin-0002 {Test mixin object gets the property const//flavor} {
  $MIXINA clay get const/ flavor
} {strawberry}


test oo-object-clay-method-native-methodcheck-0002 {Test that const//flavor would mimic method interheritance for a native class} {
  $OBJECTA flavor
} {strawberry}
test oo-object-clay-method-mixin-0002 {Test that const//flavor would mimic method interheritance for a mixed in class} {
  $MIXINA flavor
} {strawberry}
    

test oo-object-clay-method-native-0003 {Test native object gets the property const//sound} {
  $OBJECTA clay get const/ sound
} {zoink}
test oo-object-clay-method-mixin-0003 {Test mixin object gets the property const//sound} {
  $MIXINA clay get const/ sound
} {zoink}


test oo-object-clay-method-native-methodcheck-0003 {Test that const//sound would mimic method interheritance for a native class} {
  $OBJECTA sound
} {zoink}
test oo-object-clay-method-mixin-0003 {Test that const//sound would mimic method interheritance for a mixed in class} {
  $MIXINA sound
} {zoink}
    

test oo-object-clay-method-native-0004 {Test native object gets the property info//animal} {
  $OBJECTA clay get info/ animal
} {no}
test oo-object-clay-method-mixin-0004 {Test mixin object gets the property info//animal} {
  $MIXINA clay get info/ animal
} {no}


test oo-object-clay-method-native-0005 {Test native object gets the property info//building} {
  $OBJECTA clay get info/ building
} {no}
test oo-object-clay-method-mixin-0005 {Test mixin object gets the property info//building} {
  $MIXINA clay get info/ building
} {no}


test oo-object-clay-method-native-0006 {Test native object gets the property info//subelement} {
  $OBJECTA clay get info/ subelement
} {pedantic yes}
test oo-object-clay-method-mixin-0006 {Test mixin object gets the property info//subelement} {
  $MIXINA clay get info/ subelement
} {pedantic yes}

# -------------------------------------------------------------------------
# OBJECT of ::foo::classb
set OBJECTB [::foo::classb new]
# Object with ::foo::classb mixed in
set MIXINB  [::oo::object new]
oo::objdefine $MIXINB mixin ::foo::classb


test oo-object-clay-method-native-0007 {Test native object gets the property const//color} {
  $OBJECTB clay get const/ color
} {black}
test oo-object-clay-method-mixin-0007 {Test mixin object gets the property const//color} {
  $MIXINB clay get const/ color
} {black}


test oo-object-clay-method-native-methodcheck-0007 {Test that const//color would mimic method interheritance for a native class} {
  $OBJECTB color
} {black}
test oo-object-clay-method-mixin-0007 {Test that const//color would mimic method interheritance for a mixed in class} {
  $MIXINB color
} {black}
    

test oo-object-clay-method-native-0008 {Test native object gets the property const//flavor} {
  $OBJECTB clay get const/ flavor
} {vanilla}
test oo-object-clay-method-mixin-0008 {Test mixin object gets the property const//flavor} {
  $MIXINB clay get const/ flavor
} {vanilla}


test oo-object-clay-method-native-methodcheck-0008 {Test that const//flavor would mimic method interheritance for a native class} {
  $OBJECTB flavor
} {vanilla}
test oo-object-clay-method-mixin-0008 {Test that const//flavor would mimic method interheritance for a mixed in class} {
  $MIXINB flavor
} {vanilla}
    

test oo-object-clay-method-native-0009 {Test native object gets the property const//feeling} {
  $OBJECTB clay get const/ feeling
} {dread}
test oo-object-clay-method-mixin-0009 {Test mixin object gets the property const//feeling} {
  $MIXINB clay get const/ feeling
} {dread}


test oo-object-clay-method-native-methodcheck-0009 {Test that const//feeling would mimic method interheritance for a native class} {
  $OBJECTB feeling
} {dread}
test oo-object-clay-method-mixin-0009 {Test that const//feeling would mimic method interheritance for a mixed in class} {
  $MIXINB feeling
} {dread}
    

test oo-object-clay-method-native-0010 {Test native object gets the property info//subelement} {
  $OBJECTB clay get info/ subelement
} {spoon yes}
test oo-object-clay-method-mixin-0010 {Test mixin object gets the property info//subelement} {
  $MIXINB clay get info/ subelement
} {spoon yes}

# -------------------------------------------------------------------------
# OBJECT descended from ::foo::classa ::foo::classb
set OBJECTAB [::foo::class.ab new]
# Object where classes were mixed in ::foo::classa ::foo::classb
set MIXINAB  [::oo::object new]
# Test modified 2018-10-30, mixin order was wrong before
oo::objdefine $MIXINAB mixin ::foo::classb ::foo::classa


test oo-object-clay-method-native-0011 {Test native object gets the property const//color} {
  $OBJECTAB clay get const/ color
} {black}
test oo-object-clay-method-mixin-0011 {Test mixin object gets the property const//color} {
  $MIXINAB clay get const/ color
} {black}


test oo-object-clay-method-native-methodcheck-0011 {Test that const//color would mimic method interheritance for a native class} {
  $OBJECTAB color
} {black}
test oo-object-clay-method-mixin-0011 {Test that const//color would mimic method interheritance for a mixed in class} {
  $MIXINAB color
} {black}
    

test oo-object-clay-method-native-0012 {Test native object gets the property const//flavor} {
  $OBJECTAB clay get const/ flavor
} {vanilla}
test oo-object-clay-method-mixin-0012 {Test mixin object gets the property const//flavor} {
  $MIXINAB clay get const/ flavor
} {vanilla}


test oo-object-clay-method-native-methodcheck-0012 {Test that const//flavor would mimic method interheritance for a native class} {
  $OBJECTAB flavor
} {vanilla}
test oo-object-clay-method-mixin-0012 {Test that const//flavor would mimic method interheritance for a mixed in class} {
  $MIXINAB flavor
} {vanilla}
    

test oo-object-clay-method-native-0013 {Test native object gets the property const//feeling} {
  $OBJECTAB clay get const/ feeling
} {dread}
test oo-object-clay-method-mixin-0013 {Test mixin object gets the property const//feeling} {
  $MIXINAB clay get const/ feeling
} {dread}


test oo-object-clay-method-native-methodcheck-0013 {Test that const//feeling would mimic method interheritance for a native class} {
  $OBJECTAB feeling
} {dread}
test oo-object-clay-method-mixin-0013 {Test that const//feeling would mimic method interheritance for a mixed in class} {
  $MIXINAB feeling
} {dread}
    

test oo-object-clay-method-native-0014 {Test native object gets the property const//sound} {
  $OBJECTAB clay get const/ sound
} {zoink}
test oo-object-clay-method-mixin-0014 {Test mixin object gets the property const//sound} {
  $MIXINAB clay get const/ sound
} {zoink}


test oo-object-clay-method-native-methodcheck-0014 {Test that const//sound would mimic method interheritance for a native class} {
  $OBJECTAB sound
} {zoink}
test oo-object-clay-method-mixin-0014 {Test that const//sound would mimic method interheritance for a mixed in class} {
  $MIXINAB sound
} {zoink}
    

test oo-object-clay-method-native-0015 {Test native object gets the property info//subelement} {
  $OBJECTAB clay get info/ subelement
} {spoon yes}
test oo-object-clay-method-mixin-0015 {Test mixin object gets the property info//subelement} {
  $MIXINAB clay get info/ subelement
} {spoon yes}


test oo-object-clay-method-native-0016 {Test native object gets the property info//animal} {
  $OBJECTAB clay get info/ animal
} {no}
test oo-object-clay-method-mixin-0016 {Test mixin object gets the property info//animal} {
  $MIXINAB clay get info/ animal
} {no}


test oo-object-clay-method-native-0017 {Test native object gets the property info//building} {
  $OBJECTAB clay get info/ building
} {no}
test oo-object-clay-method-mixin-0017 {Test mixin object gets the property info//building} {
  $MIXINAB clay get info/ building
} {no}

# -------------------------------------------------------------------------
# OBJECT descended from ::foo::classb ::foo::classa
set OBJECTBA [::foo::class.ba new]
# Object where classes were mixed in ::foo::classb ::foo::classa
set MIXINBA  [::oo::object new]
# Test modified 2018-10-30, mixin order was wrong before
oo::objdefine $MIXINBA mixin ::foo::classa ::foo::classb


test oo-object-clay-method-native-0018 {Test native object gets the property} {
  $OBJECTBA clay get const/ color
} {blue}
test oo-object-clay-method-mixin-0018 {Test mixin object gets the property} {
  $MIXINBA clay get const/ color
} {blue}


test oo-object-clay-method-native-methodcheck-0018 {Test that const//color would mimic method interheritance for a native class} {
  $OBJECTBA color
} {blue}
test oo-object-clay-method-mixin-0018 {Test that const//color would mimic method interheritance for a mixed in class} {
  $MIXINBA color
} {blue}
    

test oo-object-clay-method-native-0019 {Test native object gets the property} {
  $OBJECTBA clay get const/ flavor
} {strawberry}
test oo-object-clay-method-mixin-0019 {Test mixin object gets the property} {
  $MIXINBA clay get const/ flavor
} {strawberry}


test oo-object-clay-method-native-methodcheck-0019 {Test that const//flavor would mimic method interheritance for a native class} {
  $OBJECTBA flavor
} {strawberry}
test oo-object-clay-method-mixin-0019 {Test that const//flavor would mimic method interheritance for a mixed in class} {
  $MIXINBA flavor
} {strawberry}
    

test oo-object-clay-method-native-0020 {Test native object gets the property} {
  $OBJECTBA clay get const/ sound
} {zoink}
test oo-object-clay-method-mixin-0020 {Test mixin object gets the property} {
  $MIXINBA clay get const/ sound
} {zoink}


test oo-object-clay-method-native-methodcheck-0020 {Test that const//sound would mimic method interheritance for a native class} {
  $OBJECTBA sound
} {zoink}
test oo-object-clay-method-mixin-0020 {Test that const//sound would mimic method interheritance for a mixed in class} {
  $MIXINBA sound
} {zoink}
    

test oo-object-clay-method-native-0021 {Test native object gets the property} {
  $OBJECTBA clay get const/ feeling
} {dread}
test oo-object-clay-method-mixin-0021 {Test mixin object gets the property} {
  $MIXINBA clay get const/ feeling
} {dread}


test oo-object-clay-method-native-methodcheck-0021 {Test that const//feeling would mimic method interheritance for a native class} {
  $OBJECTBA feeling
} {dread}
test oo-object-clay-method-mixin-0021 {Test that const//feeling would mimic method interheritance for a mixed in class} {
  $MIXINBA feeling
} {dread}
    

test oo-object-clay-method-native-0022 {Test native object gets the property} {
  $OBJECTBA clay get info/ animal
} {no}
test oo-object-clay-method-mixin-0022 {Test mixin object gets the property} {
  $MIXINBA clay get info/ animal
} {no}


test oo-object-clay-method-native-0023 {Test native object gets the property} {
  $OBJECTBA clay get info/ building
} {no}
test oo-object-clay-method-mixin-0023 {Test mixin object gets the property} {
  $MIXINBA clay get info/ building
} {no}


test oo-object-clay-method-native-0024 {Test native object gets the property} {
  $OBJECTBA clay get info/ subelement
} {pedantic yes}
test oo-object-clay-method-mixin-0024 {Test mixin object gets the property} {
  $MIXINBA clay get info/ subelement
} {pedantic yes}


###
# put a do-nothing constructor on the books
###
::clay::define ::clay::object {
  constructor args {}
}

oo::objdefine ::clay::object method foo args { return bar }

test clay-core-method-0001 {Test that adding methods to the core ::clay::object class works} {
  ::clay::object foo
} {bar}

namespace eval ::TEST {}
::clay::define ::TEST::myclass {
  clay color red
  clay flavor strawberry

}

###
# Test adding a clay property
###
test clay-class-clay-0001 {Test that a clay statement is recorded in the object of the class} {
  ::TEST::myclass clay get color
} red
test clay-class-clay-0002 {Test that a clay statement is recorded in the object of the class} {
  ::TEST::myclass clay get flavor
} strawberry

###
# Test that objects of the class get the same properties
###
set OBJ [::clay::object new {}]
set OBJ2 [::TEST::myclass new {}]

test clay-object-clay-a-0001 {Test that objects not thee class do not get properties} {
  $OBJ clay get color
} {}
test clay-object-clay-a-0002 {Test that objects not thee class do not get properties} {
  $OBJ clay get flavor
} {}
test clay-object-clay-a-0003 {Test that objects of the class get properties} {
  $OBJ2 clay get color
} red
test clay-object-clay-a-0004 {Test that objects of the class get properties} {
  $OBJ2 clay get flavor
} strawberry

###
# Test modified 2018-10-21
###
test clay-object-clay-a-0005 {Test the clay ancestors function} {
  $OBJ clay ancestors
} {::clay::object}

###
# Test modified 2018-10-21
###
test clay-object-clay-a-0006 {Test the clay ancestors function} {
  $OBJ2 clay ancestors
} {::TEST::myclass ::clay::object}

test clay-object-clay-a-0007 {Test the clay provenance  function} {
  $OBJ2 clay provenance  flavor
} ::TEST::myclass

###
# Test that object local setting override the class
###
test clay-object-clay-a-0008 {Test that object local setting override the class} {
  $OBJ2 clay set color purple
  $OBJ2 clay get color
} purple
test clay-object-clay-a-0009 {Test that object local setting override the class} {
  $OBJ2 clay provenance  color
} self

::clay::define ::TEST::myclasse {
  superclass ::TEST::myclass

  clay color blue
  method do args {
    return "I did $args"
  }

  Ensemble which::color {} {
    return [my clay get color]
  }
  clay set method_ensemble which farbe: {tailcall my Which_color {*}$args}
}

###
# Test clay information is passed town to subclasses
###
test clay-class-clay-0003 {Test that a clay statement is recorded in the object of the class} {
  ::TEST::myclasse clay get color
} blue
test clay-class-clay-0004 {Test that clay statements from the ancestors of this class are not present (we handle them seperately in objects)} {
  ::TEST::myclasse clay get flavor
} {}
test clay-class-clay-0005 {Test that clay statements from the ancestors of this class are found with the FIND method} {
  ::TEST::myclasse clay find flavor
} {strawberry}

###
# Test that properties reach objects
###
set OBJ3 [::TEST::myclasse new {}]
test clay-object-clay-b-0001 {Test that objects of the class get properties} {
  $OBJ3 clay get color
} blue
test clay-object-clay-b-0002 {Test the clay provenance  function} {
  $OBJ3 clay provenance  color
} ::TEST::myclasse
test clay-object-clay-b-0003 {Test that objects of the class get properties} {
  $OBJ3 clay get flavor
} strawberry
test clay-object-clay-b-0004 {Test the clay provenance  function} {
  $OBJ3 clay provenance  flavor
} ::TEST::myclass

###
# Test modified 2018-10-21
###
test clay-object-clay-b-0005 {Test the clay provenance  function} {
  $OBJ3 clay ancestors
} {::TEST::myclasse ::TEST::myclass ::clay::object}

###
# Test defining a standard method
###
test clay-object-method-0001 {Test and standard method} {
  $OBJ3 do this really cool thing
} {I did this really cool thing}

test clay-object-method-0003 {Test an ensemble} {
  $OBJ3 which color
} blue
# Test setting properties
test clay-object-method-0004 {Test an ensemble} {
  $OBJ3 clay set color black
  $OBJ3 which color
} black

# Test setting properties
test clay-object-method-0004 {Test an ensemble alias} {
  $OBJ3 which farbe
} black


###
# Added 2019-06-24
# Test that grabbing a leaf does not pollute the cache
###
::clay::define ::TEST::class_with_deep_tree {
  clay set tree deep has depth 1
  clay set tree shallow has depth 0
}

$OBJ3 clay mixinmap deep ::TEST::class_with_deep_tree

test clay-deep-nested-0001 {Test that a leaf query does not pollute the cache} {
  $OBJ3 clay get tree shallow has depth
} 0
test clay-deep-nested-0001 {Test that a leaf query does not pollute the cache} {
  $OBJ3 clay get tree
} {deep {has {depth 1}} shallow {has {depth 0}}}



###
# Test that if you try to replace a global command you get an error
###
test clay-nspace-0001 {Test that if you try to replace a global command you get an error} -body {
::clay::define open {
  method bar {} { return foo }

}
}  -returnCodes {error} -result "::open does not refer to an object"

::clay::define fubar {
  method bar {} { return foo }
}
test clay-nspace-0002 {Test a non qualified class ends up in the current namespace} {
  info commands ::fubar
} {::fubar}

namespace eval ::cluster {
::clay::define fubar {
  method bar {} { return foo }
}

::clay::define ::clay::pot {
  method bar {} { return foo }
}

}
test clay-nspace-0003 {Test a non qualified class ends up in the current namespace} {
  info commands ::cluster::fubar
} {::cluster::fubar}
test clay-nspace-0003 {Test a fully qualified class ends up in the proper namespace} {
  info commands ::clay::pot
} {::clay::pot}

#set ::clay::trace 3

###
# New test - Added 2019-09-15
# Test that the "method" variable is exposed to a default method
###

::clay::define ::ensembleWithDefault {
  Ensemble foo::bar {} { return A }
  Ensemble foo::baz {} { return B }
  Ensemble foo::bang {} { return C }

  Ensemble foo::default {} { return $method }
}


set OBJ [::ensembleWithDefault new]
test clay-ensemble-default-0001 {Test a normal ensemble method} {
  $OBJ foo bar
} {A}
test clay-ensemble-default-0002 {Test a normal ensemble method} {
  $OBJ foo baz
} {B}
test clay-ensemble-default-0003 {Test a normal ensemble method} {
  $OBJ foo <list>
} [lsort -dictionary {bar baz bang}]

test clay-ensemble-default-0004 {Test a normal ensemble method} {
  $OBJ foo bing
} {bing}
test clay-ensemble-default-0005 {Test a normal ensemble method} {
  $OBJ foo bong
} {bong}
###
# Mixin tests
###

###
# Define a core class
###
::clay::define ::TEST::thing {

  method do args {
    return "I did $args"
  }
}


::clay::define ::TEST::vegetable {

  clay color unknown
  clay flavor unknown

  Ensemble which::flavor {} {
    return [my clay get flavor]
  }
  Ensemble which::color {} {
    return [my clay get color]
  }

}

::clay::define ::TEST::animal {

  clay color unknown
  clay sound unknown

  Ensemble which::sound {} {
    return [my clay get sound]
  }
  Ensemble which::color {} {
    return [my clay get color]
  }
  method sound {} {
    return unknown
  }
}

::clay::define ::TEST::species.cat {
  superclass ::TEST::animal
  clay sound meow
  method sound {} {
    return meow
  }
}

::clay::define ::TEST::coloring.calico {
  clay color calico

}

::clay::define ::TEST::condition.dark {
  Ensemble which::color {} {
    return grey
  }
}

::clay::define ::TEST::mood.happy {
  Ensemble which::sound {} {
    return purr
  }
  method sound {} {
    return purr
  }
}
test clay-object-0001 {Test than an object is created when clay::define is invoked} {
  info commands ::TEST::mood.happy
} ::TEST::mood.happy

set OBJ [::TEST::thing new]
test clay-mixin-a-0001 {Test that prior to a mixin an ensemble doesn't exist} -body {
  $OBJ which color
} -returnCodes error -result {unknown method "which": must be clay, destroy or do}

test clay-mixin-a-0002 {Test and standard method from an ancestor} {
  $OBJ do this really cool thing
} {I did this really cool thing}

$OBJ clay mixinmap species ::TEST::animal
test clay-mixin-b-0001 {Test that an ensemble is created during a mixin} {
  $OBJ which color
} {unknown}

test clay-mixin-b-0002 {Test that an ensemble is created during a mixin} {
  $OBJ which sound
} {unknown}

test clay-mixin-b-0003 {Test that an ensemble is created during a mixin}  -body {$OBJ which flavor} -returnCodes {error}  -result {unknown method which flavor. Valid: color sound}

###
# Test Modified: 2018-10-21
###
test clay-mixin-b-0004 {Test that mixins resolve in the correct order} {
  $OBJ clay ancestors
} {::TEST::animal ::TEST::thing ::clay::object}

###
# Replacing a mixin replaces the behaviors
###
$OBJ clay mixinmap species ::TEST::vegetable
test clay-mixin-c-0001 {Test that an ensemble is created during a mixin} {
  $OBJ which color
} {unknown}
test clay-mixin-c-0002 {Test that an ensemble is created during a mixin}  -body {$OBJ which sound}  -returnCodes {error}  -result {unknown method which sound. Valid: color flavor}
test clay-mixin-c-0003 {Test that an ensemble is created during a mixin} {
  $OBJ which flavor
} {unknown}
###
# Test Modified: 2018-10-21
###
test clay-mixin-c-0004 {Test that mixins resolve in the correct order} {
  $OBJ clay ancestors
} {::TEST::vegetable ::TEST::thing ::clay::object}

###
# Replacing a mixin
$OBJ clay mixinmap species ::TEST::species.cat
test clay-mixin-e-0001 {Test that an ensemble is created during a mixin} {
  $OBJ which color
} {unknown}
test clay-mixin-e-0002a {Test that an ensemble is created during a mixin} {
  $OBJ sound
} {meow}
test clay-mixin-e-0002b {Test that an ensemble is created during a mixin} {
  $OBJ clay get sound
} {meow}
test clay-mixin-e-0002 {Test that an ensemble is created during a mixin} {
  $OBJ which sound
} {meow}
test clay-mixin-e-0003 {Test that an ensemble is created during a mixin}  -body {$OBJ which flavor} -returnCodes {error}  -result {unknown method which flavor. Valid: color sound}
###
# Test Modified: 2018-10-30, 2018-10-21, 2018-10-10
###
test clay-mixin-e-0004 {Test that clay data follows the rules of inheritence and order of mixin} {
  $OBJ clay ancestors
} {::TEST::species.cat ::TEST::animal ::TEST::thing ::clay::object}

$OBJ clay mixinmap coloring ::TEST::coloring.calico
test clay-mixin-f-0001 {Test that an ensemble is created during a mixin} {
  $OBJ which color
} {calico}
test clay-mixin-f-0002 {Test that an ensemble is created during a mixin} {
  $OBJ which sound
} {meow}
test clay-mixin-f-0003 {Test that an ensemble is created during a mixin}  -body {$OBJ which flavor} -returnCodes {error}  -result {unknown method which flavor. Valid: color sound}

###
# Test modified 2018-10-30, 2018-10-21, 2018-10-10
###
test clay-mixin-f-0004 {Test that clay data follows the rules of inheritence and order of mixin} {
  $OBJ clay ancestors
} {::TEST::coloring.calico ::TEST::species.cat ::TEST::animal ::TEST::thing ::clay::object}

test clay-mixin-f-0005 {Test that clay data from a mixin works} {
  $OBJ clay provenance  color
} {::TEST::coloring.calico}

###
# Test variable initialization
###
::clay::define ::TEST::has_var {
  Variable my_variable 10

  method get_my_variable {} {
    my variable my_variable
    return $my_variable
  }
}

set OBJ [::TEST::has_var new]
test clay-class-variable-0001 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay get variable/ my_variable
} {10}

# Modified 2018-10-30 (order is different)
test clay-class-variable-0002 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay get variable
} {my_variable 10 DestroyEvent 0}

# Modified 2018-10-30 (order is different)
test clay-class-variable-0003 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay dget variable
} {. {} my_variable 10 DestroyEvent 0}

test clay-class-variable-0004 {Test that variables declared in the class definition are initialized} {
  $OBJ get_my_variable
} 10

###
# Test array initialization
###
::clay::define ::TEST::has_array {
  Array my_array {timeout 10}

  method get_my_array {field} {
    my variable my_array
    return $my_array($field)
  }
}

set OBJ [::TEST::has_array new]
test clay-class-array-0001 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay get array
} {my_array {timeout 10}}

test clay-class-array-0002 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay dget array
} {. {} my_array {. {} timeout 10}}

test clay-class-array-0003 {Test that variables declared in the class definition are initialized} {
  $OBJ get_my_array timeout
} 10

::clay::define ::TEST::has_more_array {
  superclass ::TEST::has_array
  Array my_array {color blue}
}
test clay-class-array-0008 {Test that the parser injected the right value in the right place for clay to catch it} {
  ::TEST::has_more_array clay get array
} {my_array {color blue}}

test clay-class-array-0009 {Test that the parser injected the right value in the right place for clay to catch it} {
  ::TEST::has_more_array clay find array
} {my_array {timeout 10 color blue}}

# Modified 2018-10-30 (order is different)
set BOBJ [::TEST::has_more_array new]
test clay-class-array-0004 {Test that the parser injected the right value in the right place for clay to catch it} {
  $BOBJ clay get array
} {my_array {color blue timeout 10}}

# Modified 2018-10-30 (order is different)
test clay-class-array-0005 {Test that the parser injected the right value in the right place for clay to catch it} {
  $BOBJ clay dget array
} {. {} my_array {. {} color blue timeout 10}}

test clay-class-arrau-0006 {Test that variables declared in the class definition are initialized} {
  $BOBJ get_my_array timeout
} 10
test clay-class-arrau-0007 {Test that variables declared in the class definition are initialized} {
  $BOBJ get_my_array color
} blue

::clay::define ::TEST::has_empty_array {
  Array my_array {}

  method my_array_exists {} {
    my variable my_array
    return [info exists my_array]
  }
  method get {field} {
    my variable my_array
    return $my_array($field)
  }
  method set {field value} {
    my variable my_array
    set my_array($field) $value
  }
}

test clay-class-array-0008 {Test that an declaration of an array with no values produces and empty array} {
  set COBJ [::TEST::has_empty_array new]
  $COBJ my_array_exists
} 1

test clay-class-array-0009 {Test that an declaration of an array with no values produces and empty array} {
  $COBJ set test "A random value"
  $COBJ get test
} {A random value}
###
# Test dict initialization
###
::clay::define ::TEST::has_dict {
  Dict my_dict {timeout 10}

  method get_my_dict {args} {
    my variable my_dict
    if {[llength $args]==0} {
      return $my_dict
    }
    return [dict get $my_dict {*}$args]
  }

}

set OBJ [::TEST::has_dict new]
test clay-class-dict-0001 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay get dict
} {my_dict {timeout 10}}

test clay-class-dict-0002 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay dget dict
} {. {} my_dict {. {} timeout 10}}

test clay-class-dict-0003 {Test that variables declared in the class definition are initialized} {
  $OBJ get_my_dict timeout
} 10

test clay-class-dict-0004 {Test that an empty dict is annotated} {
  $OBJ clay get dict
} {my_dict {timeout 10}}


::clay::define ::TEST::has_more_dict {
  superclass ::TEST::has_dict
  Dict my_dict {color blue}
}
set BOBJ [::TEST::has_more_dict new]

# Modified 2018-10-30
test clay-class-dict-0004 {Test that the parser injected the right value in the right place for clay to catch it} {
  $BOBJ clay get dict
} {my_dict {color blue timeout 10}}

# Modified 2018-10-30
test clay-class-dict-0005 {Test that the parser injected the right value in the right place for clay to catch it} {
  $BOBJ clay dget dict
} {. {} my_dict {. {} color blue timeout 10}}

test clay-class-dict-0006 {Test that variables declared in the class definition are initialized} {
  $BOBJ get_my_dict timeout
} 10

test clay-class-dict-0007 {Test that variables declared in the class definition are initialized} {
  $BOBJ get_my_dict color
} blue

::clay::define ::TEST::has_empty_dict {
  Dict my_empty_dict {}

  method get_my_empty_dict {args} {
    my variable my_empty_dict
    if {[llength $args]==0} {
      return $my_empty_dict
    }
    return [dict get $my_empty_dict {*}$args]
  }
}

set COBJ [::TEST::has_empty_dict new]

test clay-class-dict-0008 {Test that the parser injected the right value in the right place for clay to catch it} {
  $COBJ clay dget dict
} {my_empty_dict {. {}}}

test clay-class-dict-0009 {Test that an empty dict is initialized} {
  $COBJ get_my_empty_dict
} {}

###
# Test object delegation
###
::clay::define ::TEST::organelle {
  method add args {
    set total 0
    foreach item $args {
      set total [expr {$total+$item}]
    }
    return $total
  }
}
::clay::define ::TEST::master {
  constructor {} {
    set mysub [namespace current]::sub
    ::TEST::organelle create $mysub
    my clay delegate sub $mysub
  }
}

set OBJ [::TEST::master new]
###
# Test that delegation is working
###
test clay-delegation-0001 {Test an array driven ensemble} {
  $OBJ <sub> add 5 5
} 10


###
# Test the Ensemble keyword
###
::clay::define ::TEST::with_ensemble {

  Ensemble myensemble {pattern args} {
    set ensemble [self method]
    set emap [my clay ensemble_map $ensemble]
    set mlist [dict keys $emap [string tolower $pattern]]
    if {[llength $mlist] != 1} {
      error "Couldn't figure out what to do with $pattern"
    }
    set method [lindex $mlist 0]
    set argspec [dict get $emap $method argspec]
    set body    [dict get $emap $method body]
    if {$argspec ni {args {}}} {
      ::clay::dynamic_arguments $ensemble $method [list $argspec] {*}$args
    }
    eval $body
  }

  Ensemble myensemble::go args {
    return 1
  }
}

::clay::define ::TEST::with_ensemble.dance {
  Ensemble myensemble::dance args {
    return 1
  }
}
::clay::define ::TEST::with_ensemble.cannot_dance {
  Ensemble myensemble::dance args {
    return 0
  }
}

set OBJA [::clay::object new]
set OBJB [::clay::object new]

$OBJA clay mixinmap  core ::TEST::with_ensemble  friends ::TEST::with_ensemble.dance

$OBJB clay mixinmap  core ::TEST::with_ensemble  friends ::TEST::with_ensemble.cannot_dance

# Test go
test clay-dynamic-ensemble-0001 {Test ensemble with static method} {
  $OBJA myensemble go
} {1}
test clay-dynamic-ensemble-0002 {Test ensemble with static method} {
  $OBJB myensemble go
} {1}
# Test dance
test clay-dynamic-ensemble-0003 {Test ensemble with static method} {
  $OBJA myensemble dance
} {1}
test clay-dynamic-ensemble-0004 {Test ensemble with static method} {
  $OBJB myensemble dance
} {0}


###
# Class method testing
###

clay::class create WidgetClass {
  Class_Method working {} {
    return {Works}
  }

  Class_Method unknown args {
    set tkpath [lindex $args 0]
    if {[string index $tkpath 0] eq "."} {
      set obj [my new $tkpath {*}[lrange $args 1 end]]
      $obj tkalias $tkpath
      return $tkpath
    }
    next {*}$args
  }

  constructor {TkPath args} {
    my variable hull
    set hull $TkPath
    my clay delegate hull $TkPath
  }

  method tkalias tkname {
    set oldname $tkname
    my variable tkalias
    set tkalias $tkname
    set self [self]
    set hullwidget [::info object namespace $self]::tkwidget
    my clay delegate tkwidget $hullwidget
    #rename ::$tkalias $hullwidget
    my clay delegate hullwidget $hullwidget
    #::tool::object_rename [self] ::$tkalias
    rename [self] ::$tkalias
    #my Hull_Bind $tkname
    return $hullwidget
  }
}

test tool-class-method-000 {Test that class methods actually work...} {
  WidgetClass working
} {Works}

test tool-class-method-001 {Test Tk style creator} {
  WidgetClass .foo
  .foo clay delegate hull
} {.foo}

::clay::define WidgetNewClass {
  superclass WidgetClass
}

test tool-class-method-002 {Test Tk style creator inherited by morph} {
  WidgetNewClass .bar
  .bar clay delegate hull
} {.bar}



###
# Test ensemble inheritence
###
clay::define NestedClassA {
  Ensemble do::family {} {
    return NestedClassA
  }
  Ensemble do::something {} {
    return A
  }
  Ensemble do::whop {} {
    return A
  }
}
clay::define NestedClassB {
  superclass NestedClassA
  Ensemble do::family {} {
    set r [next family]
    lappend r NestedClassB
    return $r
  }
  Ensemble do::whop {} {
    return B
  }
}
clay::define NestedClassC {
  superclass NestedClassB

  Ensemble do::somethingelse {} {
    return C
  }
}
clay::define NestedClassD {
  superclass NestedClassB

  Ensemble do::somethingelse {} {
    return D
  }
}

clay::define NestedClassE {
  superclass NestedClassD NestedClassC
}

clay::define NestedClassF {
  superclass NestedClassC NestedClassD
}

NestedClassC create NestedObjectC

###
# These tests no longer work because method ensembles are now dynamically
# generated by object, that are not attached to the class anymore
#
####
#test tool-ensemble-001 {Test that an ensemble can access [next] even if no object of the ancestor class have been instantiated} {
#  NestedObjectC do family
#} {::NestedClassA ::NestedClassB ::NestedClassC}

test tool-ensemble-002 {Test that a later ensemble definition trumps a more primitive one} {
  NestedObjectC do whop
} {B}
test tool-ensemble-003 {Test that an ensemble definitions in an ancestor carry over} {
  NestedObjectC do something
} {A}

NestedClassE create NestedObjectE
NestedClassF create NestedObjectF


test tool-ensemble-004 {Test that ensembles follow the same rules for inheritance as methods} {
  NestedObjectE do somethingelse
} {D}

test tool-ensemble-005 {Test that ensembles follow the same rules for inheritance as methods} {
  NestedObjectF do somethingelse
} {C}

###
# Set of tests to exercise the mixinmap system
###
clay::define MixinMainClass {
  Variable mainvar unchanged

  Ensemble test::which {} {
    my variable mainvar
    return $mainvar
  }

  Ensemble test::main args {
    puts [list this is main $method $args]
  }

}

set mixoutscript {my test untool $class}
set mixinscript {my test tool $class}
clay::define MixinTool {
  Variable toolvar unchanged.mixin
  clay set mixin/ unmap-script $mixoutscript
  clay set mixin/ map-script $mixinscript
  clay set mixin/ name {Generic Tool}

  Ensemble test::untool class {
    my variable toolvar mainvar
    set mainvar {}
    set toolvar {}
  }

  Ensemble test::tool class {
    my variable toolvar mainvar
    set mainvar [$class clay get mixin name]
    set toolvar [$class clay get mixin name]
  }
}

clay::define MixinToolA {
  superclass MixinTool

  clay set mixin/ name {Tool A}
}

clay::define MixinToolB {
  superclass MixinTool

  clay set mixin/ name {Tool B}

  method test_newfunc {} {
    return "B"
  }
}

test tool-mixinspec-001 {Test application of mixin specs} {
  MixinTool clay get mixin map-script
} $mixinscript

test tool-mixinspec-002 {Test application of mixin specs} {
  MixinToolA clay get mixin map-script
} {}

test tool-mixinspec-003 {Test application of mixin specs} {
  MixinToolA clay find mixin map-script
} $mixinscript

test tool-mixinspec-004 {Test application of mixin specs} {
  MixinToolB clay find mixin map-script
} $mixinscript


MixinMainClass create mixintest

test tool-mixinmap-001 {Test object prior to mixins} {
  mixintest test which
} {unchanged}

mixintest clay mixinmap tool MixinToolA
test tool-mixinmap-002 {Test mixin map script ran} {
  mixintest test which
} {Tool A}

mixintest clay mixinmap tool MixinToolB

test tool-mixinmap-003 {Test mixin map script ran} {
  mixintest test which
} {Tool B}

test tool-mixinmap-003 {Test mixin map script ran} {
  mixintest test_newfunc
} {B}

mixintest clay mixinmap tool {}
test tool-mixinmap-004 {Test object prior to mixins} {
  mixintest test which
} {}



clay::define ::clay::object {
  method path {} {
    return [self class]
  }
}


clay::define ::MixinRoot {
  clay set opts core   root
  clay set opts option unset
  clay set opts color  unset

  Ensemble info::root {} {
    return MixinRoot
  }
  Ensemble info::shade {} {
    return avacodo
  }
  Ensemble info::default {} {
    return Undefined
  }

  method did {} {
    return MixinRoot
  }

  method path {} {
    return [list [self class] {*}[next]]
  }
}

clay::define ::MixinOption1 {
  clay set opts option option1

  Ensemble info::option {} {
    return MixinOption1
  }
  Ensemble info::other {} {
    return MixinOption1
  }

  method did {} {
    return MixinOption1
  }

  method path {} {
    return [list [self class] {*}[next]]
  }
}

clay::define ::MixinOption2 {
  superclass ::MixinOption1

  clay set opts option option2

  Ensemble info::option {} {
    return MixinOption2
  }

  method did {} {
    return MixinOption2
  }

  method path {} {
    return [list [self class] {*}[next]]
  }
}


clay::define ::MixinColor1 {
  clay set opts color blue

  Ensemble info::color {} {
    return MixinColor1
  }
  Ensemble info::shade {} {
    return blue
  }

  method did {} {
    return MixinColor1
  }

  method path {} {
    return [list [self class] {*}[next]]
  }
}

clay::define ::MixinColor2 {
  clay set opts color green

  Ensemble info::color {} {
    return MixinColor2
  }
  Ensemble info::shade {} {
    return green
  }

  method did {} {
    return MixinColor2
  }

  method path {} {
    return [list [self class] {*}[next]]
  }
}

set obj [clay::object new]

$obj clay mixinmap root ::MixinRoot


test tool-prototype-0001-0001 {Mixin core} {
  $obj info root
} {MixinRoot}


test tool-prototype-0001-0002 {Mixin core} {
  $obj info option
} {Undefined}


test tool-prototype-0001-0003 {Mixin core} {
  $obj info color
} {Undefined}


test tool-prototype-0001-0004 {Mixin core} {
  $obj info other
} {Undefined}


test tool-prototype-0001-0005 {Mixin core} {
  $obj info shade
} {avacodo}


test tool-prototype-0001-0006 {Mixin core} {
  $obj did
} {MixinRoot}


test tool-prototype-0001-0007 {Mixin core} {
  $obj path
} {::MixinRoot ::clay::object}


test tool-prototype-0001-0008 {Mixin core} {
  $obj clay get opts
} {core root option unset color unset}


test tool-prototype-0001-0009 {Mixin core} {
  $obj clay get opts core
} {root}


test tool-prototype-0001-0010 {Mixin core} {
  $obj clay get opts option
} {unset}


test tool-prototype-0001-0011 {Mixin core} {
  $obj clay get opts color
} {unset}


test tool-prototype-0001-0012 {Mixin core} {
  $obj clay ancestors
} {::MixinRoot ::clay::object}

$obj clay mixinmap option ::MixinOption1

test tool-prototype-0002-0001 {Mixin option1} {
  $obj info root
} {MixinRoot}


test tool-prototype-0002-0002 {Mixin option1} {
  $obj info option
} {MixinOption1}


test tool-prototype-0002-0003 {Mixin option1} {
  $obj info color
} {Undefined}


test tool-prototype-0002-0004 {Mixin option1} {
  $obj info other
} {MixinOption1}


test tool-prototype-0002-0005 {Mixin option1} {
  $obj info shade
} {avacodo}


test tool-prototype-0002-0006 {Mixin option1} {
  $obj did
} {MixinOption1}


test tool-prototype-0002-0007 {Mixin option1} {
  $obj path
} {::MixinOption1 ::MixinRoot ::clay::object}


test tool-prototype-0002-0008 {Mixin option1} {
  $obj clay get opts
} {option option1 core root color unset}


test tool-prototype-0002-0009 {Mixin option1} {
  $obj clay get opts core
} {root}


test tool-prototype-0002-0010 {Mixin option1} {
  $obj clay get opts option
} {option1}


test tool-prototype-0002-0011 {Mixin option1} {
  $obj clay get opts color
} {unset}


test tool-prototype-0002-0012 {Mixin option1} {
  $obj clay ancestors
} {::MixinOption1 ::MixinRoot ::clay::object}


set obj2 [clay::object new]
$obj2 clay mixinmap root ::MixinRoot option ::MixinOption1

$obj clay mixinmap option ::MixinOption1

test tool-prototype-0003-0001 {Mixin option1 - clean object} {
  $obj2 info root
} {MixinRoot}


test tool-prototype-0003-0002 {Mixin option1 - clean object} {
  $obj2 info option
} {MixinOption1}


test tool-prototype-0003-0003 {Mixin option1 - clean object} {
  $obj2 info color
} {Undefined}


test tool-prototype-0003-0004 {Mixin option1 - clean object} {
  $obj2 info other
} {MixinOption1}


test tool-prototype-0003-0005 {Mixin option1 - clean object} {
  $obj2 info shade
} {avacodo}


test tool-prototype-0003-0006 {Mixin option1 - clean object} {
  $obj2 did
} {MixinOption1}


test tool-prototype-0003-0007 {Mixin option1 - clean object} {
  $obj2 path
} {::MixinOption1 ::MixinRoot ::clay::object}


test tool-prototype-0003-0008 {Mixin option1 - clean object} {
  $obj2 clay get opts
} {option option1 core root color unset}


test tool-prototype-0003-0009 {Mixin option1 - clean object} {
  $obj2 clay get opts core
} {root}


test tool-prototype-0003-0010 {Mixin option1 - clean object} {
  $obj2 clay get opts option
} {option1}


test tool-prototype-0003-0011 {Mixin option1 - clean object} {
  $obj2 clay get opts color
} {unset}


test tool-prototype-0003-0012 {Mixin option1 - clean object} {
  $obj2 clay ancestors
} {::MixinOption1 ::MixinRoot ::clay::object}

$obj clay mixinmap option ::MixinOption2

test tool-prototype-0004-0001 {Mixin option2} {
  $obj info root
} {MixinRoot}


test tool-prototype-0004-0002 {Mixin option2} {
  $obj info option
} {MixinOption2}


test tool-prototype-0004-0003 {Mixin option2} {
  $obj info color
} {Undefined}


test tool-prototype-0004-0004 {Mixin option2} {
  $obj info other
} {MixinOption1}


test tool-prototype-0004-0005 {Mixin option2} {
  $obj info shade
} {avacodo}


test tool-prototype-0004-0006 {Mixin option2} {
  $obj did
} {MixinOption2}


test tool-prototype-0004-0007 {Mixin option2} {
  $obj path
} {::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object}


test tool-prototype-0004-0008 {Mixin option2} {
  $obj clay get opts
} {option option2 core root color unset}


test tool-prototype-0004-0009 {Mixin option2} {
  $obj clay get opts core
} {root}


test tool-prototype-0004-0010 {Mixin option2} {
  $obj clay get opts option
} {option2}


test tool-prototype-0004-0011 {Mixin option2} {
  $obj clay get opts color
} {unset}


test tool-prototype-0004-0012 {Mixin option2} {
  $obj clay ancestors
} {::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object}

$obj clay mixinmap color MixinColor1

test tool-prototype-0005-0001 {Mixin color1} {
  $obj info root
} {MixinRoot}


test tool-prototype-0005-0002 {Mixin color1} {
  $obj info option
} {MixinOption2}


test tool-prototype-0005-0003 {Mixin color1} {
  $obj info color
} {MixinColor1}


test tool-prototype-0005-0004 {Mixin color1} {
  $obj info other
} {MixinOption1}


test tool-prototype-0005-0005 {Mixin color1} {
  $obj info shade
} {blue}


test tool-prototype-0005-0006 {Mixin color1} {
  $obj did
} {MixinColor1}


test tool-prototype-0005-0007 {Mixin color1} {
  $obj path
} {::MixinColor1 ::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object}


test tool-prototype-0005-0008 {Mixin color1} {
  $obj clay get opts
} {color blue option option2 core root}


test tool-prototype-0005-0009 {Mixin color1} {
  $obj clay get opts core
} {root}


test tool-prototype-0005-0010 {Mixin color1} {
  $obj clay get opts option
} {option2}


test tool-prototype-0005-0011 {Mixin color1} {
  $obj clay get opts color
} {blue}


test tool-prototype-0005-0012 {Mixin color1} {
  $obj clay ancestors
} {::MixinColor1 ::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object}

$obj clay mixinmap color MixinColor2

test tool-prototype-0006-0001 {Mixin color2} {
  $obj info root
} {MixinRoot}


test tool-prototype-0006-0002 {Mixin color2} {
  $obj info option
} {MixinOption2}


test tool-prototype-0006-0003 {Mixin color2} {
  $obj info color
} {MixinColor2}


test tool-prototype-0006-0004 {Mixin color2} {
  $obj info other
} {MixinOption1}


test tool-prototype-0006-0005 {Mixin color2} {
  $obj info shade
} {green}


test tool-prototype-0006-0006 {Mixin color2} {
  $obj clay get opts
} {color green option option2 core root}


test tool-prototype-0006-0007 {Mixin color2} {
  $obj clay get opts core
} {root}


test tool-prototype-0006-0008 {Mixin color2} {
  $obj clay get opts option
} {option2}


test tool-prototype-0006-0009 {Mixin color2} {
  $obj clay get opts color
} {green}


test tool-prototype-0006-0010 {Mixin color2} {
  $obj clay ancestors
} {::MixinColor2 ::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object}

$obj clay mixinmap option MixinOption1

test tool-prototype-0007-0001 {Mixin color2 + Option1} {
  $obj info root
} {MixinRoot}


test tool-prototype-0007-0002 {Mixin color2 + Option1} {
  $obj info option
} {MixinOption1}


test tool-prototype-0007-0003 {Mixin color2 + Option1} {
  $obj info color
} {MixinColor2}


test tool-prototype-0007-0004 {Mixin color2 + Option1} {
  $obj info other
} {MixinOption1}


test tool-prototype-0007-0005 {Mixin color2 + Option1} {
  $obj info shade
} {green}


test tool-prototype-0007-0006 {Mixin color2 + Option1} {
  $obj clay get opts
} {color green option option1 core root}


test tool-prototype-0007-0007 {Mixin color2 + Option1} {
  $obj clay get opts core
} {root}


test tool-prototype-0007-0008 {Mixin color2 + Option1} {
  $obj clay get opts option
} {option1}


test tool-prototype-0007-0009 {Mixin color2 + Option1} {
  $obj clay get opts color
} {green}


test tool-prototype-0007-0010 {Mixin color2 + Option1} {
  $obj clay ancestors
} {::MixinColor2 ::MixinOption1 ::MixinRoot ::clay::object}

$obj clay mixinmap option {}

test tool-prototype-0008-0001 {Mixin color2 + no option} {
  $obj info root
} {MixinRoot}


test tool-prototype-0008-0002 {Mixin color2 + no option} {
  $obj info option
} {Undefined}


test tool-prototype-0008-0003 {Mixin color2 + no option} {
  $obj info color
} {MixinColor2}


test tool-prototype-0008-0004 {Mixin color2 + no option} {
  $obj info other
} {Undefined}


test tool-prototype-0008-0005 {Mixin color2 + no option} {
  $obj info shade
} {green}


test tool-prototype-0008-0006 {Mixin color2 + no option} {
  $obj clay get opts
} {color green core root option unset}


test tool-prototype-0008-0007 {Mixin color2 + no option} {
  $obj clay get opts core
} {root}


test tool-prototype-0008-0008 {Mixin color2 + no option} {
  $obj clay get opts option
} {unset}


test tool-prototype-0008-0009 {Mixin color2 + no option} {
  $obj clay get opts color
} {green}


test tool-prototype-0008-0010 {Mixin color2 + no option} {
  $obj clay ancestors
} {::MixinColor2 ::MixinRoot ::clay::object}

$obj clay mixinmap color {}

test tool-prototype-0009-0001 {Mixin core (return to normal)} {
  $obj info root
} {MixinRoot}


test tool-prototype-0009-0002 {Mixin core (return to normal)} {
  $obj info option
} {Undefined}


test tool-prototype-0009-0003 {Mixin core (return to normal)} {
  $obj info color
} {Undefined}


test tool-prototype-0009-0004 {Mixin core (return to normal)} {
  $obj info other
} {Undefined}


test tool-prototype-0009-0005 {Mixin core (return to normal)} {
  $obj info shade
} {avacodo}


test tool-prototype-0009-0006 {Mixin core (return to normal)} {
  $obj clay get opts
} {core root option unset color unset}


test tool-prototype-0009-0007 {Mixin core (return to normal)} {
  $obj clay get opts core
} {root}


test tool-prototype-0009-0008 {Mixin core (return to normal)} {
  $obj clay get opts option
} {unset}


test tool-prototype-0009-0009 {Mixin core (return to normal)} {
  $obj clay get opts color
} {unset}


test tool-prototype-0009-0010 {Mixin core (return to normal)} {
  $obj clay ancestors
} {::MixinRoot ::clay::object}


###
# Tip479 Tests
###
clay::define tip479class {

  Method newitem dictargs {
    id {type: number}
    color {default: green}
    shape {options: {round square}}
    flavor {default: grape}
  } {
    my variable items
    foreach {f v} $args {
      dict set items $id $f $v
    }
    if {"color" ni [dict keys $args]} {
      dict set items $id color $color
    }
    return [dict get $items $id]
  }

  method itemget {id field} {
    my variable items
    return [dict get $id $field]
  }
}

set obj [tip479class new]
test tip479-001 {Test that a later ensemble definition trumps a more primitive one} {
  $obj newitem id 1 color orange shape round
} {id 1 color orange shape round}

# Fail because we left off a mandatory argument
test tip479-002 {Test that a later ensemble definition trumps a more primitive one} -body {
  $obj newitem id 2
} -result {shape is required} -returnCodes error

###
# Leave off a value that has a default
# note: Method had special handling for color, but not flavor
###
test tip479-003 {Test that a later ensemble definition trumps a more primitive one} {
  $obj newitem id 3 shape round
} {id 3 shape round color green}

###
# Add extra arguments
###
test tip479-004 {Test that a later ensemble definition trumps a more primitive one} {
  $obj newitem id 4 shape round trim leather
} {id 4 shape round trim leather color green}

clay::define tip479classE {

  Ensemble item::new dictargs {
    id {type: number}
    color {default: green}
    shape {options: {round square}}
    flavor {default: grape}
  } {
    my variable items
    foreach {f v} $args {
      dict set items $id $f $v
    }
    if {"color" ni [dict keys $args]} {
      dict set items $id color $color
    }
    return [dict get $items $id]
  }

  Ensemble item::get {id field} {
    my variable items
    return [dict get $id $field]
  }
}


set obj [tip479classE new]
test tip479-001 {Test that a later ensemble definition trumps a more primitive one} {
  $obj item new id 1 color orange shape round
} {id 1 color orange shape round}

# Fail because we left off a mandatory argument
test tip479-002 {Test that a later ensemble definition trumps a more primitive one} -body {
  $obj item new id 2
} -result {shape is required} -returnCodes error

###
# Leave off a value that has a default
# note: Method had special handling for color, but not flavor
###
test tip479-003 {Test that a later ensemble definition trumps a more primitive one} {
  $obj item new id 3 shape round
} {id 3 shape round color green}

###
# Add extra arguments
###
test tip479-004 {Test that a later ensemble definition trumps a more primitive one} {
  $obj item new id 4 shape round trim leather
} {id 4 shape round trim leather color green}



testsuiteCleanup

# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End:




if {![package vsatisfies [package provide Tcl] 8.7]} {return}
puts "Repeating tests with 8.7 features"
namespace eval ::oo::dialect {}
set ::oo::dialect::has(tip470) 1

# clay.test - Copyright (c) 2018 Sean Woods
# -------------------------------------------------------------------------

set MODDIR [file dirname [file dirname [file join [pwd] [info script]]]]
if {[file exists [file join $MODDIR devtools testutilities.tcl]]} {
  # Running inside tcllib
  set TCLLIBMOD $MODDIR
} else {
  set TCLLIBMOD [file join $MODDIR .. .. tcllib modules]
}
source [file join $TCLLIBMOD devtools testutilities.tcl]

testsNeedTcl     8.6
testsNeedTcltest 2
testsNeed        TclOO 1

support {}
testing {
    useLocal clay.tcl clay
}


set ::clay::trace 0



# -------------------------------------------------------------------------
# Handle multiple implementation testing
#

array set preserve [array get ::clay::uuid::accel]

proc implementations {} {
    variable ::clay::uuid::accel
    foreach {a v} [array get accel] {if {$v} {lappend r $a}}
    lappend r tcl; set r
}

proc select_implementation {impl} {
    variable ::clay::uuid::accel
    foreach e [array names accel] { set accel($e) 0 }
    if {[string compare "tcl" $impl] != 0} {
        set accel($impl) 1
    }
}

proc reset_implementation {} {
    variable ::clay::uuid::accel
    array set accel [array get ::preserve]
}

# -------------------------------------------------------------------------
# Setup any constraints
#

# -------------------------------------------------------------------------
# Now the package specific tests....
# -------------------------------------------------------------------------

# -------------------------------------------------------------------------

foreach impl [implementations] {
    select_implementation $impl

    test uuid-1.0-$impl "uuid requires args" {
        list [catch {clay::uuid} msg]
    } {1}

    test uuid-1.1-$impl "uuid generate should create a 36 char string uuid" {
        list [catch {string length [clay::uuid generate]} msg] $msg
    } {0 36}

    test uuid-1.2-$impl "uuid comparison of uuid with self should be true" {
        list [catch {
            set a [clay::uuid generate]
            clay::uuid equal $a $a
        } msg] $msg
    } {0 1}

    test uuid-1.3-$impl "uuid comparison of two different uuids should be false" {
        list [catch {
            set a [clay::uuid generate]
            set b [clay::uuid generate]
            clay::uuid equal $a $b
        } msg] $msg
    } {0 0}

    reset_implementation
}


# Modification History:
###
# Modification 2018-10-30
# Fixed an error in our ancestry mapping and developed tests to
# ensure we are actually following in the order TclOO follows methods
###
# Modification 2018-10-21
# The clay metaclass no longer exports the clay method
# to oo::class and oo::object, and clay::ancestors no
# longer returns any class that lacks the clay method
###
# Modification 2018-10-10
# clay::ancestors now rigged to descend into all classes depth-first
# and then place metaclasses at the end of the search
###
# -------------------------------------------------------------------------

# -------------------------------------------------------------------------
# Test Helpers
###
proc dict_compare {a b} {
  set result {}
  set A {}
  dict for {f v} $a {
    set f [string trim $f :/]
    if {$f eq {.}} continue
    dict set A $f $v
  }
  set B {}
  dict for {f v} $b {
    set f [string trim $f :/]
    if {$f eq {.}} continue
    dict set B $f $v
  }
  dict for {f v} $A {
    if {[dict exists $B $f]} {
      if {[dict get $B $f] ne $v} {
        lappend result [list B $f [dict get $B $f] [list != $v]]
      }
    } else {
      lappend result [list B $f $v missing]
    }
  }
  dict for {f v} $B {
    if {![dict exists $A $f]} {
      lappend result [list A $f $v missing]
    }
  }
  return $result
}

test dict-compare-001 {Test our testing method} {
  dict_compare {} {}
} {}

test dict-compare-002 {Test our testing method} {
  dict_compare {a 1} {}
} {{B a 1 missing}}

test dict-compare-003 {Test our testing method} {
  dict_compare {a 1 b 2} {a 1 b 2}
} {}

test dict-compare-003.a {Test our testing method} {
  dict_compare {a 1 b 2} {b 2 a 1 }
} {}

test dict-compare-003.b {Test our testing method} {
  dict_compare {b 2 a 1} {a 1 b 2}
} {}


test dict-compare-004 {Test our testing method} {
  dict_compare {a: 1 b: 2} {a 1 b 2}
} {}

test dict-compare-005 {Test our testing method} {
  dict_compare {a 1 b 3} {a 1 b 2}
} {{B b 2 {!= 3}}}


###
# Test canonical mapping
###


test {test-storage-0001} {Test ::clay::tree::storage with foo bar baz} {
  clay::tree::storage {foo bar baz}
} {foo bar baz}


test {test-storage-0002} {Test ::clay::tree::storage with foo bar baz/} {
  clay::tree::storage {foo bar baz/}
} {foo bar baz}


test {test-storage-0003} {Test ::clay::tree::storage with foo bar .} {
  clay::tree::storage {foo bar .}
} {foo bar .}


test {test-storage-0004} {Test ::clay::tree::storage with foo/ bar/ .} {
  clay::tree::storage {foo/ bar/ .}
} {foo bar .}


test {test-storage-0005} {Test ::clay::tree::storage with foo . bar . baz .} {
  clay::tree::storage {foo . bar . baz .}
} {foo . bar . baz .}


test {test-storage-0006} {Test ::clay::tree::storage with foo bar baz bat:} {
  clay::tree::storage {foo bar baz bat:}
} {foo bar baz bat:}


test {test-storage-0007} {Test ::clay::tree::storage with foo:} {
  clay::tree::storage {foo:}
} {foo:}


test {test-storage-0008} {Test ::clay::tree::storage with foo/bar/baz/bat:} {
  clay::tree::storage {foo/bar/baz/bat:}
} {foo bar baz bat:}


dict set r foo/ bar/ baz 1
dict set s foo/ bar/ baz 0
set t [clay::tree::merge $r $s]

test rmerge-0001 {Test that the root is marked as a branch} {
  dict get $t foo bar baz
} 0

set r [dict create]
clay::tree::dictmerge r {
  foo/ {
    bar/ {
      baz 1
      bing: 2
      bang { bim 3 boom 4 }
      womp: {a 1 b 2}
    }
  }
}

test dictmerge-0001 {Test that the root is marked as a branch} {
  dict exists $r .
} 1
test dictmerge-0002 {Test that branch foo is marked correctly} {
  dict exists $r foo .
} 1
test dictmerge-0003 {Test that branch bar is marked correctly} {
  dict exists $r foo bar .
} 1
test dictmerge-0004 {Test that leaf foo/bar/bang is not marked as branch despite being a dict} {
  dict exists $r foo bar bang .
} 0
test dictmerge-0004 {Test that leaf foo/bar/bang/bim exists} {
  dict exists $r foo bar bang bim
} 1
test dictmerge-0005 {Test that leaf foo/bar/bang/boom exists} {
  dict exists $r foo bar bang boom
} 1

###
# Replace bang with bang/
###
clay::tree::dictmerge r {
  foo/ {
    bar/ {
      bang/ {
        whoop 1
      }
    }
  }
}

test dictmerge-0006 {Test that leaf foo/bar/bang/bim ceases to exist} {
  dict exists $r foo bar bang bim
} 0
test dictmerge-0007 {Test that leaf foo/bar/bang/boom exists} {
  dict exists $r foo bar bang boom
} 0

test dictmerge-0008 {Test that leaf foo/bar/bang is now a branch} {
  dict exists $r foo bar bang .
} 1

test branch-0001 {Test that foo/ is a branch} {
  clay::tree::is_branch $r foo/
} 1
test branch-0002 {Test that foo is a branch} {
  clay::tree::is_branch $r foo
} 1
test branch-0003 {Test that foo/bar/ is a branch} {
  clay::tree::is_branch $r {foo/ bar/}
} 1
test branch-0004 {Test that foo bar is not branch} {
  clay::tree::is_branch $r {foo bar}
} 1
test branch-0004 {Test that foo/ bar is not branch} {
  clay::tree::is_branch $r {foo/ bar}
} 0


test {test-branch-0001} {Test that  foo is_branch = 1} {
  clay::tree::is_branch $r { foo}
} 1


test {test-branch-0002} {Test that  foo: is_branch = 0} {
  clay::tree::is_branch $r { foo:}
} 0


test {test-branch-0003} {Test that  foo/ is_branch = 1} {
  clay::tree::is_branch $r { foo/}
} 1


test {test-branch-0004} {Test that  .foo is_branch = 0} {
  clay::tree::is_branch $r { .foo}
} 0


test {test-branch-0005} {Test that foo bar is_branch = 1} {
  clay::tree::is_branch $r {foo bar}
} 1


test {test-branch-0006} {Test that foo bar: is_branch = 0} {
  clay::tree::is_branch $r {foo bar:}
} 0


test {test-branch-0007} {Test that foo bar/ is_branch = 1} {
  clay::tree::is_branch $r {foo bar/}
} 1


test {test-branch-0008} {Test that foo .bar is_branch = 0} {
  clay::tree::is_branch $r {foo .bar}
} 0


test {test-branch-0009} {Test that foo bar baz is_branch = 0} {
  clay::tree::is_branch $r {foo bar baz}
} 0


test {test-branch-0010} {Test that foo bar baz: is_branch = 0} {
  clay::tree::is_branch $r {foo bar baz:}
} 0


test {test-branch-0011} {Test that foo bar baz/ is_branch = 1} {
  clay::tree::is_branch $r {foo bar baz/}
} 1


test {test-branch-0012} {Test that foo bar .baz is_branch = 0} {
  clay::tree::is_branch $r {foo bar .baz}
} 0


test {test-branch-0013} {Test that foo bar bing is_branch = 0} {
  clay::tree::is_branch $r {foo bar bing}
} 0


test {test-branch-0014} {Test that foo bar bing: is_branch = 0} {
  clay::tree::is_branch $r {foo bar bing:}
} 0


test {test-branch-0015} {Test that foo bar bing/ is_branch = 1} {
  clay::tree::is_branch $r {foo bar bing/}
} 1


test {test-branch-0016} {Test that foo bar .bing is_branch = 0} {
  clay::tree::is_branch $r {foo bar .bing}
} 0


test {test-branch-0017} {Test that foo bar bang is_branch = 1} {
  clay::tree::is_branch $r {foo bar bang}
} 1


test {test-branch-0018} {Test that foo bar bang: is_branch = 0} {
  clay::tree::is_branch $r {foo bar bang:}
} 0


test {test-branch-0019} {Test that foo bar bang/ is_branch = 1} {
  clay::tree::is_branch $r {foo bar bang/}
} 1


test {test-branch-0020} {Test that foo bar .bang is_branch = 0} {
  clay::tree::is_branch $r {foo bar .bang}
} 0


test {test-branch-0021} {Test that foo bar bang whoop is_branch = 0} {
  clay::tree::is_branch $r {foo bar bang whoop}
} 0


test {test-branch-0022} {Test that foo bar bang whoop: is_branch = 0} {
  clay::tree::is_branch $r {foo bar bang whoop:}
} 0


test {test-branch-0023} {Test that foo bar bang whoop/ is_branch = 1} {
  clay::tree::is_branch $r {foo bar bang whoop/}
} 1


test {test-branch-0024} {Test that foo bar bang .whoop is_branch = 0} {
  clay::tree::is_branch $r {foo bar bang .whoop}
} 0


# -------------------------------------------------------------------------
# dictmerge Testing - oometa
unset -nocomplain foo
clay::tree::dictmerge foo {
  option/ {
    color/ {
      label Color
      default green
    }
  }
}
clay::tree::dictmerge foo {
  option/ {
    color/ {
      default purple
    }
  }
}

test oometa-0001 {Invoking dictmerge with empty args on a non existent variable create an empty variable} {
  dict get $foo option color default
} purple
test oometa-0002 {Invoking dictmerge with empty args on a non existent variable create an empty variable} {
  dict get $foo option color label
} Color

unset -nocomplain foo
set foo {. {}}
::clay::tree::dictmerge foo {. {} color {. {} default green label Color}}
::clay::tree::dictmerge foo {. {} color {. {} default purple}}
test oometa-0003 {Recursive merge problem from oometa/clay find} {
  dict get $foo color default
} purple
test oometa-0004 {Recursive merge problem from oometa/clay find} {
  dict get $foo color label
} Color

unset -nocomplain foo
set foo {. {}}
::clay::tree::dictmerge foo {. {} color {. {} default purple}}
::clay::tree::dictmerge foo {. {} color {. {} default green label Color}}
test oometa-0005 {Recursive merge problem from oometa/clay find} {
  dict get $foo color default
} green
test oometa-0006 {Recursive merge problem from oometa/clay find} {
  dict get $foo color label
} Color

test oometa-0008 {Un-Sanitized output} {
  set foo
} {. {} color {. {} default green label Color}}

test oometa-0009 {Sanitize} {
  clay::tree::sanitize $foo
} {color {default green label Color}}


# -------------------------------------------------------------------------
# dictmerge Testing - clay
unset -nocomplain foo
test clay-0001 {Invoking dictmerge with empty args on a non existent variable create an empty variable} {
  ::clay::tree::dictmerge foo
  set foo
} {. {}}

unset -nocomplain foo
::clay::tree::dictset foo bar/ baz/ bell bang

test clay-0002 {For new entries dictmerge is essentially a set} {
  dict get $foo bar baz bell
} {bang}
::clay::tree::dictset foo bar/ baz/ boom/ bang
test clay-0003 {For entries that do exist a zipper merge is performed} {
  dict get $foo bar baz bell
} {bang}
test clay-0004 {For entries that do exist a zipper merge is performed} {
  dict get $foo bar baz boom
} {bang}

::clay::tree::dictset foo bar/ baz/ bop {color green flavor strawberry}

test clay-0005 {Leaves are replaced even if they look like a dict} {
  dict get $foo bar baz bop
} {color green flavor strawberry}

::clay::tree::dictset foo bar/ baz/ bop {color yellow}
test clay-0006 {Leaves are replaced even if they look like a dict} {
  dict get $foo bar baz bop
} {color yellow}

::clay::tree::dictset foo bar/ baz/ bang/ {color green flavor strawberry}
test clay-0007a {Branches are merged} {
  dict get $foo bar baz bang
} {. {} color green flavor strawberry}

::clay::tree::dictset foo bar/ baz/ bang/ color yellow
test clay-0007b {Branches are merged}  {
  dict get $foo bar baz bang
} {. {} color yellow flavor strawberry}

::clay::tree::dictset foo bar/ baz/ bang/ {color blue}
test clay-0007c {Branches are merged}  {
  dict get $foo bar baz bang
} {. {} color blue flavor strawberry}

::clay::tree::dictset foo bar/ baz/ bang/ shape: {Sort of round}
test clay-0007d {Branches are merged} {
  dict get $foo bar baz bang
} {. {} color blue flavor strawberry shape: {Sort of round}}

::clay::tree::dictset foo bar/ baz/ bang/ color yellow
test clay-0007e {Branches are merged}  {
  dict get $foo bar baz bang
} {. {} color yellow flavor strawberry shape: {Sort of round}}

::clay::tree::dictset foo bar/ baz/ bang/ {color blue}
test clay-0007f {Branches are merged}  {
  dict get $foo bar baz bang
} {. {} color blue flavor strawberry shape: {Sort of round}}

::clay::tree::dictset foo dict my_var 10
::clay::tree::dictset foo dict my_other_var 9

test clay-0007g {Branches are merged}  {
  dict get $foo dict
} {. {} my_var 10 my_other_var 9}

::clay::tree::dictset foo dict/ my_other_other_var 8
test clay-0007h {Branches are merged}  {
  dict get $foo dict
} {. {} my_var 10 my_other_var 9 my_other_other_var 8}


::clay::tree::dictmerge foo {option/ {color {type color} flavor {sense taste}}}
::clay::tree::dictmerge foo {option/ {format {default ascii}}}

test clay-0008 {Whole dicts are merged}  {
  dict get $foo option color
} {type color}
test clay-0009 {Whole dicts are merged}  {
  dict get $foo option flavor
} {sense taste}
test clay-0010 {Whole dicts are merged}  {
  dict get $foo option format
} {default ascii}

###
# Tests for the httpd module
###
test clay-0010 {Test that leaves are merged properly}
set bar {}
::clay::tree::dictmerge bar {
   proxy/ {port 10101 host myhost.localhost}
}
::clay::tree::dictmerge bar {
   mimetxt {Host: localhost
Content_Type: text/plain
Content-Length: 15
}
   http {HTTP_HOST {} CONTENT_LENGTH 15 HOST localhost CONTENT_TYPE text/plain UUID 3a7b4cdc-28d7-49b7-b18d-9d7d18382b9e REMOTE_ADDR 127.0.0.1 REMOTE_HOST 127.0.0.1 REQUEST_METHOD POST REQUEST_URI /echo REQUEST_PATH echo REQUEST_VERSION 1.0 DOCUMENT_ROOT {} QUERY_STRING {} REQUEST_RAW {POST /echo HTTP/1.0} SERVER_PORT 10001 SERVER_NAME 127.0.0.1 SERVER_PROTOCOL HTTP/1.1 SERVER_SOFTWARE {TclHttpd 4.2.0} LOCALHOST 0} UUID 3a7b4cdc-28d7-49b7-b18d-9d7d18382b9e uriinfo {fragment {} port {} path echo scheme http host {} query {} pbare 0 pwd {} user {}}
   mixin {reply ::test::content.echo}
   prefix /echo
   proxy_port 10010
   proxy/ {host localhost}
}

test clay-0011 {Whole dicts are merged}  {
  dict get $bar proxy_port
} {10010}

test clay-0012 {Whole dicts are merged}  {
  dict get $bar http CONTENT_LENGTH
} 15
test clay-0013 {Whole dicts are merged}  {
  dict get $bar proxy host
} localhost
test clay-0014 {Whole dicts are merged}  {
  dict get $bar proxy port
} 10101


###
# Dialect Testing
###
::clay::dialect::create ::alpha

proc ::alpha::define::is_alpha {} {
  dict set ::testinfo([current_class]) is_alpha 1
}

::alpha::define ::alpha::object {
  is_alpha
}

::clay::dialect::create ::bravo ::alpha

proc ::bravo::define::is_bravo {} {
  dict set ::testinfo([current_class]) is_bravo 1
}

::bravo::define ::bravo::object {
  is_bravo
}

::clay::dialect::create ::charlie ::bravo

proc ::charlie::define::is_charlie {} {
  dict set ::testinfo([current_class]) is_charlie 1
}

::charlie::define ::charlie::object {
  is_charlie
}

::clay::dialect::create ::delta ::charlie

proc ::delta::define::is_delta {} {
  dict set ::testinfo([current_class]) is_delta 1
}

::delta::define ::delta::object {
  is_delta
}

::delta::class create adam {
  is_alpha
  is_bravo
  is_charlie
  is_delta
}

test oodialect-keyword-001 {Testing keyword application} {
  set ::testinfo(::adam)
} {is_alpha 1 is_bravo 1 is_charlie 1 is_delta 1}

test oodialect-keyword-002 {Testing keyword application} {
  set ::testinfo(::alpha::object)
} {is_alpha 1}

test oodialect-keyword-003 {Testing keyword application} {
  set ::testinfo(::bravo::object)
} {is_bravo 1}

test oodialect-keyword-004 {Testing keyword application} {
  set ::testinfo(::charlie::object)
} {is_charlie 1}

test oodialect-keyword-005 {Testing keyword application} {
  set ::testinfo(::delta::object)
} {is_delta 1}

###
# Declare an object from a namespace
###
namespace eval ::test1 {
  ::alpha::class create a {
    aliases A
    is_alpha
  }
  ::alpha::define b {
    aliases B BEE
    is_alpha
  }
  ::alpha::class create ::c {
    aliases C
    is_alpha
  }
  ::alpha::define ::d {
    aliases D
    is_alpha
  }
}

test oodialect-naming-001 {Testing keyword application} {
  set ::testinfo(::test1::a)
} {is_alpha 1}

test oodialect-naming-002 {Testing keyword application} {
  set ::testinfo(::test1::b)
} {is_alpha 1}

test oodialect-naming-003 {Testing keyword application} {
  set ::testinfo(::c)
} {is_alpha 1}

test oodialect-naming-004 {Testing keyword application} {
  set ::testinfo(::d)
} {is_alpha 1}

test oodialect-aliasing-001 {Testing keyword application} {
namespace eval ::test1 {
    ::alpha::define e {
       superclass A
    }
}
} ::test1::e

test oodialect-aliasing-002 {Testing keyword application} {
namespace eval ::test1 {
    ::bravo::define f {
       superclass A
    }
}
} ::test1::f


test oodialect-aliasing-003 {Testing aliase method on class} {
  ::test1::a aliases
} {::test1::A}

###
# Test modified 2018-10-21
###
test oodialect-ancestry-003 {Testing heritage} {
  ::clay::ancestors ::test1::f
} {}

###
# Test modified 2018-10-21
###
test oodialect-ancestry-004 {Testing heritage} {
  ::clay::ancestors ::alpha::object
} {}

###
# Test modified 2018-10-21
###
test oodialect-ancestry-005 {Testing heritage} {
  ::clay::ancestors ::delta::object
} {}



# -------------------------------------------------------------------------
# clay submodule testing
# -------------------------------------------------------------------------



# Test canonical path building
set path {const/ foo/ bar/ baz/}


test oo-clay-path-0001 "Test path: const foo bar baz" {
  ::clay::path const foo bar baz
} $path


test oo-clay-path-0002 "Test path: const/ foo/ bar/ baz" {
  ::clay::path const/ foo/ bar/ baz
} $path


test oo-clay-path-0003 "Test path: const/foo/bar/baz" {
  ::clay::path const/foo/bar/baz
} $path


test oo-clay-path-0004 "Test path: const/foo bar/baz" {
  ::clay::path const/foo bar/baz
} $path


test oo-clay-path-0005 "Test path: const/foo/bar baz" {
  ::clay::path const/foo/bar baz
} $path


test oo-clay-path-0006 "Test path: const foo/bar/baz" {
  ::clay::path const foo/bar/baz
} $path


test oo-clay-path-0007 "Test path: const foo bar/baz" {
  ::clay::path const foo bar/baz
} $path


test oo-clay-path-0008 "Test path: const/foo bar baz" {
  ::clay::path const/foo bar baz
} $path

set path {const/ foo/ bar/ baz/ bing}

test oo-clay-leaf-0001 "Test leaf: const foo bar baz bing" {
  ::clay::leaf const foo bar baz bing
} $path


test oo-clay-leaf-0002 "Test leaf: const/ foo/ bar/ baz/ bing" {
  ::clay::leaf const/ foo/ bar/ baz/ bing
} $path


test oo-clay-leaf-0003 "Test leaf: const/foo/bar/baz/bing" {
  ::clay::leaf const/foo/bar/baz/bing
} $path


test oo-clay-leaf-0004 "Test leaf: const/foo bar/baz/bing:" {
  ::clay::leaf const/foo bar/baz/bing:
} $path


test oo-clay-leaf-0005 "Test leaf: const/foo/bar baz bing" {
  ::clay::leaf const/foo/bar baz bing
} $path


test oo-clay-leaf-0006 "Test leaf: const/foo/bar baz bing:" {
  ::clay::leaf const/foo/bar baz bing:
} $path


test oo-clay-leaf-0007 "Test leaf: const foo/bar/baz/bing" {
  ::clay::leaf const foo/bar/baz/bing
} $path


test oo-clay-leaf-0008 "Test leaf: const foo bar/baz/bing" {
  ::clay::leaf const foo bar/baz/bing
} $path


test oo-clay-leaf-0009 "Test leaf: const/foo bar baz bing" {
  ::clay::leaf const/foo bar baz bing
} $path

namespace eval ::foo {}

clay::define ::foo::classa {

  clay set const color  blue
  clay set const/flavor strawberry
  clay set {const/ sound} zoink
  clay set info/ {
    animal no
    building no
    subelement {pedantic yes}
  }

  # Provide a method that returns a constant so we can compare clay's inheritance to
  # TclOO
  method color {} {
    return blue
  }
  method flavor {} {
    return strawberry
  }
  method sound {} {
    return zoink
  }

}


test oo-class-clay-method-0001 "Test ::foo::classa const/ color exists" {
  ::foo::classa clay exists const/ color
} 1


test oo-class-clay-method-0001 "Test ::foo::classa const/ color value" {
  ::foo::classa clay get const/ color
} {blue}


test oo-class-clay-method-0003 "Test ::foo::classa const/ flavor exists" {
  ::foo::classa clay exists const/ flavor
} 1


test oo-class-clay-method-0003 "Test ::foo::classa const/ flavor value" {
  ::foo::classa clay get const/ flavor
} {strawberry}


test oo-class-clay-method-0005 "Test ::foo::classa const/ sound exists" {
  ::foo::classa clay exists const/ sound
} 1


test oo-class-clay-method-0005 "Test ::foo::classa const/ sound value" {
  ::foo::classa clay get const/ sound
} {zoink}


test oo-class-clay-method-0007 "Test ::foo::classa info/ animal exists" {
  ::foo::classa clay exists info/ animal
} 1


test oo-class-clay-method-0007 "Test ::foo::classa info/ animal value" {
  ::foo::classa clay get info/ animal
} {no}


test oo-class-clay-method-0009 "Test ::foo::classa info/ building exists" {
  ::foo::classa clay exists info/ building
} 1


test oo-class-clay-method-0009 "Test ::foo::classa info/ building value" {
  ::foo::classa clay get info/ building
} {no}


test oo-class-clay-method-0011 "Test ::foo::classa info/ subelement exists" {
  ::foo::classa clay exists info/ subelement
} 1


test oo-class-clay-method-0011 "Test ::foo::classa info/ subelement value" {
  ::foo::classa clay get info/ subelement
} {pedantic yes}


clay::define ::foo::classb {
  clay set const/ color black
  method color {} {return black}
  clay set const/ flavor vanilla
  method flavor {} {return vanilla}
  clay set const/ feeling dread
  method feeling {} {return dread}
  clay set info/ subelement {spoon yes}
  method subelement {} {return {spoon yes}}

}


test oo-class-clay-method-0013 "Test ::foo::classb const/ color exists" {
  ::foo::classb clay exists const/ color
} 1


test oo-class-clay-method-0013 "Test ::foo::classb const/ color value" {
  ::foo::classb clay get const/ color
} {black}


test oo-class-clay-method-0015 "Test ::foo::classb const/ flavor exists" {
  ::foo::classb clay exists const/ flavor
} 1


test oo-class-clay-method-0015 "Test ::foo::classb const/ flavor value" {
  ::foo::classb clay get const/ flavor
} {vanilla}


test oo-class-clay-method-0017 "Test ::foo::classb const/ feeling exists" {
  ::foo::classb clay exists const/ feeling
} 1


test oo-class-clay-method-0017 "Test ::foo::classb const/ feeling value" {
  ::foo::classb clay get const/ feeling
} {dread}


test oo-class-clay-method-0019 "Test ::foo::classb info/ subelement exists" {
  ::foo::classb clay exists info/ subelement
} 1


test oo-class-clay-method-0019 "Test ::foo::classb info/ subelement value" {
  ::foo::classb clay get info/ subelement
} {spoon yes}


clay::define ::foo::class.ab {
superclass ::foo::classb ::foo::classa
}


clay::define ::foo::class.ba {
superclass ::foo::classa ::foo::classb
}

# -------------------------------------------------------------------------
# Singleton
::clay::define ::test::singletonbehavior {
  method bar {} {
    return CLASS
  }
  method booze {} {
    return CLASS
  }
  Ensemble foo::bang {} {
    return CLASS
  }
  Ensemble foo::both {} {
    return CLASS
  }
  Ensemble foo::mixin {} {
    return CLASS
  }
  Ensemble foo::sloppy {} {
    return CLASS
  }
}
::clay::define ::test::flavor.strawberry {
  clay define property flavor strawbery
  method bar {} {
    return STRAWBERRY
  }
  Ensemble foo::bing {} {
    return STRAWBERRY
  }
  Ensemble foo::both {} {
    return STRAWBERRY
  }
  Ensemble foo::mixin {} {
    return STRAWBERRY
  }
  Ensemble foo::sloppy {} {
    return STRAWBERRY
  }
}
::clay::singleton ::TEST {
  class ::test::singletonbehavior
  clay mixinmap flavor ::test::flavor.strawberry
  clay set property color green
  method bar {} {
    return OBJECT
  }
  method booze {} {
    return OBJECT
  }
  method baz {} {
    return OBJECT
  }
  Ensemble foo::bar {} {
    return OBJECT
  }
  Ensemble foo::both {} {
    return OBJECT
  }
}

test oo-object-singleton-001 {Test singleton superclass keyword} {
  ::TEST clay delegate class
} {::test::singletonbehavior}

test oo-object-singleton-002 {Test singleton ensemble 1} {
  ::TEST foo <list>
} {bang bar bing both mixin sloppy}

test oo-object-singleton-003 {Test singleton ensemble from script} {
  ::TEST foo bar
} {OBJECT}
test oo-object-singleton-004 {Test singleton ensemble from mixin} {
  ::TEST foo bing
} {STRAWBERRY}
test oo-object-singleton-005 {Test singleton ensemble from class} {
  ::TEST foo bang
} {CLASS}
# Test note: the behavior from TclOO is unexpected
# Intuitively, a local method should override a mixin
# but this is not the case
test oo-object-singleton-006 {Test singleton ensemble from conflict, should resolve to object} {
  ::TEST foo both
} {STRAWBERRY}
test oo-object-singleton-007 {Test singleton ensemble from conflict, should resolve to mixin} {
  ::TEST foo sloppy
} {STRAWBERRY}
###
# Test note:
# This should work but does not
###
#test oo-object-singleton-009 {Test property from mixin/class} {
#  ::TEST clay get property flavor
#} {strawberry}
test oo-object-singleton-008 {Test property from script} {
  ::TEST clay get property color
} {green}


# Test note: the behavior from TclOO is unexpected
# Intuitively, a local method should override a mixin
# but this is not the case
test oo-object-singleton-010 {Test method declared in script} {
  ::TEST bar
} {STRAWBERRY}

test oo-object-singleton-011 {Test method declared in script} {
  ::TEST booze
} {OBJECT}
TEST destroy

# OBJECT of ::foo::classa
set OBJECTA [::foo::classa new]

###
# Test object degation
###
proc ::foo::fakeobject {a b} {
  return [expr {$a + $b}]
}

::clay::object create TEST
TEST clay delegate funct ::foo::fakeobject
test oo-object-delegate-001 {Test object delegation} {
  ::TEST clay delegate
} {<class> ::clay::object <funct> ::foo::fakeobject}

test oo-object-delegate-002 {Test object delegation} {
  ::TEST clay delegate funct
} {::foo::fakeobject}

test oo-object-delegate-002a {Test object delegation} {
  ::TEST clay delegate <funct>
} {::foo::fakeobject}

test oo-object-delegate-003 {Test object delegation} {
  ::TEST <funct> 1 1
} {2}
test oo-object-delegate-004 {Test object delegation} {
  ::TEST <funct> 10 -7
} {3}

# Replace the function out from under
proc ::foo::fakeobject {a b} {
  return [expr {$a * $b}]
}
test oo-object-delegate-005 {Test object delegation} {
  ::TEST <funct> 10 -7
} {-70}

# Object with ::foo::classa mixed in
set MIXINA  [::oo::object new]
oo::objdefine $MIXINA mixin ::foo::classa


test oo-object-clay-method-native-0001 {Test native object gets the property const//color} {
  $OBJECTA clay get const/ color
} {blue}
test oo-object-clay-method-mixin-0001 {Test mixin object gets the property const//color} {
  $MIXINA clay get const/ color
} {blue}


test oo-object-clay-method-native-methodcheck-0001 {Test that const//color would mimic method interheritance for a native class} {
  $OBJECTA color
} {blue}
test oo-object-clay-method-mixin-0001 {Test that const//color would mimic method interheritance for a mixed in class} {
  $MIXINA color
} {blue}
    

test oo-object-clay-method-native-0002 {Test native object gets the property const//flavor} {
  $OBJECTA clay get const/ flavor
} {strawberry}
test oo-object-clay-method-mixin-0002 {Test mixin object gets the property const//flavor} {
  $MIXINA clay get const/ flavor
} {strawberry}


test oo-object-clay-method-native-methodcheck-0002 {Test that const//flavor would mimic method interheritance for a native class} {
  $OBJECTA flavor
} {strawberry}
test oo-object-clay-method-mixin-0002 {Test that const//flavor would mimic method interheritance for a mixed in class} {
  $MIXINA flavor
} {strawberry}
    

test oo-object-clay-method-native-0003 {Test native object gets the property const//sound} {
  $OBJECTA clay get const/ sound
} {zoink}
test oo-object-clay-method-mixin-0003 {Test mixin object gets the property const//sound} {
  $MIXINA clay get const/ sound
} {zoink}


test oo-object-clay-method-native-methodcheck-0003 {Test that const//sound would mimic method interheritance for a native class} {
  $OBJECTA sound
} {zoink}
test oo-object-clay-method-mixin-0003 {Test that const//sound would mimic method interheritance for a mixed in class} {
  $MIXINA sound
} {zoink}
    

test oo-object-clay-method-native-0004 {Test native object gets the property info//animal} {
  $OBJECTA clay get info/ animal
} {no}
test oo-object-clay-method-mixin-0004 {Test mixin object gets the property info//animal} {
  $MIXINA clay get info/ animal
} {no}


test oo-object-clay-method-native-0005 {Test native object gets the property info//building} {
  $OBJECTA clay get info/ building
} {no}
test oo-object-clay-method-mixin-0005 {Test mixin object gets the property info//building} {
  $MIXINA clay get info/ building
} {no}


test oo-object-clay-method-native-0006 {Test native object gets the property info//subelement} {
  $OBJECTA clay get info/ subelement
} {pedantic yes}
test oo-object-clay-method-mixin-0006 {Test mixin object gets the property info//subelement} {
  $MIXINA clay get info/ subelement
} {pedantic yes}

# -------------------------------------------------------------------------
# OBJECT of ::foo::classb
set OBJECTB [::foo::classb new]
# Object with ::foo::classb mixed in
set MIXINB  [::oo::object new]
oo::objdefine $MIXINB mixin ::foo::classb


test oo-object-clay-method-native-0007 {Test native object gets the property const//color} {
  $OBJECTB clay get const/ color
} {black}
test oo-object-clay-method-mixin-0007 {Test mixin object gets the property const//color} {
  $MIXINB clay get const/ color
} {black}


test oo-object-clay-method-native-methodcheck-0007 {Test that const//color would mimic method interheritance for a native class} {
  $OBJECTB color
} {black}
test oo-object-clay-method-mixin-0007 {Test that const//color would mimic method interheritance for a mixed in class} {
  $MIXINB color
} {black}
    

test oo-object-clay-method-native-0008 {Test native object gets the property const//flavor} {
  $OBJECTB clay get const/ flavor
} {vanilla}
test oo-object-clay-method-mixin-0008 {Test mixin object gets the property const//flavor} {
  $MIXINB clay get const/ flavor
} {vanilla}


test oo-object-clay-method-native-methodcheck-0008 {Test that const//flavor would mimic method interheritance for a native class} {
  $OBJECTB flavor
} {vanilla}
test oo-object-clay-method-mixin-0008 {Test that const//flavor would mimic method interheritance for a mixed in class} {
  $MIXINB flavor
} {vanilla}
    

test oo-object-clay-method-native-0009 {Test native object gets the property const//feeling} {
  $OBJECTB clay get const/ feeling
} {dread}
test oo-object-clay-method-mixin-0009 {Test mixin object gets the property const//feeling} {
  $MIXINB clay get const/ feeling
} {dread}


test oo-object-clay-method-native-methodcheck-0009 {Test that const//feeling would mimic method interheritance for a native class} {
  $OBJECTB feeling
} {dread}
test oo-object-clay-method-mixin-0009 {Test that const//feeling would mimic method interheritance for a mixed in class} {
  $MIXINB feeling
} {dread}
    

test oo-object-clay-method-native-0010 {Test native object gets the property info//subelement} {
  $OBJECTB clay get info/ subelement
} {spoon yes}
test oo-object-clay-method-mixin-0010 {Test mixin object gets the property info//subelement} {
  $MIXINB clay get info/ subelement
} {spoon yes}

# -------------------------------------------------------------------------
# OBJECT descended from ::foo::classa ::foo::classb
set OBJECTAB [::foo::class.ab new]
# Object where classes were mixed in ::foo::classa ::foo::classb
set MIXINAB  [::oo::object new]
# Test modified 2018-10-30, mixin order was wrong before
oo::objdefine $MIXINAB mixin ::foo::classb ::foo::classa


test oo-object-clay-method-native-0011 {Test native object gets the property const//color} {
  $OBJECTAB clay get const/ color
} {black}
test oo-object-clay-method-mixin-0011 {Test mixin object gets the property const//color} {
  $MIXINAB clay get const/ color
} {black}


test oo-object-clay-method-native-methodcheck-0011 {Test that const//color would mimic method interheritance for a native class} {
  $OBJECTAB color
} {black}
test oo-object-clay-method-mixin-0011 {Test that const//color would mimic method interheritance for a mixed in class} {
  $MIXINAB color
} {black}
    

test oo-object-clay-method-native-0012 {Test native object gets the property const//flavor} {
  $OBJECTAB clay get const/ flavor
} {vanilla}
test oo-object-clay-method-mixin-0012 {Test mixin object gets the property const//flavor} {
  $MIXINAB clay get const/ flavor
} {vanilla}


test oo-object-clay-method-native-methodcheck-0012 {Test that const//flavor would mimic method interheritance for a native class} {
  $OBJECTAB flavor
} {vanilla}
test oo-object-clay-method-mixin-0012 {Test that const//flavor would mimic method interheritance for a mixed in class} {
  $MIXINAB flavor
} {vanilla}
    

test oo-object-clay-method-native-0013 {Test native object gets the property const//feeling} {
  $OBJECTAB clay get const/ feeling
} {dread}
test oo-object-clay-method-mixin-0013 {Test mixin object gets the property const//feeling} {
  $MIXINAB clay get const/ feeling
} {dread}


test oo-object-clay-method-native-methodcheck-0013 {Test that const//feeling would mimic method interheritance for a native class} {
  $OBJECTAB feeling
} {dread}
test oo-object-clay-method-mixin-0013 {Test that const//feeling would mimic method interheritance for a mixed in class} {
  $MIXINAB feeling
} {dread}
    

test oo-object-clay-method-native-0014 {Test native object gets the property const//sound} {
  $OBJECTAB clay get const/ sound
} {zoink}
test oo-object-clay-method-mixin-0014 {Test mixin object gets the property const//sound} {
  $MIXINAB clay get const/ sound
} {zoink}


test oo-object-clay-method-native-methodcheck-0014 {Test that const//sound would mimic method interheritance for a native class} {
  $OBJECTAB sound
} {zoink}
test oo-object-clay-method-mixin-0014 {Test that const//sound would mimic method interheritance for a mixed in class} {
  $MIXINAB sound
} {zoink}
    

test oo-object-clay-method-native-0015 {Test native object gets the property info//subelement} {
  $OBJECTAB clay get info/ subelement
} {spoon yes}
test oo-object-clay-method-mixin-0015 {Test mixin object gets the property info//subelement} {
  $MIXINAB clay get info/ subelement
} {spoon yes}


test oo-object-clay-method-native-0016 {Test native object gets the property info//animal} {
  $OBJECTAB clay get info/ animal
} {no}
test oo-object-clay-method-mixin-0016 {Test mixin object gets the property info//animal} {
  $MIXINAB clay get info/ animal
} {no}


test oo-object-clay-method-native-0017 {Test native object gets the property info//building} {
  $OBJECTAB clay get info/ building
} {no}
test oo-object-clay-method-mixin-0017 {Test mixin object gets the property info//building} {
  $MIXINAB clay get info/ building
} {no}

# -------------------------------------------------------------------------
# OBJECT descended from ::foo::classb ::foo::classa
set OBJECTBA [::foo::class.ba new]
# Object where classes were mixed in ::foo::classb ::foo::classa
set MIXINBA  [::oo::object new]
# Test modified 2018-10-30, mixin order was wrong before
oo::objdefine $MIXINBA mixin ::foo::classa ::foo::classb


test oo-object-clay-method-native-0018 {Test native object gets the property} {
  $OBJECTBA clay get const/ color
} {blue}
test oo-object-clay-method-mixin-0018 {Test mixin object gets the property} {
  $MIXINBA clay get const/ color
} {blue}


test oo-object-clay-method-native-methodcheck-0018 {Test that const//color would mimic method interheritance for a native class} {
  $OBJECTBA color
} {blue}
test oo-object-clay-method-mixin-0018 {Test that const//color would mimic method interheritance for a mixed in class} {
  $MIXINBA color
} {blue}
    

test oo-object-clay-method-native-0019 {Test native object gets the property} {
  $OBJECTBA clay get const/ flavor
} {strawberry}
test oo-object-clay-method-mixin-0019 {Test mixin object gets the property} {
  $MIXINBA clay get const/ flavor
} {strawberry}


test oo-object-clay-method-native-methodcheck-0019 {Test that const//flavor would mimic method interheritance for a native class} {
  $OBJECTBA flavor
} {strawberry}
test oo-object-clay-method-mixin-0019 {Test that const//flavor would mimic method interheritance for a mixed in class} {
  $MIXINBA flavor
} {strawberry}
    

test oo-object-clay-method-native-0020 {Test native object gets the property} {
  $OBJECTBA clay get const/ sound
} {zoink}
test oo-object-clay-method-mixin-0020 {Test mixin object gets the property} {
  $MIXINBA clay get const/ sound
} {zoink}


test oo-object-clay-method-native-methodcheck-0020 {Test that const//sound would mimic method interheritance for a native class} {
  $OBJECTBA sound
} {zoink}
test oo-object-clay-method-mixin-0020 {Test that const//sound would mimic method interheritance for a mixed in class} {
  $MIXINBA sound
} {zoink}
    

test oo-object-clay-method-native-0021 {Test native object gets the property} {
  $OBJECTBA clay get const/ feeling
} {dread}
test oo-object-clay-method-mixin-0021 {Test mixin object gets the property} {
  $MIXINBA clay get const/ feeling
} {dread}


test oo-object-clay-method-native-methodcheck-0021 {Test that const//feeling would mimic method interheritance for a native class} {
  $OBJECTBA feeling
} {dread}
test oo-object-clay-method-mixin-0021 {Test that const//feeling would mimic method interheritance for a mixed in class} {
  $MIXINBA feeling
} {dread}
    

test oo-object-clay-method-native-0022 {Test native object gets the property} {
  $OBJECTBA clay get info/ animal
} {no}
test oo-object-clay-method-mixin-0022 {Test mixin object gets the property} {
  $MIXINBA clay get info/ animal
} {no}


test oo-object-clay-method-native-0023 {Test native object gets the property} {
  $OBJECTBA clay get info/ building
} {no}
test oo-object-clay-method-mixin-0023 {Test mixin object gets the property} {
  $MIXINBA clay get info/ building
} {no}


test oo-object-clay-method-native-0024 {Test native object gets the property} {
  $OBJECTBA clay get info/ subelement
} {pedantic yes}
test oo-object-clay-method-mixin-0024 {Test mixin object gets the property} {
  $MIXINBA clay get info/ subelement
} {pedantic yes}


###
# put a do-nothing constructor on the books
###
::clay::define ::clay::object {
  constructor args {}
}

oo::objdefine ::clay::object method foo args { return bar }

test clay-core-method-0001 {Test that adding methods to the core ::clay::object class works} {
  ::clay::object foo
} {bar}

namespace eval ::TEST {}
::clay::define ::TEST::myclass {
  clay color red
  clay flavor strawberry

}

###
# Test adding a clay property
###
test clay-class-clay-0001 {Test that a clay statement is recorded in the object of the class} {
  ::TEST::myclass clay get color
} red
test clay-class-clay-0002 {Test that a clay statement is recorded in the object of the class} {
  ::TEST::myclass clay get flavor
} strawberry

###
# Test that objects of the class get the same properties
###
set OBJ [::clay::object new {}]
set OBJ2 [::TEST::myclass new {}]

test clay-object-clay-a-0001 {Test that objects not thee class do not get properties} {
  $OBJ clay get color
} {}
test clay-object-clay-a-0002 {Test that objects not thee class do not get properties} {
  $OBJ clay get flavor
} {}
test clay-object-clay-a-0003 {Test that objects of the class get properties} {
  $OBJ2 clay get color
} red
test clay-object-clay-a-0004 {Test that objects of the class get properties} {
  $OBJ2 clay get flavor
} strawberry

###
# Test modified 2018-10-21
###
test clay-object-clay-a-0005 {Test the clay ancestors function} {
  $OBJ clay ancestors
} {::clay::object}

###
# Test modified 2018-10-21
###
test clay-object-clay-a-0006 {Test the clay ancestors function} {
  $OBJ2 clay ancestors
} {::TEST::myclass ::clay::object}

test clay-object-clay-a-0007 {Test the clay provenance  function} {
  $OBJ2 clay provenance  flavor
} ::TEST::myclass

###
# Test that object local setting override the class
###
test clay-object-clay-a-0008 {Test that object local setting override the class} {
  $OBJ2 clay set color purple
  $OBJ2 clay get color
} purple
test clay-object-clay-a-0009 {Test that object local setting override the class} {
  $OBJ2 clay provenance  color
} self

::clay::define ::TEST::myclasse {
  superclass ::TEST::myclass

  clay color blue
  method do args {
    return "I did $args"
  }

  Ensemble which::color {} {
    return [my clay get color]
  }
  clay set method_ensemble which farbe: {tailcall my Which_color {*}$args}
}

###
# Test clay information is passed town to subclasses
###
test clay-class-clay-0003 {Test that a clay statement is recorded in the object of the class} {
  ::TEST::myclasse clay get color
} blue
test clay-class-clay-0004 {Test that clay statements from the ancestors of this class are not present (we handle them seperately in objects)} {
  ::TEST::myclasse clay get flavor
} {}
test clay-class-clay-0005 {Test that clay statements from the ancestors of this class are found with the FIND method} {
  ::TEST::myclasse clay find flavor
} {strawberry}

###
# Test that properties reach objects
###
set OBJ3 [::TEST::myclasse new {}]
test clay-object-clay-b-0001 {Test that objects of the class get properties} {
  $OBJ3 clay get color
} blue
test clay-object-clay-b-0002 {Test the clay provenance  function} {
  $OBJ3 clay provenance  color
} ::TEST::myclasse
test clay-object-clay-b-0003 {Test that objects of the class get properties} {
  $OBJ3 clay get flavor
} strawberry
test clay-object-clay-b-0004 {Test the clay provenance  function} {
  $OBJ3 clay provenance  flavor
} ::TEST::myclass

###
# Test modified 2018-10-21
###
test clay-object-clay-b-0005 {Test the clay provenance  function} {
  $OBJ3 clay ancestors
} {::TEST::myclasse ::TEST::myclass ::clay::object}

###
# Test defining a standard method
###
test clay-object-method-0001 {Test and standard method} {
  $OBJ3 do this really cool thing
} {I did this really cool thing}

test clay-object-method-0003 {Test an ensemble} {
  $OBJ3 which color
} blue
# Test setting properties
test clay-object-method-0004 {Test an ensemble} {
  $OBJ3 clay set color black
  $OBJ3 which color
} black

# Test setting properties
test clay-object-method-0004 {Test an ensemble alias} {
  $OBJ3 which farbe
} black


###
# Added 2019-06-24
# Test that grabbing a leaf does not pollute the cache
###
::clay::define ::TEST::class_with_deep_tree {
  clay set tree deep has depth 1
  clay set tree shallow has depth 0
}

$OBJ3 clay mixinmap deep ::TEST::class_with_deep_tree

test clay-deep-nested-0001 {Test that a leaf query does not pollute the cache} {
  $OBJ3 clay get tree shallow has depth
} 0
test clay-deep-nested-0001 {Test that a leaf query does not pollute the cache} {
  $OBJ3 clay get tree
} {deep {has {depth 1}} shallow {has {depth 0}}}



###
# Test that if you try to replace a global command you get an error
###
test clay-nspace-0001 {Test that if you try to replace a global command you get an error} -body {
::clay::define open {
  method bar {} { return foo }

}
}  -returnCodes {error} -result "::open does not refer to an object"

::clay::define fubar {
  method bar {} { return foo }
}
test clay-nspace-0002 {Test a non qualified class ends up in the current namespace} {
  info commands ::fubar
} {::fubar}

namespace eval ::cluster {
::clay::define fubar {
  method bar {} { return foo }
}

::clay::define ::clay::pot {
  method bar {} { return foo }
}

}
test clay-nspace-0003 {Test a non qualified class ends up in the current namespace} {
  info commands ::cluster::fubar
} {::cluster::fubar}
test clay-nspace-0003 {Test a fully qualified class ends up in the proper namespace} {
  info commands ::clay::pot
} {::clay::pot}

#set ::clay::trace 3

###
# New test - Added 2019-09-15
# Test that the "method" variable is exposed to a default method
###

::clay::define ::ensembleWithDefault {
  Ensemble foo::bar {} { return A }
  Ensemble foo::baz {} { return B }
  Ensemble foo::bang {} { return C }

  Ensemble foo::default {} { return $method }
}


set OBJ [::ensembleWithDefault new]
test clay-ensemble-default-0001 {Test a normal ensemble method} {
  $OBJ foo bar
} {A}
test clay-ensemble-default-0002 {Test a normal ensemble method} {
  $OBJ foo baz
} {B}
test clay-ensemble-default-0003 {Test a normal ensemble method} {
  $OBJ foo <list>
} [lsort -dictionary {bar baz bang}]

test clay-ensemble-default-0004 {Test a normal ensemble method} {
  $OBJ foo bing
} {bing}
test clay-ensemble-default-0005 {Test a normal ensemble method} {
  $OBJ foo bong
} {bong}
###
# Mixin tests
###

###
# Define a core class
###
::clay::define ::TEST::thing {

  method do args {
    return "I did $args"
  }
}


::clay::define ::TEST::vegetable {

  clay color unknown
  clay flavor unknown

  Ensemble which::flavor {} {
    return [my clay get flavor]
  }
  Ensemble which::color {} {
    return [my clay get color]
  }

}

::clay::define ::TEST::animal {

  clay color unknown
  clay sound unknown

  Ensemble which::sound {} {
    return [my clay get sound]
  }
  Ensemble which::color {} {
    return [my clay get color]
  }
  method sound {} {
    return unknown
  }
}

::clay::define ::TEST::species.cat {
  superclass ::TEST::animal
  clay sound meow
  method sound {} {
    return meow
  }
}

::clay::define ::TEST::coloring.calico {
  clay color calico

}

::clay::define ::TEST::condition.dark {
  Ensemble which::color {} {
    return grey
  }
}

::clay::define ::TEST::mood.happy {
  Ensemble which::sound {} {
    return purr
  }
  method sound {} {
    return purr
  }
}
test clay-object-0001 {Test than an object is created when clay::define is invoked} {
  info commands ::TEST::mood.happy
} ::TEST::mood.happy

set OBJ [::TEST::thing new]
test clay-mixin-a-0001 {Test that prior to a mixin an ensemble doesn't exist} -body {
  $OBJ which color
} -returnCodes error -result {unknown method "which": must be clay, destroy or do}

test clay-mixin-a-0002 {Test and standard method from an ancestor} {
  $OBJ do this really cool thing
} {I did this really cool thing}

$OBJ clay mixinmap species ::TEST::animal
test clay-mixin-b-0001 {Test that an ensemble is created during a mixin} {
  $OBJ which color
} {unknown}

test clay-mixin-b-0002 {Test that an ensemble is created during a mixin} {
  $OBJ which sound
} {unknown}

test clay-mixin-b-0003 {Test that an ensemble is created during a mixin}  -body {$OBJ which flavor} -returnCodes {error}  -result {unknown method which flavor. Valid: color sound}

###
# Test Modified: 2018-10-21
###
test clay-mixin-b-0004 {Test that mixins resolve in the correct order} {
  $OBJ clay ancestors
} {::TEST::animal ::TEST::thing ::clay::object}

###
# Replacing a mixin replaces the behaviors
###
$OBJ clay mixinmap species ::TEST::vegetable
test clay-mixin-c-0001 {Test that an ensemble is created during a mixin} {
  $OBJ which color
} {unknown}
test clay-mixin-c-0002 {Test that an ensemble is created during a mixin}  -body {$OBJ which sound}  -returnCodes {error}  -result {unknown method which sound. Valid: color flavor}
test clay-mixin-c-0003 {Test that an ensemble is created during a mixin} {
  $OBJ which flavor
} {unknown}
###
# Test Modified: 2018-10-21
###
test clay-mixin-c-0004 {Test that mixins resolve in the correct order} {
  $OBJ clay ancestors
} {::TEST::vegetable ::TEST::thing ::clay::object}

###
# Replacing a mixin
$OBJ clay mixinmap species ::TEST::species.cat
test clay-mixin-e-0001 {Test that an ensemble is created during a mixin} {
  $OBJ which color
} {unknown}
test clay-mixin-e-0002a {Test that an ensemble is created during a mixin} {
  $OBJ sound
} {meow}
test clay-mixin-e-0002b {Test that an ensemble is created during a mixin} {
  $OBJ clay get sound
} {meow}
test clay-mixin-e-0002 {Test that an ensemble is created during a mixin} {
  $OBJ which sound
} {meow}
test clay-mixin-e-0003 {Test that an ensemble is created during a mixin}  -body {$OBJ which flavor} -returnCodes {error}  -result {unknown method which flavor. Valid: color sound}
###
# Test Modified: 2018-10-30, 2018-10-21, 2018-10-10
###
test clay-mixin-e-0004 {Test that clay data follows the rules of inheritence and order of mixin} {
  $OBJ clay ancestors
} {::TEST::species.cat ::TEST::animal ::TEST::thing ::clay::object}

$OBJ clay mixinmap coloring ::TEST::coloring.calico
test clay-mixin-f-0001 {Test that an ensemble is created during a mixin} {
  $OBJ which color
} {calico}
test clay-mixin-f-0002 {Test that an ensemble is created during a mixin} {
  $OBJ which sound
} {meow}
test clay-mixin-f-0003 {Test that an ensemble is created during a mixin}  -body {$OBJ which flavor} -returnCodes {error}  -result {unknown method which flavor. Valid: color sound}

###
# Test modified 2018-10-30, 2018-10-21, 2018-10-10
###
test clay-mixin-f-0004 {Test that clay data follows the rules of inheritence and order of mixin} {
  $OBJ clay ancestors
} {::TEST::coloring.calico ::TEST::species.cat ::TEST::animal ::TEST::thing ::clay::object}

test clay-mixin-f-0005 {Test that clay data from a mixin works} {
  $OBJ clay provenance  color
} {::TEST::coloring.calico}

###
# Test variable initialization
###
::clay::define ::TEST::has_var {
  Variable my_variable 10

  method get_my_variable {} {
    my variable my_variable
    return $my_variable
  }
}

set OBJ [::TEST::has_var new]
test clay-class-variable-0001 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay get variable/ my_variable
} {10}

# Modified 2018-10-30 (order is different)
test clay-class-variable-0002 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay get variable
} {my_variable 10 DestroyEvent 0}

# Modified 2018-10-30 (order is different)
test clay-class-variable-0003 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay dget variable
} {. {} my_variable 10 DestroyEvent 0}

test clay-class-variable-0004 {Test that variables declared in the class definition are initialized} {
  $OBJ get_my_variable
} 10

###
# Test array initialization
###
::clay::define ::TEST::has_array {
  Array my_array {timeout 10}

  method get_my_array {field} {
    my variable my_array
    return $my_array($field)
  }
}

set OBJ [::TEST::has_array new]
test clay-class-array-0001 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay get array
} {my_array {timeout 10}}

test clay-class-array-0002 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay dget array
} {. {} my_array {. {} timeout 10}}

test clay-class-array-0003 {Test that variables declared in the class definition are initialized} {
  $OBJ get_my_array timeout
} 10

::clay::define ::TEST::has_more_array {
  superclass ::TEST::has_array
  Array my_array {color blue}
}
test clay-class-array-0008 {Test that the parser injected the right value in the right place for clay to catch it} {
  ::TEST::has_more_array clay get array
} {my_array {color blue}}

test clay-class-array-0009 {Test that the parser injected the right value in the right place for clay to catch it} {
  ::TEST::has_more_array clay find array
} {my_array {timeout 10 color blue}}

# Modified 2018-10-30 (order is different)
set BOBJ [::TEST::has_more_array new]
test clay-class-array-0004 {Test that the parser injected the right value in the right place for clay to catch it} {
  $BOBJ clay get array
} {my_array {color blue timeout 10}}

# Modified 2018-10-30 (order is different)
test clay-class-array-0005 {Test that the parser injected the right value in the right place for clay to catch it} {
  $BOBJ clay dget array
} {. {} my_array {. {} color blue timeout 10}}

test clay-class-arrau-0006 {Test that variables declared in the class definition are initialized} {
  $BOBJ get_my_array timeout
} 10
test clay-class-arrau-0007 {Test that variables declared in the class definition are initialized} {
  $BOBJ get_my_array color
} blue

::clay::define ::TEST::has_empty_array {
  Array my_array {}

  method my_array_exists {} {
    my variable my_array
    return [info exists my_array]
  }
  method get {field} {
    my variable my_array
    return $my_array($field)
  }
  method set {field value} {
    my variable my_array
    set my_array($field) $value
  }
}

test clay-class-array-0008 {Test that an declaration of an array with no values produces and empty array} {
  set COBJ [::TEST::has_empty_array new]
  $COBJ my_array_exists
} 1

test clay-class-array-0009 {Test that an declaration of an array with no values produces and empty array} {
  $COBJ set test "A random value"
  $COBJ get test
} {A random value}
###
# Test dict initialization
###
::clay::define ::TEST::has_dict {
  Dict my_dict {timeout 10}

  method get_my_dict {args} {
    my variable my_dict
    if {[llength $args]==0} {
      return $my_dict
    }
    return [dict get $my_dict {*}$args]
  }

}

set OBJ [::TEST::has_dict new]
test clay-class-dict-0001 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay get dict
} {my_dict {timeout 10}}

test clay-class-dict-0002 {Test that the parser injected the right value in the right place for clay to catch it} {
  $OBJ clay dget dict
} {. {} my_dict {. {} timeout 10}}

test clay-class-dict-0003 {Test that variables declared in the class definition are initialized} {
  $OBJ get_my_dict timeout
} 10

test clay-class-dict-0004 {Test that an empty dict is annotated} {
  $OBJ clay get dict
} {my_dict {timeout 10}}


::clay::define ::TEST::has_more_dict {
  superclass ::TEST::has_dict
  Dict my_dict {color blue}
}
set BOBJ [::TEST::has_more_dict new]

# Modified 2018-10-30
test clay-class-dict-0004 {Test that the parser injected the right value in the right place for clay to catch it} {
  $BOBJ clay get dict
} {my_dict {color blue timeout 10}}

# Modified 2018-10-30
test clay-class-dict-0005 {Test that the parser injected the right value in the right place for clay to catch it} {
  $BOBJ clay dget dict
} {. {} my_dict {. {} color blue timeout 10}}

test clay-class-dict-0006 {Test that variables declared in the class definition are initialized} {
  $BOBJ get_my_dict timeout
} 10

test clay-class-dict-0007 {Test that variables declared in the class definition are initialized} {
  $BOBJ get_my_dict color
} blue

::clay::define ::TEST::has_empty_dict {
  Dict my_empty_dict {}

  method get_my_empty_dict {args} {
    my variable my_empty_dict
    if {[llength $args]==0} {
      return $my_empty_dict
    }
    return [dict get $my_empty_dict {*}$args]
  }
}

set COBJ [::TEST::has_empty_dict new]

test clay-class-dict-0008 {Test that the parser injected the right value in the right place for clay to catch it} {
  $COBJ clay dget dict
} {my_empty_dict {. {}}}

test clay-class-dict-0009 {Test that an empty dict is initialized} {
  $COBJ get_my_empty_dict
} {}

###
# Test object delegation
###
::clay::define ::TEST::organelle {
  method add args {
    set total 0
    foreach item $args {
      set total [expr {$total+$item}]
    }
    return $total
  }
}
::clay::define ::TEST::master {
  constructor {} {
    set mysub [namespace current]::sub
    ::TEST::organelle create $mysub
    my clay delegate sub $mysub
  }
}

set OBJ [::TEST::master new]
###
# Test that delegation is working
###
test clay-delegation-0001 {Test an array driven ensemble} {
  $OBJ <sub> add 5 5
} 10


###
# Test the Ensemble keyword
###
::clay::define ::TEST::with_ensemble {

  Ensemble myensemble {pattern args} {
    set ensemble [self method]
    set emap [my clay ensemble_map $ensemble]
    set mlist [dict keys $emap [string tolower $pattern]]
    if {[llength $mlist] != 1} {
      error "Couldn't figure out what to do with $pattern"
    }
    set method [lindex $mlist 0]
    set argspec [dict get $emap $method argspec]
    set body    [dict get $emap $method body]
    if {$argspec ni {args {}}} {
      ::clay::dynamic_arguments $ensemble $method [list $argspec] {*}$args
    }
    eval $body
  }

  Ensemble myensemble::go args {
    return 1
  }
}

::clay::define ::TEST::with_ensemble.dance {
  Ensemble myensemble::dance args {
    return 1
  }
}
::clay::define ::TEST::with_ensemble.cannot_dance {
  Ensemble myensemble::dance args {
    return 0
  }
}

set OBJA [::clay::object new]
set OBJB [::clay::object new]

$OBJA clay mixinmap  core ::TEST::with_ensemble  friends ::TEST::with_ensemble.dance

$OBJB clay mixinmap  core ::TEST::with_ensemble  friends ::TEST::with_ensemble.cannot_dance

# Test go
test clay-dynamic-ensemble-0001 {Test ensemble with static method} {
  $OBJA myensemble go
} {1}
test clay-dynamic-ensemble-0002 {Test ensemble with static method} {
  $OBJB myensemble go
} {1}
# Test dance
test clay-dynamic-ensemble-0003 {Test ensemble with static method} {
  $OBJA myensemble dance
} {1}
test clay-dynamic-ensemble-0004 {Test ensemble with static method} {
  $OBJB myensemble dance
} {0}


###
# Class method testing
###

clay::class create WidgetClass {
  Class_Method working {} {
    return {Works}
  }

  Class_Method unknown args {
    set tkpath [lindex $args 0]
    if {[string index $tkpath 0] eq "."} {
      set obj [my new $tkpath {*}[lrange $args 1 end]]
      $obj tkalias $tkpath
      return $tkpath
    }
    next {*}$args
  }

  constructor {TkPath args} {
    my variable hull
    set hull $TkPath
    my clay delegate hull $TkPath
  }

  method tkalias tkname {
    set oldname $tkname
    my variable tkalias
    set tkalias $tkname
    set self [self]
    set hullwidget [::info object namespace $self]::tkwidget
    my clay delegate tkwidget $hullwidget
    #rename ::$tkalias $hullwidget
    my clay delegate hullwidget $hullwidget
    #::tool::object_rename [self] ::$tkalias
    rename [self] ::$tkalias
    #my Hull_Bind $tkname
    return $hullwidget
  }
}

test tool-class-method-000 {Test that class methods actually work...} {
  WidgetClass working
} {Works}

test tool-class-method-001 {Test Tk style creator} {
  WidgetClass .foo
  .foo clay delegate hull
} {.foo}

::clay::define WidgetNewClass {
  superclass WidgetClass
}

test tool-class-method-002 {Test Tk style creator inherited by morph} {
  WidgetNewClass .bar
  .bar clay delegate hull
} {.bar}



###
# Test ensemble inheritence
###
clay::define NestedClassA {
  Ensemble do::family {} {
    return NestedClassA
  }
  Ensemble do::something {} {
    return A
  }
  Ensemble do::whop {} {
    return A
  }
}
clay::define NestedClassB {
  superclass NestedClassA
  Ensemble do::family {} {
    set r [next family]
    lappend r NestedClassB
    return $r
  }
  Ensemble do::whop {} {
    return B
  }
}
clay::define NestedClassC {
  superclass NestedClassB

  Ensemble do::somethingelse {} {
    return C
  }
}
clay::define NestedClassD {
  superclass NestedClassB

  Ensemble do::somethingelse {} {
    return D
  }
}

clay::define NestedClassE {
  superclass NestedClassD NestedClassC
}

clay::define NestedClassF {
  superclass NestedClassC NestedClassD
}

NestedClassC create NestedObjectC

###
# These tests no longer work because method ensembles are now dynamically
# generated by object, that are not attached to the class anymore
#
####
#test tool-ensemble-001 {Test that an ensemble can access [next] even if no object of the ancestor class have been instantiated} {
#  NestedObjectC do family
#} {::NestedClassA ::NestedClassB ::NestedClassC}

test tool-ensemble-002 {Test that a later ensemble definition trumps a more primitive one} {
  NestedObjectC do whop
} {B}
test tool-ensemble-003 {Test that an ensemble definitions in an ancestor carry over} {
  NestedObjectC do something
} {A}

NestedClassE create NestedObjectE
NestedClassF create NestedObjectF


test tool-ensemble-004 {Test that ensembles follow the same rules for inheritance as methods} {
  NestedObjectE do somethingelse
} {D}

test tool-ensemble-005 {Test that ensembles follow the same rules for inheritance as methods} {
  NestedObjectF do somethingelse
} {C}

###
# Set of tests to exercise the mixinmap system
###
clay::define MixinMainClass {
  Variable mainvar unchanged

  Ensemble test::which {} {
    my variable mainvar
    return $mainvar
  }

  Ensemble test::main args {
    puts [list this is main $method $args]
  }

}

set mixoutscript {my test untool $class}
set mixinscript {my test tool $class}
clay::define MixinTool {
  Variable toolvar unchanged.mixin
  clay set mixin/ unmap-script $mixoutscript
  clay set mixin/ map-script $mixinscript
  clay set mixin/ name {Generic Tool}

  Ensemble test::untool class {
    my variable toolvar mainvar
    set mainvar {}
    set toolvar {}
  }

  Ensemble test::tool class {
    my variable toolvar mainvar
    set mainvar [$class clay get mixin name]
    set toolvar [$class clay get mixin name]
  }
}

clay::define MixinToolA {
  superclass MixinTool

  clay set mixin/ name {Tool A}
}

clay::define MixinToolB {
  superclass MixinTool

  clay set mixin/ name {Tool B}

  method test_newfunc {} {
    return "B"
  }
}

test tool-mixinspec-001 {Test application of mixin specs} {
  MixinTool clay get mixin map-script
} $mixinscript

test tool-mixinspec-002 {Test application of mixin specs} {
  MixinToolA clay get mixin map-script
} {}

test tool-mixinspec-003 {Test application of mixin specs} {
  MixinToolA clay find mixin map-script
} $mixinscript

test tool-mixinspec-004 {Test application of mixin specs} {
  MixinToolB clay find mixin map-script
} $mixinscript


MixinMainClass create mixintest

test tool-mixinmap-001 {Test object prior to mixins} {
  mixintest test which
} {unchanged}

mixintest clay mixinmap tool MixinToolA
test tool-mixinmap-002 {Test mixin map script ran} {
  mixintest test which
} {Tool A}

mixintest clay mixinmap tool MixinToolB

test tool-mixinmap-003 {Test mixin map script ran} {
  mixintest test which
} {Tool B}

test tool-mixinmap-003 {Test mixin map script ran} {
  mixintest test_newfunc
} {B}

mixintest clay mixinmap tool {}
test tool-mixinmap-004 {Test object prior to mixins} {
  mixintest test which
} {}



clay::define ::clay::object {
  method path {} {
    return [self class]
  }
}


clay::define ::MixinRoot {
  clay set opts core   root
  clay set opts option unset
  clay set opts color  unset

  Ensemble info::root {} {
    return MixinRoot
  }
  Ensemble info::shade {} {
    return avacodo
  }
  Ensemble info::default {} {
    return Undefined
  }

  method did {} {
    return MixinRoot
  }

  method path {} {
    return [list [self class] {*}[next]]
  }
}

clay::define ::MixinOption1 {
  clay set opts option option1

  Ensemble info::option {} {
    return MixinOption1
  }
  Ensemble info::other {} {
    return MixinOption1
  }

  method did {} {
    return MixinOption1
  }

  method path {} {
    return [list [self class] {*}[next]]
  }
}

clay::define ::MixinOption2 {
  superclass ::MixinOption1

  clay set opts option option2

  Ensemble info::option {} {
    return MixinOption2
  }

  method did {} {
    return MixinOption2
  }

  method path {} {
    return [list [self class] {*}[next]]
  }
}


clay::define ::MixinColor1 {
  clay set opts color blue

  Ensemble info::color {} {
    return MixinColor1
  }
  Ensemble info::shade {} {
    return blue
  }

  method did {} {
    return MixinColor1
  }

  method path {} {
    return [list [self class] {*}[next]]
  }
}

clay::define ::MixinColor2 {
  clay set opts color green

  Ensemble info::color {} {
    return MixinColor2
  }
  Ensemble info::shade {} {
    return green
  }

  method did {} {
    return MixinColor2
  }

  method path {} {
    return [list [self class] {*}[next]]
  }
}

set obj [clay::object new]

$obj clay mixinmap root ::MixinRoot


test tool-prototype-0001-0001 {Mixin core} {
  $obj info root
} {MixinRoot}


test tool-prototype-0001-0002 {Mixin core} {
  $obj info option
} {Undefined}


test tool-prototype-0001-0003 {Mixin core} {
  $obj info color
} {Undefined}


test tool-prototype-0001-0004 {Mixin core} {
  $obj info other
} {Undefined}


test tool-prototype-0001-0005 {Mixin core} {
  $obj info shade
} {avacodo}


test tool-prototype-0001-0006 {Mixin core} {
  $obj did
} {MixinRoot}


test tool-prototype-0001-0007 {Mixin core} {
  $obj path
} {::MixinRoot ::clay::object}


test tool-prototype-0001-0008 {Mixin core} {
  $obj clay get opts
} {core root option unset color unset}


test tool-prototype-0001-0009 {Mixin core} {
  $obj clay get opts core
} {root}


test tool-prototype-0001-0010 {Mixin core} {
  $obj clay get opts option
} {unset}


test tool-prototype-0001-0011 {Mixin core} {
  $obj clay get opts color
} {unset}


test tool-prototype-0001-0012 {Mixin core} {
  $obj clay ancestors
} {::MixinRoot ::clay::object}

$obj clay mixinmap option ::MixinOption1

test tool-prototype-0002-0001 {Mixin option1} {
  $obj info root
} {MixinRoot}


test tool-prototype-0002-0002 {Mixin option1} {
  $obj info option
} {MixinOption1}


test tool-prototype-0002-0003 {Mixin option1} {
  $obj info color
} {Undefined}


test tool-prototype-0002-0004 {Mixin option1} {
  $obj info other
} {MixinOption1}


test tool-prototype-0002-0005 {Mixin option1} {
  $obj info shade
} {avacodo}


test tool-prototype-0002-0006 {Mixin option1} {
  $obj did
} {MixinOption1}


test tool-prototype-0002-0007 {Mixin option1} {
  $obj path
} {::MixinOption1 ::MixinRoot ::clay::object}


test tool-prototype-0002-0008 {Mixin option1} {
  $obj clay get opts
} {option option1 core root color unset}


test tool-prototype-0002-0009 {Mixin option1} {
  $obj clay get opts core
} {root}


test tool-prototype-0002-0010 {Mixin option1} {
  $obj clay get opts option
} {option1}


test tool-prototype-0002-0011 {Mixin option1} {
  $obj clay get opts color
} {unset}


test tool-prototype-0002-0012 {Mixin option1} {
  $obj clay ancestors
} {::MixinOption1 ::MixinRoot ::clay::object}


set obj2 [clay::object new]
$obj2 clay mixinmap root ::MixinRoot option ::MixinOption1

$obj clay mixinmap option ::MixinOption1

test tool-prototype-0003-0001 {Mixin option1 - clean object} {
  $obj2 info root
} {MixinRoot}


test tool-prototype-0003-0002 {Mixin option1 - clean object} {
  $obj2 info option
} {MixinOption1}


test tool-prototype-0003-0003 {Mixin option1 - clean object} {
  $obj2 info color
} {Undefined}


test tool-prototype-0003-0004 {Mixin option1 - clean object} {
  $obj2 info other
} {MixinOption1}


test tool-prototype-0003-0005 {Mixin option1 - clean object} {
  $obj2 info shade
} {avacodo}


test tool-prototype-0003-0006 {Mixin option1 - clean object} {
  $obj2 did
} {MixinOption1}


test tool-prototype-0003-0007 {Mixin option1 - clean object} {
  $obj2 path
} {::MixinOption1 ::MixinRoot ::clay::object}


test tool-prototype-0003-0008 {Mixin option1 - clean object} {
  $obj2 clay get opts
} {option option1 core root color unset}


test tool-prototype-0003-0009 {Mixin option1 - clean object} {
  $obj2 clay get opts core
} {root}


test tool-prototype-0003-0010 {Mixin option1 - clean object} {
  $obj2 clay get opts option
} {option1}


test tool-prototype-0003-0011 {Mixin option1 - clean object} {
  $obj2 clay get opts color
} {unset}


test tool-prototype-0003-0012 {Mixin option1 - clean object} {
  $obj2 clay ancestors
} {::MixinOption1 ::MixinRoot ::clay::object}

$obj clay mixinmap option ::MixinOption2

test tool-prototype-0004-0001 {Mixin option2} {
  $obj info root
} {MixinRoot}


test tool-prototype-0004-0002 {Mixin option2} {
  $obj info option
} {MixinOption2}


test tool-prototype-0004-0003 {Mixin option2} {
  $obj info color
} {Undefined}


test tool-prototype-0004-0004 {Mixin option2} {
  $obj info other
} {MixinOption1}


test tool-prototype-0004-0005 {Mixin option2} {
  $obj info shade
} {avacodo}


test tool-prototype-0004-0006 {Mixin option2} {
  $obj did
} {MixinOption2}


test tool-prototype-0004-0007 {Mixin option2} {
  $obj path
} {::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object}


test tool-prototype-0004-0008 {Mixin option2} {
  $obj clay get opts
} {option option2 core root color unset}


test tool-prototype-0004-0009 {Mixin option2} {
  $obj clay get opts core
} {root}


test tool-prototype-0004-0010 {Mixin option2} {
  $obj clay get opts option
} {option2}


test tool-prototype-0004-0011 {Mixin option2} {
  $obj clay get opts color
} {unset}


test tool-prototype-0004-0012 {Mixin option2} {
  $obj clay ancestors
} {::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object}

$obj clay mixinmap color MixinColor1

test tool-prototype-0005-0001 {Mixin color1} {
  $obj info root
} {MixinRoot}


test tool-prototype-0005-0002 {Mixin color1} {
  $obj info option
} {MixinOption2}


test tool-prototype-0005-0003 {Mixin color1} {
  $obj info color
} {MixinColor1}


test tool-prototype-0005-0004 {Mixin color1} {
  $obj info other
} {MixinOption1}


test tool-prototype-0005-0005 {Mixin color1} {
  $obj info shade
} {blue}


test tool-prototype-0005-0006 {Mixin color1} {
  $obj did
} {MixinColor1}


test tool-prototype-0005-0007 {Mixin color1} {
  $obj path
} {::MixinColor1 ::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object}


test tool-prototype-0005-0008 {Mixin color1} {
  $obj clay get opts
} {color blue option option2 core root}


test tool-prototype-0005-0009 {Mixin color1} {
  $obj clay get opts core
} {root}


test tool-prototype-0005-0010 {Mixin color1} {
  $obj clay get opts option
} {option2}


test tool-prototype-0005-0011 {Mixin color1} {
  $obj clay get opts color
} {blue}


test tool-prototype-0005-0012 {Mixin color1} {
  $obj clay ancestors
} {::MixinColor1 ::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object}

$obj clay mixinmap color MixinColor2

test tool-prototype-0006-0001 {Mixin color2} {
  $obj info root
} {MixinRoot}


test tool-prototype-0006-0002 {Mixin color2} {
  $obj info option
} {MixinOption2}


test tool-prototype-0006-0003 {Mixin color2} {
  $obj info color
} {MixinColor2}


test tool-prototype-0006-0004 {Mixin color2} {
  $obj info other
} {MixinOption1}


test tool-prototype-0006-0005 {Mixin color2} {
  $obj info shade
} {green}


test tool-prototype-0006-0006 {Mixin color2} {
  $obj clay get opts
} {color green option option2 core root}


test tool-prototype-0006-0007 {Mixin color2} {
  $obj clay get opts core
} {root}


test tool-prototype-0006-0008 {Mixin color2} {
  $obj clay get opts option
} {option2}


test tool-prototype-0006-0009 {Mixin color2} {
  $obj clay get opts color
} {green}


test tool-prototype-0006-0010 {Mixin color2} {
  $obj clay ancestors
} {::MixinColor2 ::MixinOption2 ::MixinOption1 ::MixinRoot ::clay::object}

$obj clay mixinmap option MixinOption1

test tool-prototype-0007-0001 {Mixin color2 + Option1} {
  $obj info root
} {MixinRoot}


test tool-prototype-0007-0002 {Mixin color2 + Option1} {
  $obj info option
} {MixinOption1}


test tool-prototype-0007-0003 {Mixin color2 + Option1} {
  $obj info color
} {MixinColor2}


test tool-prototype-0007-0004 {Mixin color2 + Option1} {
  $obj info other
} {MixinOption1}


test tool-prototype-0007-0005 {Mixin color2 + Option1} {
  $obj info shade
} {green}


test tool-prototype-0007-0006 {Mixin color2 + Option1} {
  $obj clay get opts
} {color green option option1 core root}


test tool-prototype-0007-0007 {Mixin color2 + Option1} {
  $obj clay get opts core
} {root}


test tool-prototype-0007-0008 {Mixin color2 + Option1} {
  $obj clay get opts option
} {option1}


test tool-prototype-0007-0009 {Mixin color2 + Option1} {
  $obj clay get opts color
} {green}


test tool-prototype-0007-0010 {Mixin color2 + Option1} {
  $obj clay ancestors
} {::MixinColor2 ::MixinOption1 ::MixinRoot ::clay::object}

$obj clay mixinmap option {}

test tool-prototype-0008-0001 {Mixin color2 + no option} {
  $obj info root
} {MixinRoot}


test tool-prototype-0008-0002 {Mixin color2 + no option} {
  $obj info option
} {Undefined}


test tool-prototype-0008-0003 {Mixin color2 + no option} {
  $obj info color
} {MixinColor2}


test tool-prototype-0008-0004 {Mixin color2 + no option} {
  $obj info other
} {Undefined}


test tool-prototype-0008-0005 {Mixin color2 + no option} {
  $obj info shade
} {green}


test tool-prototype-0008-0006 {Mixin color2 + no option} {
  $obj clay get opts
} {color green core root option unset}


test tool-prototype-0008-0007 {Mixin color2 + no option} {
  $obj clay get opts core
} {root}


test tool-prototype-0008-0008 {Mixin color2 + no option} {
  $obj clay get opts option
} {unset}


test tool-prototype-0008-0009 {Mixin color2 + no option} {
  $obj clay get opts color
} {green}


test tool-prototype-0008-0010 {Mixin color2 + no option} {
  $obj clay ancestors
} {::MixinColor2 ::MixinRoot ::clay::object}

$obj clay mixinmap color {}

test tool-prototype-0009-0001 {Mixin core (return to normal)} {
  $obj info root
} {MixinRoot}


test tool-prototype-0009-0002 {Mixin core (return to normal)} {
  $obj info option
} {Undefined}


test tool-prototype-0009-0003 {Mixin core (return to normal)} {
  $obj info color
} {Undefined}


test tool-prototype-0009-0004 {Mixin core (return to normal)} {
  $obj info other
} {Undefined}


test tool-prototype-0009-0005 {Mixin core (return to normal)} {
  $obj info shade
} {avacodo}


test tool-prototype-0009-0006 {Mixin core (return to normal)} {
  $obj clay get opts
} {core root option unset color unset}


test tool-prototype-0009-0007 {Mixin core (return to normal)} {
  $obj clay get opts core
} {root}


test tool-prototype-0009-0008 {Mixin core (return to normal)} {
  $obj clay get opts option
} {unset}


test tool-prototype-0009-0009 {Mixin core (return to normal)} {
  $obj clay get opts color
} {unset}


test tool-prototype-0009-0010 {Mixin core (return to normal)} {
  $obj clay ancestors
} {::MixinRoot ::clay::object}


###
# Tip479 Tests
###
clay::define tip479class {

  Method newitem dictargs {
    id {type: number}
    color {default: green}
    shape {options: {round square}}
    flavor {default: grape}
  } {
    my variable items
    foreach {f v} $args {
      dict set items $id $f $v
    }
    if {"color" ni [dict keys $args]} {
      dict set items $id color $color
    }
    return [dict get $items $id]
  }

  method itemget {id field} {
    my variable items
    return [dict get $id $field]
  }
}

set obj [tip479class new]
test tip479-001 {Test that a later ensemble definition trumps a more primitive one} {
  $obj newitem id 1 color orange shape round
} {id 1 color orange shape round}

# Fail because we left off a mandatory argument
test tip479-002 {Test that a later ensemble definition trumps a more primitive one} -body {
  $obj newitem id 2
} -result {shape is required} -returnCodes error

###
# Leave off a value that has a default
# note: Method had special handling for color, but not flavor
###
test tip479-003 {Test that a later ensemble definition trumps a more primitive one} {
  $obj newitem id 3 shape round
} {id 3 shape round color green}

###
# Add extra arguments
###
test tip479-004 {Test that a later ensemble definition trumps a more primitive one} {
  $obj newitem id 4 shape round trim leather
} {id 4 shape round trim leather color green}

clay::define tip479classE {

  Ensemble item::new dictargs {
    id {type: number}
    color {default: green}
    shape {options: {round square}}
    flavor {default: grape}
  } {
    my variable items
    foreach {f v} $args {
      dict set items $id $f $v
    }
    if {"color" ni [dict keys $args]} {
      dict set items $id color $color
    }
    return [dict get $items $id]
  }

  Ensemble item::get {id field} {
    my variable items
    return [dict get $id $field]
  }
}


set obj [tip479classE new]
test tip479-001 {Test that a later ensemble definition trumps a more primitive one} {
  $obj item new id 1 color orange shape round
} {id 1 color orange shape round}

# Fail because we left off a mandatory argument
test tip479-002 {Test that a later ensemble definition trumps a more primitive one} -body {
  $obj item new id 2
} -result {shape is required} -returnCodes error

###
# Leave off a value that has a default
# note: Method had special handling for color, but not flavor
###
test tip479-003 {Test that a later ensemble definition trumps a more primitive one} {
  $obj item new id 3 shape round
} {id 3 shape round color green}

###
# Add extra arguments
###
test tip479-004 {Test that a later ensemble definition trumps a more primitive one} {
  $obj item new id 4 shape round trim leather
} {id 4 shape round trim leather color green}



testsuiteCleanup

# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End:


Added modules/clay/pkgIndex.tcl.































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.6]} {return}


package ifneeded clay 0.8.6 [list source [file join $dir clay.tcl]]

Changes to modules/clock/iso8601.man.

39
40
41
42
43
44
45
46
47
[option -locale], and
[option -timezone]
of the builtin command [cmd {clock scan}].

[list_end]

[vset CATEGORY clock::iso8601]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

39
40
41
42
43
44
45
46
47
[option -locale], and
[option -timezone]
of the builtin command [cmd {clock scan}].

[list_end]

[vset CATEGORY clock::iso8601]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/clock/rfc2822.man.

19
20
21
22
23
24
25
26
27
This command parses an RFC2822 date string and returns
the given date in seconds since epoch. An error is thrown
if the command is unable to parse the date.

[list_end]

[vset CATEGORY clock::rfc2822]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

19
20
21
22
23
24
25
26
27
This command parses an RFC2822 date string and returns
the given date in seconds since epoch. An error is thrown
if the command is unable to parse the date.

[list_end]

[vset CATEGORY clock::rfc2822]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/cmdline/cmdline.man.

196
197
198
199
200
201
202
203
204
This example, taken (and slightly modified) from the package
[package fileutil], shows how to use cmdline.  First, a list of
options is created, then the 'args' list is passed to cmdline for
processing.  Subsequently, different options are checked to see if
they have been passed to the script, and what their value is.

[vset CATEGORY cmdline]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

196
197
198
199
200
201
202
203
204
This example, taken (and slightly modified) from the package
[package fileutil], shows how to use cmdline.  First, a list of
options is created, then the 'args' list is passed to cmdline for
processing.  Subsequently, different options are checked to see if
they have been passed to the script, and what their value is.

[vset CATEGORY cmdline]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/comm/comm.man.

1224
1225
1226
1227
1228
1229
1230
1231
1232

[para]
Andreas Kupries <[email protected]> uses
[package comm] and has built a simple nameserver as part of his Pool
library.  See [uri http://www.purl.org/net/akupries/soft/pool/index.htm].

[vset CATEGORY comm]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

1224
1225
1226
1227
1228
1229
1230
1231
1232

[para]
Andreas Kupries <[email protected]> uses
[package comm] and has built a simple nameserver as part of his Pool
library.  See [uri http://www.purl.org/net/akupries/soft/pool/index.htm].

[vset CATEGORY comm]
[include ../common-text/feedback.inc]
[manpage_end]

Deleted modules/comm/comm.slaveboot.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# -*- tcl -*-
# Script to boot a child running an open comm server

set spawncode [makeFile {
    catch {wm withdraw .}
    ##puts [set fh [open ~/foo w]] $argv ; close $fh

    source [lindex $argv 0]     ; # load 'snit'
    source [lindex $argv 1].tcl ; # load 'comm'
    # and wait for commands. But first send our
    # own server socket to the initiator
    ::comm::comm send [lindex $argv 2] [list slaveat [::comm::comm self]]
    vwait forever
} spawn]

proc slaveat {id} {
    #puts "Slave @ $id"
    proc slave {} [list return $id]
    set ::go .
}

#puts "self @ [::comm::comm self]"

exec \
    [info nameofexecutable] $spawncode \
    [tcllibPath snit/snit.tcl] \
    [file rootname [info script]] \
    [::comm::comm self] &

#puts "Waiting for spawned comm system to boot"
# Wait for the slave to initialize itself.
vwait ::go

#puts "Running tests"
#::comm::comm debug 1

proc slavestop {} {
    ::comm::comm send -async [slave] {{exit}}
    ::comm::comm abort
    removeFile spawn
    return
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















































































Changes to modules/comm/comm.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# -*- tcl -*-
# Tests for the comm module.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2001 by ActiveState Tool Corp.
# All rights reserved.
#
# RCS: @(#) $Id: comm.test,v 1.14 2010/09/15 19:48:33 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]









<
<







1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
# -*- tcl -*-
# Tests for the comm module.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2001 by ActiveState Tool Corp.
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
}

# ------------------------------------------------------------------------
# First order of things is to spawn a separate tclsh into the background
# and have it execute comm too, with some general code to respond to our
# requests

useLocalFile comm.slaveboot

# ------------------------------------------------------------------------

test comm-1.0 {set remote variable} {
    ::comm::comm send [slave] {set foo b}
} {b}








|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
}

# ------------------------------------------------------------------------
# First order of things is to spawn a separate tclsh into the background
# and have it execute comm too, with some general code to respond to our
# requests

source [asset comm.slaveboot]

# ------------------------------------------------------------------------

test comm-1.0 {set remote variable} {
    ::comm::comm send [slave] {set foo b}
} {b}

Changes to modules/comm/comm_wire.man.

276
277
278
279
280
281
282
283
284
		 negotiated.

		 IOW if v2 is used the client will not see a version
	         reply during the negotiation handshake.
}]

[vset CATEGORY comm]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

276
277
278
279
280
281
282
283
284
		 negotiated.

		 IOW if v2 is used the client will not see a version
	         reply during the negotiation handshake.
}]

[vset CATEGORY comm]
[include ../common-text/feedback.inc]
[manpage_end]

Added modules/comm/test-assets/comm.slaveboot.

































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# -*- tcl -*-
# Script to boot a child running an open comm server

set spawncode [asset slave.tcl]

proc slaveat {id} {
    #puts "Slave @ $id"
    proc slave {} [list return $id]
    set ::go .
}

#puts "self @ [::comm::comm self]"

exec \
    [info nameofexecutable] $spawncode \
    [tcllibPath snit/snit.tcl] \
    [localPath  comm.tcl] \
    [::comm::comm self] &

#puts "Waiting for spawned comm system to boot"
# Wait for the slave to initialize itself.
vwait ::go

#puts "Running tests"
#::comm::comm debug 1

proc slavestop {} {
    ::comm::comm send -async [slave] {{exit}}
    ::comm::comm abort
    removeFile spawn
    return
}

Added modules/comm/test-assets/slave.tcl.





















>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
# -*- tcl -*-
catch {wm withdraw .}
##puts [set fh [open ~/foo w]] $argv ; close $fh

source [lindex $argv 0] ; # load 'snit'
source [lindex $argv 1] ; # load 'comm'
# and wait for commands. But first send our
# own server socket to the initiator
::comm::comm send [lindex $argv 2] [list slaveat [::comm::comm self]]
vwait forever

Added modules/common-text/feedback.inc.















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[section {Bugs, Ideas, Feedback}]
[vset TRACKER http://core.tcl.tk/tcllib/reportlist]
[vset LABEL   {Tcllib Trackers}]

This document, and the package it describes, will undoubtedly contain
bugs and other problems.

Please report such in the category [emph [vset CATEGORY]] of the
[uri [vset TRACKER] [vset LABEL]].

Please also report any ideas for enhancements you may have for either
package and/or documentation.

[para]
When proposing code changes, please provide [emph {unified diffs}],
i.e the output of [const {diff -u}].

[para]
Note further that [emph attachments] are strongly preferred over
inlined patches. Attachments can be made by going to the [const Edit]
form of the ticket immediately after its creation, and then using the
left-most button in the secondary navigation bar.

Changes to modules/control/control.man.

157
158
159
160
161
162
163
164
165
% catch a
1
% catch b
0
}]

[vset CATEGORY control]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

157
158
159
160
161
162
163
164
165
% catch a
1
% catch b
0
}]

[vset CATEGORY control]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/coroutine/coro_auto.man.

38
39
40
41
42
43
44
45
46
[def [cmd global]]
[def [cmd read]]
[def [cmd update]]
[def [cmd vwait]]
[list_end]

[vset CATEGORY coroutine]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

38
39
40
41
42
43
44
45
46
[def [cmd global]]
[def [cmd read]]
[def [cmd update]]
[def [cmd vwait]]
[list_end]

[vset CATEGORY coroutine]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/coroutine/coroutine.tcl.

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
    }
    tailcall {*}$cmd
}

# - -- --- ----- -------- -------------

proc ::coroutine::util::after {delay} {
    ::after $delay [info coroutine]
    yield
    return
}

# - -- --- ----- -------- -------------

proc ::coroutine::util::exit {{status 0}} {







|







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
    }
    tailcall {*}$cmd
}

# - -- --- ----- -------- -------------

proc ::coroutine::util::after {delay} {
    ::after $delay [list [info coroutine]]
    yield
    return
}

# - -- --- ----- -------- -------------

proc ::coroutine::util::exit {{status 0}} {
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
    # Step 2. To prevent the next section of the coroutine code from
    # running entirely within the variable trace (*) we now use an
    # idle handler to defer it until the trace is definitely
    # done. This trick by Peter Spjuth.
    #
    # (*) At this point we are in VWaitTrace running the coroutine.

    ::after idle [info coroutine]
    yield
    return
}

proc ::coroutine::util::VWaitTrace {coroutine args} {
    $coroutine
    return
}

# - -- --- ----- -------- -------------

proc ::coroutine::util::update {{what {}}} {
    if {$what eq "idletasks"} {
        ::after idle [info coroutine]
    } elseif {$what ne {}} {
        # Force proper error message for bad call.
        tailcall ::tcl::update $what
    } else {
        ::after 0 [info coroutine]
    }
    yield
    return
}

# - -- --- ----- -------- -------------








|













|




|







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
    # Step 2. To prevent the next section of the coroutine code from
    # running entirely within the variable trace (*) we now use an
    # idle handler to defer it until the trace is definitely
    # done. This trick by Peter Spjuth.
    #
    # (*) At this point we are in VWaitTrace running the coroutine.

    ::after idle [list [info coroutine]]
    yield
    return
}

proc ::coroutine::util::VWaitTrace {coroutine args} {
    $coroutine
    return
}

# - -- --- ----- -------- -------------

proc ::coroutine::util::update {{what {}}} {
    if {$what eq "idletasks"} {
        ::after idle [list [info coroutine]]
    } elseif {$what ne {}} {
        # Force proper error message for bad call.
        tailcall ::tcl::update $what
    } else {
        ::after 0 [list [info coroutine]]
    }
    yield
    return
}

# - -- --- ----- -------- -------------

376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
    # Step 2. To prevent the next section of the coroutine code from
    # running entirely within the variable trace (*) we now use an
    # idle handler to defer it until the trace is definitely
    # done. This trick by Peter Spjuth.
    #
    # (*) At this point we are in AWaitSignal running the coroutine.

    ::after idle [info coroutine]
    yield

    return $choice
}

proc ::coroutine::util::AWaitSignal {coroutine var index op} {
    if {$op ne "write"} { return }







|







376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
    # Step 2. To prevent the next section of the coroutine code from
    # running entirely within the variable trace (*) we now use an
    # idle handler to defer it until the trace is definitely
    # done. This trick by Peter Spjuth.
    #
    # (*) At this point we are in AWaitSignal running the coroutine.

    ::after idle [list [info coroutine]]
    yield

    return $choice
}

proc ::coroutine::util::AWaitSignal {coroutine var index op} {
    if {$op ne "write"} { return }

Changes to modules/coroutine/tcllib_coroutine.man.

109
110
111
112
113
114
115
116
117

This command causes the coroutine calling it to wait for a write to
the named namespace variable [arg varname].

[list_end]

[vset CATEGORY coroutine]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

109
110
111
112
113
114
115
116
117

This command causes the coroutine calling it to wait for a write to
the named namespace variable [arg varname].

[list_end]

[vset CATEGORY coroutine]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/counter/counter.man.

242
243
244
245
246
247
248
249
250
Resets the counter with the name [arg tag] to an initial state. The
[arg args] determine the new characteristics of the counter. They have
the same meaning as described for [cmd ::counter::init].

[list_end]

[vset CATEGORY counter]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

242
243
244
245
246
247
248
249
250
Resets the counter with the name [arg tag] to an initial state. The
[arg args] determine the new characteristics of the counter. They have
the same meaning as described for [cmd ::counter::init].

[list_end]

[vset CATEGORY counter]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/crc/cksum.man.

123
124
125
126
127
128
129
130
131
2609532967
}]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY crc]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

123
124
125
126
127
128
129
130
131
2609532967
}]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY crc]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/crc/crc16.man.

141
142
143
144
145
146
147
148
149
51675
}]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY crc]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

141
142
143
144
145
146
147
148
149
51675
}]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY crc]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/crc/crc32.man.

144
145
146
147
148
149
150
151
152
3964322768
}]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY crc]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

144
145
146
147
148
149
150
151
152
3964322768
}]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY crc]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/crc/sum.man.

100
101
102
103
104
105
106
107
108
13392
}]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY crc]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

100
101
102
103
104
105
106
107
108
13392
}]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY crc]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/cron/cron.man.

178
179
180
181
182
183
184
185
186
[para]
[arg newtime] is expressed in absolute milliseconds since the beginning of the epoch.


[list_end]
[para]
[vset CATEGORY odie]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

178
179
180
181
182
183
184
185
186
[para]
[arg newtime] is expressed in absolute milliseconds since the beginning of the epoch.


[list_end]
[para]
[vset CATEGORY odie]
[include ../common-text/feedback.inc]
[manpage_end]

Deleted modules/csv/2926387.csv.

1
2
3
4
a,b,c
d,"e,
e",f

<
<
<
<








Changes to modules/csv/csv.man.

239
240
241
242
243
244
245
246
247
d) (the empty string)
}]

instead. As can be seen only item (d) is different, now the empty string
instead of a ".

[vset CATEGORY csv]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

239
240
241
242
243
244
245
246
247
d) (the empty string)
}]

instead. As can be seen only item (d) is different, now the empty string
instead of a ".

[vset CATEGORY csv]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/csv/csv.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# -*- tcl -*-
# Tests for the find function.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2001-2011 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: csv.test,v 1.23 2011/11/23 02:22:10 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]









<
<







1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
# -*- tcl -*-
# Tests for the find function.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2001-2011 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

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
    ::struct::matrix m
    catch {::csv::read2matrix dummy m foo} result
    m destroy
    set result
} {illegal separator character "foo", is a string}

test csv-5.1 {reading csv files} {
    set f [open [file join $::tcltest::testsDirectory mem_debug_bench.csv] r]
    ::struct::queue q
    ::csv::read2queue $f q
    close $f
    set result [list [q size] [q get 2]]
    q destroy
    set result
} {251 {{000 VERSIONS: 2:8.4a3 1:8.4a3 1:8.4a3%} {001 {CATCH return ok} 7 13 53.85}}}

test csv-5.2 {reading csv files} {
    set f [open [file join $::tcltest::testsDirectory mem_debug_bench_a.csv] r]
    ::struct::queue q
    ::csv::read2queue $f q
    close $f
    set result [list [q size] [q get 2]]
    q destroy
    set result
} {251 {{000 VERSIONS: 2:8.4a3 1:8.4a3 1:8.4a3%} {001 {CATCH return ok} 7 13 53.85}}}

test csv-5.3 {reading csv files} {
    set f [open [file join $::tcltest::testsDirectory mem_debug_bench.csv] r]
    ::struct::matrix m
    m add columns 5
    ::csv::read2matrix $f m
    close $f
    set result [m get rect 0 227 end 231]
    m destroy
    set result
} {{227 {STR append (1MB + 1MB * 3)} 125505 327765 38.29} {228 {STR append (1MB + 1MB * 5)} 158507 855295 18.53} {229 {STR append (1MB + (1b + 1K + 1b) * 100)} 33101 174031 19.02} {230 {STR info locals match} 946 1521 62.20} {231 {TRACE no trace set} 34 121 28.10}}

test csv-5.4 {reading csv files} {
    set f [open [file join $::tcltest::testsDirectory mem_debug_bench_a.csv] r]
    ::struct::matrix m
    m add columns 5
    ::csv::read2matrix $f m
    close $f
    set result [m get rect 0 227 end 231]
    m destroy
    set result
} {{227 {STR append (1MB + 1MB * 3)} 125505 327765 38.29} {228 {STR append (1MB + 1MB * 5)} 158507 855295 18.53} {229 {STR append (1MB + (1b + 1K + 1b) * 100)} 33101 174031 19.02} {230 {STR info locals match} 946 1521 62.20} {231 {TRACE no trace set} 34 121 28.10}}

test csv-5.5 {reading csv files} {
    set f [open [file join $::tcltest::testsDirectory mem_debug_bench.csv] r]
    ::struct::matrix m
    m add columns 5
    ::csv::read2matrix $f m
    close $f

    set result [list]
    foreach c {0 1 2 3 4} {
	lappend result [m columnwidth $c]
    }
    m destroy
    set result
} {3 39 7 7 8}

test csv-5.6 {reading csv files, linking} {
    set f [open [file join $::tcltest::testsDirectory mem_debug_bench.csv] r]
    ::struct::matrix m
    m add columns 5
    ::csv::read2matrix $f m
    close $f
    m link a
    set result [array size a]
    m destroy
    set result
} {1255}


test csv-5.7 {reading csv files, empty expansion mode} {
    set f [open [file join $::tcltest::testsDirectory mem_debug_bench.csv] r]
    ::struct::matrix m
    ::csv::read2matrix $f m , empty
    close $f
    set result [m get rect 0 227 end 231]
    m destroy
    set result
} {{227 {STR append (1MB + 1MB * 3)} 125505 327765 38.29} {228 {STR append (1MB + 1MB * 5)} 158507 855295 18.53} {229 {STR append (1MB + (1b + 1K + 1b) * 100)} 33101 174031 19.02} {230 {STR info locals match} 946 1521 62.20} {231 {TRACE no trace set} 34 121 28.10}}

test csv-5.8 {reading csv files, auto expansion mode} {
    set f [open [file join $::tcltest::testsDirectory mem_debug_bench.csv] r]
    ::struct::matrix m
    m add columns 1
    ::csv::read2matrix $f m , auto
    close $f
    set result [m get rect 0 227 end 231]
    m destroy
    set result
} {{227 {STR append (1MB + 1MB * 3)} 125505 327765 38.29} {228 {STR append (1MB + 1MB * 5)} 158507 855295 18.53} {229 {STR append (1MB + (1b + 1K + 1b) * 100)} 33101 174031 19.02} {230 {STR info locals match} 946 1521 62.20} {231 {TRACE no trace set} 34 121 28.10}}

# =========================================================================
# Bug 2926387

test csv-5.9.0 {reading csv files, inner field newline processing, bug 2926387} {
    set m [struct::matrix]
    set f [open [file join $::tcltest::testsDirectory 2926387.csv] r]
    csv::read2matrix $f $m , auto
    close $f
    set result [$m serialize]
    $m destroy
    set result
} {2 3 {{a b c} {d {e,
e} f}}}

test csv-5.9.1 {reading csv files, inner field newline processing, bug 2926387} {
    set q [struct::queue]
    set f [open [file join $::tcltest::testsDirectory 2926387.csv] r]
    csv::read2queue $f $q
    close $f
    set result [$q get [$q size]]
    $q destroy
    set result
} {{a b c} {d {e,
e} f}}

# =========================================================================

test csv-6.1 {writing csv files} {
    set f [open [localPath eval.csv] r]
    ::struct::matrix m
    m add columns 5
    ::csv::read2matrix $f m
    close $f

    set f [open [makeFile {} eval-out1.csv] w]
    ::csv::writematrix m $f







|









|









|










|










|














|












|









|














|










|











|







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
    ::struct::matrix m
    catch {::csv::read2matrix dummy m foo} result
    m destroy
    set result
} {illegal separator character "foo", is a string}

test csv-5.1 {reading csv files} {
    set f [open [asset mem_debug_bench.csv] r]
    ::struct::queue q
    ::csv::read2queue $f q
    close $f
    set result [list [q size] [q get 2]]
    q destroy
    set result
} {251 {{000 VERSIONS: 2:8.4a3 1:8.4a3 1:8.4a3%} {001 {CATCH return ok} 7 13 53.85}}}

test csv-5.2 {reading csv files} {
    set f [open [asset mem_debug_bench_a.csv] r]
    ::struct::queue q
    ::csv::read2queue $f q
    close $f
    set result [list [q size] [q get 2]]
    q destroy
    set result
} {251 {{000 VERSIONS: 2:8.4a3 1:8.4a3 1:8.4a3%} {001 {CATCH return ok} 7 13 53.85}}}

test csv-5.3 {reading csv files} {
    set f [open [asset mem_debug_bench.csv] r]
    ::struct::matrix m
    m add columns 5
    ::csv::read2matrix $f m
    close $f
    set result [m get rect 0 227 end 231]
    m destroy
    set result
} {{227 {STR append (1MB + 1MB * 3)} 125505 327765 38.29} {228 {STR append (1MB + 1MB * 5)} 158507 855295 18.53} {229 {STR append (1MB + (1b + 1K + 1b) * 100)} 33101 174031 19.02} {230 {STR info locals match} 946 1521 62.20} {231 {TRACE no trace set} 34 121 28.10}}

test csv-5.4 {reading csv files} {
    set f [open [asset mem_debug_bench_a.csv] r]
    ::struct::matrix m
    m add columns 5
    ::csv::read2matrix $f m
    close $f
    set result [m get rect 0 227 end 231]
    m destroy
    set result
} {{227 {STR append (1MB + 1MB * 3)} 125505 327765 38.29} {228 {STR append (1MB + 1MB * 5)} 158507 855295 18.53} {229 {STR append (1MB + (1b + 1K + 1b) * 100)} 33101 174031 19.02} {230 {STR info locals match} 946 1521 62.20} {231 {TRACE no trace set} 34 121 28.10}}

test csv-5.5 {reading csv files} {
    set f [open [asset mem_debug_bench.csv] r]
    ::struct::matrix m
    m add columns 5
    ::csv::read2matrix $f m
    close $f

    set result [list]
    foreach c {0 1 2 3 4} {
	lappend result [m columnwidth $c]
    }
    m destroy
    set result
} {3 39 7 7 8}

test csv-5.6 {reading csv files, linking} {
    set f [open [asset mem_debug_bench.csv] r]
    ::struct::matrix m
    m add columns 5
    ::csv::read2matrix $f m
    close $f
    m link a
    set result [array size a]
    m destroy
    set result
} {1255}


test csv-5.7 {reading csv files, empty expansion mode} {
    set f [open [asset mem_debug_bench.csv] r]
    ::struct::matrix m
    ::csv::read2matrix $f m , empty
    close $f
    set result [m get rect 0 227 end 231]
    m destroy
    set result
} {{227 {STR append (1MB + 1MB * 3)} 125505 327765 38.29} {228 {STR append (1MB + 1MB * 5)} 158507 855295 18.53} {229 {STR append (1MB + (1b + 1K + 1b) * 100)} 33101 174031 19.02} {230 {STR info locals match} 946 1521 62.20} {231 {TRACE no trace set} 34 121 28.10}}

test csv-5.8 {reading csv files, auto expansion mode} {
    set f [open [asset mem_debug_bench.csv] r]
    ::struct::matrix m
    m add columns 1
    ::csv::read2matrix $f m , auto
    close $f
    set result [m get rect 0 227 end 231]
    m destroy
    set result
} {{227 {STR append (1MB + 1MB * 3)} 125505 327765 38.29} {228 {STR append (1MB + 1MB * 5)} 158507 855295 18.53} {229 {STR append (1MB + (1b + 1K + 1b) * 100)} 33101 174031 19.02} {230 {STR info locals match} 946 1521 62.20} {231 {TRACE no trace set} 34 121 28.10}}

# =========================================================================
# Bug 2926387

test csv-5.9.0 {reading csv files, inner field newline processing, bug 2926387} {
    set m [struct::matrix]
    set f [open [asset 2926387.csv] r]
    csv::read2matrix $f $m , auto
    close $f
    set result [$m serialize]
    $m destroy
    set result
} {2 3 {{a b c} {d {e,
e} f}}}

test csv-5.9.1 {reading csv files, inner field newline processing, bug 2926387} {
    set q [struct::queue]
    set f [open [asset 2926387.csv] r]
    csv::read2queue $f $q
    close $f
    set result [$q get [$q size]]
    $q destroy
    set result
} {{a b c} {d {e,
e} f}}

# =========================================================================

test csv-6.1 {writing csv files} {
    set f [open [asset eval.csv] r]
    ::struct::matrix m
    m add columns 5
    ::csv::read2matrix $f m
    close $f

    set f [open [makeFile {} eval-out1.csv] w]
    ::csv::writematrix m $f
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
024,EVAL cmd eval as list,23,42,54.76
025,EVAL cmd eval as string,53,92,57.61
026,EVAL cmd and mixed lists,3805,11276,33.74
027,EVAL list cmd and mixed lists,3812,11325,33.66
028,EVAL list cmd and pure lists,592,1598,37.05}

test csv-6.2 {writing csv files} {
    set f [open [localPath eval.csv] r]
    ::struct::queue q
    ::csv::read2queue $f q
    close $f

    set f [open [makeFile {} eval-out2.csv] w]
    ::csv::writequeue q $f
    close $f







|







487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
024,EVAL cmd eval as list,23,42,54.76
025,EVAL cmd eval as string,53,92,57.61
026,EVAL cmd and mixed lists,3805,11276,33.74
027,EVAL list cmd and mixed lists,3812,11325,33.66
028,EVAL list cmd and pure lists,592,1598,37.05}

test csv-6.2 {writing csv files} {
    set f [open [asset eval.csv] r]
    ::struct::queue q
    ::csv::read2queue $f q
    close $f

    set f [open [makeFile {} eval-out2.csv] w]
    ::csv::writequeue q $f
    close $f
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
025,EVAL cmd eval as string,53,92,57.61
026,EVAL cmd and mixed lists,3805,11276,33.74
027,EVAL list cmd and mixed lists,3812,11325,33.66
028,EVAL list cmd and pure lists,592,1598,37.05}


test csv-7.1 {reporting} {
    set f [open [localPath eval.csv] r]
    ::struct::matrix m
    m add columns 5
    ::csv::read2matrix $f m
    close $f

    set result [m format 2string csv::report]
    m destroy
    set result
} {023,EVAL cmd eval in list obj var,26,45,57.78
024,EVAL cmd eval as list,23,42,54.76
025,EVAL cmd eval as string,53,92,57.61
026,EVAL cmd and mixed lists,3805,11276,33.74
027,EVAL list cmd and mixed lists,3812,11325,33.66
028,EVAL list cmd and pure lists,592,1598,37.05
}

test csv-7.2 {reporting} {
    set f [open [localPath eval.csv] r]
    ::struct::matrix m
    m add columns 5
    ::csv::read2matrix $f m
    close $f

    set f [open [makeFile {} eval-out3.csv] w]
    m format 2chan csv::report $f







|

















|







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
025,EVAL cmd eval as string,53,92,57.61
026,EVAL cmd and mixed lists,3805,11276,33.74
027,EVAL list cmd and mixed lists,3812,11325,33.66
028,EVAL list cmd and pure lists,592,1598,37.05}


test csv-7.1 {reporting} {
    set f [open [asset eval.csv] r]
    ::struct::matrix m
    m add columns 5
    ::csv::read2matrix $f m
    close $f

    set result [m format 2string csv::report]
    m destroy
    set result
} {023,EVAL cmd eval in list obj var,26,45,57.78
024,EVAL cmd eval as list,23,42,54.76
025,EVAL cmd eval as string,53,92,57.61
026,EVAL cmd and mixed lists,3805,11276,33.74
027,EVAL list cmd and mixed lists,3812,11325,33.66
028,EVAL list cmd and pure lists,592,1598,37.05
}

test csv-7.2 {reporting} {
    set f [open [asset eval.csv] r]
    ::struct::matrix m
    m add columns 5
    ::csv::read2matrix $f m
    close $f

    set f [open [makeFile {} eval-out3.csv] w]
    m format 2chan csv::report $f

Deleted modules/csv/eval.csv.

1
2
3
4
5
6
023,EVAL cmd eval in list obj var,26,45,57.78
024,EVAL cmd eval as list,23,42,54.76
025,EVAL cmd eval as string,53,92,57.61
026,EVAL cmd and mixed lists,3805,11276,33.74
027,EVAL list cmd and mixed lists,3812,11325,33.66
028,EVAL list cmd and pure lists,592,1598,37.05
<
<
<
<
<
<












Deleted modules/csv/mem_debug_bench.csv.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
000,VERSIONS:,2:8.4a3,1:8.4a3,1:8.4a3%
001,CATCH return ok,7,13,53.85
002,CATCH return error,68,91,74.73
003,CATCH no catch used,7,14,50.00
004,IF if true numeric,12,33,36.36
005,IF elseif true numeric,15,47,31.91
006,IF else true numeric,15,46,32.61
007,IF if true num/num,13,32,40.62
008,IF if false num/num,13,32,40.62
009,IF if false al/num,28,57,49.12
010,IF if true al/num,34,54,62.96
011,IF if false al/num,34,58,58.62
012,IF if true al/al,33,100,33.00
013,IF elseif true al/al,50,87,57.47
014,IF else true al/al,50,92,54.35
015,SWITCH first true,50,81,61.73
016,SWITCH second true,55,84,65.48
017,SWITCH ninth true,56,96,58.33
018,SWITCH default true,48,81,59.26
019,DATA create in a list,5419,13514,40.10
020,DATA create in an array,5861,15537,37.72
021,DATA access in a list,4424,9967,44.39
022,DATA access in an array,4373,9167,47.70
023,EVAL cmd eval in list obj var,26,45,57.78
024,EVAL cmd eval as list,23,42,54.76
025,EVAL cmd eval as string,53,92,57.61
026,EVAL cmd and mixed lists,3805,11276,33.74
027,EVAL list cmd and mixed lists,3812,11325,33.66
028,EVAL list cmd and pure lists,592,1598,37.05
029,EXPR unbraced,174,250,69.60
030,EXPR braced,27,60,45.00
031,EXPR inline,28,51,54.90
032,EXPR one operand,8,13,61.54
033,EXPR ten operands,15,25,60.00
034,EXPR fifty operands,46,73,63.01
035,EXPR incr with incr,13,20,65.00
036,EXPR incr with expr,8,14,57.14
037,KLIST shuffle0 llength 1,154,260,59.23
038,KLIST shuffle0 llength 10,521,950,54.84
039,KLIST shuffle0 llength 100,4126,7781,53.03
040,KLIST shuffle0 llength 1000,46309,85434,54.20
041,KLIST shuffle0 llength 10000,612676,1000055,61.26
042,KLIST shuffle1 llength 1,100,181,55.25
043,KLIST shuffle1 llength 10,432,835,51.74
044,KLIST shuffle1 llength 100,5872,14144,41.52
045,KLIST shuffle1 llength 1000,1293956,1235661,104.72
046,KLIST shuffle1a llength 1,115,200,57.50
047,KLIST shuffle1a llength 10,442,1012,43.68
048,KLIST shuffle1a llength 100,4212,9609,43.83
049,KLIST shuffle1a llength 1000,42350,98262,43.10
050,KLIST shuffle1a llength 10000,445084,1052460,42.29
051,KLIST shuffle2 llength 1,123,205,60.00
052,KLIST shuffle2 llength 10,484,922,52.49
053,KLIST shuffle2 llength 100,4377,8347,52.44
054,KLIST shuffle2 llength 1000,46002,89585,51.35
055,KLIST shuffle2 llength 10000,525442,926369,56.72
056,KLIST shuffle3 llength 1,116,196,59.18
057,KLIST shuffle3 llength 10,420,911,46.10
058,KLIST shuffle3 llength 100,3730,8465,44.06
059,KLIST shuffle3 llength 1000,39397,87416,45.07
060,KLIST shuffle3 llength 10000,949689,1391544,68.25
061,KLIST shuffle4 llength 1,116,204,56.86
062,KLIST shuffle4 llength 10,450,1000,45.00
063,KLIST shuffle4 llength 100,4067,9326,43.61
064,KLIST shuffle4 llength 1000,39142,92580,42.28
065,KLIST shuffle4 llength 10000,421581,944205,44.65
066,"STR/LIST length; obj shimmer",3268,6767,48.29
067,"LIST length; pure list",17,21,80.95
068,STR length of a LIST,12,25,48.00
069,"LIST exact search; first item",18,24,75.00
070,"LIST exact search; middle item",74,111,66.67
071,"LIST exact search; last item",142,236,60.17
072,"LIST exact search; non-item",344,603,57.05
073,"LIST sorted search; first item",19,29,65.52
074,"LIST sorted search; middle item",19,27,70.37
075,"LIST sorted search; last item",19,27,70.37
076,"LIST sorted search; non-item",19,27,70.37
077,"LIST exact search; untyped item",148,230,64.35
078,"LIST exact search; typed item",107,119,89.92
079,"LIST sorted search; typed item",18,29,62.07
080,LIST sort,3620,4994,72.49
081,LIST typed sort,2923,3885,75.24
082,LIST remove first element,310,763,40.63
083,LIST remove middle element,308,761,40.47
084,LIST remove last element,312,757,41.22
085,LIST replace first element,291,740,39.32
086,LIST replace middle element,295,741,39.81
087,LIST replace last element,295,743,39.70
088,LIST replace first el with multiple,315,770,40.91
089,LIST replace middle el with multiple,314,764,41.10
090,LIST replace last el with multiple,288,750,38.40
091,LIST replace range,288,737,39.08
092,LIST remove in mixed list,411,959,42.86
093,LIST replace in mixed list,398,932,42.70
094,LIST index first element,14,24,58.33
095,LIST index middle element,14,28,50.00
096,LIST index last element,14,28,50.00
097,LIST insert an item at start,297,750,39.60
098,LIST insert an item at middle,303,746,40.62
099,"LIST insert an item at ""end""",299,746,40.08
100,"LIST small; early range",26,41,63.41
101,"LIST small; late range",23,33,69.70
102,"LIST large; early range",42,94,44.68
103,"LIST large; late range",41,106,38.68
104,LIST append to list,406,426,95.31
105,LIST join list,1147,1687,67.99
106,"LOOP for; iterate list",6848,16393,41.77
107,"LOOP foreach; iterate list",2169,5913,36.68
108,LOOP for (to 1000),2756,8183,33.68
109,LOOP while (to 1000),2753,8181,33.65
110,"LOOP for; iterate string",8350,15966,52.30
111,"LOOP foreach; iterate string",2684,7094,37.83
112,MAP string 1 val,686,1097,62.53
113,MAP string 2 val,1578,2375,66.44
114,MAP string 3 val,1938,2674,72.48
115,MAP string 4 val,2427,3324,73.01
116,MAP string 1 val -nocase,3772,5524,68.28
117,MAP string 2 val -nocase,6633,9624,68.92
118,MAP string 3 val -nocase,8809,12682,69.46
119,MAP string 4 val -nocase,10692,15353,69.64
120,MAP regsub 1 val,3884,4345,89.39
121,MAP regsub 2 val,16420,17435,94.18
122,MAP regsub 3 val,22056,23287,94.71
123,MAP regsub 4 val,27550,29333,93.92
124,MAP regsub 1 val -nocase,4004,4322,92.64
125,MAP regsub 2 val -nocase,16519,17289,95.55
126,MAP regsub 3 val -nocase,22075,23427,94.23
127,MAP regsub 4 val -nocase,27981,29438,95.05
128,"MAP string; no match",1011,1734,58.30
129,"MAP string -nocase; no match",7090,10589,66.96
130,"MAP regsub; no match",1226,2328,52.66
131,"MAP regsub -nocase; no match",1287,2295,56.08
132,MAP string short,44,58,75.86
133,MAP regsub short,188,219,85.84
134,MTHD direct ns proc call,8,15,53.33
135,MTHD imported ns proc call,8,16,50.00
136,MTHD interp alias proc call,25,44,56.82
137,MTHD indirect proc eval,36,58,62.07
138,MTHD indirect proc eval #2,58,100,58.00
139,MTHD array stored proc call,11,25,44.00
140,MTHD switch method call,53,86,61.63
141,MTHD ns lookup call,113,189,59.79
142,MTHD inline call,3,9,33.33
143,PROC explicit return,7,12,58.33
144,PROC implicit return,7,17,41.18
145,PROC explicit return (2),7,13,53.85
146,PROC implicit return (2),7,15,46.67
147,PROC explicit return (3),7,12,58.33
148,PROC implicit return (3),7,12,58.33
149,PROC heavily commented,7,12,58.33
150,"PROC do-nothing; no args",6,11,54.55
151,"PROC do-nothing; one arg",7,12,58.33
152,PROC local links with global,1611,2827,56.99
153,PROC local links with upvar,1308,2630,49.73
154,PROC local links with variable,1309,2358,55.51
155,"READ 595K; gets",386913,551429,70.17
156,"READ 595K; read",85889,164758,52.13
157,"READ 595K; read & size",86171,164854,52.27
158,"READ 3050b; gets",2152,3481,61.82
159,"READ 3050b; read",561,682,82.26
160,"READ 3050b; read & size",606,738,82.11
161,"BREAD 595K; gets",392519,568992,68.98
162,"BREAD 595K; read",51133,110961,46.08
163,"BREAD 595K; read & size",51194,110552,46.31
164,"BREAD 3050b; gets",2213,3174,69.72
165,"BREAD 3050b; read",329,472,69.70
166,"BREAD 3050b; read & size",377,517,72.92
167,REGEXP literal regexp,48,58,82.76
168,REGEXP var-based regexp,51,60,85.00
169,REGEXP count all matches,149,161,92.55
170,REGEXP extract all matches,201,255,78.82
171,STARTUP time to launch tclsh,26402,32329,81.67
172,STR str [string compare],15,38,39.47
173,STR str [string equal],15,38,39.47
174,"STR str $a equal """"",13,32,40.62
175,"STR str num == """"",15,38,39.47
176,STR str $a eq $b,21,49,42.86
177,STR str $a ne $b,21,49,42.86
178,STR str $a eq $b (same obj),19,45,42.22
179,STR str $a ne $b (same obj),19,46,41.30
180,STR length (==4010),13,23,56.52
181,STR index 0,19,30,63.33
182,STR index 100,20,31,64.52
183,STR index 500,19,30,63.33
184,STR index2 0,20,32,62.50
185,STR index2 100,21,30,70.00
186,STR index2 500,20,31,64.52
187,STR first (success),17,23,73.91
188,STR first (failure),115,116,99.14
189,STR first (total failure),106,103,102.91
190,STR last (success),17,23,73.91
191,STR last (failure),91,109,83.49
192,STR last (total failure),82,86,95.35
193,"STR match; simple (success early)",17,31,54.84
194,"STR match; simple (success late)",18,30,60.00
195,"STR match; simple (failure)",18,28,64.29
196,"STR match; simple (total failure)",16,29,55.17
197,"STR match; complex (success early)",18,34,52.94
198,"STR match; complex (success late)",152,165,92.12
199,"STR match; complex (failure)",121,134,90.30
200,"STR match; complex (total failure)",95,101,94.06
201,"STR range; index 100..200 of 4010",26,40,65.00
202,"STR replace; no replacement",87,126,69.05
203,"STR replace; equal replacement",93,133,69.92
204,"STR replace; longer replacement",103,146,70.55
205,"STR repeat; abcdefghij * 10",16,23,69.57
206,"STR repeat; abcdefghij * 100",48,47,102.13
207,"STR repeat; abcdefghij * 1000",231,257,89.88
208,"STR repeat; 4010 chars * 10",282,744,37.90
209,"STR repeat; 4010 chars * 100",6976,14673,47.54
210,"STR reverse iter1; 100 chars",1534,2295,66.84
211,"STR reverse iter1; 100 uchars",1457,2322,62.75
212,"STR reverse iter2; 100 chars",1123,2042,55.00
213,"STR reverse iter2; 100 uchars",1042,1972,52.84
214,"STR reverse recur1; 100 chars",3458,7067,48.93
215,"STR reverse recur1; 100 uchars",3523,6650,52.98
216,"STR split; 4010 chars",2806,4605,60.93
217,"STR split; 12100 uchars",7890,13813,57.12
218,"STR split iter; 4010 chars",11129,28087,39.62
219,"STR split iter; 12100 uchars",33318,86314,38.60
220,STR append,99,160,61.88
221,STR append (1KB + 1KB),95,134,70.90
222,STR append (10KB + 1KB),209,537,38.92
223,STR append (1MB + 2b * 1000),38681,190529,20.30
224,STR append (1MB + 1KB),28344,173073,16.38
225,STR append (1MB + 1KB * 20),29077,173622,16.75
226,STR append (1MB + 1KB * 1000),66893,207868,32.18
227,STR append (1MB + 1MB * 3),125505,327765,38.29
228,STR append (1MB + 1MB * 5),158507,855295,18.53
229,STR append (1MB + (1b + 1K + 1b) * 100),33101,174031,19.02
230,STR info locals match,946,1521,62.20
231,TRACE no trace set,34,121,28.10
232,TRACE read,34,50,68.00
233,TRACE write,33,50,66.00
234,TRACE unset,33,48,68.75
235,TRACE all set (rwu),34,52,65.38
236,UNSET var exists,12,19,63.16
237,UNSET catch var exists,13,23,56.52
238,UNSET catch var !exist,77,105,73.33
239,UNSET info check var exists,16,27,59.26
240,UNSET info check var !exist,12,27,44.44
241,UNSET nocomplain var exists,12,18,66.67
242,UNSET nocomplain var !exist,12,16,75.00
243,VAR access locally set,10,19,52.63
244,VAR access local proc arg,10,20,50.00
245,VAR access global,35,49,71.43
246,VAR access upvar,40,54,74.07
247,VAR set scalar,7,15,46.67
248,VAR set array element,14,28,50.00
249,VAR 100 'set's in array,161,272,59.19
250,VAR 'array set' of 100 elems,306,467,65.52
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






















































































































































































































































































































































































































































































































Deleted modules/csv/mem_debug_bench_a.csv.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
000,VERSIONS:,2:8.4a3,1:8.4a3,1:8.4a3%
001,CATCH return ok,7,13,53.85
002,CATCH return error,68,91,74.73
003,CATCH no catch used,7,14,50.00
004,IF if true numeric,12,33,36.36
005,IF elseif true numeric,15,47,31.91

006,IF else true numeric,15,46,32.61
007,IF if true num/num,13,32,40.62
008,IF if false num/num,13,32,40.62
009,IF if false al/num,28,57,49.12
010,IF if true al/num,34,54,62.96
011,IF if false al/num,34,58,58.62
012,IF if true al/al,33,100,33.00
013,IF elseif true al/al,50,87,57.47
014,IF else true al/al,50,92,54.35
015,SWITCH first true,50,81,61.73
016,SWITCH second true,55,84,65.48
017,SWITCH ninth true,56,96,58.33
018,SWITCH default true,48,81,59.26
019,DATA create in a list,5419,13514,40.10
020,DATA create in an array,5861,15537,37.72
021,DATA access in a list,4424,9967,44.39

022,DATA access in an array,4373,9167,47.70
023,EVAL cmd eval in list obj var,26,45,57.78
024,EVAL cmd eval as list,23,42,54.76
025,EVAL cmd eval as string,53,92,57.61
026,EVAL cmd and mixed lists,3805,11276,33.74
027,EVAL list cmd and mixed lists,3812,11325,33.66
028,EVAL list cmd and pure lists,592,1598,37.05
029,EXPR unbraced,174,250,69.60
030,EXPR braced,27,60,45.00
031,EXPR inline,28,51,54.90
032,EXPR one operand,8,13,61.54
033,EXPR ten operands,15,25,60.00


034,EXPR fifty operands,46,73,63.01
035,EXPR incr with incr,13,20,65.00
036,EXPR incr with expr,8,14,57.14
037,KLIST shuffle0 llength 1,154,260,59.23
038,KLIST shuffle0 llength 10,521,950,54.84
039,KLIST shuffle0 llength 100,4126,7781,53.03
040,KLIST shuffle0 llength 1000,46309,85434,54.20
041,KLIST shuffle0 llength 10000,612676,1000055,61.26
042,KLIST shuffle1 llength 1,100,181,55.25
043,KLIST shuffle1 llength 10,432,835,51.74
044,KLIST shuffle1 llength 100,5872,14144,41.52
045,KLIST shuffle1 llength 1000,1293956,1235661,104.72
046,KLIST shuffle1a llength 1,115,200,57.50
047,KLIST shuffle1a llength 10,442,1012,43.68
048,KLIST shuffle1a llength 100,4212,9609,43.83
049,KLIST shuffle1a llength 1000,42350,98262,43.10
050,KLIST shuffle1a llength 10000,445084,1052460,42.29
051,KLIST shuffle2 llength 1,123,205,60.00
052,KLIST shuffle2 llength 10,484,922,52.49

053,KLIST shuffle2 llength 100,4377,8347,52.44
054,KLIST shuffle2 llength 1000,46002,89585,51.35
055,KLIST shuffle2 llength 10000,525442,926369,56.72
056,KLIST shuffle3 llength 1,116,196,59.18
057,KLIST shuffle3 llength 10,420,911,46.10
058,KLIST shuffle3 llength 100,3730,8465,44.06
059,KLIST shuffle3 llength 1000,39397,87416,45.07
060,KLIST shuffle3 llength 10000,949689,1391544,68.25
061,KLIST shuffle4 llength 1,116,204,56.86
062,KLIST shuffle4 llength 10,450,1000,45.00
063,KLIST shuffle4 llength 100,4067,9326,43.61
064,KLIST shuffle4 llength 1000,39142,92580,42.28
065,KLIST shuffle4 llength 10000,421581,944205,44.65
066,"STR/LIST length; obj shimmer",3268,6767,48.29
067,"LIST length; pure list",17,21,80.95
068,STR length of a LIST,12,25,48.00
069,"LIST exact search; first item",18,24,75.00
070,"LIST exact search; middle item",74,111,66.67
071,"LIST exact search; last item",142,236,60.17
072,"LIST exact search; non-item",344,603,57.05
073,"LIST sorted search; first item",19,29,65.52
074,"LIST sorted search; middle item",19,27,70.37
075,"LIST sorted search; last item",19,27,70.37
076,"LIST sorted search; non-item",19,27,70.37
077,"LIST exact search; untyped item",148,230,64.35
078,"LIST exact search; typed item",107,119,89.92
079,"LIST sorted search; typed item",18,29,62.07
080,LIST sort,3620,4994,72.49
081,LIST typed sort,2923,3885,75.24
082,LIST remove first element,310,763,40.63
083,LIST remove middle element,308,761,40.47
084,LIST remove last element,312,757,41.22
085,LIST replace first element,291,740,39.32
086,LIST replace middle element,295,741,39.81
087,LIST replace last element,295,743,39.70
088,LIST replace first el with multiple,315,770,40.91
089,LIST replace middle el with multiple,314,764,41.10
090,LIST replace last el with multiple,288,750,38.40
091,LIST replace range,288,737,39.08
092,LIST remove in mixed list,411,959,42.86
093,LIST replace in mixed list,398,932,42.70
094,LIST index first element,14,24,58.33
095,LIST index middle element,14,28,50.00
096,LIST index last element,14,28,50.00
097,LIST insert an item at start,297,750,39.60
098,LIST insert an item at middle,303,746,40.62
099,"LIST insert an item at ""end""",299,746,40.08
100,"LIST small; early range",26,41,63.41
101,"LIST small; late range",23,33,69.70
102,"LIST large; early range",42,94,44.68
103,"LIST large; late range",41,106,38.68
104,LIST append to list,406,426,95.31
105,LIST join list,1147,1687,67.99
106,"LOOP for; iterate list",6848,16393,41.77
107,"LOOP foreach; iterate list",2169,5913,36.68
108,LOOP for (to 1000),2756,8183,33.68
109,LOOP while (to 1000),2753,8181,33.65
110,"LOOP for; iterate string",8350,15966,52.30
111,"LOOP foreach; iterate string",2684,7094,37.83
112,MAP string 1 val,686,1097,62.53
113,MAP string 2 val,1578,2375,66.44
114,MAP string 3 val,1938,2674,72.48
115,MAP string 4 val,2427,3324,73.01
116,MAP string 1 val -nocase,3772,5524,68.28
117,MAP string 2 val -nocase,6633,9624,68.92
118,MAP string 3 val -nocase,8809,12682,69.46
119,MAP string 4 val -nocase,10692,15353,69.64
120,MAP regsub 1 val,3884,4345,89.39
121,MAP regsub 2 val,16420,17435,94.18
122,MAP regsub 3 val,22056,23287,94.71
123,MAP regsub 4 val,27550,29333,93.92
124,MAP regsub 1 val -nocase,4004,4322,92.64
125,MAP regsub 2 val -nocase,16519,17289,95.55
126,MAP regsub 3 val -nocase,22075,23427,94.23
127,MAP regsub 4 val -nocase,27981,29438,95.05
128,"MAP string; no match",1011,1734,58.30
129,"MAP string -nocase; no match",7090,10589,66.96
130,"MAP regsub; no match",1226,2328,52.66
131,"MAP regsub -nocase; no match",1287,2295,56.08
132,MAP string short,44,58,75.86
133,MAP regsub short,188,219,85.84
134,MTHD direct ns proc call,8,15,53.33
135,MTHD imported ns proc call,8,16,50.00
136,MTHD interp alias proc call,25,44,56.82
137,MTHD indirect proc eval,36,58,62.07
138,MTHD indirect proc eval #2,58,100,58.00
139,MTHD array stored proc call,11,25,44.00
140,MTHD switch method call,53,86,61.63
141,MTHD ns lookup call,113,189,59.79
142,MTHD inline call,3,9,33.33
143,PROC explicit return,7,12,58.33
144,PROC implicit return,7,17,41.18
145,PROC explicit return (2),7,13,53.85
146,PROC implicit return (2),7,15,46.67
147,PROC explicit return (3),7,12,58.33
148,PROC implicit return (3),7,12,58.33
149,PROC heavily commented,7,12,58.33
150,"PROC do-nothing; no args",6,11,54.55
151,"PROC do-nothing; one arg",7,12,58.33
152,PROC local links with global,1611,2827,56.99
153,PROC local links with upvar,1308,2630,49.73
154,PROC local links with variable,1309,2358,55.51
155,"READ 595K; gets",386913,551429,70.17
156,"READ 595K; read",85889,164758,52.13
157,"READ 595K; read & size",86171,164854,52.27
158,"READ 3050b; gets",2152,3481,61.82
159,"READ 3050b; read",561,682,82.26
160,"READ 3050b; read & size",606,738,82.11
161,"BREAD 595K; gets",392519,568992,68.98
162,"BREAD 595K; read",51133,110961,46.08
163,"BREAD 595K; read & size",51194,110552,46.31
164,"BREAD 3050b; gets",2213,3174,69.72
165,"BREAD 3050b; read",329,472,69.70
166,"BREAD 3050b; read & size",377,517,72.92
167,REGEXP literal regexp,48,58,82.76
168,REGEXP var-based regexp,51,60,85.00
169,REGEXP count all matches,149,161,92.55
170,REGEXP extract all matches,201,255,78.82
171,STARTUP time to launch tclsh,26402,32329,81.67
172,STR str [string compare],15,38,39.47
173,STR str [string equal],15,38,39.47
174,"STR str $a equal """"",13,32,40.62
175,"STR str num == """"",15,38,39.47
176,STR str $a eq $b,21,49,42.86
177,STR str $a ne $b,21,49,42.86
178,STR str $a eq $b (same obj),19,45,42.22
179,STR str $a ne $b (same obj),19,46,41.30
180,STR length (==4010),13,23,56.52
181,STR index 0,19,30,63.33
182,STR index 100,20,31,64.52
183,STR index 500,19,30,63.33
184,STR index2 0,20,32,62.50
185,STR index2 100,21,30,70.00
186,STR index2 500,20,31,64.52
187,STR first (success),17,23,73.91
188,STR first (failure),115,116,99.14
189,STR first (total failure),106,103,102.91
190,STR last (success),17,23,73.91
191,STR last (failure),91,109,83.49
192,STR last (total failure),82,86,95.35
193,"STR match; simple (success early)",17,31,54.84
194,"STR match; simple (success late)",18,30,60.00
195,"STR match; simple (failure)",18,28,64.29
196,"STR match; simple (total failure)",16,29,55.17
197,"STR match; complex (success early)",18,34,52.94
198,"STR match; complex (success late)",152,165,92.12
199,"STR match; complex (failure)",121,134,90.30
200,"STR match; complex (total failure)",95,101,94.06
201,"STR range; index 100..200 of 4010",26,40,65.00
202,"STR replace; no replacement",87,126,69.05
203,"STR replace; equal replacement",93,133,69.92
204,"STR replace; longer replacement",103,146,70.55
205,"STR repeat; abcdefghij * 10",16,23,69.57
206,"STR repeat; abcdefghij * 100",48,47,102.13
207,"STR repeat; abcdefghij * 1000",231,257,89.88
208,"STR repeat; 4010 chars * 10",282,744,37.90
209,"STR repeat; 4010 chars * 100",6976,14673,47.54
210,"STR reverse iter1; 100 chars",1534,2295,66.84
211,"STR reverse iter1; 100 uchars",1457,2322,62.75
212,"STR reverse iter2; 100 chars",1123,2042,55.00
213,"STR reverse iter2; 100 uchars",1042,1972,52.84
214,"STR reverse recur1; 100 chars",3458,7067,48.93
215,"STR reverse recur1; 100 uchars",3523,6650,52.98
216,"STR split; 4010 chars",2806,4605,60.93
217,"STR split; 12100 uchars",7890,13813,57.12
218,"STR split iter; 4010 chars",11129,28087,39.62
219,"STR split iter; 12100 uchars",33318,86314,38.60
220,STR append,99,160,61.88
221,STR append (1KB + 1KB),95,134,70.90
222,STR append (10KB + 1KB),209,537,38.92
223,STR append (1MB + 2b * 1000),38681,190529,20.30
224,STR append (1MB + 1KB),28344,173073,16.38
225,STR append (1MB + 1KB * 20),29077,173622,16.75
226,STR append (1MB + 1KB * 1000),66893,207868,32.18
227,STR append (1MB + 1MB * 3),125505,327765,38.29
228,STR append (1MB + 1MB * 5),158507,855295,18.53
229,STR append (1MB + (1b + 1K + 1b) * 100),33101,174031,19.02
230,STR info locals match,946,1521,62.20
231,TRACE no trace set,34,121,28.10
232,TRACE read,34,50,68.00
233,TRACE write,33,50,66.00
234,TRACE unset,33,48,68.75
235,TRACE all set (rwu),34,52,65.38
236,UNSET var exists,12,19,63.16
237,UNSET catch var exists,13,23,56.52
238,UNSET catch var !exist,77,105,73.33
239,UNSET info check var exists,16,27,59.26
240,UNSET info check var !exist,12,27,44.44
241,UNSET nocomplain var exists,12,18,66.67
242,UNSET nocomplain var !exist,12,16,75.00
243,VAR access locally set,10,19,52.63
244,VAR access local proc arg,10,20,50.00
245,VAR access global,35,49,71.43
246,VAR access upvar,40,54,74.07
247,VAR set scalar,7,15,46.67
248,VAR set array element,14,28,50.00
249,VAR 100 'set's in array,161,272,59.19
250,VAR 'array set' of 100 elems,306,467,65.52
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































































































































































































































































































































































Added modules/csv/test-assets/2926387.csv.









>
>
>
>
1
2
3
4
a,b,c
d,"e,
e",f

Added modules/csv/test-assets/eval.csv.













>
>
>
>
>
>
1
2
3
4
5
6
023,EVAL cmd eval in list obj var,26,45,57.78
024,EVAL cmd eval as list,23,42,54.76
025,EVAL cmd eval as string,53,92,57.61
026,EVAL cmd and mixed lists,3805,11276,33.74
027,EVAL list cmd and mixed lists,3812,11325,33.66
028,EVAL list cmd and pure lists,592,1598,37.05

Added modules/csv/test-assets/mem_debug_bench.csv.























































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
000,VERSIONS:,2:8.4a3,1:8.4a3,1:8.4a3%
001,CATCH return ok,7,13,53.85
002,CATCH return error,68,91,74.73
003,CATCH no catch used,7,14,50.00
004,IF if true numeric,12,33,36.36
005,IF elseif true numeric,15,47,31.91
006,IF else true numeric,15,46,32.61
007,IF if true num/num,13,32,40.62
008,IF if false num/num,13,32,40.62
009,IF if false al/num,28,57,49.12
010,IF if true al/num,34,54,62.96
011,IF if false al/num,34,58,58.62
012,IF if true al/al,33,100,33.00
013,IF elseif true al/al,50,87,57.47
014,IF else true al/al,50,92,54.35
015,SWITCH first true,50,81,61.73
016,SWITCH second true,55,84,65.48
017,SWITCH ninth true,56,96,58.33
018,SWITCH default true,48,81,59.26
019,DATA create in a list,5419,13514,40.10
020,DATA create in an array,5861,15537,37.72
021,DATA access in a list,4424,9967,44.39
022,DATA access in an array,4373,9167,47.70
023,EVAL cmd eval in list obj var,26,45,57.78
024,EVAL cmd eval as list,23,42,54.76
025,EVAL cmd eval as string,53,92,57.61
026,EVAL cmd and mixed lists,3805,11276,33.74
027,EVAL list cmd and mixed lists,3812,11325,33.66
028,EVAL list cmd and pure lists,592,1598,37.05
029,EXPR unbraced,174,250,69.60
030,EXPR braced,27,60,45.00
031,EXPR inline,28,51,54.90
032,EXPR one operand,8,13,61.54
033,EXPR ten operands,15,25,60.00
034,EXPR fifty operands,46,73,63.01
035,EXPR incr with incr,13,20,65.00
036,EXPR incr with expr,8,14,57.14
037,KLIST shuffle0 llength 1,154,260,59.23
038,KLIST shuffle0 llength 10,521,950,54.84
039,KLIST shuffle0 llength 100,4126,7781,53.03
040,KLIST shuffle0 llength 1000,46309,85434,54.20
041,KLIST shuffle0 llength 10000,612676,1000055,61.26
042,KLIST shuffle1 llength 1,100,181,55.25
043,KLIST shuffle1 llength 10,432,835,51.74
044,KLIST shuffle1 llength 100,5872,14144,41.52
045,KLIST shuffle1 llength 1000,1293956,1235661,104.72
046,KLIST shuffle1a llength 1,115,200,57.50
047,KLIST shuffle1a llength 10,442,1012,43.68
048,KLIST shuffle1a llength 100,4212,9609,43.83
049,KLIST shuffle1a llength 1000,42350,98262,43.10
050,KLIST shuffle1a llength 10000,445084,1052460,42.29
051,KLIST shuffle2 llength 1,123,205,60.00
052,KLIST shuffle2 llength 10,484,922,52.49
053,KLIST shuffle2 llength 100,4377,8347,52.44
054,KLIST shuffle2 llength 1000,46002,89585,51.35
055,KLIST shuffle2 llength 10000,525442,926369,56.72
056,KLIST shuffle3 llength 1,116,196,59.18
057,KLIST shuffle3 llength 10,420,911,46.10
058,KLIST shuffle3 llength 100,3730,8465,44.06
059,KLIST shuffle3 llength 1000,39397,87416,45.07
060,KLIST shuffle3 llength 10000,949689,1391544,68.25
061,KLIST shuffle4 llength 1,116,204,56.86
062,KLIST shuffle4 llength 10,450,1000,45.00
063,KLIST shuffle4 llength 100,4067,9326,43.61
064,KLIST shuffle4 llength 1000,39142,92580,42.28
065,KLIST shuffle4 llength 10000,421581,944205,44.65
066,"STR/LIST length; obj shimmer",3268,6767,48.29
067,"LIST length; pure list",17,21,80.95
068,STR length of a LIST,12,25,48.00
069,"LIST exact search; first item",18,24,75.00
070,"LIST exact search; middle item",74,111,66.67
071,"LIST exact search; last item",142,236,60.17
072,"LIST exact search; non-item",344,603,57.05
073,"LIST sorted search; first item",19,29,65.52
074,"LIST sorted search; middle item",19,27,70.37
075,"LIST sorted search; last item",19,27,70.37
076,"LIST sorted search; non-item",19,27,70.37
077,"LIST exact search; untyped item",148,230,64.35
078,"LIST exact search; typed item",107,119,89.92
079,"LIST sorted search; typed item",18,29,62.07
080,LIST sort,3620,4994,72.49
081,LIST typed sort,2923,3885,75.24
082,LIST remove first element,310,763,40.63
083,LIST remove middle element,308,761,40.47
084,LIST remove last element,312,757,41.22
085,LIST replace first element,291,740,39.32
086,LIST replace middle element,295,741,39.81
087,LIST replace last element,295,743,39.70
088,LIST replace first el with multiple,315,770,40.91
089,LIST replace middle el with multiple,314,764,41.10
090,LIST replace last el with multiple,288,750,38.40
091,LIST replace range,288,737,39.08
092,LIST remove in mixed list,411,959,42.86
093,LIST replace in mixed list,398,932,42.70
094,LIST index first element,14,24,58.33
095,LIST index middle element,14,28,50.00
096,LIST index last element,14,28,50.00
097,LIST insert an item at start,297,750,39.60
098,LIST insert an item at middle,303,746,40.62
099,"LIST insert an item at ""end""",299,746,40.08
100,"LIST small; early range",26,41,63.41
101,"LIST small; late range",23,33,69.70
102,"LIST large; early range",42,94,44.68
103,"LIST large; late range",41,106,38.68
104,LIST append to list,406,426,95.31
105,LIST join list,1147,1687,67.99
106,"LOOP for; iterate list",6848,16393,41.77
107,"LOOP foreach; iterate list",2169,5913,36.68
108,LOOP for (to 1000),2756,8183,33.68
109,LOOP while (to 1000),2753,8181,33.65
110,"LOOP for; iterate string",8350,15966,52.30
111,"LOOP foreach; iterate string",2684,7094,37.83
112,MAP string 1 val,686,1097,62.53
113,MAP string 2 val,1578,2375,66.44
114,MAP string 3 val,1938,2674,72.48
115,MAP string 4 val,2427,3324,73.01
116,MAP string 1 val -nocase,3772,5524,68.28
117,MAP string 2 val -nocase,6633,9624,68.92
118,MAP string 3 val -nocase,8809,12682,69.46
119,MAP string 4 val -nocase,10692,15353,69.64
120,MAP regsub 1 val,3884,4345,89.39
121,MAP regsub 2 val,16420,17435,94.18
122,MAP regsub 3 val,22056,23287,94.71
123,MAP regsub 4 val,27550,29333,93.92
124,MAP regsub 1 val -nocase,4004,4322,92.64
125,MAP regsub 2 val -nocase,16519,17289,95.55
126,MAP regsub 3 val -nocase,22075,23427,94.23
127,MAP regsub 4 val -nocase,27981,29438,95.05
128,"MAP string; no match",1011,1734,58.30
129,"MAP string -nocase; no match",7090,10589,66.96
130,"MAP regsub; no match",1226,2328,52.66
131,"MAP regsub -nocase; no match",1287,2295,56.08
132,MAP string short,44,58,75.86
133,MAP regsub short,188,219,85.84
134,MTHD direct ns proc call,8,15,53.33
135,MTHD imported ns proc call,8,16,50.00
136,MTHD interp alias proc call,25,44,56.82
137,MTHD indirect proc eval,36,58,62.07
138,MTHD indirect proc eval #2,58,100,58.00
139,MTHD array stored proc call,11,25,44.00
140,MTHD switch method call,53,86,61.63
141,MTHD ns lookup call,113,189,59.79
142,MTHD inline call,3,9,33.33
143,PROC explicit return,7,12,58.33
144,PROC implicit return,7,17,41.18
145,PROC explicit return (2),7,13,53.85
146,PROC implicit return (2),7,15,46.67
147,PROC explicit return (3),7,12,58.33
148,PROC implicit return (3),7,12,58.33
149,PROC heavily commented,7,12,58.33
150,"PROC do-nothing; no args",6,11,54.55
151,"PROC do-nothing; one arg",7,12,58.33
152,PROC local links with global,1611,2827,56.99
153,PROC local links with upvar,1308,2630,49.73
154,PROC local links with variable,1309,2358,55.51
155,"READ 595K; gets",386913,551429,70.17
156,"READ 595K; read",85889,164758,52.13
157,"READ 595K; read & size",86171,164854,52.27
158,"READ 3050b; gets",2152,3481,61.82
159,"READ 3050b; read",561,682,82.26
160,"READ 3050b; read & size",606,738,82.11
161,"BREAD 595K; gets",392519,568992,68.98
162,"BREAD 595K; read",51133,110961,46.08
163,"BREAD 595K; read & size",51194,110552,46.31
164,"BREAD 3050b; gets",2213,3174,69.72
165,"BREAD 3050b; read",329,472,69.70
166,"BREAD 3050b; read & size",377,517,72.92
167,REGEXP literal regexp,48,58,82.76
168,REGEXP var-based regexp,51,60,85.00
169,REGEXP count all matches,149,161,92.55
170,REGEXP extract all matches,201,255,78.82
171,STARTUP time to launch tclsh,26402,32329,81.67
172,STR str [string compare],15,38,39.47
173,STR str [string equal],15,38,39.47
174,"STR str $a equal """"",13,32,40.62
175,"STR str num == """"",15,38,39.47
176,STR str $a eq $b,21,49,42.86
177,STR str $a ne $b,21,49,42.86
178,STR str $a eq $b (same obj),19,45,42.22
179,STR str $a ne $b (same obj),19,46,41.30
180,STR length (==4010),13,23,56.52
181,STR index 0,19,30,63.33
182,STR index 100,20,31,64.52
183,STR index 500,19,30,63.33
184,STR index2 0,20,32,62.50
185,STR index2 100,21,30,70.00
186,STR index2 500,20,31,64.52
187,STR first (success),17,23,73.91
188,STR first (failure),115,116,99.14
189,STR first (total failure),106,103,102.91
190,STR last (success),17,23,73.91
191,STR last (failure),91,109,83.49
192,STR last (total failure),82,86,95.35
193,"STR match; simple (success early)",17,31,54.84
194,"STR match; simple (success late)",18,30,60.00
195,"STR match; simple (failure)",18,28,64.29
196,"STR match; simple (total failure)",16,29,55.17
197,"STR match; complex (success early)",18,34,52.94
198,"STR match; complex (success late)",152,165,92.12
199,"STR match; complex (failure)",121,134,90.30
200,"STR match; complex (total failure)",95,101,94.06
201,"STR range; index 100..200 of 4010",26,40,65.00
202,"STR replace; no replacement",87,126,69.05
203,"STR replace; equal replacement",93,133,69.92
204,"STR replace; longer replacement",103,146,70.55
205,"STR repeat; abcdefghij * 10",16,23,69.57
206,"STR repeat; abcdefghij * 100",48,47,102.13
207,"STR repeat; abcdefghij * 1000",231,257,89.88
208,"STR repeat; 4010 chars * 10",282,744,37.90
209,"STR repeat; 4010 chars * 100",6976,14673,47.54
210,"STR reverse iter1; 100 chars",1534,2295,66.84
211,"STR reverse iter1; 100 uchars",1457,2322,62.75
212,"STR reverse iter2; 100 chars",1123,2042,55.00
213,"STR reverse iter2; 100 uchars",1042,1972,52.84
214,"STR reverse recur1; 100 chars",3458,7067,48.93
215,"STR reverse recur1; 100 uchars",3523,6650,52.98
216,"STR split; 4010 chars",2806,4605,60.93
217,"STR split; 12100 uchars",7890,13813,57.12
218,"STR split iter; 4010 chars",11129,28087,39.62
219,"STR split iter; 12100 uchars",33318,86314,38.60
220,STR append,99,160,61.88
221,STR append (1KB + 1KB),95,134,70.90
222,STR append (10KB + 1KB),209,537,38.92
223,STR append (1MB + 2b * 1000),38681,190529,20.30
224,STR append (1MB + 1KB),28344,173073,16.38
225,STR append (1MB + 1KB * 20),29077,173622,16.75
226,STR append (1MB + 1KB * 1000),66893,207868,32.18
227,STR append (1MB + 1MB * 3),125505,327765,38.29
228,STR append (1MB + 1MB * 5),158507,855295,18.53
229,STR append (1MB + (1b + 1K + 1b) * 100),33101,174031,19.02
230,STR info locals match,946,1521,62.20
231,TRACE no trace set,34,121,28.10
232,TRACE read,34,50,68.00
233,TRACE write,33,50,66.00
234,TRACE unset,33,48,68.75
235,TRACE all set (rwu),34,52,65.38
236,UNSET var exists,12,19,63.16
237,UNSET catch var exists,13,23,56.52
238,UNSET catch var !exist,77,105,73.33
239,UNSET info check var exists,16,27,59.26
240,UNSET info check var !exist,12,27,44.44
241,UNSET nocomplain var exists,12,18,66.67
242,UNSET nocomplain var !exist,12,16,75.00
243,VAR access locally set,10,19,52.63
244,VAR access local proc arg,10,20,50.00
245,VAR access global,35,49,71.43
246,VAR access upvar,40,54,74.07
247,VAR set scalar,7,15,46.67
248,VAR set array element,14,28,50.00
249,VAR 100 'set's in array,161,272,59.19
250,VAR 'array set' of 100 elems,306,467,65.52

Added modules/csv/test-assets/mem_debug_bench_a.csv.

































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
000,VERSIONS:,2:8.4a3,1:8.4a3,1:8.4a3%
001,CATCH return ok,7,13,53.85
002,CATCH return error,68,91,74.73
003,CATCH no catch used,7,14,50.00
004,IF if true numeric,12,33,36.36
005,IF elseif true numeric,15,47,31.91

006,IF else true numeric,15,46,32.61
007,IF if true num/num,13,32,40.62
008,IF if false num/num,13,32,40.62
009,IF if false al/num,28,57,49.12
010,IF if true al/num,34,54,62.96
011,IF if false al/num,34,58,58.62
012,IF if true al/al,33,100,33.00
013,IF elseif true al/al,50,87,57.47
014,IF else true al/al,50,92,54.35
015,SWITCH first true,50,81,61.73
016,SWITCH second true,55,84,65.48
017,SWITCH ninth true,56,96,58.33
018,SWITCH default true,48,81,59.26
019,DATA create in a list,5419,13514,40.10
020,DATA create in an array,5861,15537,37.72
021,DATA access in a list,4424,9967,44.39

022,DATA access in an array,4373,9167,47.70
023,EVAL cmd eval in list obj var,26,45,57.78
024,EVAL cmd eval as list,23,42,54.76
025,EVAL cmd eval as string,53,92,57.61
026,EVAL cmd and mixed lists,3805,11276,33.74
027,EVAL list cmd and mixed lists,3812,11325,33.66
028,EVAL list cmd and pure lists,592,1598,37.05
029,EXPR unbraced,174,250,69.60
030,EXPR braced,27,60,45.00
031,EXPR inline,28,51,54.90
032,EXPR one operand,8,13,61.54
033,EXPR ten operands,15,25,60.00


034,EXPR fifty operands,46,73,63.01
035,EXPR incr with incr,13,20,65.00
036,EXPR incr with expr,8,14,57.14
037,KLIST shuffle0 llength 1,154,260,59.23
038,KLIST shuffle0 llength 10,521,950,54.84
039,KLIST shuffle0 llength 100,4126,7781,53.03
040,KLIST shuffle0 llength 1000,46309,85434,54.20
041,KLIST shuffle0 llength 10000,612676,1000055,61.26
042,KLIST shuffle1 llength 1,100,181,55.25
043,KLIST shuffle1 llength 10,432,835,51.74
044,KLIST shuffle1 llength 100,5872,14144,41.52
045,KLIST shuffle1 llength 1000,1293956,1235661,104.72
046,KLIST shuffle1a llength 1,115,200,57.50
047,KLIST shuffle1a llength 10,442,1012,43.68
048,KLIST shuffle1a llength 100,4212,9609,43.83
049,KLIST shuffle1a llength 1000,42350,98262,43.10
050,KLIST shuffle1a llength 10000,445084,1052460,42.29
051,KLIST shuffle2 llength 1,123,205,60.00
052,KLIST shuffle2 llength 10,484,922,52.49

053,KLIST shuffle2 llength 100,4377,8347,52.44
054,KLIST shuffle2 llength 1000,46002,89585,51.35
055,KLIST shuffle2 llength 10000,525442,926369,56.72
056,KLIST shuffle3 llength 1,116,196,59.18
057,KLIST shuffle3 llength 10,420,911,46.10
058,KLIST shuffle3 llength 100,3730,8465,44.06
059,KLIST shuffle3 llength 1000,39397,87416,45.07
060,KLIST shuffle3 llength 10000,949689,1391544,68.25
061,KLIST shuffle4 llength 1,116,204,56.86
062,KLIST shuffle4 llength 10,450,1000,45.00
063,KLIST shuffle4 llength 100,4067,9326,43.61
064,KLIST shuffle4 llength 1000,39142,92580,42.28
065,KLIST shuffle4 llength 10000,421581,944205,44.65
066,"STR/LIST length; obj shimmer",3268,6767,48.29
067,"LIST length; pure list",17,21,80.95
068,STR length of a LIST,12,25,48.00
069,"LIST exact search; first item",18,24,75.00
070,"LIST exact search; middle item",74,111,66.67
071,"LIST exact search; last item",142,236,60.17
072,"LIST exact search; non-item",344,603,57.05
073,"LIST sorted search; first item",19,29,65.52
074,"LIST sorted search; middle item",19,27,70.37
075,"LIST sorted search; last item",19,27,70.37
076,"LIST sorted search; non-item",19,27,70.37
077,"LIST exact search; untyped item",148,230,64.35
078,"LIST exact search; typed item",107,119,89.92
079,"LIST sorted search; typed item",18,29,62.07
080,LIST sort,3620,4994,72.49
081,LIST typed sort,2923,3885,75.24
082,LIST remove first element,310,763,40.63
083,LIST remove middle element,308,761,40.47
084,LIST remove last element,312,757,41.22
085,LIST replace first element,291,740,39.32
086,LIST replace middle element,295,741,39.81
087,LIST replace last element,295,743,39.70
088,LIST replace first el with multiple,315,770,40.91
089,LIST replace middle el with multiple,314,764,41.10
090,LIST replace last el with multiple,288,750,38.40
091,LIST replace range,288,737,39.08
092,LIST remove in mixed list,411,959,42.86
093,LIST replace in mixed list,398,932,42.70
094,LIST index first element,14,24,58.33
095,LIST index middle element,14,28,50.00
096,LIST index last element,14,28,50.00
097,LIST insert an item at start,297,750,39.60
098,LIST insert an item at middle,303,746,40.62
099,"LIST insert an item at ""end""",299,746,40.08
100,"LIST small; early range",26,41,63.41
101,"LIST small; late range",23,33,69.70
102,"LIST large; early range",42,94,44.68
103,"LIST large; late range",41,106,38.68
104,LIST append to list,406,426,95.31
105,LIST join list,1147,1687,67.99
106,"LOOP for; iterate list",6848,16393,41.77
107,"LOOP foreach; iterate list",2169,5913,36.68
108,LOOP for (to 1000),2756,8183,33.68
109,LOOP while (to 1000),2753,8181,33.65
110,"LOOP for; iterate string",8350,15966,52.30
111,"LOOP foreach; iterate string",2684,7094,37.83
112,MAP string 1 val,686,1097,62.53
113,MAP string 2 val,1578,2375,66.44
114,MAP string 3 val,1938,2674,72.48
115,MAP string 4 val,2427,3324,73.01
116,MAP string 1 val -nocase,3772,5524,68.28
117,MAP string 2 val -nocase,6633,9624,68.92
118,MAP string 3 val -nocase,8809,12682,69.46
119,MAP string 4 val -nocase,10692,15353,69.64
120,MAP regsub 1 val,3884,4345,89.39
121,MAP regsub 2 val,16420,17435,94.18
122,MAP regsub 3 val,22056,23287,94.71
123,MAP regsub 4 val,27550,29333,93.92
124,MAP regsub 1 val -nocase,4004,4322,92.64
125,MAP regsub 2 val -nocase,16519,17289,95.55
126,MAP regsub 3 val -nocase,22075,23427,94.23
127,MAP regsub 4 val -nocase,27981,29438,95.05
128,"MAP string; no match",1011,1734,58.30
129,"MAP string -nocase; no match",7090,10589,66.96
130,"MAP regsub; no match",1226,2328,52.66
131,"MAP regsub -nocase; no match",1287,2295,56.08
132,MAP string short,44,58,75.86
133,MAP regsub short,188,219,85.84
134,MTHD direct ns proc call,8,15,53.33
135,MTHD imported ns proc call,8,16,50.00
136,MTHD interp alias proc call,25,44,56.82
137,MTHD indirect proc eval,36,58,62.07
138,MTHD indirect proc eval #2,58,100,58.00
139,MTHD array stored proc call,11,25,44.00
140,MTHD switch method call,53,86,61.63
141,MTHD ns lookup call,113,189,59.79
142,MTHD inline call,3,9,33.33
143,PROC explicit return,7,12,58.33
144,PROC implicit return,7,17,41.18
145,PROC explicit return (2),7,13,53.85
146,PROC implicit return (2),7,15,46.67
147,PROC explicit return (3),7,12,58.33
148,PROC implicit return (3),7,12,58.33
149,PROC heavily commented,7,12,58.33
150,"PROC do-nothing; no args",6,11,54.55
151,"PROC do-nothing; one arg",7,12,58.33
152,PROC local links with global,1611,2827,56.99
153,PROC local links with upvar,1308,2630,49.73
154,PROC local links with variable,1309,2358,55.51
155,"READ 595K; gets",386913,551429,70.17
156,"READ 595K; read",85889,164758,52.13
157,"READ 595K; read & size",86171,164854,52.27
158,"READ 3050b; gets",2152,3481,61.82
159,"READ 3050b; read",561,682,82.26
160,"READ 3050b; read & size",606,738,82.11
161,"BREAD 595K; gets",392519,568992,68.98
162,"BREAD 595K; read",51133,110961,46.08
163,"BREAD 595K; read & size",51194,110552,46.31
164,"BREAD 3050b; gets",2213,3174,69.72
165,"BREAD 3050b; read",329,472,69.70
166,"BREAD 3050b; read & size",377,517,72.92
167,REGEXP literal regexp,48,58,82.76
168,REGEXP var-based regexp,51,60,85.00
169,REGEXP count all matches,149,161,92.55
170,REGEXP extract all matches,201,255,78.82
171,STARTUP time to launch tclsh,26402,32329,81.67
172,STR str [string compare],15,38,39.47
173,STR str [string equal],15,38,39.47
174,"STR str $a equal """"",13,32,40.62
175,"STR str num == """"",15,38,39.47
176,STR str $a eq $b,21,49,42.86
177,STR str $a ne $b,21,49,42.86
178,STR str $a eq $b (same obj),19,45,42.22
179,STR str $a ne $b (same obj),19,46,41.30
180,STR length (==4010),13,23,56.52
181,STR index 0,19,30,63.33
182,STR index 100,20,31,64.52
183,STR index 500,19,30,63.33
184,STR index2 0,20,32,62.50
185,STR index2 100,21,30,70.00
186,STR index2 500,20,31,64.52
187,STR first (success),17,23,73.91
188,STR first (failure),115,116,99.14
189,STR first (total failure),106,103,102.91
190,STR last (success),17,23,73.91
191,STR last (failure),91,109,83.49
192,STR last (total failure),82,86,95.35
193,"STR match; simple (success early)",17,31,54.84
194,"STR match; simple (success late)",18,30,60.00
195,"STR match; simple (failure)",18,28,64.29
196,"STR match; simple (total failure)",16,29,55.17
197,"STR match; complex (success early)",18,34,52.94
198,"STR match; complex (success late)",152,165,92.12
199,"STR match; complex (failure)",121,134,90.30
200,"STR match; complex (total failure)",95,101,94.06
201,"STR range; index 100..200 of 4010",26,40,65.00
202,"STR replace; no replacement",87,126,69.05
203,"STR replace; equal replacement",93,133,69.92
204,"STR replace; longer replacement",103,146,70.55
205,"STR repeat; abcdefghij * 10",16,23,69.57
206,"STR repeat; abcdefghij * 100",48,47,102.13
207,"STR repeat; abcdefghij * 1000",231,257,89.88
208,"STR repeat; 4010 chars * 10",282,744,37.90
209,"STR repeat; 4010 chars * 100",6976,14673,47.54
210,"STR reverse iter1; 100 chars",1534,2295,66.84
211,"STR reverse iter1; 100 uchars",1457,2322,62.75
212,"STR reverse iter2; 100 chars",1123,2042,55.00
213,"STR reverse iter2; 100 uchars",1042,1972,52.84
214,"STR reverse recur1; 100 chars",3458,7067,48.93
215,"STR reverse recur1; 100 uchars",3523,6650,52.98
216,"STR split; 4010 chars",2806,4605,60.93
217,"STR split; 12100 uchars",7890,13813,57.12
218,"STR split iter; 4010 chars",11129,28087,39.62
219,"STR split iter; 12100 uchars",33318,86314,38.60
220,STR append,99,160,61.88
221,STR append (1KB + 1KB),95,134,70.90
222,STR append (10KB + 1KB),209,537,38.92
223,STR append (1MB + 2b * 1000),38681,190529,20.30
224,STR append (1MB + 1KB),28344,173073,16.38
225,STR append (1MB + 1KB * 20),29077,173622,16.75
226,STR append (1MB + 1KB * 1000),66893,207868,32.18
227,STR append (1MB + 1MB * 3),125505,327765,38.29
228,STR append (1MB + 1MB * 5),158507,855295,18.53
229,STR append (1MB + (1b + 1K + 1b) * 100),33101,174031,19.02
230,STR info locals match,946,1521,62.20
231,TRACE no trace set,34,121,28.10
232,TRACE read,34,50,68.00
233,TRACE write,33,50,66.00
234,TRACE unset,33,48,68.75
235,TRACE all set (rwu),34,52,65.38
236,UNSET var exists,12,19,63.16
237,UNSET catch var exists,13,23,56.52
238,UNSET catch var !exist,77,105,73.33
239,UNSET info check var exists,16,27,59.26
240,UNSET info check var !exist,12,27,44.44
241,UNSET nocomplain var exists,12,18,66.67
242,UNSET nocomplain var !exist,12,16,75.00
243,VAR access locally set,10,19,52.63
244,VAR access local proc arg,10,20,50.00
245,VAR access global,35,49,71.43
246,VAR access upvar,40,54,74.07
247,VAR set scalar,7,15,46.67
248,VAR set array element,14,28,50.00
249,VAR 100 'set's in array,161,272,59.19
250,VAR 'array set' of 100 elems,306,467,65.52

Changes to modules/debug/debug.man.

239
240
241
242
243
244
245
246
247

[para] The result of the method is the specified text.

[comment {= = == === ===== ======== ============= =====================}]
[list_end]

[vset CATEGORY debug]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

239
240
241
242
243
244
245
246
247

[para] The result of the method is the specified text.

[comment {= = == === ===== ======== ============= =====================}]
[list_end]

[vset CATEGORY debug]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/debug/debug_caller.man.

36
37
38
39
40
41
42
43
44
The main anticipiated use case for this is the exclusion of arguments
expected to contain large Tcl values, i.e. long lists, large
dictionaries, etc. to prevent them from overwhelming the narrative.

[list_end]

[vset CATEGORY debug]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

36
37
38
39
40
41
42
43
44
The main anticipiated use case for this is the exclusion of arguments
expected to contain large Tcl values, i.e. long lists, large
dictionaries, etc. to prevent them from overwhelming the narrative.

[list_end]

[vset CATEGORY debug]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/debug/debug_heartbeat.man.

1
2
3
4
5
6
7
8
9
[comment {-*- tcl -*- doctools manpage}]
[vset VERSION 1]
[manpage_begin debug::heartbeat n [vset VERSION]]
[keywords debug]
[keywords heartbeat]
[keywords log]
[keywords narrative]
[keywords trace]
[copyright {200?, Colin McCormack, Wub Server Utilities}]

|







1
2
3
4
5
6
7
8
9
[comment {-*- tcl -*- doctools manpage}]
[vset VERSION 1.0.1]
[manpage_begin debug::heartbeat n [vset VERSION]]
[keywords debug]
[keywords heartbeat]
[keywords log]
[keywords narrative]
[keywords trace]
[copyright {200?, Colin McCormack, Wub Server Utilities}]
35
36
37
38
39
40
41
42
43
counter and the time in milliseconds since the last beat, thus
providing insight into timing variationsn and deviations from the
nominal [arg delta].

[list_end]

[vset CATEGORY debug]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

35
36
37
38
39
40
41
42
43
counter and the time in milliseconds since the last beat, thus
providing insight into timing variationsn and deviations from the
nominal [arg delta].

[list_end]

[vset CATEGORY debug]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/debug/debug_timestamp.man.

26
27
28
29
30
31
32
33
34
last call, making it useful in a tag-specific prefix to automatically
provide caller information for all uses of the tag. Or in a message,
when only specific places need such detail.

[list_end]

[vset CATEGORY debug]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

26
27
28
29
30
31
32
33
34
last call, making it useful in a tag-specific prefix to automatically
provide caller information for all uses of the tag. Or in a message,
when only specific places need such detail.

[list_end]

[vset CATEGORY debug]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/debug/heartbeat.tcl.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
    variable duration $delta
    variable timer

    if {$duration > 0} {
	# stop a previous heartbeat before starting the next
	catch { after cancel $timer }
	on heartbeat
	every $duration {
	    debug.heartbeat {[debug::pulse]}
	}
    } else {
	catch { after cancel $timer }
	off heartbeat
    }
}








|
|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
    variable duration $delta
    variable timer

    if {$duration > 0} {
	# stop a previous heartbeat before starting the next
	catch { after cancel $timer }
	on heartbeat
	::debug::every $duration {
	    debug.heartbeat {[::debug::pulse]}
	}
    } else {
	catch { after cancel $timer }
	off heartbeat
    }
}

60
61
62
63
64
65
66
67
68
    variable hbtimer   [::tcl::clock::milliseconds]
    variable timer
}

# # ## ### ##### ######## ############# #####################
## Ready

package provide debug::heartbeat 1
return







|

60
61
62
63
64
65
66
67
68
    variable hbtimer   [::tcl::clock::milliseconds]
    variable timer
}

# # ## ### ##### ######## ############# #####################
## Ready

package provide debug::heartbeat 1.0.1
return

Added modules/debug/heartbeat.test.



















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# heartbeat.test - Copyright (c) 2019 A. Kupries
# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2

testing {
    useLocal heartbeat.tcl debug::heartbeat
}

# -------------------------------------------------------------------------

test heartbeat-1.0 {wrong args, too many} -body {
    debug heartbeat 500 X
} -returnCodes error -result {wrong # args: should be "debug heartbeat ?delta?"}

test heartbeat-2.0 {run the beat} -setup {
    # capture the beat
    rename ::puts ::puts_x
    proc puts {args} {
        lappend ::captured [info level 0]
    }
    set forever {}
    set captured {}
    set sep "\n    "
} -cleanup {
    # undo capture
    rename ::puts {}
    rename ::puts_x ::puts
    unset forever captured sep _
} -body {
    after 1100 { set ::forever now }
    debug heartbeat 200
    vwait forever
    set _ "${sep}[join [lreplace $captured 0 0 start] ${sep}]\n"
} -match glob -result {
    start
    puts stderr {heartbeat | 1 *}
    puts stderr {heartbeat | 2 *}
    puts stderr {heartbeat | 3 *}
    puts stderr {heartbeat | 4 *}
    puts stderr {heartbeat | 5 *}
    puts stderr {heartbeat | 6 *}
}

# -------------------------------------------------------------------------

testsuiteCleanup
return
# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End:

Changes to modules/debug/pkgIndex.tcl.

1
2
3
4
5
if {![package vsatisfies [package require Tcl] 8.5]} return
package ifneeded debug            1.0.6 [list source [file join $dir debug.tcl]]
package ifneeded debug::heartbeat 1     [list source [file join $dir heartbeat.tcl]]
package ifneeded debug::timestamp 1     [list source [file join $dir timestamp.tcl]]
package ifneeded debug::caller    1.1   [list source [file join $dir caller.tcl]]


|


1
2
3
4
5
if {![package vsatisfies [package require Tcl] 8.5]} return
package ifneeded debug            1.0.6 [list source [file join $dir debug.tcl]]
package ifneeded debug::heartbeat 1.0.1 [list source [file join $dir heartbeat.tcl]]
package ifneeded debug::timestamp 1     [list source [file join $dir timestamp.tcl]]
package ifneeded debug::caller    1.1   [list source [file join $dir caller.tcl]]

Changes to modules/defer/defer.man.

94
95
96
97
98
99
100
101
102
[enum]
[list_end]

[section AUTHORS]
Roy Keene

[vset CATEGORY defer]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

94
95
96
97
98
99
100
101
102
[enum]
[list_end]

[section AUTHORS]
Roy Keene

[vset CATEGORY defer]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/des/des.man.

198
199
200
201
202
203
204
205
206

[section "AUTHORS"]
Jochen C Loewer,
Mac Cody,
Pat Thoyts

[vset CATEGORY des]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

198
199
200
201
202
203
204
205
206

[section "AUTHORS"]
Jochen C Loewer,
Mac Cody,
Pat Thoyts

[vset CATEGORY des]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/des/tcldes.man.

18
19
20
21
22
23
24
25
26
[para]

The [package tclDES] package is a helper package for [package des].

[para] Please see the documentation of [package des] for details.

[vset CATEGORY des]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

18
19
20
21
22
23
24
25
26
[para]

The [package tclDES] package is a helper package for [package des].

[para] Please see the documentation of [package des] for details.

[vset CATEGORY des]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/des/tcldesjr.man.

18
19
20
21
22
23
24
25
26
[para]

The [package tclDESjr] package is a helper package for [package des].

[para] Please see the documentation of [package des] for details.

[vset CATEGORY des]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

18
19
20
21
22
23
24
25
26
[para]

The [package tclDESjr] package is a helper package for [package des].

[para] Please see the documentation of [package des] for details.

[vset CATEGORY des]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/devtools/testutilities.tcl.

164
165
166
167
168
169
170








171
172
173
174
175
176
177
## Easy definition and initialization of test constraints.

proc InitializeTclTest {} {
    global tcltestinit
    if {[info exists tcltestinit] && $tcltestinit} return
    set tcltestinit 1









    if {![package vsatisfies [package provide tcltest] 2.0]} {
	# Tcltest 2.0+ provides a documented public API to define and
	# initialize a test constraint. For earlier versions of the
	# package the user has to directly set a non-public undocumented
	# variable in the package's namespace. We create a command doing
	# this and emulating the public API.








>
>
>
>
>
>
>
>







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
## Easy definition and initialization of test constraints.

proc InitializeTclTest {} {
    global tcltestinit
    if {[info exists tcltestinit] && $tcltestinit} return
    set tcltestinit 1

    proc ::tcltest::byConstraint {dict} {
	foreach {constraint value} $dict {
	    if {![testConstraint $constraint]} continue
	    return $value
	}
	return -code error "No result available. Failed to match any of the constraints ([join [lsort -dict [dict keys $dict]] ,])."
    }
    
    if {![package vsatisfies [package provide tcltest] 2.0]} {
	# Tcltest 2.0+ provides a documented public API to define and
	# initialize a test constraint. For earlier versions of the
	# package the user has to directly set a non-public undocumented
	# variable in the package's namespace. We create a command doing
	# this and emulating the public API.

200
201
202
203
204
205
206



207
208





209
210
211
212
213
214
215







216
217
218
219
220
221
222

    ::tcltest::testConstraint tcl8.3only \
	[expr {![package vsatisfies [package provide Tcl] 8.4]}]

    ::tcltest::testConstraint tcl8.3plus \
	[expr {[package vsatisfies [package provide Tcl] 8.3]}]




    ::tcltest::testConstraint tcl8.4plus \
	[expr {[package vsatisfies [package provide Tcl] 8.4]}]






    ::tcltest::testConstraint tcl8.5plus \
	[expr {[package vsatisfies [package provide Tcl] 8.5]}]

    ::tcltest::testConstraint tcl8.6plus \
	[expr {[package vsatisfies [package provide Tcl] 8.6]}]








    ::tcltest::testConstraint tcl8.4minus \
	[expr {![package vsatisfies [package provide Tcl] 8.5]}]

    ::tcltest::testConstraint tcl8.5minus \
	[expr {![package vsatisfies [package provide Tcl] 8.6]}]

    # ### ### ### ######### ######### #########







>
>
>


>
>
>
>
>







>
>
>
>
>
>
>







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

    ::tcltest::testConstraint tcl8.3only \
	[expr {![package vsatisfies [package provide Tcl] 8.4]}]

    ::tcltest::testConstraint tcl8.3plus \
	[expr {[package vsatisfies [package provide Tcl] 8.3]}]

    ::tcltest::testConstraint tcl8.4only \
	[expr {![package vsatisfies [package provide Tcl] 8.5]}]

    ::tcltest::testConstraint tcl8.4plus \
	[expr {[package vsatisfies [package provide Tcl] 8.4]}]

    ::tcltest::testConstraint tcl8.5only [expr {
	![package vsatisfies [package provide Tcl] 8.6] &&
	 [package vsatisfies [package provide Tcl] 8.5]
    }]

    ::tcltest::testConstraint tcl8.5plus \
	[expr {[package vsatisfies [package provide Tcl] 8.5]}]

    ::tcltest::testConstraint tcl8.6plus \
	[expr {[package vsatisfies [package provide Tcl] 8.6]}]

    ::tcltest::testConstraint tcl8.6not10 \
	[expr { [package vsatisfies [package provide Tcl] 8.6] &&
	       ![package vsatisfies [package provide Tcl] 8.6.10]}]

    ::tcltest::testConstraint tcl8.6.10plus \
	[expr {[package vsatisfies [package provide Tcl] 8.6.10]}]

    ::tcltest::testConstraint tcl8.4minus \
	[expr {![package vsatisfies [package provide Tcl] 8.5]}]

    ::tcltest::testConstraint tcl8.5minus \
	[expr {![package vsatisfies [package provide Tcl] 8.6]}]

    # ### ### ### ######### ######### #########
401
402
403
404
405
406
407













408
409
410
411

412
413
414
415
416
417
418
# ### ### ### ######### ######### #########
## Commands to load files from various locations within the local
## Tcllib, and the loading of local Tcllib packages. None of them goes
## through the auto-loader, nor the regular package management, to
## avoid contamination of the testsuite by packages and code outside
## of the Tcllib under test.














proc localPath {fname} {
    return [file join $::tcltest::testsDirectory $fname]
}


proc tcllibPath {fname} {
    return [file join $::tcllib::testutils::tcllib $fname]
}

proc useLocalFile {fname} {
    return [uplevel 1 [list source [localPath $fname]]]
}







>
>
>
>
>
>
>
>
>
>
>
>
>




>







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
# ### ### ### ######### ######### #########
## Commands to load files from various locations within the local
## Tcllib, and the loading of local Tcllib packages. None of them goes
## through the auto-loader, nor the regular package management, to
## avoid contamination of the testsuite by packages and code outside
## of the Tcllib under test.

# Shorthand for access to module-local assets files for tests.
proc asset {path} {
    file join $::tcltest::testsDirectory test-assets $path
}

proc asset-get {path} {
    set c [open [asset $path] r]
    set d [read $c]
    close $c
    return $d
}

# General access to module-local files
proc localPath {fname} {
    return [file join $::tcltest::testsDirectory $fname]
}

# General access to global (project-local) files
proc tcllibPath {fname} {
    return [file join $::tcllib::testutils::tcllib $fname]
}

proc useLocalFile {fname} {
    return [uplevel 1 [list source [localPath $fname]]]
}

Changes to modules/dicttool/dicttool.man.


1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

[comment {-*- tcl -*- doctools manpage}]
[manpage_begin dicttool n 1.0]
[keywords dict]
[copyright {2017 Sean Woods <[email protected]>}]
[moddesc   {Extensions to the standard "dict" command}]
[category Utilities]
[titledesc {Dictionary Tools}]
[require Tcl 8.5]

[description]
[para]
The [package dicttool] package enhances the standard [emph dict] command with several new
commands. In addition, the package also defines several "creature comfort" list commands as well.
Each command checks to see if a command already exists of the same name before adding itself,
just in case any of these slip into the core.

[list_begin definitions]
[call [cmd ladd] [arg varname] [arg args]]

This command will add a new instance of each element in [arg args] to [arg varname], but only if that element
is not already present.

[call [cmd ldelete] [arg varname] [arg args]]

This command will add a delete all instances of each element in [arg args] from [arg varname].

[call [cmd {dict getnull}] [arg args]]

Operates like [cmd {dict get}], however if the key [arg args] does not exist, it returns an empty
list instead of throwing an error.

[call [cmd {dict print}] [arg dict]]
>

|






>















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[vset VERSION 1.0]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin dicttool n [vset VERSION]]
[keywords dict]
[copyright {2017 Sean Woods <[email protected]>}]
[moddesc   {Extensions to the standard "dict" command}]
[category Utilities]
[titledesc {Dictionary Tools}]
[require Tcl 8.5]
[require dicttool [opt [vset VERSION]]]
[description]
[para]
The [package dicttool] package enhances the standard [emph dict] command with several new
commands. In addition, the package also defines several "creature comfort" list commands as well.
Each command checks to see if a command already exists of the same name before adding itself,
just in case any of these slip into the core.

[list_begin definitions]
[call [cmd ladd] [arg varname] [arg args]]

This command will add a new instance of each element in [arg args] to [arg varname], but only if that element
is not already present.

[call [cmd ldelete] [arg varname] [arg args]]

This command will delete all instances of each element in [arg args] from [arg varname].

[call [cmd {dict getnull}] [arg args]]

Operates like [cmd {dict get}], however if the key [arg args] does not exist, it returns an empty
list instead of throwing an error.

[call [cmd {dict print}] [arg dict]]
68
69
70
71
72
73
74
75
76
  }
}
}]

[list_end]

[vset CATEGORY dict]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

70
71
72
73
74
75
76
77
78
  }
}
}]

[list_end]

[vset CATEGORY dict]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/dicttool/dicttool.md.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#### ladd *varname* *args*

This command will add a new instance of each element in *args* to *varname*,
but only if that element is not already present.

#### ldelete] *varname* *args*

This command will add a delete all instances of each element in *args* from *varname*.

#### dict getnull *args*

Operates like **dict get**, however if the key *args* does not exist, it returns an empty
list instead of throwing an error.

#### dict print *dict*







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#### ladd *varname* *args*

This command will add a new instance of each element in *args* to *varname*,
but only if that element is not already present.

#### ldelete] *varname* *args*

This command will delete all instances of each element in *args* from *varname*.

#### dict getnull *args*

Operates like **dict get**, however if the key *args* does not exist, it returns an empty
list instead of throwing an error.

#### dict print *dict*

Changes to modules/dns/dns.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# dns.tcl - Copyright (C) 2002 Pat Thoyts <[email protected]>
#
# Provide a Tcl only Domain Name Service client. See RFC 1034 and RFC 1035
# for information about the DNS protocol. This should insulate Tcl scripts
# from problems with using the system library resolver for slow name servers.
#
# This implementation uses TCP only for DNS queries. The protocol reccommends
# that UDP be used in these cases but Tcl does not include UDP sockets by
# default. The package should be simple to extend to use a TclUDP extension
# in the future.
#
# Support for SPF (http://spf.pobox.com/rfcs.html) will need updating
# if or when the proposed draft becomes accepted.
#






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
# dns.tcl - Copyright (C) 2002 Pat Thoyts <[email protected]>
#
# Provide a Tcl only Domain Name Service client. See RFC 1034 and RFC 1035
# for information about the DNS protocol. This should insulate Tcl scripts
# from problems with using the system library resolver for slow name servers.
#
# This implementation uses TCP only for DNS queries. The protocol recommends
# that UDP be used in these cases but Tcl does not include UDP sockets by
# default. The package should be simple to extend to use a TclUDP extension
# in the future.
#
# Support for SPF (http://spf.pobox.com/rfcs.html) will need updating
# if or when the proposed draft becomes accepted.
#
282
283
284
285
286
287
288
289
290
291
292
293







294
295
296
297
298
299
300
        if {[llength [package provide ceptcl]] == 0 \
                && [llength [package provide udp]] == 0} {
            return -code error "udp support is not available,\
                get ceptcl or tcludp"
        }
    }

    # Check for reverse lookups
    if {[regexp {^(?:\d{0,3}\.){3}\d{0,3}$} $state(query)]} {
        set addr [lreverse [split $state(query) .]]
        lappend addr in-addr arpa
        set state(query) [join $addr .]







        set state(-type) PTR
    }

    BuildMessage $token
    
    if {$state(-protocol) == "tcp"} {
        TcpTransmit $token







|




>
>
>
>
>
>
>







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
        if {[llength [package provide ceptcl]] == 0 \
                && [llength [package provide udp]] == 0} {
            return -code error "udp support is not available,\
                get ceptcl or tcludp"
        }
    }

    # Check for reverse lookups. IPv4 first, then IPv6.
    if {[regexp {^(?:\d{0,3}\.){3}\d{0,3}$} $state(query)]} {
        set addr [lreverse [split $state(query) .]]
        lappend addr in-addr arpa
        set state(query) [join $addr .]
        set state(-type) PTR
    } elseif {[string match {*:*} $state(query)]} {
        set addr [ip::normalize $state(query)]
        set addr [split [string reverse $addr] :]
        set addr [join [split [join $addr ""] {}] .]
        lappend addr ip6 arpa
        set state(query) [join $addr .]
        set state(-type) PTR
    }

    BuildMessage $token
    
    if {$state(-protocol) == "tcp"} {
        TcpTransmit $token
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
    return "dns:$query"
}

# -------------------------------------------------------------------------

catch {dns::configure -nameserver [lindex [dns::nameservers] 0]}

package provide dns 1.4.0

# -------------------------------------------------------------------------
# Local Variables:
#   indent-tabs-mode: nil
# End:







|





1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
    return "dns:$query"
}

# -------------------------------------------------------------------------

catch {dns::configure -nameserver [lindex [dns::nameservers] 0]}

package provide dns 1.4.1

# -------------------------------------------------------------------------
# Local Variables:
#   indent-tabs-mode: nil
# End:

Changes to modules/dns/dns.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# dns.test - Copyright (C) 2002 Pat Thoyts <[email protected]>
#
# Tests for the Tcllib dns package
#
# -------------------------------------------------------------------------
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# -------------------------------------------------------------------------
# RCS: @(#) $Id: dns.test,v 1.6 2006/10/09 21:41:40 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]









<







1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
# dns.test - Copyright (C) 2002 Pat Thoyts <[email protected]>
#
# Tests for the Tcllib dns package
#
# -------------------------------------------------------------------------
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# -------------------------------------------------------------------------


# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

Changes to modules/dns/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
# pkgIndex.tcl -
#
# $Id: pkgIndex.tcl,v 1.21 2010/08/16 17:35:18 andreas_kupries Exp $

if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded dns    1.4.0 [list source [file join $dir dns.tcl]]
package ifneeded resolv 1.0.3 [list source [file join $dir resolv.tcl]]
package ifneeded ip     1.4   [list source [file join $dir ip.tcl]]
package ifneeded spf    1.1.1 [list source [file join $dir spf.tcl]]

|
<
<

|



1
2


3
4
5
6
7
# pkgIndex.tcl -



if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded dns    1.4.1 [list source [file join $dir dns.tcl]]
package ifneeded resolv 1.0.3 [list source [file join $dir resolv.tcl]]
package ifneeded ip     1.4   [list source [file join $dir ip.tcl]]
package ifneeded spf    1.1.1 [list source [file join $dir spf.tcl]]

Changes to modules/dns/tcllib_dns.man.

1
2
3
4
5
6
7
8
[vset DNS_VERSION 1.4.0]
[manpage_begin dns n [vset DNS_VERSION]]
[see_also resolver(5)]
[keywords DNS]
[keywords {domain name service}]
[keywords resolver]
[keywords {rfc 1034}]
[keywords {rfc 1035}]
|







1
2
3
4
5
6
7
8
[vset DNS_VERSION 1.4.1]
[manpage_begin dns n [vset DNS_VERSION]]
[see_also resolver(5)]
[keywords DNS]
[keywords {domain name service}]
[keywords resolver]
[keywords {rfc 1034}]
[keywords {rfc 1035}]
283
284
285
286
287
288
289
290
291

[list_end]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY dns]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

283
284
285
286
287
288
289
290
291

[list_end]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY dns]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/dns/tcllib_ip.man.

443
444
445
446
447
448
449
450
451

[list_end]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY dns]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

443
444
445
446
447
448
449
450
451

[list_end]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY dns]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/changelog.man.

79
80
81
82
83
84
85
86
87
command merges all of them into a single structure, and collapses
multiple entries for the same date and author into a single entry. The
new structure is returned as the result of the command.

[list_end]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

79
80
81
82
83
84
85
86
87
command merges all of them into a single structure, and collapses
multiple entries for the same date and author into a single entry. The
new structure is returned as the result of the command.

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/checker.tcl.

612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
		}
		set pid $sect($fid)
	    }
	}
    }

    # If we have no text take the section title as text, if we
    # can. Last fallback for thext is the id.
    if {$title == {}} {
	if {$pid != {}} {
	    set title $sectt($fid)
	} else {
	    set title $id
	}
    }







|







612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
		}
		set pid $sect($fid)
	    }
	}
    }

    # If we have no text take the section title as text, if we
    # can. Last fallback for text is the id.
    if {$title == {}} {
	if {$pid != {}} {
	    set title $sectt($fid)
	} else {
	    set title $id
	}
    }

Changes to modules/doctools/cvs.man.

93
94
95
96
97
98
99
100
101
logs. It takes this information and converts it into a text in the
format of a ChangeLog as accepted and generated by [syscmd emacs]. The
constructed text is returned as the result of the command.

[list_end]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

93
94
95
96
97
98
99
100
101
logs. It takes this information and converts it into a text in the
format of a ChangeLog as accepted and generated by [syscmd emacs]. The
constructed text is returned as the result of the command.

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/docidx.man.

402
403
404
405
406
407
408
409
410

This engine generates Wiki markup as understood by Jean Claude
Wippler's [syscmd wikit] application.

[list_end]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

402
403
404
405
406
407
408
409
410

This engine generates Wiki markup as understood by Jean Claude
Wippler's [syscmd wikit] application.

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/docidx_intro.man.

98
99
100
101
102
103
104
105
106
respectively.

They are described in their own sets of documents, starting at the
[term {doctoc introduction}] and the [term {doctools introduction}],
respectively.

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

98
99
100
101
102
103
104
105
106
respectively.

They are described in their own sets of documents, starting at the
[term {doctoc introduction}] and the [term {doctools introduction}],
respectively.

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/docidx_lang_cmdref.man.

108
109
110
111
112
113
114
115
116

Templating. In this form the command is replaced by the value of the
named document variable

[list_end]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

108
109
110
111
112
113
114
115
116

Templating. In this form the command is replaced by the value of the
named document variable

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/docidx_lang_faq.man.

20
21
22
23
24
25
26
27
28

[section OVERVIEW]

[include include/placeholder.inc]
[include include/examples.inc]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

20
21
22
23
24
25
26
27
28

[section OVERVIEW]

[include include/placeholder.inc]
[include include/examples.inc]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/docidx_lang_intro.man.

206
207
208
209
210
211
212
213
214
On the other hand, docidx is perfectly suited for the automatic
generation from doctools documents, and this is the route Tcllib's
easy and simple [syscmd dtplite] goes, creating an index for a set of
documents behind the scenes, without the writer having to do so on
their own.

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

206
207
208
209
210
211
212
213
214
On the other hand, docidx is perfectly suited for the automatic
generation from doctools documents, and this is the route Tcllib's
easy and simple [syscmd dtplite] goes, creating an index for a set of
documents behind the scenes, without the writer having to do so on
their own.

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/docidx_lang_syntax.man.

112
113
114
115
116
117
118
119
120
[enum][cmd rb], or
[enum][cmd vset] (1-argument form).
[list_end]

[list_end]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

112
113
114
115
116
117
118
119
120
[enum][cmd rb], or
[enum][cmd vset] (1-argument form).
[list_end]

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/docidx_plugin_apiref.man.

413
414
415
416
417
418
419
420
421
[para] The formatted text is expected as the result of the command,
and added to the output. If no special processing is required it has
to simply return its argument without change.

[list_end]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

413
414
415
416
417
418
419
420
421
[para] The formatted text is expected as the result of the command,
and added to the output. If no special processing is required it has
to simply return its argument without change.

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/doctoc.man.

402
403
404
405
406
407
408
409
410

This engine generates Wiki markup as understood by Jean Claude
Wippler's [syscmd wikit] application.

[list_end]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

402
403
404
405
406
407
408
409
410

This engine generates Wiki markup as understood by Jean Claude
Wippler's [syscmd wikit] application.

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/doctoc_intro.man.

97
98
99
100
101
102
103
104
105
of [term {keyword indices}], and general documentation, respectively.

They are described in their own sets of documents, starting at the
[term {docidx introduction}] and the [term {doctools introduction}],
respectively.

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

97
98
99
100
101
102
103
104
105
of [term {keyword indices}], and general documentation, respectively.

They are described in their own sets of documents, starting at the
[term {docidx introduction}] and the [term {doctools introduction}],
respectively.

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/doctoc_lang_cmdref.man.

119
120
121
122
123
124
125
126
127

Templating. In this form the command is replaced by the value of the
named document variable

[list_end]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

119
120
121
122
123
124
125
126
127

Templating. In this form the command is replaced by the value of the
named document variable

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/doctoc_lang_faq.man.

20
21
22
23
24
25
26
27
28

[section OVERVIEW]

[include include/placeholder.inc]
[include include/examples.inc]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

20
21
22
23
24
25
26
27
28

[section OVERVIEW]

[include include/placeholder.inc]
[include include/examples.inc]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/doctoc_lang_intro.man.

289
290
291
292
293
294
295
296
297
On the other hand, doctoc is perfectly suited for the automatic
generation from doctools documents, and this is the route Tcllib's
easy and simple [syscmd dtplite] goes, creating a table of contents
for a set of documents behind the scenes, without the writer having to
do so on their own.

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

289
290
291
292
293
294
295
296
297
On the other hand, doctoc is perfectly suited for the automatic
generation from doctools documents, and this is the route Tcllib's
easy and simple [syscmd dtplite] goes, creating a table of contents
for a set of documents behind the scenes, without the writer having to
do so on their own.

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/doctoc_lang_syntax.man.

97
98
99
100
101
102
103
104
105

division  = DIVISION_START
            contents
            DIVISION_END
}]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

97
98
99
100
101
102
103
104
105

division  = DIVISION_START
            contents
            DIVISION_END
}]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/doctoc_plugin_apiref.man.

413
414
415
416
417
418
419
420
421
[para] The formatted text is expected as the result of the command,
and added to the output. If no special processing is required it has
to simply return its argument without change.

[list_end]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

413
414
415
416
417
418
419
420
421
[para] The formatted text is expected as the result of the command,
and added to the output. If no special processing is required it has
to simply return its argument without change.

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/doctools.man.

1
2
3
4
5
6
7
8
9
[comment {-*- tcl -*- doctools manpage}]
[vset PACKAGE_VERSION 1.5.1]
[manpage_begin doctools n [vset PACKAGE_VERSION]]
[see_also doctools_intro]
[see_also doctools_lang_cmdref]
[see_also doctools_lang_intro]
[see_also doctools_lang_syntax]
[see_also doctools_plugin_apiref]
[keywords conversion]

|







1
2
3
4
5
6
7
8
9
[comment {-*- tcl -*- doctools manpage}]
[vset PACKAGE_VERSION 1.5.6]
[manpage_begin doctools n [vset PACKAGE_VERSION]]
[see_also doctools_intro]
[see_also doctools_lang_cmdref]
[see_also doctools_lang_intro]
[see_also doctools_lang_syntax]
[see_also doctools_plugin_apiref]
[keywords conversion]
567
568
569
570
571
572
573
574
575

This engine generates Wiki markup as understood by Jean Claude
Wippler's [syscmd wikit] application.

[list_end]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

567
568
569
570
571
572
573
574
575

This engine generates Wiki markup as understood by Jean Claude
Wippler's [syscmd wikit] application.

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/doctools.tcl.

1354
1355
1356
1357
1358
1359
1360
1361
    # => FOO/mpformats

    #catch {search [file join $here                lib doctools mpformats]}
    #catch {search [file join [file dirname $here] lib doctools mpformats]}
    catch {search [file join $here                             mpformats]}
}

package provide doctools 1.5.1







|
1354
1355
1356
1357
1358
1359
1360
1361
    # => FOO/mpformats

    #catch {search [file join $here                lib doctools mpformats]}
    #catch {search [file join [file dirname $here] lib doctools mpformats]}
    catch {search [file join $here                             mpformats]}
}

package provide doctools 1.5.6

Changes to modules/doctools/doctools_intro.man.

95
96
97
98
99
100
101
102
103
respectively.

They are described in their own sets of documents, starting at the
[term {docidx introduction}] and the [term {doctoc introduction}],
respectively.

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

95
96
97
98
99
100
101
102
103
respectively.

They are described in their own sets of documents, starting at the
[term {docidx introduction}] and the [term {doctoc introduction}],
respectively.

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/doctools_lang_cmdref.man.

462
463
464
465
466
467
468
469
470
Text markup. The argument is marked up as the name of a
[term widget]. The text may have other markup already applied to
it. Main use is the highlighting of widget names in free-form text.

[list_end]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

462
463
464
465
466
467
468
469
470
Text markup. The argument is marked up as the name of a
[term widget]. The text may have other markup already applied to
it. Main use is the highlighting of widget names in free-form text.

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/doctools_lang_faq.man.

20
21
22
23
24
25
26
27
28

[section OVERVIEW]

[include include/placeholder.inc]
[include include/examples.inc]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

20
21
22
23
24
25
26
27
28

[section OVERVIEW]

[include include/placeholder.inc]
[include include/examples.inc]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/doctools_lang_intro.man.

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
[keywords {doctools language}]
[keywords {doctools markup}]
[keywords {doctools syntax}]
[keywords markup]
[keywords {semantic markup}]
    [description]
    [vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]
}]

This also shows us that all doctools documents are split into two
parts, the [term header] and the [term body]. Everything coming before
[lb][cmd description][rb] belongs to the header, and everything coming
after belongs to the body, with the whole document bracketed by the







|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
[keywords {doctools language}]
[keywords {doctools markup}]
[keywords {doctools syntax}]
[keywords markup]
[keywords {semantic markup}]
    [description]
    [vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]
}]

This also shows us that all doctools documents are split into two
parts, the [term header] and the [term body]. Everything coming before
[lb][cmd description][rb] belongs to the header, and everything coming
after belongs to the body, with the whole document bracketed by the
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
Remember that the whitespace is optional. The document

[example {
    [manpage_begin NAME SECTION VERSION]
    [copyright {YEAR AUTHOR}][titledesc TITLE][moddesc MODULE_TITLE]
    [require PACKAGE VERSION][require PACKAGE][description]
    [vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]
}]

has the same meaning as the example before.

[para]








|







132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
Remember that the whitespace is optional. The document

[example {
    [manpage_begin NAME SECTION VERSION]
    [copyright {YEAR AUTHOR}][titledesc TITLE][moddesc MODULE_TITLE]
    [require PACKAGE VERSION][require PACKAGE][description]
    [vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]
}]

has the same meaning as the example before.

[para]

609
610
611
612
613
614
615
616
617
To be able to validate a document while writing it, it is also
recommended to familiarize oneself with one of the applications for
the processing and conversion of doctools documents, i.e. either
Tcllib's easy and simple [syscmd dtplite], or Tclapps'
ultra-configurable [syscmd dtp].

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

609
610
611
612
613
614
615
616
617
To be able to validate a document while writing it, it is also
recommended to familiarize oneself with one of the applications for
the processing and conversion of doctools documents, i.e. either
Tcllib's easy and simple [syscmd dtplite], or Tclapps'
ultra-configurable [syscmd dtp].

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/doctools_lang_syntax.man.

134
135
136
137
138
139
140
141
142
enum_list   = [ <WHITE> ] { ENUM         paras }
item_list   = [ <WHITE> ] { ITEM         paras }
optd_list   = [ <WHITE> ] { OPT_DEF      paras }
tkoptd_list = [ <WHITE> ] { TKOPTION_DEF paras }
}]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

134
135
136
137
138
139
140
141
142
enum_list   = [ <WHITE> ] { ENUM         paras }
item_list   = [ <WHITE> ] { ITEM         paras }
optd_list   = [ <WHITE> ] { OPT_DEF      paras }
tkoptd_list = [ <WHITE> ] { TKOPTION_DEF paras }
}]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/doctools_plugin_apiref.man.

470
471
472
473
474
475
476
477
478
[para] The formatted text is expected as the result of the command,
and added to the output. If no special processing is required it has
to simply return its argument without change.

[list_end]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

470
471
472
473
474
475
476
477
478
[para] The formatted text is expected as the result of the command,
and added to the output. If no special processing is required it has
to simply return its argument without change.

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/mpexpand.man.

99
100
101
102
103
104
105
106
107

[section NOTES]
[para]

Possible future formats are plain text, pdf and postscript.

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

99
100
101
102
103
104
105
106
107

[section NOTES]
[para]

Possible future formats are plain text, pdf and postscript.

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools/mpformats/_markdown.tcl.

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

proc Sub4Title {lb title} {
    upvar 1 $lb lines
    lappend lines "[Hash][Hash][Hash][Hash] $title"
    return
}

proc Strong {text} { return [Undr][Undr]${text}[Undr][Undr] }
proc Em     {text} { return [Star]${text}[Star] }

##
# # ## ### ##### ########
##

set __comments 0








|
|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

proc Sub4Title {lb title} {
    upvar 1 $lb lines
    lappend lines "[Hash][Hash][Hash][Hash] $title"
    return
}

proc _Strong {text} { return [Undr][Undr]${text}[Undr][Undr] }
proc _Em     {text} { return [Star]${text}[Star] }

##
# # ## ### ##### ########
##

set __comments 0

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# Modified bulleting

DIB [list [Dash] [Star] [Plus]]
DEB [list "1[Dot]" "1[CPar]"]

proc Unmark {x} {
    lappend map "\1\n" "  \n"
    # Marked special characters are commands. Covnert into regular
    # form. Unmarked special characters need quoting.
    lappend map \1\\ \\
    lappend map \1`  `
    lappend map \1*  *
    lappend map \1_  _
    lappend map \1#  "#"
    lappend map \1+  +







|







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# Modified bulleting

DIB [list [Dash] [Star] [Plus]]
DEB [list "1[Dot]" "1[CPar]"]

proc Unmark {x} {
    lappend map "\1\n" "  \n"
    # Marked special characters are commands. Convert into regular
    # form. Unmarked special characters need quoting.
    lappend map \1\\ \\
    lappend map \1`  `
    lappend map \1*  *
    lappend map \1_  _
    lappend map \1#  "#"
    lappend map \1+  +

Changes to modules/doctools/mpformats/_text.tcl.

117
118
119
120
121
122
123



124
125

























126
127
128
129
130
131
132
    upvar 1 $lb lines
    #lappend lines ""
    lappend lines $title
    lappend lines [RepeatM - $title]
    return
}




proc Strong {text} { return *${text}* }
proc Em     {text} { return _${text}_ }


























# # ## ### ##### ########
## Bulleting
#
# itembullet  = index of the bullet to use in the next itemized list
# enumbullet  = index of the bullet to use in the next enumerated list








>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    upvar 1 $lb lines
    #lappend lines ""
    lappend lines $title
    lappend lines [RepeatM - $title]
    return
}

proc Strong {text} { SplitLine $text _Strong }
proc Em     {text} { SplitLine $text _Em }

proc _Strong {text} { return *${text}* }
proc _Em     {text} { return _${text}_ }

proc SplitLine {text cmd} {
    #puts_stderr AAA/SLI=[string map [list \1 \\1 \t \\t { } \\s] <<[join [split $text \n] >>\n<<]>>]
    if {![string match *\n* $text]} {
	foreach {lead content} [LeadSplit $text] break
	return ${lead}[uplevel 1 [list $cmd $content]]
    }
    set r {}   
    foreach line [split $text \n] {
	foreach {lead content} [LeadSplit $line] break
	if {$content == {}} {
	    lappend r {}
	    continue
	}
	lappend r ${lead}[uplevel 1 [list $cmd $content]]
    }
    set text [string trimright [join $r \n]]\n
    #puts_stderr AAA/SLE=[string map [list \1 \\1 \t \\t { } \\s] <<[join [split $text \n] >>\n<<]>>]
    return $text
}

proc LeadSplit {line} {
    regexp {^([ \t]*)(.*)([ \t]*)$} $line -> lead content _
    list $lead $content
}

# # ## ### ##### ########
## Bulleting
#
# itembullet  = index of the bullet to use in the next itemized list
# enumbullet  = index of the bullet to use in the next enumerated list

Changes to modules/doctools/mpformats/_text_para.tcl.

20
21
22
23
24
25
26
27







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46


47
48
49
50
51
52
53
    return
}
proc Text?     {} { global __currentp ; return $__currentp }
proc TextClear {} { global __currentp ; set __currentp "" }

proc TextTrimLeadingSpace {} {
    global __currentp
    regsub {^([ \t\v\f]*\n)*} $__currentp {} __currentp







    return
}

proc TextPlain {text} {
    #puts_stderr "<<text_plain_text>>"

    if  {[IsOff]} {return}

    # Note: Whenever we get plain text it is possible that a macro for
    # visual markup actually generated output before the expander got
    # to the current text. This output was captured by the expander in
    # its current context. Given the current organization of the
    # engine we have to retrieve this formatted text from the expander
    # or it will be lost. This is the purpose of the 'ctopandclear',
    # which retrieves the data and also clears the capture buffer. The
    # latter to prevent us from retrieving it again later, after the
    # next macro added more data.

    set text [ex_ctopandclear]$text



    # ... TODO ... Handling of example => verbatim

    if {[string length [string trim $text]] == 0} return

    Text $text
    return







|
>
>
>
>
>
>
>




<
<













>
>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
    return
}
proc Text?     {} { global __currentp ; return $__currentp }
proc TextClear {} { global __currentp ; set __currentp "" }

proc TextTrimLeadingSpace {} {
    global __currentp
    regsub {^([ \t\v\f]*\x01?\n)*} $__currentp {} __currentp
    return
}

proc TextTrimTrailingSpace {} {
    global __currentp
    regsub {([ \t\v\f]*\x01?\n)*$} $__currentp {} __currentp
    append __currentp \n
    return
}

proc TextPlain {text} {


    if  {[IsOff]} {return}

    # Note: Whenever we get plain text it is possible that a macro for
    # visual markup actually generated output before the expander got
    # to the current text. This output was captured by the expander in
    # its current context. Given the current organization of the
    # engine we have to retrieve this formatted text from the expander
    # or it will be lost. This is the purpose of the 'ctopandclear',
    # which retrieves the data and also clears the capture buffer. The
    # latter to prevent us from retrieving it again later, after the
    # next macro added more data.

    set text [ex_ctopandclear]$text

    #puts_stderr "<<text_plain_text>>=<<[string map [list \t \\t { } \\s \n \\n \r \\r \v \\v \f \\f \1 \\1] $text]>>"

    # ... TODO ... Handling of example => verbatim

    if {[string length [string trim $text]] == 0} return

    Text $text
    return

Changes to modules/doctools/mpformats/fmt.html.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16



17
18
19
20
21
22
23
# -*- tcl -*-
#
# fmt.html
#
# Copyright (c) 2001-2008 Andreas Kupries <[email protected]>
#
# Definitions to convert a tcl based manpage definition into
# a manpage based upon HTML markup.
#
################################################################
################################################################

dt_source _common.tcl   ; # Shared code
dt_source _html.tcl     ; # HTML basic formatting
dt_source _xref.tcl     ; # xref management




proc c_copyrightsymbol {} {return "[markup "&"]copy;"}

proc bgcolor {} {return ""}
proc border  {} {return 0}
proc Year    {} {clock format [clock seconds] -format %Y}

c_holdBuffers require synopsis




|











>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# -*- tcl -*-
#
# fmt.html
#
# Copyright (c) 2001-2019 Andreas Kupries <[email protected]>
#
# Definitions to convert a tcl based manpage definition into
# a manpage based upon HTML markup.
#
################################################################
################################################################

dt_source _common.tcl   ; # Shared code
dt_source _html.tcl     ; # HTML basic formatting
dt_source _xref.tcl     ; # xref management

global _in_example
set    _in_example 0

proc c_copyrightsymbol {} {return "[markup "&"]copy;"}

proc bgcolor {} {return ""}
proc border  {} {return 0}
proc Year    {} {clock format [clock seconds] -format %Y}

c_holdBuffers require synopsis
45
46
47
48
49
50
51




52
53
54
55
56
57
58
    set liststack [lreplace $liststack end end]
    foreach {t l} $t break
    litc_set $l
    return $t
}

proc fmt_plain_text {text} {




    return $text
}

################################################################
# Formatting commands.

c_pass 1 fmt_manpage_begin {title section version} {c_cinit ; c_clrSections ; return}







>
>
>
>







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    set liststack [lreplace $liststack end end]
    foreach {t l} $t break
    litc_set $l
    return $t
}

proc fmt_plain_text {text} {
    global _in_example
    if {$_in_example} {
	set text [string map [list \\\\\n \\\n] $text]
    }
    return $text
}

################################################################
# Formatting commands.

c_pass 1 fmt_manpage_begin {title section version} {c_cinit ; c_clrSections ; return}
348
349
350
351
352
353
354

355
356
357

358
359
360
361
362
363
364
    append text "Database Class:\t[bold $dbclass optdbclass][tag br]\n"
    fmt_lst_item $text
}

################################################################

proc fmt_example_begin {} {

	return [para_close]\n[tag* pre class doctools_example]
}
proc fmt_example_end   {} {

    return [tag/ pre]\n[para_open]
}
proc fmt_example {code} {
    return "[fmt_example_begin][fmt_plain_text $code][fmt_example_end]"
}

################################################################







>
|


>







355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
    append text "Database Class:\t[bold $dbclass optdbclass][tag br]\n"
    fmt_lst_item $text
}

################################################################

proc fmt_example_begin {} {
    global _in_example ; set _in_example 1
    return [para_close]\n[tag* pre class doctools_example]
}
proc fmt_example_end   {} {
    global _in_example ; set _in_example 0
    return [tag/ pre]\n[para_open]
}
proc fmt_example {code} {
    return "[fmt_example_begin][fmt_plain_text $code][fmt_example_end]"
}

################################################################

Changes to modules/doctools/mpformats/fmt.latex.

15
16
17
18
19
20
21



22
23
24
25



26
27
28
29
30
31
32

global _in_example
set    _in_example 0

global _has_images
set    _has_images 0




# Called to handle plain text from the input
proc fmt_plain_text {text} {
    global _in_example
    if {$_in_example} {



	return $text
    }
    return [texEscape $text]
}

proc Year {} {clock format [clock seconds] -format %Y}








>
>
>



|
>
>
>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

global _in_example
set    _in_example 0

global _has_images
set    _has_images 0

global _has_examples
set    _has_examples 0

# Called to handle plain text from the input
proc fmt_plain_text {text} {
    global _in_example
    if {$_in_example} {	
	lappend map \\\\\n \1\\textbackslash\n
	lappend map \\\n   \1\\textbackslash\n	
	set text [string map $map $text]
	return $text
    }
    return [texEscape $text]
}

proc Year {} {clock format [clock seconds] -format %Y}

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74



75
76
77
78
79
80
81
}

################################################################
## Backend for LaTeX markup

c_pass 1 fmt_manpage_begin {title section version} NOP
c_pass 2 fmt_manpage_begin {title section version} {
    global _has_images

    set module      [dt_module]
    set shortdesc   [c_get_module]
    set description [c_get_title]
    set copyright   [c_get_copyright]

    set     hdr ""
    append  hdr [Comment [c_provenance]] \n
    if {$copyright != {}} {
	append  hdr [Comment $copyright] \n
    }
    append  hdr [Comment "$title.$section"] \n
    append  hdr \n
    append  hdr "\1\\documentclass\{article\}" \n

    if {$_has_images} {
	append hdr "\1\\usepackage{epsfig}" \n
	append hdr "\1\\usepackage{epstopdf}" \n
    }




    append  hdr "\1\\begin\{document\}" \n
    append  hdr "\1\\author\{[dt_user]\}" \n

    set    titletext ""
    append titletext "$module / $title -- "
    append titletext "$shortdesc : $description"







|



















>
>
>







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
}

################################################################
## Backend for LaTeX markup

c_pass 1 fmt_manpage_begin {title section version} NOP
c_pass 2 fmt_manpage_begin {title section version} {
    global _has_images _has_examples

    set module      [dt_module]
    set shortdesc   [c_get_module]
    set description [c_get_title]
    set copyright   [c_get_copyright]

    set     hdr ""
    append  hdr [Comment [c_provenance]] \n
    if {$copyright != {}} {
	append  hdr [Comment $copyright] \n
    }
    append  hdr [Comment "$title.$section"] \n
    append  hdr \n
    append  hdr "\1\\documentclass\{article\}" \n

    if {$_has_images} {
	append hdr "\1\\usepackage{epsfig}" \n
	append hdr "\1\\usepackage{epstopdf}" \n
    }
    if {$_has_examples} {
	append hdr "\1\\usepackage{alltt}" \n
    }

    append  hdr "\1\\begin\{document\}" \n
    append  hdr "\1\\author\{[dt_user]\}" \n

    set    titletext ""
    append titletext "$module / $title -- "
    append titletext "$shortdesc : $description"
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
    append text "Database Class:	[Bold $dbclass]\\\\\n"
    return "\n%\n\1\\item\[\] $text\n%\n"
}

################################################################

proc fmt_example_begin {} {
    global _in_example

    set    _in_example 1
    return {\begin{verbatim}}
}
proc fmt_example_end   {} {
    global _in_example
    set    _in_example 0
    return {\end{verbatim}}
}
# No mapping of special characters
proc fmt_example {code} { return "\1\\begin\{verbatim\}\n${code}\n\1\\end\{verbatim\}\n" }



proc fmt_arg    {text} {Underline $text}
proc fmt_cmd    {text} {Bold      $text}
proc fmt_emph   {text} {Italic    $text}
proc fmt_opt    {text} {return   ?$text?}

proc fmt_comment {text} {







|
>

|




|


|
>
>







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
    append text "Database Class:	[Bold $dbclass]\\\\\n"
    return "\n%\n\1\\item\[\] $text\n%\n"
}

################################################################

proc fmt_example_begin {} {
    global _has_examples _in_example
    set _has_examples 1
    set    _in_example 1
    return "\1\\begin{alltt}\n"
}
proc fmt_example_end   {} {
    global _in_example
    set    _in_example 0
    return "\1\\end{alltt}\n"
}
# No mapping of special characters
proc fmt_example {code} {
    return [fmt_example_begin][fmt_plain_text $code][fmt_example_end]
}

proc fmt_arg    {text} {Underline $text}
proc fmt_cmd    {text} {Bold      $text}
proc fmt_emph   {text} {Italic    $text}
proc fmt_opt    {text} {return   ?$text?}

proc fmt_comment {text} {

Changes to modules/doctools/mpformats/fmt.markdown.

1
2
3
4
5
6
7
8
9












10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31











32
33
34








35
36
37
38
39
40
41
# -*- tcl -*-
# Convert a doctools document into markdown formatted text
#
# Copyright (c) 2019 Andreas Kupries <[email protected]>

# Note: While markdown is a text format its intended target is HTML,
# making its formatting nearer to that with the ability to set anchors
# and refer to them, linkage in general.













# # ## ### ##### ######## #############
## Load shared code and modify it to our needs.

dt_source _common.tcl
dt_source _text.tcl
dt_source fmt.text
dt_source _markdown.tcl
dt_source _xref.tcl

# # ## ### ##### ########
## Override crucial parts of the regular text formatter

proc In? {} {
    if {![CAttrHas mdindent]} {
	CAttrSet mdindent ""
    }
    CAttrGet mdindent
}

proc In! {ws} {
    CAttrSet mdindent $ws
}












proc NewExample {} {
    return [ContextNew Example {
	VerbatimOn ; Example! ; Prefix+ "    "








    }] ; # {}
}

proc NewUnorderedList {} {
    # Itemized list - unordered list - bullet
    # 1. Base context provides indentation.
    # 2. First paragraph in a list item.









>
>
>
>
>
>
>
>
>
>
>
>


















>




>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# -*- tcl -*-
# Convert a doctools document into markdown formatted text
#
# Copyright (c) 2019 Andreas Kupries <[email protected]>

# Note: While markdown is a text format its intended target is HTML,
# making its formatting nearer to that with the ability to set anchors
# and refer to them, linkage in general.

# Notes, Attention
# - A number of characters are special to markdown. Such characters in
#   user input are \-quoted to make them non-special to the markdown
#   processor handling our generated document.
#
# - Exceptions are the special characters in verbatim code-blocks
#   (indent 4), and in `...` sequences (verbatim inline). In such
#   blocks they are not special and must not be quoted.
#
#   The generator currently only used verbatim blocks, for doctools
#   examples. It does not use verbatim inlines.

# # ## ### ##### ######## #############
## Load shared code and modify it to our needs.

dt_source _common.tcl
dt_source _text.tcl
dt_source fmt.text
dt_source _markdown.tcl
dt_source _xref.tcl

# # ## ### ##### ########
## Override crucial parts of the regular text formatter

proc In? {} {
    if {![CAttrHas mdindent]} {
	CAttrSet mdindent ""
    }
    CAttrGet mdindent
}

proc In! {ws} {
    CAttrSet mdindent $ws
}

proc Example {complex} {
    if {![CAttrHas exenv$complex]} {
	ContextPush
	set exenv [NewExample $complex]
	ContextPop
	CAttrSet exenv$complex $exenv
	ContextCommit
    }
    return [CAttrGet exenv$complex]
}

proc NewExample {complex} {
    return [ContextNew Example$complex {
	VerbatimOn
	Example!
	if {$complex} {
	    # Block quote
	    Prefix+ "> "
	} else {
	    # Code block
	    Prefix+ "    "
	}
    }] ; # {}
}

proc NewUnorderedList {} {
    # Itemized list - unordered list - bullet
    # 1. Base context provides indentation.
    # 2. First paragraph in a list item.
262
263
264
265
266
267
268
269








270
271
272
273
274
275
276
    set shortdesc   [c_get_module]
    set description [c_get_title]
    set copyright   [c_get_copyright]
    set pagetitle   "$title - $shortdesc"

    MDComment  "$title - $shortdesc"
    MDComment  [c_provenance]
    if {$copyright != {}} { MDComment $copyright }








    MDComment  "[string trimleft $title :]($section) $version $module \"$shortdesc\""
    MDCDone

    Text [GetT header @TITLE@ $pagetitle]
    CloseParagraph

    Section NAME







|
>
>
>
>
>
>
>
>







294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
    set shortdesc   [c_get_module]
    set description [c_get_title]
    set copyright   [c_get_copyright]
    set pagetitle   "$title - $shortdesc"

    MDComment  "$title - $shortdesc"
    MDComment  [c_provenance]
    if {$copyright != {}} {
	# Note, multiple copyright clauses => multiple lines, comments
	# are single-line => split for generation, strip MD markup for
	# linebreaks, will be re-added when committing the complete
	# comment block.
	foreach line [split $copyright \n] {
	    MDComment [string trimright $line " \t\1"]
	}
    }
    MDComment  "[string trimleft $title :]($section) $version $module \"$shortdesc\""
    MDCDone

    Text [GetT header @TITLE@ $pagetitle]
    CloseParagraph

    Section NAME
330
331
332
333
334
335
336
337
338







































































339
340
341
342
343
344
345
    set kw [c_xref_keywords]
    set ca [c_xref_category]
    set ct [c_get_copyright]

    CloseParagraph
    if {[llength $sa]} { Special {SEE ALSO} seealso   [join [XrefList [lsort $sa] sa] ", "] }
    if {[llength $kw]} { Special KEYWORDS   keywords  [join [XrefList [lsort $kw] kw] ", "] }
    if {$ca ne ""}     { Special CATEGORY   category  $ca                     }
    if {$ct != {}}     { Special COPYRIGHT  copyright $ct [Verbatim]          }







































































    return
}

proc c_get_copyright {} {
    return [join [c_get_copyright_r] [LB]]
}








|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    set kw [c_xref_keywords]
    set ca [c_xref_category]
    set ct [c_get_copyright]

    CloseParagraph
    if {[llength $sa]} { Special {SEE ALSO} seealso   [join [XrefList [lsort $sa] sa] ", "] }
    if {[llength $kw]} { Special KEYWORDS   keywords  [join [XrefList [lsort $kw] kw] ", "] }
    if {$ca ne ""}     { Special CATEGORY   category  $ca            }
    if {$ct != {}}     { Special COPYRIGHT  copyright $ct [Verbatim] }
    return
}

proc Breaks {lines} {
    set r {}
    foreach line $lines { lappend r $line[LB] }
    return $r
}

proc LeadSpaces {lines} {
    set r {}
    foreach line $lines { lappend r [LeadSpace $line] }
    return $r
}

proc LeadSpace {line} {
    # Split into leading and trailing whitespace, plus content
    regexp {^([ \t]*)(.*)([ \t]*)$} $line -> lead content _
    # Drop trailing spaces, make leading non-breaking, keep content (and inner spaces).
    return [RepeatM "&nbsp;" $lead]$content
}

c_pass 2 fmt_example_end {} {
    #puts_stderr "AAA/fmt_example_end"
    # Flush markup from preceding commands into the text buffer.
    TextPlain ""

    TextTrimLeadingSpace

    # Check for protected markdown markup in the input. If present
    # this is a complex example with highlighted parts.
    set complex [string match *\1* [Text?]]

    #puts_stderr "AAA/fmt_example_end/$complex"
    
    # In examples (verbatim markup) markdown's special characters are
    # no such by default, thus must not be quoted. Mark them as
    # protected from quoting. Further look for and convert
    # continuation lines protected from Tcl substitution into a
    # regular continuation line.
    set t [Text?]
    set t [string map [list \\\\\n \\\n] $t]
    if {$complex} {
	# Process for block quote
	# - make leading spaces non-breaking
	# - force linebreaks
	set t [join [Breaks [LeadSpaces [split $t \n]]] {}]
    } else {
	# Process for code block (verbatim)
	set t [Mark $t]
    }
    TextClear
    Text $t
    TextTrimTrailingSpace
    
    set penv [GetCurrent]
    if {$penv != {}} {
	# In a list we save the current list context, activate the
	# proper paragraph context and create its example
	# variant. After closing the paragraph using the example we
	# restore and reactivate the list context.
	ContextPush
	ContextSet $penv
	CloseParagraph [Example $complex]
	ContextPop
    } else {
	# In a regular paragraph we simple close the example
	CloseParagraph [Example $complex]
    }

    #puts_stderr "AAA/fmt_example_end/Done"
    return
}

proc c_get_copyright {} {
    return [join [c_get_copyright_r] [LB]]
}

Changes to modules/doctools/mpformats/fmt.nroff.

11
12
13
14
15
16
17



18
19









20
21
22
23
24
25
26

################################################################
# Load shared code, load nroff support.

dt_source _common.tcl
dt_source _nroff.tcl




################################################################
# Define the API commands.










c_pass 1 fmt_manpage_begin {title section version} c_begin
c_pass 2 fmt_manpage_begin {title section version} {
    c_begin

    set module      [dt_module]
    set shortdesc   [c_get_module]







>
>
>


>
>
>
>
>
>
>
>
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

################################################################
# Load shared code, load nroff support.

dt_source _common.tcl
dt_source _nroff.tcl

global _in_example
set    _in_example 0

################################################################
# Define the API commands.

# Called to handle plain text from the input
proc fmt_plain_text {text} {
    global _in_example
    if {$_in_example} {
	set text [string map [list \\\\\n \\\n] $text]
    }
    return $text
}

c_pass 1 fmt_manpage_begin {title section version} c_begin
c_pass 2 fmt_manpage_begin {title section version} {
    c_begin

    set module      [dt_module]
    set shortdesc   [c_get_module]
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
    append text "[nr_item]\n"
    return $text
}

################################################################

proc fmt_example_begin {} {

    return [nr_cs]\n
}
proc fmt_example_end   {} {

    if {[dt_lnesting]} {
	return [nr_ce][nr_item]
    }
    nr_ce
}
proc fmt_example {code} { 

    set lines [list "" [nr_cs]]
    foreach line [split $code "\n"] {
    	lappend lines [fmt_plain_text $line]
    }
    lappend lines [nr_ce] ""

    return [join $lines "\n"]
}

proc fmt_nl     {}     {nr_vspace}
proc fmt_arg    {text} {underline $text}
proc fmt_cmd    {text} {bold      $text}
proc fmt_emph   {text} {underline $text}







>



>





|
>





>







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
    append text "[nr_item]\n"
    return $text
}

################################################################

proc fmt_example_begin {} {
    global _in_example ; set _in_example 1
    return [nr_cs]\n
}
proc fmt_example_end   {} {
    global _in_example ; set _in_example 0
    if {[dt_lnesting]} {
	return [nr_ce][nr_item]
    }
    nr_ce
}
proc fmt_example {code} {
    global _in_example ; set _in_example 1
    set lines [list "" [nr_cs]]
    foreach line [split $code "\n"] {
    	lappend lines [fmt_plain_text $line]
    }
    lappend lines [nr_ce] ""
    set _in_example 0
    return [join $lines "\n"]
}

proc fmt_nl     {}     {nr_vspace}
proc fmt_arg    {text} {underline $text}
proc fmt_cmd    {text} {bold      $text}
proc fmt_emph   {text} {underline $text}

Changes to modules/doctools/mpformats/fmt.text.

461
462
463
464
465
466
467





468








469
470
471
472
473
474
475
    #puts_stderr "AAA/fmt_example_begin/Done"
    return
}

c_pass 1 fmt_example_end {} NOP
c_pass 2 fmt_example_end {} {
    #puts_stderr "AAA/fmt_example_end"





    TextTrimLeadingSpace








    
    set penv [GetCurrent]
    if {$penv != {}} {
	# In a list we save the current list context, activate the
	# proper paragraph context and create its example
	# variant. After closing the paragraph using the example we
	# restore and reactivate the list context.







>
>
>
>
>

>
>
>
>
>
>
>
>







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
    #puts_stderr "AAA/fmt_example_begin/Done"
    return
}

c_pass 1 fmt_example_end {} NOP
c_pass 2 fmt_example_end {} {
    #puts_stderr "AAA/fmt_example_end"
    #puts_stderr AAA/EIN=[string map [list \1 \\1 \t \\t { } \\s] <<[join [split [Text?] \n] >>\n<<]>>]

    # Flush markup from preceding commands into the text buffer.
    TextPlain ""
    
    TextTrimLeadingSpace

    # Look for and convert continuation lines protected from Tcl
    # substitution into a regular continuation line.
    set t [string map [list \\\\\n \\\n] [Text?]]
    TextClear
    Text $t

    #puts_stderr AAA/EFT=[string map [list \1\\1 \t \\t { } \\s] <<[join [split [Text?] \n] >>\n<<]>>]
    
    set penv [GetCurrent]
    if {$penv != {}} {
	# In a list we save the current list context, activate the
	# proper paragraph context and create its example
	# variant. After closing the paragraph using the example we
	# restore and reactivate the list context.

Changes to modules/doctools/mpformats/fmt.tmml.

36
37
38
39
40
41
42
43



44





45












46
47
48
49
50
51
52
proc fmt_cmd	{text}	{ wrap $text cmd }
proc fmt_emph	{text}	{ wrap $text emph }
proc fmt_opt 	{text}	{ wrap $text o }

c_pass 1 fmt_example_begin {}	NOP
c_pass 1 fmt_example_end {} 	NOP
c_pass 1 fmt_example {code}	NOP
c_pass 2 fmt_example_begin {}	{ sequence [xmlContext $::block] [start example] }



c_pass 2 fmt_example_end   {}	{ end example }





c_pass 2 fmt_example {code} 	{ sequence [xmlContext $::block] [wrap $code example] }













proc fmt_comment {text} {xmlComment $text}
proc fmt_sectref {text {id {}}} {
    global SectionNames
    if {$id == {}} {
	set id [c_sectionId $text]
    }







|
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
proc fmt_cmd	{text}	{ wrap $text cmd }
proc fmt_emph	{text}	{ wrap $text emph }
proc fmt_opt 	{text}	{ wrap $text o }

c_pass 1 fmt_example_begin {}	NOP
c_pass 1 fmt_example_end {} 	NOP
c_pass 1 fmt_example {code}	NOP
c_pass 2 fmt_example_begin {}	{
    global inexample ; set inexample 1
    sequence [xmlContext $::block] [start example]
}
c_pass 2 fmt_example_end   {}	{
    global inexample ; set inexample 0
    end example
}
c_pass 2 fmt_example {code} {
    set code [string map [list \\\\\n \\\n] $code]
    sequence [xmlContext $::block] [wrap $code example]
}

global inexample
set    inexample 0

proc fmt_plain_text {text} {
    global inexample
    if {$inexample} {
	set text [string map [list \\\\\n \\\n] $text]
    }
    return $text
}

proc fmt_comment {text} {xmlComment $text}
proc fmt_sectref {text {id {}}} {
    global SectionNames
    if {$id == {}} {
	set id [c_sectionId $text]
    }

Changes to modules/doctools/mpformats/fmt.wiki.

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
    return $text
}

################################################################

global textmode
set    textmode ""









proc fmt_example_begin {} {
    global  mode_save textmode
    lappend mode_save $textmode
    set     textmode example
    return "\n======\n"
}
proc fmt_example_end   {} {
    global  mode_save textmode
    set textmode  [lindex $mode_save end]
    set mode_save [lrange $mode_save 0 end-1]
    return "\n======\n"
}
proc fmt_example {code} {

    return "$code"
}

proc emph    {text} {return ''$text''}
proc strong  {text} {return '''$text'''}

proc fmt_arg     {text} {return ''$text''}
proc fmt_cmd     {text} {return '''$text'''}







>
>
>
>
>
>
>
>














>
|







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
    return $text
}

################################################################

global textmode
set    textmode ""

# NOTE: The example_begin/end combo allows for the example
# text to contain markup. The currently used verbatim
# environment will cause show the wiki markup of the example,
# instead of formatting per that markup.
#
# TODO: Strip internal markup from the example text, wiki cannot
# handle such at all.

proc fmt_example_begin {} {
    global  mode_save textmode
    lappend mode_save $textmode
    set     textmode example
    return "\n======\n"
}
proc fmt_example_end   {} {
    global  mode_save textmode
    set textmode  [lindex $mode_save end]
    set mode_save [lrange $mode_save 0 end-1]
    return "\n======\n"
}
proc fmt_example {code} {
    set code [string map [list \\\\\n \\\n] $code]
    return "\n======\n$code\n======\n"
}

proc emph    {text} {return ''$text''}
proc strong  {text} {return '''$text'''}

proc fmt_arg     {text} {return ''$text''}
proc fmt_cmd     {text} {return '''$text'''}
281
282
283
284
285
286
287

288
289
290
291
292
293
294
295
    # For the wiki we have to force certain text into a single line.
    # We also have to make sure that the text is on the same line as
    # the initiator (i.e. list bullet).

    global textmode

    if {"$textmode" == "example"} {

	return "$text"
    }

    regsub -all "\[ \t\n\]+" $text { } text
    return $text
}

################################################################







>








290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
    # For the wiki we have to force certain text into a single line.
    # We also have to make sure that the text is on the same line as
    # the initiator (i.e. list bullet).

    global textmode

    if {"$textmode" == "example"} {
	set text [string map [list \\\\\n \\\n] $text]
	return "$text"
    }

    regsub -all "\[ \t\n\]+" $text { } text
    return $text
}

################################################################

Changes to modules/doctools/pkgIndex.tcl.

1
2
3
4
5
6
if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded doctools            1.5.1 [list source [file join $dir doctools.tcl]]
package ifneeded doctools::toc       1.2   [list source [file join $dir doctoc.tcl]]
package ifneeded doctools::idx       1.1   [list source [file join $dir docidx.tcl]]
package ifneeded doctools::cvs       1     [list source [file join $dir cvs.tcl]]
package ifneeded doctools::changelog 1.1   [list source [file join $dir changelog.tcl]]

|




1
2
3
4
5
6
if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded doctools            1.5.6 [list source [file join $dir doctools.tcl]]
package ifneeded doctools::toc       1.2   [list source [file join $dir doctoc.tcl]]
package ifneeded doctools::idx       1.1   [list source [file join $dir docidx.tcl]]
package ifneeded doctools::cvs       1     [list source [file join $dir cvs.tcl]]
package ifneeded doctools::changelog 1.1   [list source [file join $dir changelog.tcl]]

Added modules/doctools/tests/fmt/desc/25.

Added modules/doctools/tests/fmt/desc/26.

Added modules/doctools/tests/fmt/desc/27.

Added modules/doctools/tests/fmt/desc/28.

Added modules/doctools/tests/fmt/html/25.

















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
<!DOCTYPE html><html><head>
<title>TEST - </title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
	color:	 	black;
    }
    DIV.doctools {
	margin-left:	10%;
	margin-right:	10%;
    }
    DIV.doctools H1,DIV.doctools H2 {
	margin-left:	-5%;
    }
    H1, H2, H3, H4 {
	margin-top: 	1em;
	font-family:	sans-serif;
	font-size:	large;
	color:		#005A9C;
	background: 	transparent;
	text-align:		left;
    }
    H1.doctools_title {
	text-align: center;
    }
    UL,OL {
	margin-right: 0em;
	margin-top: 3pt;
	margin-bottom: 3pt;
    }
    UL LI {
	list-style: disc;
    }
    OL LI {
	list-style: decimal;
    }
    DT {
	padding-top: 	1ex;
    }
    UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
	font:		normal 12pt/14pt sans-serif;
	list-style:	none;
    }
    LI.doctools_section, LI.doctools_subsection {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding: 	0em;
    }
    PRE {
	display: 	block;
	font-family:	monospace;
	white-space:	pre;
	margin:		0%;
	padding-top:	0.5ex;
	padding-bottom:	0.5ex;
	padding-left:	1ex;
	padding-right:	1ex;
	width:		100%;
    }
    PRE.doctools_example {
	color: 		black;
	background: 	#f5dcb3;
	border:		1px solid black;
    }
    UL.doctools_requirements LI, UL.doctools_syntax LI {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding:	0em;
    }
    DIV.doctools_synopsis {
	color: 		black;
	background: 	#80ffff;
	border:		1px solid black;
	font-family:	serif;
	margin-top: 	1em;
	margin-bottom: 	1em;
    }
    UL.doctools_syntax {
	margin-top: 	1em;
	border-top:	1px solid black;
    }
    UL.doctools_requirements {
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file '.FILE.' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; .COPYRIGHT.
   -->
<!-- TEST.z
   -->
<body><div class="doctools">
<h1 class="doctools_title">TEST(z) 3.14.15.926 .MODULE. &quot;&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>TEST -</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<pre class="doctools_example">
Special markdown __non-special__
</pre>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; .COPYRIGHT.</p>
</div>
</div></body></html>

Added modules/doctools/tests/fmt/html/26.











































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
<!DOCTYPE html><html><head>
<title>TEST - </title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
	color:	 	black;
    }
    DIV.doctools {
	margin-left:	10%;
	margin-right:	10%;
    }
    DIV.doctools H1,DIV.doctools H2 {
	margin-left:	-5%;
    }
    H1, H2, H3, H4 {
	margin-top: 	1em;
	font-family:	sans-serif;
	font-size:	large;
	color:		#005A9C;
	background: 	transparent;
	text-align:		left;
    }
    H1.doctools_title {
	text-align: center;
    }
    UL,OL {
	margin-right: 0em;
	margin-top: 3pt;
	margin-bottom: 3pt;
    }
    UL LI {
	list-style: disc;
    }
    OL LI {
	list-style: decimal;
    }
    DT {
	padding-top: 	1ex;
    }
    UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
	font:		normal 12pt/14pt sans-serif;
	list-style:	none;
    }
    LI.doctools_section, LI.doctools_subsection {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding: 	0em;
    }
    PRE {
	display: 	block;
	font-family:	monospace;
	white-space:	pre;
	margin:		0%;
	padding-top:	0.5ex;
	padding-bottom:	0.5ex;
	padding-left:	1ex;
	padding-right:	1ex;
	width:		100%;
    }
    PRE.doctools_example {
	color: 		black;
	background: 	#f5dcb3;
	border:		1px solid black;
    }
    UL.doctools_requirements LI, UL.doctools_syntax LI {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding:	0em;
    }
    DIV.doctools_synopsis {
	color: 		black;
	background: 	#80ffff;
	border:		1px solid black;
	font-family:	serif;
	margin-top: 	1em;
	margin-bottom: 	1em;
    }
    UL.doctools_syntax {
	margin-top: 	1em;
	border-top:	1px solid black;
    }
    UL.doctools_requirements {
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file '.FILE.' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; .COPYRIGHT.
   -->
<!-- TEST.z
   -->
<body><div class="doctools">
<h1 class="doctools_title">TEST(z) 3.14.15.926 .MODULE. &quot;&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>TEST -</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<pre class="doctools_example">
Example Block  More Lines \
Ever More
Never
</pre>
<p>............... Weiter .............</p>
<pre class="doctools_example">
Second \
Continuing Lines \
Done
</pre>
<p>............... Vorwaerts ..........</p>
<pre class="doctools_example">
   <b class="cmd">command</b>    x \
-- <b class="cmd">command</b> --
</pre>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; .COPYRIGHT.</p>
</div>
</div></body></html>

Added modules/doctools/tests/fmt/html/27.































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
<!DOCTYPE html><html><head>
<title>TEST - </title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
	color:	 	black;
    }
    DIV.doctools {
	margin-left:	10%;
	margin-right:	10%;
    }
    DIV.doctools H1,DIV.doctools H2 {
	margin-left:	-5%;
    }
    H1, H2, H3, H4 {
	margin-top: 	1em;
	font-family:	sans-serif;
	font-size:	large;
	color:		#005A9C;
	background: 	transparent;
	text-align:		left;
    }
    H1.doctools_title {
	text-align: center;
    }
    UL,OL {
	margin-right: 0em;
	margin-top: 3pt;
	margin-bottom: 3pt;
    }
    UL LI {
	list-style: disc;
    }
    OL LI {
	list-style: decimal;
    }
    DT {
	padding-top: 	1ex;
    }
    UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
	font:		normal 12pt/14pt sans-serif;
	list-style:	none;
    }
    LI.doctools_section, LI.doctools_subsection {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding: 	0em;
    }
    PRE {
	display: 	block;
	font-family:	monospace;
	white-space:	pre;
	margin:		0%;
	padding-top:	0.5ex;
	padding-bottom:	0.5ex;
	padding-left:	1ex;
	padding-right:	1ex;
	width:		100%;
    }
    PRE.doctools_example {
	color: 		black;
	background: 	#f5dcb3;
	border:		1px solid black;
    }
    UL.doctools_requirements LI, UL.doctools_syntax LI {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding:	0em;
    }
    DIV.doctools_synopsis {
	color: 		black;
	background: 	#80ffff;
	border:		1px solid black;
	font-family:	serif;
	margin-top: 	1em;
	margin-bottom: 	1em;
    }
    UL.doctools_syntax {
	margin-top: 	1em;
	border-top:	1px solid black;
    }
    UL.doctools_requirements {
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file '.FILE.' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; .COPYRIGHT.
   -->
<!-- TEST.T
   -->
<body><div class="doctools">
<h1 class="doctools_title">TEST(T) 0 .MODULE. &quot;&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>TEST -</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
<p>= = == === ===== ======== =============</p>
<pre class="doctools_example">[<b class="cmd">bar</b> \
  foo]</pre>
<p>= = == === ===== ======== =============</p>
<pre class="doctools_example">
<em>  many lines
  highlighted
</em>
</pre>
<p>= = == === ===== ======== =============</p>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; .COPYRIGHT.</p>
</div>
</div></body></html>

Added modules/doctools/tests/fmt/html/28.















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
<!DOCTYPE html><html><head>
<title>TEST - </title>
<style type="text/css"><!--
    HTML {
	background: 	#FFFFFF;
	color: 		black;
    }
    BODY {
	background: 	#FFFFFF;
	color:	 	black;
    }
    DIV.doctools {
	margin-left:	10%;
	margin-right:	10%;
    }
    DIV.doctools H1,DIV.doctools H2 {
	margin-left:	-5%;
    }
    H1, H2, H3, H4 {
	margin-top: 	1em;
	font-family:	sans-serif;
	font-size:	large;
	color:		#005A9C;
	background: 	transparent;
	text-align:		left;
    }
    H1.doctools_title {
	text-align: center;
    }
    UL,OL {
	margin-right: 0em;
	margin-top: 3pt;
	margin-bottom: 3pt;
    }
    UL LI {
	list-style: disc;
    }
    OL LI {
	list-style: decimal;
    }
    DT {
	padding-top: 	1ex;
    }
    UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL {
	font:		normal 12pt/14pt sans-serif;
	list-style:	none;
    }
    LI.doctools_section, LI.doctools_subsection {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding: 	0em;
    }
    PRE {
	display: 	block;
	font-family:	monospace;
	white-space:	pre;
	margin:		0%;
	padding-top:	0.5ex;
	padding-bottom:	0.5ex;
	padding-left:	1ex;
	padding-right:	1ex;
	width:		100%;
    }
    PRE.doctools_example {
	color: 		black;
	background: 	#f5dcb3;
	border:		1px solid black;
    }
    UL.doctools_requirements LI, UL.doctools_syntax LI {
	list-style: 	none;
	margin-left: 	0em;
	text-indent:	0em;
	padding:	0em;
    }
    DIV.doctools_synopsis {
	color: 		black;
	background: 	#80ffff;
	border:		1px solid black;
	font-family:	serif;
	margin-top: 	1em;
	margin-bottom: 	1em;
    }
    UL.doctools_syntax {
	margin-top: 	1em;
	border-top:	1px solid black;
    }
    UL.doctools_requirements {
	margin-bottom: 	1em;
	border-bottom:	1px solid black;
    }
--></style>
</head>
<!-- Generated from file '.FILE.' by tcllib/doctools with format 'html'
   -->
<!-- Copyright &amp;copy; 2019 Me   -- Copyright &amp;copy; 2019 Myself   -- Copyright &amp;copy; 2019 And I
   -->
<!-- TEST.z
   -->
<body><div class="doctools">
<h1 class="doctools_title">TEST(z) 1.1.23.58132.1 .MODULE. &quot;&quot;</h1>
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2>
<p>TEST -</p>
</div>
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2>
<ul class="doctools_toc">
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li>
<li class="doctools_section"><a href="#section1">Description</a></li>
<li class="doctools_section"><a href="#copyright">Copyright</a></li>
</ul>
</div>
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2>
</div>
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2>
<p>Copyright &copy; 2019 Me<br>
Copyright &copy; 2019 Myself<br>
Copyright &copy; 2019 And I</p>
</div>
</div></body></html>

Changes to modules/doctools/tests/fmt/latex/04.

1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% TEST.z
\documentclass{article}

\begin{document}
\author{@USR@}
\title{.MODULE. / TEST --  : }
\maketitle
\section{Description}\label{section1}
BEGINNE HIER
\begin{verbatim}
	 Example Block  More Lines
\end{verbatim}

\begin{verbatim}
Inlined Example \
Next Line
\end{verbatim}
FERTIG
\section{Copyright}\label{copyright}
\begin{flushleft}
Copyright (c) .COPYRIGHT.\linebreak
\end{flushleft}
\end{document}




>






|

|

|
|

|






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% TEST.z
\documentclass{article}
\usepackage{alltt}
\begin{document}
\author{@USR@}
\title{.MODULE. / TEST --  : }
\maketitle
\section{Description}\label{section1}
BEGINNE HIER
\begin{alltt}
	 Example Block  More Lines
\end{alltt}

\begin{alltt}
Inlined Example \textbackslash
Next Line
\end{alltt}
FERTIG
\section{Copyright}\label{copyright}
\begin{flushleft}
Copyright (c) .COPYRIGHT.\linebreak
\end{flushleft}
\end{document}

Changes to modules/doctools/tests/fmt/latex/08.

1
2
3
4

5
6
7
8
9
10
11
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) **Copyright**
% ALL.a
\documentclass{article}

\begin{document}
\author{@USR@}
\title{.MODULE. / ALL -- ..THE\_MODULE.. : ..THE\_TITLE..}
\maketitle
\section{Synopsis}\label{synopsis}
\begin{flushleft}
package require {\bf AAA}




>







1
2
3
4
5
6
7
8
9
10
11
12
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) **Copyright**
% ALL.a
\documentclass{article}
\usepackage{alltt}
\begin{document}
\author{@USR@}
\title{.MODULE. / ALL -- ..THE\_MODULE.. : ..THE\_TITLE..}
\maketitle
\section{Synopsis}\label{synopsis}
\begin{flushleft}
package require {\bf AAA}
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
\item[] \underline{NAME} TYPE
%
 DESCRIPTION ::{\bf Option}::
%
\item[] \underline{NAME} TYPE (MODE)
%
 DESCRIPTION ::?Optional?::
\begin{verbatim}
    THE ARGUMENT IS USED IN THIS
    AND/OR THAT MANNER
\end{verbatim}
\end{itemize}
%
\item[] CMDNAME ...
%
 DESCRIPTION ::{\bf Package}::
%
\item[] CMDNAME ...







|


|







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
\item[] \underline{NAME} TYPE
%
 DESCRIPTION ::{\bf Option}::
%
\item[] \underline{NAME} TYPE (MODE)
%
 DESCRIPTION ::?Optional?::
\begin{alltt}
    THE ARGUMENT IS USED IN THIS
    AND/OR THAT MANNER
\end{alltt}
\end{itemize}
%
\item[] CMDNAME ...
%
 DESCRIPTION ::{\bf Package}::
%
\item[] CMDNAME ...

Changes to modules/doctools/tests/fmt/latex/09.

1
2
3
4

5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
31
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% TEST.z
\documentclass{article}

\begin{document}
\author{@USR@}
\title{.MODULE. / TEST --  : }
\maketitle
\section{Description}\label{section1}
lorem
\begin{verbatim}
1 lorem ipsum dolores
\end{verbatim}
ipsum

\begin{verbatim} 2 lorem ipsum dolores \end{verbatim}
dolores
\begin{verbatim}
3 lorem ipsum dolores
\end{verbatim}
lorem

\begin{verbatim} 4 lorem ipsum dolores
\end{verbatim}
ipsum
\begin{verbatim}
5 lorem ipsum dolores \end{verbatim}
dolores
\section{Copyright}\label{copyright}
\begin{flushleft}
Copyright (c) .COPYRIGHT.\linebreak
\end{flushleft}
\end{document}




>






|

|

>
|

|

|

>
|
|

|
|






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% TEST.z
\documentclass{article}
\usepackage{alltt}
\begin{document}
\author{@USR@}
\title{.MODULE. / TEST --  : }
\maketitle
\section{Description}\label{section1}
lorem
\begin{alltt}
1 lorem ipsum dolores
\end{alltt}
ipsum
\begin{alltt}
 2 lorem ipsum dolores \end{alltt}
dolores
\begin{alltt}
3 lorem ipsum dolores
\end{alltt}
lorem
\begin{alltt}
 4 lorem ipsum dolores
\end{alltt}
ipsum
\begin{alltt}
5 lorem ipsum dolores \end{alltt}
dolores
\section{Copyright}\label{copyright}
\begin{flushleft}
Copyright (c) .COPYRIGHT.\linebreak
\end{flushleft}
\end{document}

Changes to modules/doctools/tests/fmt/latex/13.

1
2
3
4

5
6
7
8
9
10
11
12
13
14

15
16
17
18
19

20
21
22
23
24
25

26
27
28
29
30
31
32
33
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-itemized-examples.1
\documentclass{article}

\begin{document}
\author{@USR@}
\title{.MODULE. / test-itemized-examples --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{itemize}
%
\item
%

\begin{verbatim} A lorem ipsum dolores \end{verbatim}
%
\item
%
 lorem ipsum dolores

\begin{verbatim} B lorem ipsum dolores \end{verbatim}
lorem ipsum dolores
%
\item
%
 lorem ipsum dolores

\begin{verbatim} C lorem ipsum dolores \end{verbatim}
%
\item
%
 lorem ipsum dolores
\end{itemize}
\section{Copyright}\label{copyright}
\begin{flushleft}




>










>
|




>
|





>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-itemized-examples.1
\documentclass{article}
\usepackage{alltt}
\begin{document}
\author{@USR@}
\title{.MODULE. / test-itemized-examples --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{itemize}
%
\item
%
\begin{alltt}
 A lorem ipsum dolores \end{alltt}
%
\item
%
 lorem ipsum dolores
\begin{alltt}
 B lorem ipsum dolores \end{alltt}
lorem ipsum dolores
%
\item
%
 lorem ipsum dolores
\begin{alltt}
 C lorem ipsum dolores \end{alltt}
%
\item
%
 lorem ipsum dolores
\end{itemize}
\section{Copyright}\label{copyright}
\begin{flushleft}

Changes to modules/doctools/tests/fmt/latex/14.

1
2
3
4

5
6
7
8
9
10
11
12
13
14

15
16
17
18
19

20
21
22
23
24
25

26
27
28
29
30
31
32
33
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-enumerated-examples.1
\documentclass{article}

\begin{document}
\author{@USR@}
\title{.MODULE. / test-enumerated-examples --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{enumerate}
%
\item
%

\begin{verbatim} A1 lorem ipsum dolores \end{verbatim}
%
\item
%
 lorem ipsum dolores

\begin{verbatim} B2 lorem ipsum dolores \end{verbatim}
lorem ipsum dolores
%
\item
%
 lorem ipsum dolores

\begin{verbatim} C3 lorem ipsum dolores \end{verbatim}
%
\item
%
 lorem ipsum dolores
\end{enumerate}
\section{Copyright}\label{copyright}
\begin{flushleft}




>










>
|




>
|





>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-enumerated-examples.1
\documentclass{article}
\usepackage{alltt}
\begin{document}
\author{@USR@}
\title{.MODULE. / test-enumerated-examples --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{enumerate}
%
\item
%
\begin{alltt}
 A1 lorem ipsum dolores \end{alltt}
%
\item
%
 lorem ipsum dolores
\begin{alltt}
 B2 lorem ipsum dolores \end{alltt}
lorem ipsum dolores
%
\item
%
 lorem ipsum dolores
\begin{alltt}
 C3 lorem ipsum dolores \end{alltt}
%
\item
%
 lorem ipsum dolores
\end{enumerate}
\section{Copyright}\label{copyright}
\begin{flushleft}

Changes to modules/doctools/tests/fmt/latex/15.

1
2
3
4

5
6
7
8
9
10
11
12
13
14

15
16
17
18
19

20
21
22
23
24
25

26
27
28
29
30
31
32
33
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-definition-examples.1
\documentclass{article}

\begin{document}
\author{@USR@}
\title{.MODULE. / test-definition-examples --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{itemize}
%
\item[] lorem
%

\begin{verbatim} A1 lorem ipsum dolores \end{verbatim}
%
\item[] lorem
%
 ipsum dolores

\begin{verbatim} B2 lorem ipsum dolores \end{verbatim}
lorem ipsum dolores
%
\item[] lorem
%
 ipsum dolores

\begin{verbatim} C3 lorem ipsum dolores \end{verbatim}
%
\item[] lorem
%
 ipsum dolores
\end{itemize}
\section{Copyright}\label{copyright}
\begin{flushleft}




>










>
|




>
|





>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-definition-examples.1
\documentclass{article}
\usepackage{alltt}
\begin{document}
\author{@USR@}
\title{.MODULE. / test-definition-examples --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{itemize}
%
\item[] lorem
%
\begin{alltt}
 A1 lorem ipsum dolores \end{alltt}
%
\item[] lorem
%
 ipsum dolores
\begin{alltt}
 B2 lorem ipsum dolores \end{alltt}
lorem ipsum dolores
%
\item[] lorem
%
 ipsum dolores
\begin{alltt}
 C3 lorem ipsum dolores \end{alltt}
%
\item[] lorem
%
 ipsum dolores
\end{itemize}
\section{Copyright}\label{copyright}
\begin{flushleft}

Changes to modules/doctools/tests/fmt/latex/19.

1
2
3
4
5
6
7
8
9
10
11
12
13
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-itemized-enumerated.1
\documentclass{article}
\begin{document}
\author{aku}
\title{.MODULE. / test-itemized-enumerated --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{itemize}
%
\item





|







1
2
3
4
5
6
7
8
9
10
11
12
13
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-itemized-enumerated.1
\documentclass{article}
\begin{document}
\author{@USR@}
\title{.MODULE. / test-itemized-enumerated --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{itemize}
%
\item

Changes to modules/doctools/tests/fmt/latex/20.

1
2
3
4
5
6
7
8
9
10
11
12
13
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-enumerated-itemized.1
\documentclass{article}
\begin{document}
\author{aku}
\title{.MODULE. / test-enumerated-itemized --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{enumerate}
%
\item





|







1
2
3
4
5
6
7
8
9
10
11
12
13
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-enumerated-itemized.1
\documentclass{article}
\begin{document}
\author{@USR@}
\title{.MODULE. / test-enumerated-itemized --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{enumerate}
%
\item

Changes to modules/doctools/tests/fmt/latex/21.

1
2
3
4
5
6
7
8
9
10
11
12
13
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-definitions-itemized.1
\documentclass{article}
\begin{document}
\author{aku}
\title{.MODULE. / test-definitions-itemized --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{itemize}
%
\item[] lorem





|







1
2
3
4
5
6
7
8
9
10
11
12
13
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-definitions-itemized.1
\documentclass{article}
\begin{document}
\author{@USR@}
\title{.MODULE. / test-definitions-itemized --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{itemize}
%
\item[] lorem

Changes to modules/doctools/tests/fmt/latex/22.

1
2
3
4
5
6
7
8
9
10
11
12
13
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-itemized-definitions.1
\documentclass{article}
\begin{document}
\author{aku}
\title{.MODULE. / test-itemized-definitions --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{itemize}
%
\item





|







1
2
3
4
5
6
7
8
9
10
11
12
13
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-itemized-definitions.1
\documentclass{article}
\begin{document}
\author{@USR@}
\title{.MODULE. / test-itemized-definitions --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{itemize}
%
\item

Changes to modules/doctools/tests/fmt/latex/23.

1
2
3
4
5
6
7
8
9
10
11
12
13
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-enumerated-definitions.1
\documentclass{article}
\begin{document}
\author{aku}
\title{.MODULE. / test-enumerated-definitions --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{enumerate}
%
\item





|







1
2
3
4
5
6
7
8
9
10
11
12
13
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-enumerated-definitions.1
\documentclass{article}
\begin{document}
\author{@USR@}
\title{.MODULE. / test-enumerated-definitions --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{enumerate}
%
\item

Changes to modules/doctools/tests/fmt/latex/24.

1
2
3
4
5
6
7
8
9
10
11
12
13
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-definitions-enumerated.1
\documentclass{article}
\begin{document}
\author{aku}
\title{.MODULE. / test-definitions-enumerated --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{itemize}
%
\item[] lorem





|







1
2
3
4
5
6
7
8
9
10
11
12
13
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% test-definitions-enumerated.1
\documentclass{article}
\begin{document}
\author{@USR@}
\title{.MODULE. / test-definitions-enumerated --  : }
\maketitle
\section{Description}\label{section1}
lorem ipsum dolores
\begin{itemize}
%
\item[] lorem

Added modules/doctools/tests/fmt/latex/25.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% TEST.z
\documentclass{article}
\usepackage{alltt}
\begin{document}
\author{@USR@}
\title{.MODULE. / TEST --  : }
\maketitle
\section{Description}\label{section1}
\begin{alltt}
Special markdown __non-special__
\end{alltt}
\section{Copyright}\label{copyright}
\begin{flushleft}
Copyright (c) .COPYRIGHT.\linebreak
\end{flushleft}
\end{document}

Added modules/doctools/tests/fmt/latex/26.



































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% TEST.z
\documentclass{article}
\usepackage{alltt}
\begin{document}
\author{@USR@}
\title{.MODULE. / TEST --  : }
\maketitle
\section{Description}\label{section1}
\begin{alltt}
Example Block  More Lines \textbackslash
Ever More
Never
\end{alltt}

............... Weiter .............

\begin{alltt}
Second \textbackslash
Continuing Lines \textbackslash
Done
\end{alltt}
............... Vorwaerts ..........
\begin{alltt}
   {\bf command}    x \textbackslash
-- {\bf command} --
\end{alltt}
\section{Copyright}\label{copyright}
\begin{flushleft}
Copyright (c) .COPYRIGHT.\linebreak
\end{flushleft}
\end{document}

Added modules/doctools/tests/fmt/latex/27.





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) .COPYRIGHT.
% TEST.T
\documentclass{article}
\usepackage{alltt}
\begin{document}
\author{@USR@}
\title{.MODULE. / TEST --  : }
\maketitle
\section{Description}\label{section1}
= = == === ===== ======== =============
\begin{alltt}
[{\bf bar} \textbackslash
  foo]\end{alltt}
= = == === ===== ======== =============
\begin{alltt}
{\it   many lines
  highlighted
}
\end{alltt}
= = == === ===== ======== =============
\section{Copyright}\label{copyright}
\begin{flushleft}
Copyright (c) .COPYRIGHT.\linebreak
\end{flushleft}
\end{document}

Added modules/doctools/tests/fmt/latex/28.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
% Generated from file '.FILE.' by tcllib/doctools with format 'latex'
% Copyright (c) 2019 Me
% Copyright (c) 2019 Myself
% Copyright (c) 2019 And I
% TEST.z
\documentclass{article}
\begin{document}
\author{@USR@}
\title{.MODULE. / TEST --  : }
\maketitle
\section{Description}\label{section1}
\section{Copyright}\label{copyright}
\begin{flushleft}
Copyright (c) 2019 Me\linebreak
Copyright (c) 2019 Myself\linebreak
Copyright (c) 2019 And I\linebreak
\end{flushleft}
\end{document}

Added modules/doctools/tests/fmt/list/25.



>
1
manpage {seealso {} keywords {} file .FILE. section z category {} module .MODULE. version 3.14.15.926 title TEST shortdesc {} desc {} fid .FILE}

Added modules/doctools/tests/fmt/list/26.



>
1
manpage {seealso {} keywords {} file .FILE. section z category {} module .MODULE. version 3.14.15.926 title TEST shortdesc {} desc {} fid .FILE}

Added modules/doctools/tests/fmt/list/27.



>
1
manpage {seealso {} keywords {} file .FILE. section T category {} module .MODULE. version 0 title TEST shortdesc {} desc {} fid .FILE}

Added modules/doctools/tests/fmt/list/28.



>
1
manpage {seealso {} keywords {} file .FILE. section z category {} module .MODULE. version 1.1.23.58132.1 title TEST shortdesc {} desc {} fid .FILE}

Added modules/doctools/tests/fmt/man/25.















>
>
>
>
>
>
>
1
2
3
4
5
6
7
[comment { -- Example 2 }]
[manpage_begin TEST z 3.14.15.926]
[description]
[example {
Special markdown __non-special__
}]
[manpage_end]

Added modules/doctools/tests/fmt/man/26.















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[comment { -- Example 3 }]
[manpage_begin TEST z 3.14.15.926]
[description]
[example {
Example Block \
More Lines \\
Ever More
Never
}]
[para]
............... Weiter .............
[para]
[example_begin]
Second \
Continuing Lines \\
Done
[example_end]
............... Vorwaerts ..........
[example_begin]
   [cmd command]    x \\
-- [cmd command] --
[example_end]
[manpage_end]

Added modules/doctools/tests/fmt/man/27.





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[comment { -- Example 4 }]
[manpage_begin TEST T 0]
[description]
= = == === ===== ======== =============
[example_begin][lb][cmd bar] \
  foo[rb][example_end]
= = == === ===== ======== =============
[example_begin]
[emph {  many lines
  highlighted
}]
[example_end]
= = == === ===== ======== =============
[manpage_end]

Added modules/doctools/tests/fmt/man/28.















>
>
>
>
>
>
>
1
2
3
4
5
6
7
[comment { -- Multi copyright }]
[manpage_begin TEST z 1.1.23.58132.1]
[copyright {2019 Me}]
[copyright {2019 Myself}]
[copyright {2019 And I}]
[description]
[manpage_end]

Changes to modules/doctools/tests/fmt/markdown/04.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# <a name='description'></a>DESCRIPTION

BEGINNE HIER

    Example Block  More Lines

    Inlined Example \\
    Next Line

FERTIG

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; \.COPYRIGHT\.







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# <a name='description'></a>DESCRIPTION

BEGINNE HIER

    Example Block  More Lines

    Inlined Example \
    Next Line

FERTIG

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; \.COPYRIGHT\.

Added modules/doctools/tests/fmt/markdown/25.



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

[//000000001]: # (TEST \- )
[//000000002]: # (Generated from file '\.FILE\.' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; \.COPYRIGHT\.)
[//000000004]: # (TEST\(z\) 3\.14\.15\.926 \.MODULE\. "")

# NAME

TEST \-

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Description](#section1)

  - [Copyright](#copyright)

# <a name='description'></a>DESCRIPTION

    Special markdown __non-special__

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; \.COPYRIGHT\.

Added modules/doctools/tests/fmt/markdown/26.













































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

[//000000001]: # (TEST \- )
[//000000002]: # (Generated from file '\.FILE\.' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; \.COPYRIGHT\.)
[//000000004]: # (TEST\(z\) 3\.14\.15\.926 \.MODULE\. "")

# NAME

TEST \-

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Description](#section1)

  - [Copyright](#copyright)

# <a name='description'></a>DESCRIPTION

    Example Block  More Lines \
    Ever More
    Never

\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Weiter \.\.\.\.\.\.\.\.\.\.\.\.\.

    Second \
    Continuing Lines \
    Done

\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. Vorwaerts \.\.\.\.\.\.\.\.\.\.

> __command__    x \\  
> \-\- __command__ \-\-

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; \.COPYRIGHT\.

Added modules/doctools/tests/fmt/markdown/27.







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

[//000000001]: # (TEST \- )
[//000000002]: # (Generated from file '\.FILE\.' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; \.COPYRIGHT\.)
[//000000004]: # (TEST\(T\) 0 \.MODULE\. "")

# NAME

TEST \-

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Description](#section1)

  - [Copyright](#copyright)

# <a name='description'></a>DESCRIPTION

= = == === ===== ======== =============

> \[__bar__ \\  
> &nbsp;&nbsp;foo\]

= = == === ===== ======== =============

> &nbsp;&nbsp;*many lines*  
> &nbsp;&nbsp;*highlighted*

= = == === ===== ======== =============

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; \.COPYRIGHT\.

Added modules/doctools/tests/fmt/markdown/28.























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

[//000000001]: # (TEST \- )
[//000000002]: # (Generated from file '\.FILE\.' by tcllib/doctools with format 'markdown')
[//000000003]: # (Copyright &copy; 2019 Me)
[//000000004]: # (Copyright &copy; 2019 Myself)
[//000000005]: # (Copyright &copy; 2019 And I)
[//000000006]: # (TEST\(z\) 1\.1\.23\.58132\.1 \.MODULE\. "")

# NAME

TEST \-

# <a name='toc'></a>Table Of Contents

  - [Table Of Contents](#toc)

  - [Description](#section1)

  - [Copyright](#copyright)

# <a name='description'></a>DESCRIPTION

# <a name='copyright'></a>COPYRIGHT

Copyright &copy; 2019 Me  
Copyright &copy; 2019 Myself  
Copyright &copy; 2019 And I

Added modules/doctools/tests/fmt/nroff/25.











































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
'\"
'\" Generated from file '\&.FILE\&.' by tcllib/doctools with format 'nroff'
'\" Copyright (c) \&.COPYRIGHT\&.
'\"
.TH "TEST" z 3\&.14\&.15\&.926 \&.MODULE\&. ""
.so man.macros
.BS
.SH NAME
TEST \-
.SH DESCRIPTION
.CS


Special markdown __non-special__

.CE
.SH COPYRIGHT
.nf
Copyright (c) \&.COPYRIGHT\&.

.fi

Added modules/doctools/tests/fmt/nroff/26.





















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
'\"
'\" Generated from file '\&.FILE\&.' by tcllib/doctools with format 'nroff'
'\" Copyright (c) \&.COPYRIGHT\&.
'\"
.TH "TEST" z 3\&.14\&.15\&.926 \&.MODULE\&. ""
.so man.macros
.BS
.SH NAME
TEST \-
.SH DESCRIPTION
.CS


Example Block  More Lines \\
Ever More
Never

.CE
.PP
\&.\&.\&.\&.\&.\&.\&.\&.\&.\&.\&.\&.\&.\&.\&. Weiter \&.\&.\&.\&.\&.\&.\&.\&.\&.\&.\&.\&.\&.
.PP
.CS


Second \\
Continuing Lines \\
Done

.CE
\&.\&.\&.\&.\&.\&.\&.\&.\&.\&.\&.\&.\&.\&.\&. Vorwaerts \&.\&.\&.\&.\&.\&.\&.\&.\&.\&.
.CS


   \fBcommand\fR    x \\
-- \fBcommand\fR --

.CE
.SH COPYRIGHT
.nf
Copyright (c) \&.COPYRIGHT\&.

.fi

Added modules/doctools/tests/fmt/nroff/27.































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
'\"
'\" Generated from file '\&.FILE\&.' by tcllib/doctools with format 'nroff'
'\" Copyright (c) \&.COPYRIGHT\&.
'\"
.TH "TEST" T 0 \&.MODULE\&. ""
.so man.macros
.BS
.SH NAME
TEST \-
.SH DESCRIPTION
= = == === ===== ======== =============
.CS

[\fBbar\fR \\
  foo]
.CE
= = == === ===== ======== =============
.CS


\fI  many lines
  highlighted
\fR

.CE
= = == === ===== ======== =============
.SH COPYRIGHT
.nf
Copyright (c) \&.COPYRIGHT\&.

.fi

Added modules/doctools/tests/fmt/nroff/28.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
'\"
'\" Generated from file '\&.FILE\&.' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2019 Me
'\" Copyright (c) 2019 Myself
'\" Copyright (c) 2019 And I
'\"
.TH "TEST" z 1\&.1\&.23\&.58132\&.1 \&.MODULE\&. ""
.so man.macros
.BS
.SH NAME
TEST \-
.SH DESCRIPTION
.SH COPYRIGHT
.nf
Copyright (c) 2019 Me
Copyright (c) 2019 Myself
Copyright (c) 2019 And I

.fi

Added modules/doctools/tests/fmt/null/25.

Added modules/doctools/tests/fmt/null/26.

Added modules/doctools/tests/fmt/null/27.

Added modules/doctools/tests/fmt/null/28.

Added modules/doctools/tests/fmt/syntax/26.

Added modules/doctools/tests/fmt/syntax/28.

Added modules/doctools/tests/fmt/text/25.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

TEST - 
Generated from file '.FILE.' by tcllib/doctools with format 'text'
TEST(z) 3.14.15.926 .MODULE. ""

NAME
====

TEST -

DESCRIPTION
===========

| Special markdown __non-special__

COPYRIGHT
=========

Copyright (c) .COPYRIGHT.

Added modules/doctools/tests/fmt/text/26.

































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

TEST - 
Generated from file '.FILE.' by tcllib/doctools with format 'text'
TEST(z) 3.14.15.926 .MODULE. ""

NAME
====

TEST -

DESCRIPTION
===========

| Example Block  More Lines \
| Ever More
| Never

............... Weiter .............

| Second \
| Continuing Lines \
| Done

............... Vorwaerts ..........

| command    x \
| -- command --

COPYRIGHT
=========

Copyright (c) .COPYRIGHT.

Added modules/doctools/tests/fmt/text/27.



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

TEST - 
Generated from file '.FILE.' by tcllib/doctools with format 'text'
TEST(T) 0 .MODULE. ""

NAME
====

TEST -

DESCRIPTION
===========

= = == === ===== ======== =============

| [bar \
|   foo]

= = == === ===== ======== =============

| _many lines_
| _highlighted_

= = == === ===== ======== =============

COPYRIGHT
=========

Copyright (c) .COPYRIGHT.

Added modules/doctools/tests/fmt/text/28.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

TEST - 
Generated from file '.FILE.' by tcllib/doctools with format 'text'
TEST(z) 1.1.23.58132.1 .MODULE. ""

NAME
====

TEST -

DESCRIPTION
===========

COPYRIGHT
=========

Copyright (c) 2019 Me
Copyright (c) 2019 Myself
Copyright (c) 2019 And I

Added modules/doctools/tests/fmt/tmml/25.

















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- Generated from file '.FILE.' by tcllib/doctools with format 'tmml' -->
<manpage id='.FILE' cat='cmd' title='TEST' version='3.14.15.926' package='.MODULE.'>
<head>
<info key='copyright' value='Copyright (c) .COPYRIGHT.'/>
</head>
<namesection>
<name>TEST</name>
<desc></desc>

</namesection>


<section id='section1'>
<title>DESCRIPTION</title>

<example>
Special markdown __non-special__

</example>
</section>



</manpage>

Added modules/doctools/tests/fmt/tmml/26.



























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!-- Generated from file '.FILE.' by tcllib/doctools with format 'tmml' -->
<manpage id='.FILE' cat='cmd' title='TEST' version='3.14.15.926' package='.MODULE.'>
<head>
<info key='copyright' value='Copyright (c) .COPYRIGHT.'/>
</head>
<namesection>
<name>TEST</name>
<desc></desc>

</namesection>


<section id='section1'>
<title>DESCRIPTION</title>

<example>
Example Block  More Lines \
Ever More
Never

</example>

<p>
............... Weiter .............
</p>
<p>
</p>
<example>
Second \
Continuing Lines \
Done

</example>
............... Vorwaerts ..........

<example>
   <cmd>command</cmd>    x \
-- <cmd>command</cmd> --

</example>
</section>



</manpage>

Added modules/doctools/tests/fmt/tmml/27.



































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!-- Generated from file '.FILE.' by tcllib/doctools with format 'tmml' -->
<manpage id='.FILE' cat='cmd' title='TEST' version='0' package='.MODULE.'>
<head>
<info key='copyright' value='Copyright (c) .COPYRIGHT.'/>
</head>
<namesection>
<name>TEST</name>
<desc></desc>

</namesection>


<section id='section1'>
<title>DESCRIPTION</title>
= = == === ===== ======== =============

<example>[<cmd>bar</cmd> \
  foo]
</example>
= = == === ===== ======== =============

<example>
<emph>  many lines
  highlighted
</emph>

</example>
= = == === ===== ======== =============
</section>



</manpage>

Added modules/doctools/tests/fmt/tmml/28.

















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- Generated from file '.FILE.' by tcllib/doctools with format 'tmml' -->
<manpage id='.FILE' cat='cmd' title='TEST' version='1.1.23.58132.1' package='.MODULE.'>
<head>
<info key='copyright' value='Copyright (c) 2019 Me'/>
<info key='copyright' value='Copyright (c) 2019 Myself'/>
<info key='copyright' value='Copyright (c) 2019 And I'/>
</head>
<namesection>
<name>TEST</name>
<desc></desc>

</namesection>





<section id='section1'>
<title>DESCRIPTION</title>
</section>



</manpage>

Added modules/doctools/tests/fmt/wiki/25.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
'''TEST 3.14.15.926''' '''.MODULE.'''




**DESCRIPTION**


======

Special markdown __non-special__

======


**COPYRIGHT**

 Copyright (c) .COPYRIGHT.

Added modules/doctools/tests/fmt/wiki/26.











































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
'''TEST 3.14.15.926''' '''.MODULE.'''




**DESCRIPTION**


======

Example Block  More Lines \
Ever More
Never

======

............... Weiter .............

======

Second \
Continuing Lines \
Done

======
............... Vorwaerts ..........
======

   '''command'''    x \
-- '''command''' --

======


**COPYRIGHT**

 Copyright (c) .COPYRIGHT.

Added modules/doctools/tests/fmt/wiki/27.



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
'''TEST 0''' '''.MODULE.'''




**DESCRIPTION**

= = == === ===== ======== =============
======
['''bar''' \
  foo]
======
= = == === ===== ======== =============
======

''  many lines
  highlighted
''

======
= = == === ===== ======== =============

**COPYRIGHT**

 Copyright (c) .COPYRIGHT.

Added modules/doctools/tests/fmt/wiki/28.





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
'''TEST 1.1.23.58132.1''' '''.MODULE.'''




**DESCRIPTION**



**COPYRIGHT**

 Copyright (c) 2019 Me
 Copyright (c) 2019 Myself
 Copyright (c) 2019 And I

Deleted modules/doctools2base/config.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# docidx.tcl --
#
#	Generic configuration management, for use by import and export
#	managers.
#
# Copyright (c) 2009 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: config.tcl,v 1.2 2011/11/17 08:00:45 andreas_kupries Exp $

# Each object manages a set of configuration variables.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.4
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::doctools::config {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creating, destruction

    # Default constructor.
    # Default destructor.

    # ### ### ### ######### ######### #########
    ## Public methods. Reading and writing the configuration.

    method names {} {
	return [array names myconfiguration]
    }

    method get {} {
	return [array get myconfiguration]
    }

    method set {name {value {}}} {
	# 7 instead of 3 in the condition below, because of the 4
	# implicit arguments snit is providing to each method.
	if {[llength [info level 0]] == 7} {
	    set myconfiguration($name) $value
	} elseif {![info exists myconfiguration($name)]} {
	    return -code error "can't read \"$name\": no such variable"
	}
	return $myconfiguration($name)
    }

    method unset {args} {
	if {![llength $args]} { lappend args * }
	foreach pattern $args {
	    array unset myconfiguration $pattern
	}
	return
    }

    # ### ### ### ######### ######### #########
    ## Internal methods :: None.

    # ### ### ### ######### ######### #########
    ## State :: Configuration data, Tcl array

    variable myconfiguration -array {}

    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide doctools::config 0.1
return
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































































































































































Changes to modules/doctools2base/html_cssdefaults.man.

32
33
34
35
36
37
38
39
40

This command returns the text of the default CSS style to use for HTML
markup generated by the various HTML export plugins.

[list_end]

[vset CATEGORY doctools]
[include include/feedback.inc]
[manpage_end]







|

32
33
34
35
36
37
38
39
40

This command returns the text of the default CSS style to use for HTML
markup generated by the various HTML export plugins.

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Deleted modules/doctools2base/include/feedback.inc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[section {Bugs, Ideas, Feedback}]
[vset TRACKER http://core.tcl.tk/tcllib/reportlist]
[vset LABEL   {Tcllib Trackers}]

This document, and the package it describes, will undoubtedly contain
bugs and other problems.

Please report such in the category [emph [vset CATEGORY]] of the
[uri [vset TRACKER] [vset LABEL]].

Please also report any ideas for enhancements you may have for either
package and/or documentation.

[para]
When proposing code changes, please provide [emph {unified diffs}],
i.e the output of [const {diff -u}].

[para]
Note further that [emph attachments] are strongly preferred over
inlined patches. Attachments can be made by going to the [const Edit]
form of the ticket immediately after its creation, and then using the
left-most button in the secondary navigation bar.

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














































Changes to modules/doctools2base/nroff_manmacros.man.

32
33
34
35
36
37
38
39
40

This command returns the text of the default CSS style to use for NROFF
generated by the various NROFF export plugins.

[list_end]

[vset CATEGORY doctools]
[include include/feedback.inc]
[manpage_end]







|

32
33
34
35
36
37
38
39
40

This command returns the text of the default CSS style to use for NROFF
generated by the various NROFF export plugins.

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Deleted modules/doctools2base/paths.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# docidx.tcl --
#
#	Generic path list management, for use by import management.
#
# Copyright (c) 2009 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: paths.tcl,v 1.2 2009/04/29 02:09:46 andreas_kupries Exp $

# Each object manages a list of paths.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.4
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::doctools::paths {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creation, destruction

    # Default constructor.
    # Default destructor.

    # ### ### ### ######### ######### #########
    ## Methods :: Querying and manipulating the list of paths.

    method paths {} {
	return $mypaths
    }

    method add {path} {
	set pos [lsearch $mypaths $path]
	if {$pos >= 0 } return
	lappend mypaths $path
	return
    }

    method remove {path} {
	set pos [lsearch $mypaths $path]
	if {$pos < 0} return
	set  mypaths [lreplace $mypaths $pos $pos]
	return
    }

    method clear {} {
	set mypaths {}
	return
    }

    # ### ### ### ######### ######### #########
    ## Internal methods :: None

    # ### ### ### ######### ######### #########
    ## State :: List of paths.

    variable mypaths {}

    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide doctools::paths 0.1
return
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































































































































Changes to modules/doctools2base/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if {![package vsatisfies [package provide Tcl] 8.4]} {return}

# Packages for the doctools {idx,toc,doc} v2 implementation
# (still v1.1 doc{idx,toc} languages).

# Supporting packages
# - Handling configuration variables, and include paths.
# - Handling text generation, the nroff man.macros definitions,
#            HTML/XML generation, and the default CSS style
# - Handling of message catalogs as packages.
# - Recursive descent parser for Tcl strings (as expected by 'subst -novariables').

package ifneeded doctools::config            0.1 [list source [file join $dir config.tcl]]
package ifneeded doctools::paths             0.1 [list source [file join $dir paths.tcl]]
package ifneeded doctools::text              0.1 [list source [file join $dir text.tcl]]
package ifneeded doctools::nroff::man_macros 0.1 [list source [file join $dir nroff_manmacros.tcl]]
package ifneeded doctools::html              0.1 [list source [file join $dir html.tcl]]
package ifneeded doctools::html::cssdefaults 0.1 [list source [file join $dir html_cssdefaults.tcl]]
package ifneeded doctools::msgcat            0.1 [list source [file join $dir msgcat.tcl]]
package ifneeded doctools::tcl::parse        0.1 [list source [file join $dir tcl_parse.tcl]]






<





<
<






1
2
3
4
5
6

7
8
9
10
11


12
13
14
15
16
17
if {![package vsatisfies [package provide Tcl] 8.4]} {return}

# Packages for the doctools {idx,toc,doc} v2 implementation
# (still v1.1 doc{idx,toc} languages).

# Supporting packages

# - Handling text generation, the nroff man.macros definitions,
#            HTML/XML generation, and the default CSS style
# - Handling of message catalogs as packages.
# - Recursive descent parser for Tcl strings (as expected by 'subst -novariables').



package ifneeded doctools::text              0.1 [list source [file join $dir text.tcl]]
package ifneeded doctools::nroff::man_macros 0.1 [list source [file join $dir nroff_manmacros.tcl]]
package ifneeded doctools::html              0.1 [list source [file join $dir html.tcl]]
package ifneeded doctools::html::cssdefaults 0.1 [list source [file join $dir html_cssdefaults.tcl]]
package ifneeded doctools::msgcat            0.1 [list source [file join $dir msgcat.tcl]]
package ifneeded doctools::tcl::parse        0.1 [list source [file join $dir tcl_parse.tcl]]

Changes to modules/doctools2base/tcl_parse.man.

176
177
178
179
180
181
182
183
184

[enum]
All leaves of the tree are either Text or Command nodes.
Word nodes cannot be leaves.
[list_end]

[vset CATEGORY doctools]
[include include/feedback.inc]
[manpage_end]







|

176
177
178
179
180
181
182
183
184

[enum]
All leaves of the tree are either Text or Command nodes.
Word nodes cannot be leaves.
[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2base/tcllib_msgcat.man.

59
60
61
62
63
64
65
66
67
"doctools::msgcat::[arg prefix]::[var langcode]", with [arg prefix]
the argument to the command, and the [var langcode] supplied by the
result of [cmd msgcat::mcpreferences].

[list_end]

[vset CATEGORY doctools]
[include include/feedback.inc]
[manpage_end]







|

59
60
61
62
63
64
65
66
67
"doctools::msgcat::[arg prefix]::[var langcode]", with [arg prefix]
the argument to the command, and the [var langcode] supplied by the
result of [cmd msgcat::mcpreferences].

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2idx/container.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23

24
25
26
27
28
29
30
31
32
33
# -*- tcl -*-
# idx.test:  Tests for the doctools::idx package. Index management.
#
# Copyright (c) 2009 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: container.test,v 1.2 2009/04/29 02:10:34 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2

support {
    use struct/list.tcl          struct::list
    use snit/snit.tcl            snit
    use fileutil/fileutil.tcl    fileutil

    use log/logger.tcl           logger
    use pluginmgr/pluginmgr.tcl  pluginmgr


    use doctools2base/config.tcl          doctools::config
    use doctools2base/paths.tcl           doctools::paths
    useLocal export.tcl      doctools::idx::export
    useLocal import.tcl      doctools::idx::import
    use doctools2base/nroff_manmacros.tcl doctools::nroff::man_macros

    source [tcllibPath doctools2base/tests/common]
}
testing {



|

<
<














>


>

<
<







1
2
3
4
5


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24


25
26
27
28
29
30
31
# -*- tcl -*-
# idx.test:  Tests for the doctools::idx package. Index management.
#
# Copyright (c) 2009-2019 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2

support {
    use struct/list.tcl          struct::list
    use snit/snit.tcl            snit
    use fileutil/fileutil.tcl    fileutil
    use fileutil/paths.tcl       fileutil::paths
    use log/logger.tcl           logger
    use pluginmgr/pluginmgr.tcl  pluginmgr
    use struct/map.tcl           struct::map



    useLocal export.tcl      doctools::idx::export
    useLocal import.tcl      doctools::idx::import
    use doctools2base/nroff_manmacros.tcl doctools::nroff::man_macros

    source [tcllibPath doctools2base/tests/common]
}
testing {

Changes to modules/doctools2idx/export.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# export.tcl --
#
#	Exporting indices into other formats.
#
# Copyright (c) 2009-2018 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: export.tcl,v 1.1 2009/04/01 04:28:37 andreas_kupries Exp $

# Each object manages a set of plugins for the conversion of keyword
# indices into some textual representation. I.e. this object manages
# the conversion to specialized serializations of keyword indices.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.4
package require doctools::config
package require doctools::idx::structure
package require pluginmgr
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::doctools::idx::export {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creation, destruction.

    constructor {} {
	install myconfig using ::doctools::config ${selfns}::config
	return
    }

    destructor {
	$myconfig destroy
	# Clear the cache of loaded export plugins.
	foreach k [array names myplugin] {




|



<
<









|
















|







1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# export.tcl --
#
#	Exporting indices into other formats.
#
# Copyright (c) 2009-2019 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.



# Each object manages a set of plugins for the conversion of keyword
# indices into some textual representation. I.e. this object manages
# the conversion to specialized serializations of keyword indices.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.4
package require struct::map
package require doctools::idx::structure
package require pluginmgr
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::doctools::idx::export {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creation, destruction.

    constructor {} {
	install myconfig using ::struct::map ${selfns}::config
	return
    }

    destructor {
	$myconfig destroy
	# Clear the cache of loaded export plugins.
	foreach k [array names myplugin] {
117
118
119
120
121
122
123
124
125
    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide doctools::idx::export 0.2
return







|

115
116
117
118
119
120
121
122
123
    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide doctools::idx::export 0.2.1
return

Changes to modules/doctools2idx/export.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
# -*- tcl -*-
# idx.test:  tests for the doctools::idx package.
#
# Copyright (c) 2009 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: export.test,v 1.2 2009/04/29 02:10:34 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2

support {
    use fileutil/fileutil.tcl    fileutil      ;# tests/common

    use struct/list.tcl          struct::list
    use snit/snit.tcl            snit
    use log/logger.tcl           logger
    use pluginmgr/pluginmgr.tcl  pluginmgr


    use doctools2base/config.tcl          doctools::config
    useLocal structure.tcl   doctools::idx::structure
    use doctools2base/nroff_manmacros.tcl doctools::nroff::man_macros

    source [tcllibPath doctools2base/tests/common]
}
testing {
    useLocalKeep export.tcl doctools::idx::export



|

<
<

















>

<







1
2
3
4
5


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
# -*- tcl -*-
# idx.test:  tests for the doctools::idx package.
#
# Copyright (c) 2009-2019 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2

support {
    use fileutil/fileutil.tcl    fileutil      ;# tests/common

    use struct/list.tcl          struct::list
    use snit/snit.tcl            snit
    use log/logger.tcl           logger
    use pluginmgr/pluginmgr.tcl  pluginmgr
    use struct/map.tcl           struct::map


    useLocal structure.tcl   doctools::idx::structure
    use doctools2base/nroff_manmacros.tcl doctools::nroff::man_macros

    source [tcllibPath doctools2base/tests/common]
}
testing {
    useLocalKeep export.tcl doctools::idx::export
73
74
75
76
77
78
79
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

test doctools-idx-export-5.0 {config names, wrong#args} -setup {
    doctools::idx::export E
} -body {
    E config names X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodnames type selfns win self"}

test doctools-idx-export-6.0 {config get, wrong#args} -setup {
    doctools::idx::export E
} -body {
    E config get X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodget type selfns win self"}

test doctools-idx-export-7.0 {config set, wrong#args} -setup {
    doctools::idx::export E
} -body {
    E config set
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodset type selfns win self name ?value?"}

test doctools-idx-export-7.1 {config set, wrong#args} -setup {
    doctools::idx::export E
} -body {
    E config set N V X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodset type selfns win self name ?value?"}

# -------------------------------------------------------------------------

test doctools-idx-export-12.0 {config set, define single var} -setup {
    doctools::idx::export E
} -body {
    E config set N V







|







|







|







|







71
72
73
74
75
76
77
78
79
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

test doctools-idx-export-5.0 {config names, wrong#args} -setup {
    doctools::idx::export E
} -body {
    E config names X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodnames type selfns win self"}

test doctools-idx-export-6.0 {config get, wrong#args} -setup {
    doctools::idx::export E
} -body {
    E config get X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodget type selfns win self"}

test doctools-idx-export-7.0 {config set, wrong#args} -setup {
    doctools::idx::export E
} -body {
    E config set
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

test doctools-idx-export-7.1 {config set, wrong#args} -setup {
    doctools::idx::export E
} -body {
    E config set N V X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

# -------------------------------------------------------------------------

test doctools-idx-export-12.0 {config set, define single var} -setup {
    doctools::idx::export E
} -body {
    E config set N V

Changes to modules/doctools2idx/export_docidx.man.

1
2
3
4
5
6
7
[comment {-*- tcl -*- --- doctools ---}]
[vset PACKAGE docidx]
[vset NAME    docidx]
[vset REQUIRE null]
[vset CONFIG  docidx]
[vset VERSION 0.1]
[include include/export/plugin.inc]





|

1
2
3
4
5
6
7
[comment {-*- tcl -*- --- doctools ---}]
[vset PACKAGE docidx]
[vset NAME    docidx]
[vset REQUIRE null]
[vset CONFIG  docidx]
[vset VERSION 0.2.1]
[include include/export/plugin.inc]

Changes to modules/doctools2idx/idx_container.man.

288
289
290
291
292
293
294
295
296
In that case an error will be thrown if the container has no export
manager attached to it.

[list_end]

[include include/serialization.inc]
[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

288
289
290
291
292
293
294
295
296
In that case an error will be thrown if the container has no export
manager attached to it.

[list_end]

[include include/serialization.inc]
[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2idx/idx_export.man.

1
2
3
4
5
6
7
8
[vset VERSION 0.2]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin doctools::idx::export n [vset VERSION]]
[keywords conversion]
[keywords docidx]
[keywords documentation]
[keywords export]
[keywords formatting]
|







1
2
3
4
5
6
7
8
[vset VERSION 0.2.1]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin doctools::idx::export n [vset VERSION]]
[keywords conversion]
[keywords docidx]
[keywords documentation]
[keywords export]
[keywords formatting]
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[keywords nroff]
[keywords plugin]
[keywords reference]
[keywords {tcler's wiki}]
[keywords text]
[keywords url]
[keywords wiki]
[copyright {2009-2018 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc {Exporting keyword indices}]
[category  {Documentation tools}]
[require doctools::idx::export [opt [vset VERSION]]]
[require Tcl 8.4]
[require doctools::config]
[require doctools::idx::structure]
[require snit]
[require pluginmgr]
[description]

This package provides a class to manage the plugins for the export of
keyword indices to other formats, i.e. their conversion to, for







|





|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[keywords nroff]
[keywords plugin]
[keywords reference]
[keywords {tcler's wiki}]
[keywords text]
[keywords url]
[keywords wiki]
[copyright {2009-2019 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc {Exporting keyword indices}]
[category  {Documentation tools}]
[require doctools::idx::export [opt [vset VERSION]]]
[require Tcl 8.4]
[require struct::map]
[require doctools::idx::structure]
[require snit]
[require pluginmgr]
[description]

This package provides a class to manage the plugins for the export of
keyword indices to other formats, i.e. their conversion to, for
301
302
303
304
305
306
307
308
309
       the command [cmd export]. This call has to leave the plugin in
       a state where another usage cycle can be run without problems.

[list_end]

[include include/serialization.inc]
[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

301
302
303
304
305
306
307
308
309
       the command [cmd export]. This call has to leave the plugin in
       a state where another usage cycle can be run without problems.

[list_end]

[include include/serialization.inc]
[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2idx/idx_import.man.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[vset VERSION 0.2]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin doctools::idx::import n [vset VERSION]]
[keywords conversion]
[keywords docidx]
[keywords documentation]
[keywords import]
[keywords index]
[keywords json]
[keywords {keyword index}]
[keywords manpage]
[keywords markup]
[keywords parsing]
[keywords plugin]
[keywords reference]
[keywords url]
[copyright {2009-2018 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc {Importing keyword indices}]
[category  {Documentation tools}]
[require doctools::idx::import [opt [vset VERSION]]]
[require Tcl 8.4]
[require doctools::config]
[require doctools::idx::structure]
[require snit]
[require pluginmgr]
[description]

This package provides a class to manage the plugins for the import of
keyword indices from other formats, i.e. their conversion from, for
|















|





|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[vset VERSION 0.2.1]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin doctools::idx::import n [vset VERSION]]
[keywords conversion]
[keywords docidx]
[keywords documentation]
[keywords import]
[keywords index]
[keywords json]
[keywords {keyword index}]
[keywords manpage]
[keywords markup]
[keywords parsing]
[keywords plugin]
[keywords reference]
[keywords url]
[copyright {2009-2019 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc {Importing keyword indices}]
[category  {Documentation tools}]
[require doctools::idx::import [opt [vset VERSION]]]
[require Tcl 8.4]
[require struct::map]
[require doctools::idx::structure]
[require snit]
[require pluginmgr]
[description]

This package provides a class to manage the plugins for the import of
keyword indices from other formats, i.e. their conversion from, for
387
388
389
390
391
392
393
394
395
       the command [cmd import]. This call has to leave the plugin in
       a state where another usage cycle can be run without problems.

[list_end]

[include include/serialization.inc]
[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

387
388
389
390
391
392
393
394
395
       the command [cmd import]. This call has to leave the plugin in
       a state where another usage cycle can be run without problems.

[list_end]

[include include/serialization.inc]
[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2idx/idx_introduction.man.

138
139
140
141
142
143
144
145
146
the [manpage {DocTools - Tables Of Contents}] and
the [manpage {DocTools - General}], respectively.

[section {Package Overview}]
[include include/dependencies.inc]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

138
139
140
141
142
143
144
145
146
the [manpage {DocTools - Tables Of Contents}] and
the [manpage {DocTools - General}], respectively.

[section {Package Overview}]
[include include/dependencies.inc]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2idx/idx_parse.man.

167
168
169
170
171
172
173
174
175
[list_end]
[list_end]

[include include/format/docidx.inc]
[include include/serialization.inc]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

167
168
169
170
171
172
173
174
175
[list_end]
[list_end]

[include include/format/docidx.inc]
[include include/serialization.inc]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2idx/idx_structure.man.

121
122
123
124
125
126
127
128
129
[sectref {Keyword index serialization format}].

[list_end]

[include include/serialization.inc]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

121
122
123
124
125
126
127
128
129
[sectref {Keyword index serialization format}].

[list_end]

[include include/serialization.inc]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2idx/import.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# import.tcl --
#
#	Importing indices into other formats.
#
# Copyright (c) 2009-2018 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: import.tcl,v 1.2 2011/11/17 08:00:45 andreas_kupries Exp $

# Each object manages a set of plugins for the conversion of keyword
# indices into some textual representation. I.e. this object manages
# the conversion to specialized serializations of keyword indices.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.4
package require doctools::config
package require doctools::idx::structure
package require doctools::paths
package require pluginmgr
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::doctools::idx::import {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creation, destruction.

    constructor {} {
	install myconfig  using ::doctools::config ${selfns}::config
	install myinclude using ::doctools::paths  ${selfns}::include
	return
    }

    destructor {
	$myconfig  destroy
	$myinclude destroy
	# Clear the cache of loaded import plugins.




|



<
<









|

|















|
|







1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# import.tcl --
#
#	Importing indices into other formats.
#
# Copyright (c) 2009-2019 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.



# Each object manages a set of plugins for the conversion of keyword
# indices into some textual representation. I.e. this object manages
# the conversion to specialized serializations of keyword indices.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.4
package require struct::map
package require doctools::idx::structure
package require fileutil::paths
package require pluginmgr
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::doctools::idx::import {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creation, destruction.

    constructor {} {
	install myconfig  using ::struct::map     ${selfns}::config
	install myinclude using ::fileutil::paths ${selfns}::include
	return
    }

    destructor {
	$myconfig  destroy
	$myinclude destroy
	# Clear the cache of loaded import plugins.
183
184
185
186
187
188
189
190
191
    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide doctools::idx::import 0.2
return







|

181
182
183
184
185
186
187
188
189
    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide doctools::idx::import 0.2.1
return

Changes to modules/doctools2idx/import.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
# -*- tcl -*-
# -- idx_import.test:
# -- Tests for package "doctools::idx::import": Management of import plugins.
#
# Copyright (c) 2009 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: import.test,v 1.1 2009/04/01 04:28:37 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2

support {
    use struct/list.tcl         struct::list
    use snit/snit.tcl           snit
    use fileutil/fileutil.tcl   fileutil

    use log/logger.tcl          logger
    use pluginmgr/pluginmgr.tcl pluginmgr

    use      doctools2base/config.tcl    doctools::config
    use      doctools2base/paths.tcl     doctools::paths

    source [tcllibPath doctools2base/tests/common]
}
testing {
    useLocalKeep import.tcl doctools::idx::import
}





|

<
<














>


|
<
<







1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24


25
26
27
28
29
30
31
# -*- tcl -*-
# -- idx_import.test:
# -- Tests for package "doctools::idx::import": Management of import plugins.
#
# Copyright (c) 2009-2019 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2

support {
    use struct/list.tcl         struct::list
    use snit/snit.tcl           snit
    use fileutil/fileutil.tcl   fileutil
    use fileutil/paths.tcl      fileutil::paths
    use log/logger.tcl          logger
    use pluginmgr/pluginmgr.tcl pluginmgr
    use struct/map.tcl          struct::map



    source [tcllibPath doctools2base/tests/common]
}
testing {
    useLocalKeep import.tcl doctools::idx::import
}

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

test doctools-idx-import-5.0 {config names, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I config names X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodnames type selfns win self"}

test doctools-idx-import-6.0 {config get, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I config get X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodget type selfns win self"}

test doctools-idx-import-7.0 {config set, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I config set
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodset type selfns win self name ?value?"}

test doctools-idx-import-7.1 {config set, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I config set N V X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodset type selfns win self name ?value?"}

# config unset - accepts any number of arguments.




test doctools-idx-import-8.0 {include paths, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I include paths X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::paths::Snit_methodpaths type selfns win self"}

test doctools-idx-import-9.0 {include clear, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I include clear X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::paths::Snit_methodclear type selfns win self"}

test doctools-idx-import-10.0 {include add, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I include add
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::paths::Snit_methodadd type selfns win self path"}

test doctools-idx-import-10.1 {include add, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I include add P X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::paths::Snit_methodadd type selfns win self path"}

test doctools-idx-import-11.0 {include remove, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I include remove
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::paths::Snit_methodremove type selfns win self path"}

test doctools-idx-import-11.1 {include remove, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I include remove P X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::paths::Snit_methodremove type selfns win self path"}

# -------------------------------------------------------------------------

test doctools-idx-import-12.0 {config set, define single var} -setup {
    doctools::idx::import I
} -body {
    I config set N V







|







|







|







|



>
>
>






|







|







|







|







|







|







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

test doctools-idx-import-5.0 {config names, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I config names X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodnames type selfns win self"}

test doctools-idx-import-6.0 {config get, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I config get X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodget type selfns win self"}

test doctools-idx-import-7.0 {config set, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I config set
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

test doctools-idx-import-7.1 {config set, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I config set N V X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

# config unset - accepts any number of arguments.

# -------------------------------------------------------------------------
## `include paths` component, provided via fileutil::paths, search path for includes

test doctools-idx-import-8.0 {include paths, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I include paths X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodpaths type selfns win self"}

test doctools-idx-import-9.0 {include clear, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I include clear X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodclear type selfns win self"}

test doctools-idx-import-10.0 {include add, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I include add
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodadd type selfns win self path"}

test doctools-idx-import-10.1 {include add, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I include add P X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodadd type selfns win self path"}

test doctools-idx-import-11.0 {include remove, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I include remove
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodremove type selfns win self path"}

test doctools-idx-import-11.1 {include remove, wrong#args} -setup {
    doctools::idx::import I
} -body {
    I include remove P X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodremove type selfns win self path"}

# -------------------------------------------------------------------------

test doctools-idx-import-12.0 {config set, define single var} -setup {
    doctools::idx::import I
} -body {
    I config set N V

Changes to modules/doctools2idx/include/dependencies.inc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[comment {
         ASCII diagram of the dependencies between the doctools v2 idx packages
         ======================================================================
}][example {
                                    ~~~~~~~~~~~ doctools::idx ~~~~~~~~~~~
                                   ~~                   |               ~~
                doctools::idx::export ~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ doctools::idx::import
                        |                               |                       |
        +---------------+-------------------------+     |    +------------------+---------------+-----------------------+---------------+
        |               |                         |     |    |                  |               |                       |               |
doctools::config        =                         |     |    |                  =       doctools::include       doctools::config doctools::paths
                        |                         |     |    |                  |
                doctools::idx::export::<*>        |     |    |          doctools::idx::import::<*>
                        docidx                    |     |    |                  docidx, json
                        json                      |     |    |                  |           \\
                        html                      |     |    |          doctools::idx::parse \\
                        nroff                     |     |    |                  |             \\
                        wiki                      |     |    |  +---------------+              json










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[comment {
         ASCII diagram of the dependencies between the doctools v2 idx packages
         ======================================================================
}][example {
                                    ~~~~~~~~~~~ doctools::idx ~~~~~~~~~~~
                                   ~~                   |               ~~
                doctools::idx::export ~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ doctools::idx::import
                        |                               |                       |
        +---------------+-------------------------+     |    +------------------+---------------+-----------------------+---------------+
        |               |                         |     |    |                  |               |                       |               |
struct::map             =                         |     |    |                  =       doctools::include       struct::map      fileutil::paths
                        |                         |     |    |                  |
                doctools::idx::export::<*>        |     |    |          doctools::idx::import::<*>
                        docidx                    |     |    |                  docidx, json
                        json                      |     |    |                  |           \\
                        html                      |     |    |          doctools::idx::parse \\
                        nroff                     |     |    |                  |             \\
                        wiki                      |     |    |  +---------------+              json

Changes to modules/doctools2idx/include/export/plugin.inc.

1
2
3
4
5
6
7
8
9
10
[comment {-*- tcl -*- --- !doctools ---}]
[manpage_begin doctools::idx::export::[vset PACKAGE] n [vset VERSION]]
[copyright {2009 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc "[vset NAME] export plugin"]
[category  {Text formatter plugin}]
[require Tcl 8.4]
[require doctools::idx::export::[vset PACKAGE] [opt [vset VERSION]]]
[include format/[vset REQUIRE].inc]
[keywords doctools index serialization export [vset NAME]]


|







1
2
3
4
5
6
7
8
9
10
[comment {-*- tcl -*- --- !doctools ---}]
[manpage_begin doctools::idx::export::[vset PACKAGE] n [vset VERSION]]
[copyright {2009-2019 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc "[vset NAME] export plugin"]
[category  {Text formatter plugin}]
[require Tcl 8.4]
[require doctools::idx::export::[vset PACKAGE] [opt [vset VERSION]]]
[include format/[vset REQUIRE].inc]
[keywords doctools index serialization export [vset NAME]]
47
48
49
50
51
52
53
54
55

[list_end]

[include config/[vset CONFIG].inc]
[include ../serialization.inc]

[vset CATEGORY doctools]
[include ../../../doctools2base/include/feedback.inc]
[manpage_end]







|

47
48
49
50
51
52
53
54
55

[list_end]

[include config/[vset CONFIG].inc]
[include ../serialization.inc]

[vset CATEGORY doctools]
[include ../../../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2idx/include/import/plugin.inc.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
[comment {-*- tcl -*- --- !doctools ---}]

[manpage_begin doctools::idx::import::[vset PACKAGE] n 0.1]
[copyright {2009 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc "[vset NAME] import plugin"]
[category  {Text formatter plugin}]
[require Tcl 8.4]
[require doctools::idx::import::[vset PACKAGE] [opt 0.1]]
[include format/[vset REQUIRE].inc]
[keywords doctools index deserialization import [vset NAME]]
[description]

This package implements the doctools keyword index import plugin for
the parsing of [vset NAME] markup.


>
|
|



|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[comment {-*- tcl -*- --- !doctools ---}]
[vset VERSION 0.2.1]
[manpage_begin doctools::idx::import::[vset PACKAGE] n [vset VERSION]]
[copyright {2009-2019 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc "[vset NAME] import plugin"]
[category  {Text formatter plugin}]
[require Tcl 8.5]
[require doctools::idx::import::[vset PACKAGE] [opt [vset VERSION]]]
[include format/[vset REQUIRE].inc]
[keywords doctools index deserialization import [vset NAME]]
[description]

This package implements the doctools keyword index import plugin for
the parsing of [vset NAME] markup.

47
48
49
50
51
52
53
54
55
[list_end]


[include config/[vset CONFIG].inc]
[include ../serialization.inc]

[vset CATEGORY doctools]
[include ../../../doctools2base/include/feedback.inc]
[manpage_end]







|

48
49
50
51
52
53
54
55
56
[list_end]


[include config/[vset CONFIG].inc]
[include ../serialization.inc]

[vset CATEGORY doctools]
[include ../../../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2idx/include/msgcat.inc.

38
39
40
41
42
43
44
45
46

[section API]

This package has no exported API.


[vset CATEGORY doctools]
[include ../../doctools2base/include/feedback.inc]
[manpage_end]







|

38
39
40
41
42
43
44
45
46

[section API]

This package has no exported API.


[vset CATEGORY doctools]
[include ../../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2idx/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33




if {![package vsatisfies [package provide Tcl] 8.4]} {return}

# Packages for the doctools idx v2 implementation
# (still v1.1 docidx language).

# - Index container, mutable index objects
# - Export and import management
# - Export and import plugins
# - Parser for docidx markup, and handling serializations
# - Message catalogs for the parser

package ifneeded doctools::idx                 2   [list source [file join $dir container.tcl]]

package ifneeded doctools::idx::export         0.2 [list source [file join $dir export.tcl]]
package ifneeded doctools::idx::import         0.2 [list source [file join $dir import.tcl]]

package ifneeded doctools::idx::export::docidx 0.1 [list source [file join $dir export_docidx.tcl]]
package ifneeded doctools::idx::export::html   0.2 [list source [file join $dir export_html.tcl]]
package ifneeded doctools::idx::export::json   0.1 [list source [file join $dir export_json.tcl]]
package ifneeded doctools::idx::export::nroff  0.3 [list source [file join $dir export_nroff.tcl]]
package ifneeded doctools::idx::export::text   0.2 [list source [file join $dir export_text.tcl]]
package ifneeded doctools::idx::export::wiki   0.2 [list source [file join $dir export_wiki.tcl]]

package ifneeded doctools::idx::import::docidx 0.1 [list source [file join $dir import_docidx.tcl]]
package ifneeded doctools::idx::import::json   0.1 [list source [file join $dir import_json.tcl]]

package ifneeded doctools::idx::parse          0.1 [list source [file join $dir parse.tcl]]
package ifneeded doctools::idx::structure      0.1 [list source [file join $dir structure.tcl]]

package ifneeded doctools::msgcat::idx::c      0.1 [list source [file join $dir msgcat_c.tcl]]
package ifneeded doctools::msgcat::idx::de     0.1 [list source [file join $dir msgcat_de.tcl]]
package ifneeded doctools::msgcat::idx::en     0.1 [list source [file join $dir msgcat_en.tcl]]
package ifneeded doctools::msgcat::idx::fr     0.1 [list source [file join $dir msgcat_fr.tcl]]















|
<
|
<


















>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12

13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
if {![package vsatisfies [package provide Tcl] 8.4]} {return}

# Packages for the doctools idx v2 implementation
# (still v1.1 docidx language).

# - Index container, mutable index objects
# - Export and import management
# - Export and import plugins
# - Parser for docidx markup, and handling serializations
# - Message catalogs for the parser

package ifneeded doctools::idx                 2     [list source [file join $dir container.tcl]]

package ifneeded doctools::idx::export         0.2.1 [list source [file join $dir export.tcl]]


package ifneeded doctools::idx::export::docidx 0.1 [list source [file join $dir export_docidx.tcl]]
package ifneeded doctools::idx::export::html   0.2 [list source [file join $dir export_html.tcl]]
package ifneeded doctools::idx::export::json   0.1 [list source [file join $dir export_json.tcl]]
package ifneeded doctools::idx::export::nroff  0.3 [list source [file join $dir export_nroff.tcl]]
package ifneeded doctools::idx::export::text   0.2 [list source [file join $dir export_text.tcl]]
package ifneeded doctools::idx::export::wiki   0.2 [list source [file join $dir export_wiki.tcl]]

package ifneeded doctools::idx::import::docidx 0.1 [list source [file join $dir import_docidx.tcl]]
package ifneeded doctools::idx::import::json   0.1 [list source [file join $dir import_json.tcl]]

package ifneeded doctools::idx::parse          0.1 [list source [file join $dir parse.tcl]]
package ifneeded doctools::idx::structure      0.1 [list source [file join $dir structure.tcl]]

package ifneeded doctools::msgcat::idx::c      0.1 [list source [file join $dir msgcat_c.tcl]]
package ifneeded doctools::msgcat::idx::de     0.1 [list source [file join $dir msgcat_de.tcl]]
package ifneeded doctools::msgcat::idx::en     0.1 [list source [file join $dir msgcat_en.tcl]]
package ifneeded doctools::msgcat::idx::fr     0.1 [list source [file join $dir msgcat_fr.tcl]]

if {![package vsatisfies [package provide Tcl] 8.5]} {return}

package ifneeded doctools::idx::import         0.2.1 [list source [file join $dir import.tcl]]

Changes to modules/doctools2toc/container.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26

27
28
29
30
31
32
33
34
35
36
# -*- tcl -*-
# toc.test:  Tests for the doctools::toc package. ToC management.
#
# Copyright (c) 2009 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: container.test,v 1.3 2009/11/15 05:50:03 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2

support {
    useAccel [useTcllibC] struct/tree.tcl  struct::tree
    TestAccelInit                          struct::tree

    use struct/list.tcl          struct::list
    use snit/snit.tcl            snit
    use fileutil/fileutil.tcl    fileutil

    use log/logger.tcl           logger
    use pluginmgr/pluginmgr.tcl  pluginmgr


    use doctools2base/config.tcl          doctools::config
    use doctools2base/paths.tcl           doctools::paths
    useLocal export.tcl      doctools::toc::export
    useLocal import.tcl      doctools::toc::import
    use doctools2base/nroff_manmacros.tcl doctools::nroff::man_macros

    source [tcllibPath doctools2base/tests/common]
}
testing {



|

<
<

















>


>

<
<







1
2
3
4
5


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27


28
29
30
31
32
33
34
# -*- tcl -*-
# toc.test:  Tests for the doctools::toc package. ToC management.
#
# Copyright (c) 2009-2019 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2

support {
    useAccel [useTcllibC] struct/tree.tcl  struct::tree
    TestAccelInit                          struct::tree

    use struct/list.tcl          struct::list
    use snit/snit.tcl            snit
    use fileutil/fileutil.tcl    fileutil
    use fileutil/paths.tcl       fileutil::paths
    use log/logger.tcl           logger
    use pluginmgr/pluginmgr.tcl  pluginmgr
    use struct/map.tcl           struct::map



    useLocal export.tcl      doctools::toc::export
    useLocal import.tcl      doctools::toc::import
    use doctools2base/nroff_manmacros.tcl doctools::nroff::man_macros

    source [tcllibPath doctools2base/tests/common]
}
testing {

Changes to modules/doctools2toc/export.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# export.tcl --
#
#	Exporting indices into other formats.
#
# Copyright (c) 2009-2018 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: export.tcl,v 1.2 2009/11/15 05:50:03 andreas_kupries Exp $

# Each object manages a set of plugins for the conversion of keyword
# indices into some textual representation. I.e. this object manages
# the conversion to specialized serializations of keyword indices.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.4
package require doctools::config
package require doctools::toc::structure
package require pluginmgr
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::doctools::toc::export {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creation, destruction.

    constructor {} {
	install myconfig using ::doctools::config ${selfns}::config
	return
    }

    destructor {
	$myconfig destroy
	# Clear the cache of loaded export plugins.
	foreach k [array names myplugin] {




|



<
<









|
















|







1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# export.tcl --
#
#	Exporting indices into other formats.
#
# Copyright (c) 2009-2019 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.



# Each object manages a set of plugins for the conversion of keyword
# indices into some textual representation. I.e. this object manages
# the conversion to specialized serializations of keyword indices.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.4
package require struct::map
package require doctools::toc::structure
package require pluginmgr
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::doctools::toc::export {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creation, destruction.

    constructor {} {
	install myconfig using ::struct::map ${selfns}::config
	return
    }

    destructor {
	$myconfig destroy
	# Clear the cache of loaded export plugins.
	foreach k [array names myplugin] {
117
118
119
120
121
122
123
124
125
    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide doctools::toc::export 0.2
return







|

115
116
117
118
119
120
121
122
123
    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide doctools::toc::export 0.2.1
return

Changes to modules/doctools2toc/export.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
# -*- tcl -*-
# toc.test:  tests for the doctools::toc package.
#
# Copyright (c) 2009 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: export.test,v 1.2 2009/04/29 02:10:56 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2

support {
    use fileutil/fileutil.tcl    fileutil      ;# tests/common

    use struct/list.tcl          struct::list
    use snit/snit.tcl            snit
    use log/logger.tcl           logger
    use pluginmgr/pluginmgr.tcl  pluginmgr


    use doctools2base/config.tcl          doctools::config
    useLocal structure.tcl   doctools::toc::structure
    use doctools2base/nroff_manmacros.tcl doctools::nroff::man_macros

    source [tcllibPath doctools2base/tests/common]
}
testing {
    useLocalKeep export.tcl doctools::toc::export



|

<
<

















>

<







1
2
3
4
5


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
# -*- tcl -*-
# toc.test:  tests for the doctools::toc package.
#
# Copyright (c) 2009-2019 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2

support {
    use fileutil/fileutil.tcl    fileutil      ;# tests/common

    use struct/list.tcl          struct::list
    use snit/snit.tcl            snit
    use log/logger.tcl           logger
    use pluginmgr/pluginmgr.tcl  pluginmgr
    use struct/map.tcl           struct::map


    useLocal structure.tcl   doctools::toc::structure
    use doctools2base/nroff_manmacros.tcl doctools::nroff::man_macros

    source [tcllibPath doctools2base/tests/common]
}
testing {
    useLocalKeep export.tcl doctools::toc::export
73
74
75
76
77
78
79
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

test doctools-toc-export-5.0 {config names, wrong#args} -setup {
    doctools::toc::export E
} -body {
    E config names X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodnames type selfns win self"}

test doctools-toc-export-6.0 {config get, wrong#args} -setup {
    doctools::toc::export E
} -body {
    E config get X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodget type selfns win self"}

test doctools-toc-export-7.0 {config set, wrong#args} -setup {
    doctools::toc::export E
} -body {
    E config set
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodset type selfns win self name ?value?"}

test doctools-toc-export-7.1 {config set, wrong#args} -setup {
    doctools::toc::export E
} -body {
    E config set N V X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodset type selfns win self name ?value?"}

# -------------------------------------------------------------------------

test doctools-toc-export-12.0 {config set, define single var} -setup {
    doctools::toc::export E
} -body {
    E config set N V







|







|







|







|







71
72
73
74
75
76
77
78
79
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

test doctools-toc-export-5.0 {config names, wrong#args} -setup {
    doctools::toc::export E
} -body {
    E config names X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodnames type selfns win self"}

test doctools-toc-export-6.0 {config get, wrong#args} -setup {
    doctools::toc::export E
} -body {
    E config get X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodget type selfns win self"}

test doctools-toc-export-7.0 {config set, wrong#args} -setup {
    doctools::toc::export E
} -body {
    E config set
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

test doctools-toc-export-7.1 {config set, wrong#args} -setup {
    doctools::toc::export E
} -body {
    E config set N V X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

# -------------------------------------------------------------------------

test doctools-toc-export-12.0 {config set, define single var} -setup {
    doctools::toc::export E
} -body {
    E config set N V

Changes to modules/doctools2toc/export_doctoc.man.

1
2
3
4
5
6
7
[comment {-*- tcl -*- --- doctools ---}]
[vset PACKAGE doctoc]
[vset NAME    doctoc]
[vset REQUIRE null]
[vset CONFIG  doctoc]
[vset VERSION 0.1]
[include include/export/plugin.inc]





|

1
2
3
4
5
6
7
[comment {-*- tcl -*- --- doctools ---}]
[vset PACKAGE doctoc]
[vset NAME    doctoc]
[vset REQUIRE null]
[vset CONFIG  doctoc]
[vset VERSION 0.2.1]
[include include/export/plugin.inc]

Changes to modules/doctools2toc/import.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# import.tcl --
#
#	Importing indices into other formats.
#
# Copyright (c) 2009-2018 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: import.tcl,v 1.3 2011/11/17 08:00:45 andreas_kupries Exp $

# Each object manages a set of plugins for the conversion of keyword
# indices into some textual representation. I.e. this object manages
# the conversion to specialized serializations of keyword indices.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.4
package require doctools::config
package require doctools::toc::structure
package require doctools::paths
package require pluginmgr
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::doctools::toc::import {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creation, destruction.

    constructor {} {
	install myconfig  using ::doctools::config ${selfns}::config
	install myinclude using ::doctools::paths  ${selfns}::include
	return
    }

    destructor {
	$myconfig  destroy
	$myinclude destroy
	# Clear the cache of loaded import plugins.




|



<
<









|

|















|
|







1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# import.tcl --
#
#	Importing indices into other formats.
#
# Copyright (c) 2009-2019 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.



# Each object manages a set of plugins for the conversion of keyword
# indices into some textual representation. I.e. this object manages
# the conversion to specialized serializations of keyword indices.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.4
package require struct::map
package require doctools::toc::structure
package require fileutil::paths
package require pluginmgr
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::doctools::toc::import {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creation, destruction.

    constructor {} {
	install myconfig  using ::struct::map     ${selfns}::config
	install myinclude using ::fileutil::paths ${selfns}::include
	return
    }

    destructor {
	$myconfig  destroy
	$myinclude destroy
	# Clear the cache of loaded import plugins.
183
184
185
186
187
188
189
190
191
    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide doctools::toc::import 0.2
return







|

181
182
183
184
185
186
187
188
189
    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide doctools::toc::import 0.2.1
return

Changes to modules/doctools2toc/import.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
# -*- tcl -*-
# -- toc_import.test:
# -- Tests for package "doctools::toc::import": Management of import plugins.
#
# Copyright (c) 2009 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: import.test,v 1.1 2009/04/18 21:14:18 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2

support {
    use struct/list.tcl         struct::list
    use snit/snit.tcl           snit
    use fileutil/fileutil.tcl   fileutil

    use log/logger.tcl          logger
    use pluginmgr/pluginmgr.tcl pluginmgr

    use      doctools2base/config.tcl    doctools::config
    use      doctools2base/paths.tcl     doctools::paths

    source [tcllibPath doctools2base/tests/common]
}
testing {
    useLocalKeep import.tcl doctools::toc::import
}





|

<
<














>


|
<
<







1
2
3
4
5
6


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24


25
26
27
28
29
30
31
# -*- tcl -*-
# -- toc_import.test:
# -- Tests for package "doctools::toc::import": Management of import plugins.
#
# Copyright (c) 2009-2019 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2

support {
    use struct/list.tcl         struct::list
    use snit/snit.tcl           snit
    use fileutil/fileutil.tcl   fileutil
    use fileutil/paths.tcl      fileutil::paths
    use log/logger.tcl          logger
    use pluginmgr/pluginmgr.tcl pluginmgr
    use struct/map.tcl          struct::map



    source [tcllibPath doctools2base/tests/common]
}
testing {
    useLocalKeep import.tcl doctools::toc::import
}

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

test doctools-toc-import-5.0 {config names, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I config names X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodnames type selfns win self"}

test doctools-toc-import-6.0 {config get, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I config get X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodget type selfns win self"}

test doctools-toc-import-7.0 {config set, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I config set
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodset type selfns win self name ?value?"}

test doctools-toc-import-7.1 {config set, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I config set N V X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::config::Snit_methodset type selfns win self name ?value?"}

# config unset - accepts any number of arguments.




test doctools-toc-import-8.0 {include paths, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I include paths X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::paths::Snit_methodpaths type selfns win self"}

test doctools-toc-import-9.0 {include clear, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I include clear X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::paths::Snit_methodclear type selfns win self"}

test doctools-toc-import-10.0 {include add, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I include add
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::paths::Snit_methodadd type selfns win self path"}

test doctools-toc-import-10.1 {include add, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I include add P X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::paths::Snit_methodadd type selfns win self path"}

test doctools-toc-import-11.0 {include remove, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I include remove
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::paths::Snit_methodremove type selfns win self path"}

test doctools-toc-import-11.1 {include remove, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I include remove P X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::doctools::paths::Snit_methodremove type selfns win self path"}

# -------------------------------------------------------------------------

test doctools-toc-import-12.0 {config set, define single var} -setup {
    doctools::toc::import I
} -body {
    I config set N V







|







|







|







|



>
>
>






|







|







|







|







|







|







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

test doctools-toc-import-5.0 {config names, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I config names X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodnames type selfns win self"}

test doctools-toc-import-6.0 {config get, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I config get X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodget type selfns win self"}

test doctools-toc-import-7.0 {config set, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I config set
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

test doctools-toc-import-7.1 {config set, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I config set N V X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

# config unset - accepts any number of arguments.

# -------------------------------------------------------------------------
## `include paths` component, provided via fileutil::paths, search path for includes

test doctools-toc-import-8.0 {include paths, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I include paths X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodpaths type selfns win self"}

test doctools-toc-import-9.0 {include clear, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I include clear X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodclear type selfns win self"}

test doctools-toc-import-10.0 {include add, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I include add
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodadd type selfns win self path"}

test doctools-toc-import-10.1 {include add, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I include add P X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodadd type selfns win self path"}

test doctools-toc-import-11.0 {include remove, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I include remove
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodremove type selfns win self path"}

test doctools-toc-import-11.1 {include remove, wrong#args} -setup {
    doctools::toc::import I
} -body {
    I include remove P X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodremove type selfns win self path"}

# -------------------------------------------------------------------------

test doctools-toc-import-12.0 {config set, define single var} -setup {
    doctools::toc::import I
} -body {
    I config set N V

Changes to modules/doctools2toc/include/dependencies.inc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[comment {
         ASCII diagram of the dependencies between the doctools v2 toc packages
         ======================================================================
}][example {
                                    ~~~~~~~~~~~ doctools::toc ~~~~~~~~~~~
                                   ~~                   |               ~~
                doctools::toc::export ~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ doctools::toc::import
                        |                               |                       |
        +---------------+-------------------------+     |    +------------------+---------------+-----------------------+---------------+
        |               |                         |     |    |                  |               |                       |               |
doctools::config        =                         |     |    |                  =       doctools::include       doctools::config doctools::paths
                        |                         |     |    |                  |
                doctools::toc::export::<*>        |     |    |          doctools::toc::import::<*>
                        doctoc                    |     |    |                  doctoc, json
                        json                      |     |    |                  |           \\
                        html                      |     |    |          doctools::toc::parse \\
                        nroff                     |     |    |                  |             \\
                        wiki                      |     |    |  +---------------+              json










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[comment {
         ASCII diagram of the dependencies between the doctools v2 toc packages
         ======================================================================
}][example {
                                    ~~~~~~~~~~~ doctools::toc ~~~~~~~~~~~
                                   ~~                   |               ~~
                doctools::toc::export ~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~ doctools::toc::import
                        |                               |                       |
        +---------------+-------------------------+     |    +------------------+---------------+-----------------------+---------------+
        |               |                         |     |    |                  |               |                       |               |
struct:map              =                         |     |    |                  =       doctools::include       struct::map      fileutil::paths
                        |                         |     |    |                  |
                doctools::toc::export::<*>        |     |    |          doctools::toc::import::<*>
                        doctoc                    |     |    |                  doctoc, json
                        json                      |     |    |                  |           \\
                        html                      |     |    |          doctools::toc::parse \\
                        nroff                     |     |    |                  |             \\
                        wiki                      |     |    |  +---------------+              json

Changes to modules/doctools2toc/include/export/plugin.inc.

1
2
3
4
5
6
7
8
9
10
[comment {-*- tcl -*- --- !doctools ---}]
[manpage_begin doctools::toc::export::[vset PACKAGE] n [vset VERSION]]
[copyright {2009 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc "[vset NAME] export plugin"]
[category  {Text formatter plugin}]
[require Tcl 8.4]
[require doctools::toc::export::[vset PACKAGE] [opt [vset VERSION]]]
[include format/[vset REQUIRE].inc]
[keywords doctools toc {table of contents} serialization export [vset NAME]]


|







1
2
3
4
5
6
7
8
9
10
[comment {-*- tcl -*- --- !doctools ---}]
[manpage_begin doctools::toc::export::[vset PACKAGE] n [vset VERSION]]
[copyright {2009-2019 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc "[vset NAME] export plugin"]
[category  {Text formatter plugin}]
[require Tcl 8.4]
[require doctools::toc::export::[vset PACKAGE] [opt [vset VERSION]]]
[include format/[vset REQUIRE].inc]
[keywords doctools toc {table of contents} serialization export [vset NAME]]
47
48
49
50
51
52
53
54
55

[list_end]

[include config/[vset CONFIG].inc]
[include ../serialization.inc]

[vset CATEGORY doctools]
[include ../../../doctools2base/include/feedback.inc]
[manpage_end]







|

47
48
49
50
51
52
53
54
55

[list_end]

[include config/[vset CONFIG].inc]
[include ../serialization.inc]

[vset CATEGORY doctools]
[include ../../../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2toc/include/import/plugin.inc.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
[comment {-*- tcl -*- --- !doctools ---}]

[manpage_begin doctools::toc::import::[vset PACKAGE] n 0.1]
[copyright {2009 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc "[vset NAME] import plugin"]
[category  {Text formatter plugin}]
[require Tcl 8.4]
[require doctools::toc::import::[vset PACKAGE] [opt 0.1]]
[include format/[vset REQUIRE].inc]
[keywords doctools toc {table of contents} deserialization import [vset NAME]]
[description]

This package implements the doctools table of contents import plugin
for the parsing of [vset NAME] markup.


>
|
|



|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[comment {-*- tcl -*- --- !doctools ---}]
[vset VERSION 0.2.1]
[manpage_begin doctools::toc::import::[vset PACKAGE] n [vset VERSION]]
[copyright {2009-2019 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc "[vset NAME] import plugin"]
[category  {Text formatter plugin}]
[require Tcl 8.5]
[require doctools::toc::import::[vset PACKAGE] [opt [vset VERSION]]]
[include format/[vset REQUIRE].inc]
[keywords doctools toc {table of contents} deserialization import [vset NAME]]
[description]

This package implements the doctools table of contents import plugin
for the parsing of [vset NAME] markup.

47
48
49
50
51
52
53
54
55
[list_end]


[include config/[vset CONFIG].inc]
[include ../serialization.inc]

[vset CATEGORY doctools]
[include ../../../doctools2base/include/feedback.inc]
[manpage_end]







|

48
49
50
51
52
53
54
55
56
[list_end]


[include config/[vset CONFIG].inc]
[include ../serialization.inc]

[vset CATEGORY doctools]
[include ../../../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2toc/include/msgcat.inc.

38
39
40
41
42
43
44
45
46

[section API]

This package has no exported API.


[vset CATEGORY doctools]
[include ../../doctools2base/include/feedback.inc]
[manpage_end]







|

38
39
40
41
42
43
44
45
46

[section API]

This package has no exported API.


[vset CATEGORY doctools]
[include ../../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2toc/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33




if {![package vsatisfies [package provide Tcl] 8.4]} {return}

# Packages for the doctools toc v2 implementation
# (still v1.1 doctoc language).

# - Index container, mutable toc objects
# - Export and import management
# - Export and import plugins
# - Parser for doctoc markup, and handling serializations
# - Message catalogs for the parser

package ifneeded doctools::toc                 2   [list source [file join $dir container.tcl]]

package ifneeded doctools::toc::export         0.2 [list source [file join $dir export.tcl]]
package ifneeded doctools::toc::import         0.2 [list source [file join $dir import.tcl]]

package ifneeded doctools::toc::export::doctoc 0.1 [list source [file join $dir export_doctoc.tcl]]
package ifneeded doctools::toc::export::html   0.1 [list source [file join $dir export_html.tcl]]
package ifneeded doctools::toc::export::json   0.1 [list source [file join $dir export_json.tcl]]
package ifneeded doctools::toc::export::nroff  0.2 [list source [file join $dir export_nroff.tcl]]
package ifneeded doctools::toc::export::text   0.1 [list source [file join $dir export_text.tcl]]
package ifneeded doctools::toc::export::wiki   0.1 [list source [file join $dir export_wiki.tcl]]

package ifneeded doctools::toc::import::doctoc 0.1 [list source [file join $dir import_doctoc.tcl]]
package ifneeded doctools::toc::import::json   0.1 [list source [file join $dir import_json.tcl]]

package ifneeded doctools::toc::parse          0.1 [list source [file join $dir parse.tcl]]
package ifneeded doctools::toc::structure      0.1 [list source [file join $dir structure.tcl]]

package ifneeded doctools::msgcat::toc::c      0.1 [list source [file join $dir msgcat_c.tcl]]
package ifneeded doctools::msgcat::toc::de     0.1 [list source [file join $dir msgcat_de.tcl]]
package ifneeded doctools::msgcat::toc::en     0.1 [list source [file join $dir msgcat_en.tcl]]
package ifneeded doctools::msgcat::toc::fr     0.1 [list source [file join $dir msgcat_fr.tcl]]















|
<
|
<


















>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12

13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
if {![package vsatisfies [package provide Tcl] 8.4]} {return}

# Packages for the doctools toc v2 implementation
# (still v1.1 doctoc language).

# - Index container, mutable toc objects
# - Export and import management
# - Export and import plugins
# - Parser for doctoc markup, and handling serializations
# - Message catalogs for the parser

package ifneeded doctools::toc                 2     [list source [file join $dir container.tcl]]

package ifneeded doctools::toc::export         0.2.1 [list source [file join $dir export.tcl]]


package ifneeded doctools::toc::export::doctoc 0.1 [list source [file join $dir export_doctoc.tcl]]
package ifneeded doctools::toc::export::html   0.1 [list source [file join $dir export_html.tcl]]
package ifneeded doctools::toc::export::json   0.1 [list source [file join $dir export_json.tcl]]
package ifneeded doctools::toc::export::nroff  0.2 [list source [file join $dir export_nroff.tcl]]
package ifneeded doctools::toc::export::text   0.1 [list source [file join $dir export_text.tcl]]
package ifneeded doctools::toc::export::wiki   0.1 [list source [file join $dir export_wiki.tcl]]

package ifneeded doctools::toc::import::doctoc 0.1 [list source [file join $dir import_doctoc.tcl]]
package ifneeded doctools::toc::import::json   0.1 [list source [file join $dir import_json.tcl]]

package ifneeded doctools::toc::parse          0.1 [list source [file join $dir parse.tcl]]
package ifneeded doctools::toc::structure      0.1 [list source [file join $dir structure.tcl]]

package ifneeded doctools::msgcat::toc::c      0.1 [list source [file join $dir msgcat_c.tcl]]
package ifneeded doctools::msgcat::toc::de     0.1 [list source [file join $dir msgcat_de.tcl]]
package ifneeded doctools::msgcat::toc::en     0.1 [list source [file join $dir msgcat_en.tcl]]
package ifneeded doctools::msgcat::toc::fr     0.1 [list source [file join $dir msgcat_fr.tcl]]

if {![package vsatisfies [package provide Tcl] 8.5]} {return}

package ifneeded doctools::toc::import         0.2.1 [list source [file join $dir import.tcl]]

Changes to modules/doctools2toc/toc_container.man.

362
363
364
365
366
367
368
369
370
In that case an error will be thrown if the container has no export
manager attached to it.

[list_end]

[include include/serialization.inc]
[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

362
363
364
365
366
367
368
369
370
In that case an error will be thrown if the container has no export
manager attached to it.

[list_end]

[include include/serialization.inc]
[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2toc/toc_export.man.

1
2
3
4
5
6
7
8
[vset VERSION 0.2]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin doctools::toc::export n [vset VERSION]]
[keywords conversion]
[keywords doctoc]
[keywords documentation]
[keywords export]
[keywords formatting]
|







1
2
3
4
5
6
7
8
[vset VERSION 0.2.1]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin doctools::toc::export n [vset VERSION]]
[keywords conversion]
[keywords doctoc]
[keywords documentation]
[keywords export]
[keywords formatting]
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[keywords reference]
[keywords table]
[keywords {table of contents}]
[keywords {tcler's wiki}]
[keywords text]
[keywords url]
[keywords wiki]
[copyright {2009-2018 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc {Exporting tables of contents}]
[category  {Documentation tools}]
[require doctools::toc::export [opt [vset VERSION]]]
[require Tcl 8.4]
[require doctools::config]
[require doctools::toc::structure]
[require snit]
[require pluginmgr]
[description]

This package provides a class to manage the plugins for the export of
tables of contents to other formats, i.e. their conversion to, for







|





|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[keywords reference]
[keywords table]
[keywords {table of contents}]
[keywords {tcler's wiki}]
[keywords text]
[keywords url]
[keywords wiki]
[copyright {2009-2019 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc {Exporting tables of contents}]
[category  {Documentation tools}]
[require doctools::toc::export [opt [vset VERSION]]]
[require Tcl 8.4]
[require struct::map]
[require doctools::toc::structure]
[require snit]
[require pluginmgr]
[description]

This package provides a class to manage the plugins for the export of
tables of contents to other formats, i.e. their conversion to, for
299
300
301
302
303
304
305
306
307
       the command [cmd export]. This call has to leave the plugin in
       a state where another usage cycle can be run without problems.

[list_end]

[include include/serialization.inc]
[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

299
300
301
302
303
304
305
306
307
       the command [cmd export]. This call has to leave the plugin in
       a state where another usage cycle can be run without problems.

[list_end]

[include include/serialization.inc]
[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2toc/toc_import.man.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[vset VERSION 0.2]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin doctools::toc::import n [vset VERSION]]
[keywords conversion]
[keywords doctoc]
[keywords documentation]
[keywords import]
[keywords json]
[keywords manpage]
[keywords markup]
[keywords parsing]
[keywords plugin]
[keywords reference]
[keywords table]
[keywords {table of contents}]
[keywords url]
[copyright {2009-2018 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc {Importing keyword indices}]
[category  {Documentation tools}]
[require doctools::toc::import [opt [vset VERSION]]]
[require Tcl 8.4]
[require doctools::config]
[require doctools::toc::structure]
[require snit]
[require pluginmgr]
[description]

This package provides a class to manage the plugins for the import of
tables of contents from other formats, i.e. their conversion from, for
|















|





|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[vset VERSION 0.2.1]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin doctools::toc::import n [vset VERSION]]
[keywords conversion]
[keywords doctoc]
[keywords documentation]
[keywords import]
[keywords json]
[keywords manpage]
[keywords markup]
[keywords parsing]
[keywords plugin]
[keywords reference]
[keywords table]
[keywords {table of contents}]
[keywords url]
[copyright {2009-2019 Andreas Kupries <[email protected]>}]
[moddesc   {Documentation tools}]
[titledesc {Importing keyword indices}]
[category  {Documentation tools}]
[require doctools::toc::import [opt [vset VERSION]]]
[require Tcl 8.4]
[require struct::map]
[require doctools::toc::structure]
[require snit]
[require pluginmgr]
[description]

This package provides a class to manage the plugins for the import of
tables of contents from other formats, i.e. their conversion from, for
387
388
389
390
391
392
393
394
395
       the command [cmd import]. This call has to leave the plugin in
       a state where another usage cycle can be run without problems.

[list_end]

[include include/serialization.inc]
[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

387
388
389
390
391
392
393
394
395
       the command [cmd import]. This call has to leave the plugin in
       a state where another usage cycle can be run without problems.

[list_end]

[include include/serialization.inc]
[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2toc/toc_introduction.man.

135
136
137
138
139
140
141
142
143
the [manpage {DocTools - Keyword Indices}] and
the [manpage {DocTools - General}], respectively.

[section {Package Overview}]
[include include/dependencies.inc]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

135
136
137
138
139
140
141
142
143
the [manpage {DocTools - Keyword Indices}] and
the [manpage {DocTools - General}], respectively.

[section {Package Overview}]
[include include/dependencies.inc]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2toc/toc_parse.man.

167
168
169
170
171
172
173
174
175
[list_end]
[list_end]

[include include/format/doctoc.inc]
[include include/serialization.inc]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

167
168
169
170
171
172
173
174
175
[list_end]
[list_end]

[include include/format/doctoc.inc]
[include include/serialization.inc]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/doctools2toc/toc_structure.man.

143
144
145
146
147
148
149
150
151
section [sectref {ToC serialization format}].

[list_end]

[include include/serialization.inc]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

143
144
145
146
147
148
149
150
151
section [sectref {ToC serialization format}].

[list_end]

[include include/serialization.inc]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/dtplite/pkg_dtplite.man.

441
442
443
444
445
446
447
448
449

They are left in place, i.e. not deleted, to serve as demonstrations
of doctoc and docidx markup.

[list_end]

[vset CATEGORY doctools]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

441
442
443
444
445
446
447
448
449

They are left in place, i.e. not deleted, to serve as demonstrations
of doctoc and docidx markup.

[list_end]

[vset CATEGORY doctools]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/exif/exif.man.

72
73
74
75
76
77
78
79
80

[section ACKNOWLEDGEMENTS]

This code is a direct translation of version 1.3 of exif.pl by Chris
Breeze.  See the source for full headers, references, etc.

[vset CATEGORY exif]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

72
73
74
75
76
77
78
79
80

[section ACKNOWLEDGEMENTS]

This code is a direct translation of version 1.3 of exif.pl by Chris
Breeze.  See the source for full headers, references, etc.

[vset CATEGORY exif]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/exif/exif.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# -*- tcl -*-
# exif.test:  tests for the exif structure.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2001-2006 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: exif.test,v 1.6 2006/10/09 21:41:40 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.3
testsNeedTcltest 1.0

testing {
    useLocal exif.tcl exif
}

# -------------------------------------------------------------------------

test exif-makernote-19.0 {makernote field 19 (afpoint) is optional} {
    # AFPoint == AutoFocus Point

    set f [open [file join $::tcltest::testsDirectory noafpoint.jpg] r]
    fconfigure $f -translation binary
    array set resa [exif::analyze $f]
    close $f
    set resa(FocalPlaneXResolution) [format %13.8f $resa(FocalPlaneXResolution)]
    set resa(FocalPlaneYResolution) [format %13.8f $resa(FocalPlaneYResolution)]
    set res [dictsort [array get resa]]
    unset resa
    set res
} {AFPointsUsed {3 right} AperatureValue 7.1 AutoFocusMode {AI servo} CameraMake Canon CameraModel {Canon PowerShot S100} ColorSpace 1 ComponentsConfigured 0x00030201 Contrast Normal DateTime {2004:09:06 05:22:56} DateTimeDigitized {2004:09:06 05:22:56} DateTimeOriginal {2004:09:06 05:22:56} ExifImageHeight 1200 ExifImageWidth 1600 ExifInteroperabilityOffset 1088 ExifVersion 0210 ExposureBiasValue 0 ExposureTime {1/250.0 seconds} FNumber 7.1 FileSource {3 - Digital camera} FirmwareVersion {Firmware Version 1.0} Flash no FlashMode auto FlashPixVersion 0100 FocalLength {5.40625 mm} FocalPlaneResolutionUnit inch FocalPlaneXResolution 7766.99029126 FocalPlaneYResolution 7741.93548387 ISO unknown ImageFormat {IMG:JPEG file} ImageNumber 140-4060 ImageQuality Fine ImageSize large MacroMode normal MeteringMode unknown Orientation 1 Owner Irochka ResolutionUnit inch Saturation Normal SensingMethod 2 Sharpness Normal ShootingMode {Single frame} ShutterSpeedValue {250 Hz} SubjectDistance {3.358 m} UnknownTag-0x10 100925440 UserComment {554 - } WhiteBalance Auto XResolution 180.0 YCbCrPositioning {Center of pixel array} YResolution 180.0}

testsuiteCleanup









<
<



















|











1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# -*- tcl -*-
# exif.test:  tests for the exif structure.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2001-2006 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.3
testsNeedTcltest 1.0

testing {
    useLocal exif.tcl exif
}

# -------------------------------------------------------------------------

test exif-makernote-19.0 {makernote field 19 (afpoint) is optional} {
    # AFPoint == AutoFocus Point

    set f [open [asset noafpoint.jpg] r]
    fconfigure $f -translation binary
    array set resa [exif::analyze $f]
    close $f
    set resa(FocalPlaneXResolution) [format %13.8f $resa(FocalPlaneXResolution)]
    set resa(FocalPlaneYResolution) [format %13.8f $resa(FocalPlaneYResolution)]
    set res [dictsort [array get resa]]
    unset resa
    set res
} {AFPointsUsed {3 right} AperatureValue 7.1 AutoFocusMode {AI servo} CameraMake Canon CameraModel {Canon PowerShot S100} ColorSpace 1 ComponentsConfigured 0x00030201 Contrast Normal DateTime {2004:09:06 05:22:56} DateTimeDigitized {2004:09:06 05:22:56} DateTimeOriginal {2004:09:06 05:22:56} ExifImageHeight 1200 ExifImageWidth 1600 ExifInteroperabilityOffset 1088 ExifVersion 0210 ExposureBiasValue 0 ExposureTime {1/250.0 seconds} FNumber 7.1 FileSource {3 - Digital camera} FirmwareVersion {Firmware Version 1.0} Flash no FlashMode auto FlashPixVersion 0100 FocalLength {5.40625 mm} FocalPlaneResolutionUnit inch FocalPlaneXResolution 7766.99029126 FocalPlaneYResolution 7741.93548387 ISO unknown ImageFormat {IMG:JPEG file} ImageNumber 140-4060 ImageQuality Fine ImageSize large MacroMode normal MeteringMode unknown Orientation 1 Owner Irochka ResolutionUnit inch Saturation Normal SensingMethod 2 Sharpness Normal ShootingMode {Single frame} ShutterSpeedValue {250 Hz} SubjectDistance {3.358 m} UnknownTag-0x10 100925440 UserComment {554 - } WhiteBalance Auto XResolution 180.0 YCbCrPositioning {Center of pixel array} YResolution 180.0}

testsuiteCleanup

Deleted modules/exif/noafpoint.jpg.

cannot compute difference between binary files

Added modules/exif/test-assets/noafpoint.jpg.

cannot compute difference between binary files

Changes to modules/fileutil/filetype.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- tcl -*-
# Tests for the find function.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
# Copyright (c) 2001 by ActiveState Tool Corp.
# Copyright (c) 2005-2007,2017 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: filetype.test,v 1.1 2007/08/03 23:07:25 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]











<
<







1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
# -*- tcl -*-
# Tests for the find function.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
# Copyright (c) 2001 by ActiveState Tool Corp.
# Copyright (c) 2005-2007,2017 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

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
    set f [makeGzipFile]
    set res [catch {fileutil::fileType $f} msg]
    removeGzipFile
    list $res $msg
} [list 0 [list binary compressed gzip]]

test fileType-1.22 {text pdf} {
    set f [localPath test-data/pdf4tcl_01.pdf]
    set res [catch {fileutil::fileType $f} msg]
    list $res $msg
} [list 0 [list text pdf]]

# -------------------------------------------------------------------------

test fileType-1.23 {sqlite3, fossil repo} {
    set f [localPath test-data/p.fossil]
    set res [catch {fileutil::fileType $f} msg]
    list $res $msg
} [list 0 [list binary sqlite3 fossil-repository]]

test fileType-1.24 {sqlite3, fossil checkout} {
    set f [localPath test-data/p.ckout]
    set res [catch {fileutil::fileType $f} msg]
    list $res $msg
} [list 0 [list binary sqlite3 fossil-checkout]]

test fileType-1.25 {sqlite3, fossil global config} {
    set f [localPath test-data/p.global]
    set res [catch {fileutil::fileType $f} msg]
    list $res $msg
} [list 0 [list binary sqlite3 fossil-global-config]]

test fileType-1.26 {sqlite3, no app} {
    set f [localPath test-data/p.sqlite]
    set res [catch {fileutil::fileType $f} msg]
    list $res $msg
} [list 0 [list binary sqlite3 A00000000]]

# -------------------------------------------------------------------------

unset path
testsuiteCleanup
return







|







|





|





|





|









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
    set f [makeGzipFile]
    set res [catch {fileutil::fileType $f} msg]
    removeGzipFile
    list $res $msg
} [list 0 [list binary compressed gzip]]

test fileType-1.22 {text pdf} {
    set f [asset pdf4tcl_01.pdf]
    set res [catch {fileutil::fileType $f} msg]
    list $res $msg
} [list 0 [list text pdf]]

# -------------------------------------------------------------------------

test fileType-1.23 {sqlite3, fossil repo} {
    set f [asset p.fossil]
    set res [catch {fileutil::fileType $f} msg]
    list $res $msg
} [list 0 [list binary sqlite3 fossil-repository]]

test fileType-1.24 {sqlite3, fossil checkout} {
    set f [asset p.ckout]
    set res [catch {fileutil::fileType $f} msg]
    list $res $msg
} [list 0 [list binary sqlite3 fossil-checkout]]

test fileType-1.25 {sqlite3, fossil global config} {
    set f [asset p.global]
    set res [catch {fileutil::fileType $f} msg]
    list $res $msg
} [list 0 [list binary sqlite3 fossil-global-config]]

test fileType-1.26 {sqlite3, no app} {
    set f [asset p.sqlite]
    set res [catch {fileutil::fileType $f} msg]
    list $res $msg
} [list 0 [list binary sqlite3 A00000000]]

# -------------------------------------------------------------------------

unset path
testsuiteCleanup
return

Changes to modules/fileutil/fileutil.man.

514
515
516
517
518
519
520
521
522
option to prevent the traverser from following symbolic links, like so:

[include include/cross-index-trav.inc]

[list_end]

[vset CATEGORY fileutil]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

514
515
516
517
518
519
520
521
522
option to prevent the traverser from following symbolic links, like so:

[include include/cross-index-trav.inc]

[list_end]

[vset CATEGORY fileutil]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/fileutil/fileutil.tcl.

622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
	}
	return $path
    }
}

# ::fileutil::jail --
#
#	Ensures that the input path 'filename' stays within the the
#	directory 'jail'. In this way it preventsuser-supplied paths
#	from escaping the jail.
#
# Arguments:
#	jail		The path to the directory the other must
#			not escape from.
#	filename	The path to prevent from escaping.
#







|
|







622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
	}
	return $path
    }
}

# ::fileutil::jail --
#
#	Ensures that the input path 'filename' stays within the
#	directory 'jail'. In this way it prevents user-supplied paths
#	from escaping the jail.
#
# Arguments:
#	jail		The path to the directory the other must
#			not escape from.
#	filename	The path to prevent from escaping.
#

Changes to modules/fileutil/multi.man.

48
49
50
51
52
53
54
55
56

The result of the command is the result generated by the last file
command it executed.

[list_end]

[vset CATEGORY fileutil]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

48
49
50
51
52
53
54
55
56

The result of the command is the result generated by the last file
command it executed.

[list_end]

[vset CATEGORY fileutil]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/fileutil/multiop.man.

394
395
396
397
398
399
400
401
402
    into /scratch           \\
    but not *.html not index \\
    the  index               \\
    as   pkgIndex.tcl
}]

[vset CATEGORY fileutil]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

394
395
396
397
398
399
400
401
402
    into /scratch           \\
    but not *.html not index \\
    the  index               \\
    as   pkgIndex.tcl
}]

[vset CATEGORY fileutil]
[include ../common-text/feedback.inc]
[manpage_end]

Added modules/fileutil/paths.man.

























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
[comment {-*- text -*- doctools manpage}]
[vset VERSION 1]
[manpage_begin fileutil::paths n [vset VERSION]]
[titledesc {Manage search path pools}]
[require Tcl 8.4]
[require fileutil::paths [opt [vset VERSION]]]
[description]

Provides a snit class whose instances manage a pool of (search) paths.

[section API]

The main command provides construction of search path pools:

[list_begin definitions]

[call [cmd ::fileutil::paths] [arg poolName]]

Creates a new, empty pool of search paths with an associated global
Tcl command whose name is [arg poolName].

It may be used to invoke various operations on the pool.

It has the following general form:

[list_begin definitions]
[call [cmd poolName] [method method] [opt [arg "arg arg ..."]]]
[method method] and [arg arg]uments determine the exact behavior of
the command.
[list_end][comment --instance-command--]

If [arg poolName] is specified as [const %AUTO%] a unique name will be
generated by the package itself.

The result of the command is the fully-qualified name of the instance
command. 

[list_end][comment --class-command--]

[para]

The following commands are possible for pool objects:

[list_begin definitions]

[call [arg poolName] [method add] [arg path]]

Adds the [arg path] to the pool.

Nothing is done if the [arg path] is already known to the pool.

The result of the command is the empty string.

[call [arg poolName] [method clear]]

Clears the entire pool. In other words, removes all paths from it.

The result of the command is the empty string.

[call [arg poolName] [method paths]]

Returns the list of all paths known to the pool, in the order they
were added.

[call [arg poolName] [method remove] [arg path]]

Removes the [arg path] from the pool, if it is known to the pool.

Unknown paths are ignored without error.

The result of the command is the empty string.

[list_end]

[include ../common-text/feedback.inc]
[manpage_end]

Added modules/fileutil/paths.tcl.





















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# paths.tcl --
#
#	Manage lists of search paths.
#
# Copyright (c) 2009-2019 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# Each object instance manages a list of paths.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.4
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::fileutil::paths {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creation, destruction

    # Default constructor.
    # Default destructor.

    # ### ### ### ######### ######### #########
    ## Methods :: Querying and manipulating the list of paths.

    method paths {} {
	return $mypaths
    }

    method add {path} {
	set pos [lsearch $mypaths $path]
	if {$pos >= 0 } return
	lappend mypaths $path
	return
    }

    method remove {path} {
	set pos [lsearch $mypaths $path]
	if {$pos < 0} return
	set mypaths [lreplace $mypaths $pos $pos]
	return
    }

    method clear {} {
	set mypaths {}
	return
    }

    # ### ### ### ######### ######### #########
    ## Internal methods :: None

    # ### ### ### ######### ######### #########
    ## State :: List of paths.

    variable mypaths {}

    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide fileutil::paths 1
return

Added modules/fileutil/paths.test.















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# -*- tcl -*-
# paths.test:  Testsuite for package fileutil::paths
#
# Copyright (c) 2019 by Andreas Kupries <[email protected]>
# All rights reserved.

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2.0

support {
    use snit/snit.tcl snit
}    
testing {
    useLocal paths.tcl fileutil::paths
}

# ---------------------------------------------------------------------
# [] constructor
# [] destructor
# [] paths
# [] add
# [] remove
# [] clear

#----------------------------------------------------------------------
## Constructor, destructor

test fileutil-paths-1.0 {constructor, wrong args, too many} -body {
    fileutil::paths P X
} -returnCodes error -result {Error in constructor: wrong # args: should be "::fileutil::paths::Snit_constructor type selfns win self"}

test fileutil-paths-1.1 {instance, bogus method} -setup {
    fileutil::paths P
} -cleanup {
    P destroy
} -body {
    P bogus
} -returnCodes error -result {"::P bogus" is not defined}

#----------------------------------------------------------------------
## paths

test fileutil-paths-2.0 {paths, wrong args, too many} -setup {
    fileutil::paths P
} -cleanup {
    P destroy
} -body {
    P paths X
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodpaths type selfns win self"}

test fileutil-paths-2.1 {paths, base state, none} -setup {
    fileutil::paths P
} -cleanup {
    P destroy
} -body {
    P paths
} -result {}

#----------------------------------------------------------------------
## add

test fileutil-paths-3.0 {add, wrong args, not enough} -setup {
    fileutil::paths P
} -cleanup {
    P destroy
} -body {
    P add
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodadd type selfns win self path"}

test fileutil-paths-3.1 {add, wrong args, too many} -setup {
    fileutil::paths P
} -cleanup {
    P destroy
} -body {
    P add F X
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodadd type selfns win self path"}

test fileutil-paths-3.2 {add, state change, result} -setup {
    fileutil::paths P
} -cleanup {
    P destroy
} -body {
    list [P add F] [P paths]
} -result {{} F}

#----------------------------------------------------------------------
## remove

test fileutil-paths-4.0 {remove, wrong args, not enough} -setup {
    fileutil::paths P
} -cleanup {
    P destroy
} -body {
    P remove
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodremove type selfns win self path"}

test fileutil-paths-4.1 {remove, wrong args, too many} -setup {
    fileutil::paths P
} -cleanup {
    P destroy
} -body {
    P remove F X
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodremove type selfns win self path"}

test fileutil-paths-4.2 {remove, known path, state change, result} -setup {
    fileutil::paths P
    P add F
} -cleanup {
    P destroy
} -body {
    list [P remove F] [P paths]
} -result {{} {}}

test fileutil-paths-4.3 {remove, missing path, no state change, result} -setup {
    fileutil::paths P
    P add Z
} -cleanup {
    P destroy
} -body {
    list [P remove F] [P paths]
} -result {{} Z}

#----------------------------------------------------------------------
## clear

test fileutil-paths-5.0 {clear, wrong args, too many} -setup {
    fileutil::paths P
} -cleanup {
    P destroy
} -body {
    P clear X
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodclear type selfns win self"}

test fileutil-paths-5.1 {clear, return to base state} -setup {
    fileutil::paths P
    P add F
} -cleanup {
    P destroy
} -body {
    list [P clear] [P paths]
} -result {{} {}}

#----------------------------------------------------------------------
testsuiteCleanup
return

Changes to modules/fileutil/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10





if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded fileutil 1.16 [list source [file join $dir fileutil.tcl]]

if {![package vsatisfies [package provide Tcl] 8.3]} {return}
package ifneeded fileutil::traverse 0.6 [list source [file join $dir traverse.tcl]]

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded fileutil::multi     0.1   [list source [file join $dir multi.tcl]]
package ifneeded fileutil::multi::op 0.5.3 [list source [file join $dir multiop.tcl]]
package ifneeded fileutil::decode    0.2.1 [list source [file join $dir decode.tcl]]















>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded fileutil 1.16 [list source [file join $dir fileutil.tcl]]

if {![package vsatisfies [package provide Tcl] 8.3]} {return}
package ifneeded fileutil::traverse 0.6 [list source [file join $dir traverse.tcl]]

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded fileutil::multi     0.1   [list source [file join $dir multi.tcl]]
package ifneeded fileutil::multi::op 0.5.3 [list source [file join $dir multiop.tcl]]
package ifneeded fileutil::decode    0.2.1 [list source [file join $dir decode.tcl]]
package ifneeded fileutil::paths     1     [list source [file join $dir paths.tcl]]

if {![package vsatisfies [package provide Tcl] 8.5]} return

if {![package vsatisfies [package provide Tcl] 8.6]} return

Added modules/fileutil/test-assets/p.ckout.

cannot compute difference between binary files

Added modules/fileutil/test-assets/p.fossil.

cannot compute difference between binary files

Added modules/fileutil/test-assets/p.global.

cannot compute difference between binary files

Added modules/fileutil/test-assets/p.sqlite.

cannot compute difference between binary files

Added modules/fileutil/test-assets/pdf4tcl_01.pdf.







































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
%PDF-1.4
%���
5 0 obj
<<
/Length 6 0 R
>>
stream
/Courier 12 Tf
0 Tr
12 TL
BT
(Hello) Tj

ET

endstream
endobj

6 0 obj
45
endobj

4 0 obj
<</Type /Page
/Parent 2 0 R
/Resources 3 0 R
/MediaBox [0 0 595 842]
/Contents [5 0 R]
>>
endobj

7 0 obj
<<
/Type /Font
/Subtype /Type1
/Encoding /WinAnsiEncoding
/Name /Courier
/BaseFont /Courier
>>
endobj
1 0 obj
<<
/Type /Catalog
/Pages 2 0 R
>>
endobj

2 0 obj
<<
/Type /Pages
/Count 1
/Kids [4 0 R ]
>>
endobj

3 0 obj
<<
/ProcSet[/PDF /Text /ImageC]
/Font <<
/Courier 7 0 R
>>
>>
endobj

xref
0 8
0000000000 65535 f 
0000000347 00000 n 
0000000397 00000 n 
0000000456 00000 n 
0000000131 00000 n 
0000000014 00000 n 
0000000112 00000 n 
0000000237 00000 n 
trailer
<<
/Size 8
/Root 1 0 R
>>

startxref
534
%%EOF

Deleted modules/fileutil/test-data/p.ckout.

cannot compute difference between binary files

Deleted modules/fileutil/test-data/p.fossil.

cannot compute difference between binary files

Deleted modules/fileutil/test-data/p.global.

cannot compute difference between binary files

Deleted modules/fileutil/test-data/p.sqlite.

cannot compute difference between binary files

Deleted modules/fileutil/test-data/pdf4tcl_01.pdf.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
%PDF-1.4
%���
5 0 obj
<<
/Length 6 0 R
>>
stream
/Courier 12 Tf
0 Tr
12 TL
BT
(Hello) Tj

ET

endstream
endobj

6 0 obj
45
endobj

4 0 obj
<</Type /Page
/Parent 2 0 R
/Resources 3 0 R
/MediaBox [0 0 595 842]
/Contents [5 0 R]
>>
endobj

7 0 obj
<<
/Type /Font
/Subtype /Type1
/Encoding /WinAnsiEncoding
/Name /Courier
/BaseFont /Courier
>>
endobj
1 0 obj
<<
/Type /Catalog
/Pages 2 0 R
>>
endobj

2 0 obj
<<
/Type /Pages
/Count 1
/Kids [4 0 R ]
>>
endobj

3 0 obj
<<
/ProcSet[/PDF /Text /ImageC]
/Font <<
/Courier 7 0 R
>>
>>
endobj

xref
0 8
0000000000 65535 f 
0000000347 00000 n 
0000000397 00000 n 
0000000456 00000 n 
0000000131 00000 n 
0000000014 00000 n 
0000000112 00000 n 
0000000237 00000 n 
trailer
<<
/Size 8
/Root 1 0 R
>>

startxref
534
%%EOF
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






































































































































































Changes to modules/fileutil/traverse.man.

157
158
159
160
161
162
163
164
165
traverser from following symbolic links, like so:

[include include/cross-index-trav.inc]

[list_end]

[vset CATEGORY fileutil]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

157
158
159
160
161
162
163
164
165
traverser from following symbolic links, like so:

[include include/cross-index-trav.inc]

[list_end]

[vset CATEGORY fileutil]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/ftp/ftp.man.

432
433
434
435
436
437
438
439
440
[para]

An update command placed in the procedure [cmd ::ftp::DisplayMsg] may
run into persistent errors or infinite loops. The solution to this
problem is to use [cmd {update idletasks}] instead of [cmd update].

[vset CATEGORY ftp]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

432
433
434
435
436
437
438
439
440
[para]

An update command placed in the procedure [cmd ::ftp::DisplayMsg] may
run into persistent errors or infinite loops. The solution to this
problem is to use [cmd {update idletasks}] instead of [cmd update].

[vset CATEGORY ftp]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/ftp/ftp_geturl.man.

49
50
51
52
53
54
55
56
57

The attributes of the link, including the path it refers to.

[list_end]
[list_end]

[vset CATEGORY ftp]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

49
50
51
52
53
54
55
56
57

The attributes of the link, including the path it refers to.

[list_end]
[list_end]

[vset CATEGORY ftp]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/ftpd/ftpd.man.

271
272
273
274
275
276
277
278
279
Accessible to all callbacks and all filesystem commands (which are a
special form of callback) and contains the handle of the socket
channel which was active when the callback was invoked.

[list_end]

[vset CATEGORY ftpd]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

271
272
273
274
275
276
277
278
279
Accessible to all callbacks and all filesystem commands (which are a
special form of callback) and contains the handle of the socket
channel which was active when the callback was invoked.

[list_end]

[vset CATEGORY ftpd]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/fumagic/cfront.man.

63
64
65
66
67
68
69
70
71
The name of each new procedure is derived from the name of the
file/directory used in its creation, with file/directory [file FOO]
causing the creation of procedure [const ::fileutil::magic::/FOO::run].

[list_end]

[vset CATEGORY {fileutil :: magic}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

63
64
65
66
67
68
69
70
71
The name of each new procedure is derived from the name of the
file/directory used in its creation, with file/directory [file FOO]
causing the creation of procedure [const ::fileutil::magic::/FOO::run].

[list_end]

[vset CATEGORY {fileutil :: magic}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/fumagic/cgen.man.

55
56
57
58
59
60
61
62
63
The generated script makes extensive use of the commands provided by
the recognizer runtime package [package fileutil::magic::rt] to
perform its duties.

[list_end]

[vset CATEGORY {fileutil :: magic}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

55
56
57
58
59
60
61
62
63
The generated script makes extensive use of the commands provided by
the recognizer runtime package [package fileutil::magic::rt] to
perform its duties.

[list_end]

[vset CATEGORY {fileutil :: magic}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/fumagic/filetypes.man.

54
55
56
57
58
59
60
61
62
This site contains the current sources for the file command, including
the magic definitions used by it. The latter were used by us to
generate this recognizer.

[list_end]

[vset CATEGORY {fileutil :: magic}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

54
55
56
57
58
59
60
61
62
This site contains the current sources for the file command, including
the magic definitions used by it. The latter were used by us to
generate this recognizer.

[list_end]

[vset CATEGORY {fileutil :: magic}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/fumagic/filetypes.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# -*- tcl -*-
#
# Testing "fumagic" (FileUtil Magic). Filetype recognizer.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2005-2006 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: filetypes.test,v 1.9 2006/10/09 21:41:40 andreas_kupries Exp $

# -------------------------------------------------------------------------

package require tcltest
source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]









<
<







1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
# -*- tcl -*-
#
# Testing "fumagic" (FileUtil Magic). Filetype recognizer.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2005-2006 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

package require tcltest
source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

Changes to modules/fumagic/rtcore.man.

243
244
245
246
247
248
249
250
251
[def [const ledate]]  see above, stored in small/little endian
[def [const ldate]]   32-bit integer timestamp, stored in native endianess
[def [const beldate]] see above, stored in big endian
[def [const leldate]] see above, stored in small/little endian
[list_end]

[vset CATEGORY {fileutil :: magic}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

243
244
245
246
247
248
249
250
251
[def [const ledate]]  see above, stored in small/little endian
[def [const ldate]]   32-bit integer timestamp, stored in native endianess
[def [const beldate]] see above, stored in big endian
[def [const leldate]] see above, stored in small/little endian
[list_end]

[vset CATEGORY {fileutil :: magic}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/gpx/gpx.man.

150
151
152
153
154
155
156
157
158

[list_end]

[section AUTHOR]
Keith Vetter

[vset CATEGORY gpx]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

150
151
152
153
154
155
156
157
158

[list_end]

[section AUTHOR]
Keith Vetter

[vset CATEGORY gpx]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/grammar_fa/dacceptor.man.

94
95
96
97
98
99
100
101
102
[list_end]

[para]

[section EXAMPLES]

[vset CATEGORY grammar_fa]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

94
95
96
97
98
99
100
101
102
[list_end]

[para]

[section EXAMPLES]

[vset CATEGORY grammar_fa]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/grammar_fa/dexec.man.

175
176
177
178
179
180
181
182
183
[list_end]

[para]

[section EXAMPLES]

[vset CATEGORY grammar_fa]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

175
176
177
178
179
180
181
182
183
[list_end]

[para]

[section EXAMPLES]

[vset CATEGORY grammar_fa]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/grammar_fa/fa.man.

644
645
646
647
648
649
650
651
652

[para]

Transducers are not handled by this package. They will get their own
package in the future.

[vset CATEGORY grammar_fa]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

644
645
646
647
648
649
650
651
652

[para]

Transducers are not handled by this package. They will get their own
package in the future.

[vset CATEGORY grammar_fa]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/grammar_fa/faop.man.

472
473
474
475
476
477
478
479
480
[list_end]

[para]

[section EXAMPLES]

[vset CATEGORY grammar_fa]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

472
473
474
475
476
477
478
479
480
[list_end]

[para]

[section EXAMPLES]

[vset CATEGORY grammar_fa]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/grammar_me/gasm.man.

431
432
433
434
435
436
437
438
439
[para]

The command returns the empty string as its result.

[list_end]

[vset CATEGORY grammar_me]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

431
432
433
434
435
436
437
438
439
[para]

The command returns the empty string as its result.

[list_end]

[vset CATEGORY grammar_me]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/grammar_me/me_ast.man.

126
127
128
129
130
131
132
133
134
This new attribute is defined for all nodes, and contains the
locations from attribute [term range] translated into line number and
column index. Lines are counted from 1, columns are counted from 0.

[list_end]

[vset CATEGORY grammar_me]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

126
127
128
129
130
131
132
133
134
This new attribute is defined for all nodes, and contains the
locations from attribute [term range] translated into line number and
column index. Lines are counted from 1, columns are counted from 0.

[list_end]

[vset CATEGORY grammar_me]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/grammar_me/me_cpu.man.

281
282
283
284
285
286
287
288
289
[call [arg meName] [method destroy]]

This method deletes the object and releases all resurces it claimed.

[list_end]

[vset CATEGORY grammar_me]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

281
282
283
284
285
286
287
288
289
[call [arg meName] [method destroy]]

This method deletes the object and releases all resurces it claimed.

[list_end]

[vset CATEGORY grammar_me]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/grammar_me/me_cpucore.man.

366
367
368
369
370
371
372
373
374
[para]

[term nc], the nonterminal cache is keyed by nonterminal name and
location, each value a four-element list containing current location,
match status, semantic value, and error status, in this order.

[vset CATEGORY grammar_me]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

366
367
368
369
370
371
372
373
374
[para]

[term nc], the nonterminal cache is keyed by nonterminal name and
location, each value a four-element list containing current location,
match status, semantic value, and error status, in this order.

[vset CATEGORY grammar_me]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/grammar_me/me_intro.man.

86
87
88
89
90
91
92
93
94
Core functionality for state manipulation and stepping used in the
bytecode based implementation of ME virtual machines.

[list_end]
[para]

[vset CATEGORY grammar_me]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

86
87
88
89
90
91
92
93
94
Core functionality for state manipulation and stepping used in the
bytecode based implementation of ME virtual machines.

[list_end]
[para]

[vset CATEGORY grammar_me]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/grammar_me/me_tcl.man.

335
336
337
338
339
340
341
342
343
The command takes the marker as argument as it comes from the
Tcl stack, not the machine state. It replaces [term ias_mpop].

[list_end]
[para]

[vset CATEGORY grammar_me]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

335
336
337
338
339
340
341
342
343
The command takes the marker as argument as it comes from the
Tcl stack, not the machine state. It replaces [term ias_mpop].

[list_end]
[para]

[vset CATEGORY grammar_me]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/grammar_me/me_util.man.

75
76
77
78
79
80
81
82
83
If a [arg root] node is specified the AST is generated from that node
downward. Otherwise the root of the tree object is used as the
starting point.

[list_end]

[vset CATEGORY grammar_me]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

75
76
77
78
79
80
81
82
83
If a [arg root] node is specified the AST is generated from that node
downward. Otherwise the root of the tree object is used as the
starting point.

[list_end]

[vset CATEGORY grammar_me]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/grammar_me/me_vm.man.

655
656
657
658
659
660
661
662
663

This instruction pops an entry from the AST Marker stack [term MS] and
discards it.

[list_end]

[vset CATEGORY grammar_me]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

655
656
657
658
659
660
661
662
663

This instruction pops an entry from the AST Marker stack [term MS] and
discards it.

[list_end]

[vset CATEGORY grammar_me]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/grammar_peg/peg.man.

713
714
715
716
717
718
719
720
721
[enum]
[uri {http://scifac.ru.ac.za/compilers/} \
	{Compilers and Compiler Generators}], an online book using
CoCo/R, a generator for recursive descent parsers.
[list_end]

[vset CATEGORY grammar_peg]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

713
714
715
716
717
718
719
720
721
[enum]
[uri {http://scifac.ru.ac.za/compilers/} \
	{Compilers and Compiler Generators}], an online book using
CoCo/R, a generator for recursive descent parsers.
[list_end]

[vset CATEGORY grammar_peg]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/grammar_peg/peg_interp.man.

114
115
116
117
118
119
120
121
122
described in section [sectref-external {AST VALUES}] of
document [term grammar::me_ast].

[list_end]
[para]

[vset CATEGORY grammar_peg]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

114
115
116
117
118
119
120
121
122
described in section [sectref-external {AST VALUES}] of
document [term grammar::me_ast].

[list_end]
[para]

[vset CATEGORY grammar_peg]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/hook/hook.man.

367
368
369
370
371
372
373
374
375
All bindings involving [widget .view] are deleted.

[section Credits]

Hook has been designed and implemented by William H. Duquette.

[vset CATEGORY hook]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

367
368
369
370
371
372
373
374
375
All bindings involving [widget .view] are deleted.

[section Credits]

Hook has been designed and implemented by William H. Duquette.

[vset CATEGORY hook]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/hook/hook.test.

1
2
3
4
5

6
7
8
9
10
11
12
# hook.test -*- tcl -*-
#
#       This file contains the test suite for hook-0.1.tcl.
#
# Copyright (C) 2010 by Will Duquette

#
# See the file "license.terms" for information on usage and 
# redistribution of this file, and for a DISCLAIMER OF ALL 
# WARRANTIES.

#-----------------------------------------------------------------------



|


>







1
2
3
4
5
6
7
8
9
10
11
12
13
# hook.test -*- tcl -*-
#
#       This file contains the test suite for hook.tcl.
#
# Copyright (C) 2010 by Will Duquette
# Copyright (c) 2019 by Andreas Kupries
#
# See the file "license.terms" for information on usage and 
# redistribution of this file, and for a DISCLAIMER OF ALL 
# WARRANTIES.

#-----------------------------------------------------------------------

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

proc GetError {} {
    variable info

    return $info(errorList)
}

if {[package vsatisfies [package provide Tcl] 8.6]} {
    proc EResult {a b} { return $b }
} else {
    proc EResult {a b} { return $a }
}

#-----------------------------------------------------------------------
# cget

test cget-1.1 {unknown option name} -body {
    hook cget -nonesuch
} -returnCodes {
    error







<
<
<
<
<
<







93
94
95
96
97
98
99






100
101
102
103
104
105
106

proc GetError {} {
    variable info

    return $info(errorList)
}







#-----------------------------------------------------------------------
# cget

test cget-1.1 {unknown option name} -body {
    hook cget -nonesuch
} -returnCodes {
    error
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
    hook configure -errorcommand ErrorCommand

    hook bind S1 <H1> O1 {error "simulated error"}
    hook call S1 <H1>
    GetError
} -cleanup {
    cleanup
} -result [EResult \
	       {{{S1 <H1> {} O1} {simulated error} {-code 1 -level 0 -errorcode NONE}}} \
	       {{{S1 <H1> {} O1} {simulated error} {-code 1 -level 0 -errorstack {INNER {error {simulated error}} UP 1 CALL {call S1 <H1>}} -errorcode NONE}}}]



test errorcommand-1.3 {handled errors don't break sequence of calls} -body {
    hook configure -errorcommand ErrorCommand

    TestBind  S1 <H1> O1
    hook bind S1 <H1> O2 {error "simulated error"}
    TestBind  S1 <H1> O3
    hook call S1 <H1>
    list [GetCalls] [GetError]
} -cleanup {
    cleanup
} -result [EResult \
	       {{{S1 <H1> O1 {}} {S1 <H1> O3 {}}} {{{S1 <H1> {} O2} {simulated error} {-code 1 -level 0 -errorcode NONE}}}} \
	       {{{S1 <H1> O1 {}} {S1 <H1> O3 {}}} {{{S1 <H1> {} O2} {simulated error} {-code 1 -level 0 -errorstack {INNER {error {simulated error}} UP 1 CALL {call S1 <H1>}} -errorcode NONE}}}}]



test errorcommand-1.4 {-errorcommand handles other exceptions} -body {
    hook configure -errorcommand ErrorCommand

    hook bind S1 <H1> O1 {return -code break "simulated break"}
    hook call S1 <H1>
    GetError
} -cleanup {
    cleanup
} -result {{{S1 <H1> {} O1} {simulated break} {-code 3 -level 1}}}


#-----------------------------------------------------------------------
# -tracecommand

test tracecommand-1.1 {-tracecommand is called} -body {
    TestBind S1 <H1> O1
    TestBind S1 <H1> O2







|
|
|
>
>











|
|
|
>
>










<







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
    hook configure -errorcommand ErrorCommand

    hook bind S1 <H1> O1 {error "simulated error"}
    hook call S1 <H1>
    GetError
} -cleanup {
    cleanup
} -result [tcltest::byConstraint {
    tcl8.6.10plus {{{S1 <H1> {} O1} {simulated error} {-code 1 -level 0 -errorstack {INNER {error {simulated error}} UP 1 CALL {::hook::call S1 <H1>}} -errorcode NONE}}}
    tcl8.6not10   {{{S1 <H1> {} O1} {simulated error} {-code 1 -level 0 -errorstack {INNER {error {simulated error}} UP 1 CALL {call S1 <H1>}} -errorcode NONE}}}
    tcl8.5minus   {{{S1 <H1> {} O1} {simulated error} {-code 1 -level 0 -errorcode NONE}}}
}]

test errorcommand-1.3 {handled errors don't break sequence of calls} -body {
    hook configure -errorcommand ErrorCommand

    TestBind  S1 <H1> O1
    hook bind S1 <H1> O2 {error "simulated error"}
    TestBind  S1 <H1> O3
    hook call S1 <H1>
    list [GetCalls] [GetError]
} -cleanup {
    cleanup
} -result [tcltest::byConstraint {
    tcl8.6.10plus {{{S1 <H1> O1 {}} {S1 <H1> O3 {}}} {{{S1 <H1> {} O2} {simulated error} {-code 1 -level 0 -errorstack {INNER {error {simulated error}} UP 1 CALL {::hook::call S1 <H1>}} -errorcode NONE}}}}
    tcl8.6not10   {{{S1 <H1> O1 {}} {S1 <H1> O3 {}}} {{{S1 <H1> {} O2} {simulated error} {-code 1 -level 0 -errorstack {INNER {error {simulated error}} UP 1 CALL {call S1 <H1>}} -errorcode NONE}}}}
    tcl8.5minus   {{{S1 <H1> O1 {}} {S1 <H1> O3 {}}} {{{S1 <H1> {} O2} {simulated error} {-code 1 -level 0 -errorcode NONE}}}}
}]

test errorcommand-1.4 {-errorcommand handles other exceptions} -body {
    hook configure -errorcommand ErrorCommand

    hook bind S1 <H1> O1 {return -code break "simulated break"}
    hook call S1 <H1>
    GetError
} -cleanup {
    cleanup
} -result {{{S1 <H1> {} O1} {simulated break} {-code 3 -level 1}}}


#-----------------------------------------------------------------------
# -tracecommand

test tracecommand-1.1 {-tracecommand is called} -body {
    TestBind S1 <H1> O1
    TestBind S1 <H1> O2
486
487
488
489
490
491
492

    cleanup
} -result {{S1 <H1> {} {O1 O2}} {S2 <H2> {} O2} {S3 <H3> {} {}}}

#-----------------------------------------------------------------------
# Clean up and finish

::tcltest::cleanupTests








>
484
485
486
487
488
489
490
491
    cleanup
} -result {{S1 <H1> {} {O1 O2}} {S2 <H2> {} O2} {S3 <H3> {} {}}}

#-----------------------------------------------------------------------
# Clean up and finish

::tcltest::cleanupTests
return

Changes to modules/html/html.man.

1
2
3
4
5
6
7
8
9
[comment {-*- tcl -*- doctools manpage}]
[vset HTML_VERSION 1.4.4]
[manpage_begin html n [vset HTML_VERSION]]
[see_also htmlparse]
[see_also ncgi]
[keywords checkbox]
[keywords checkbutton]
[keywords form]
[keywords html]

|







1
2
3
4
5
6
7
8
9
[comment {-*- tcl -*- doctools manpage}]
[vset HTML_VERSION 1.5]
[manpage_begin html n [vset HTML_VERSION]]
[see_also htmlparse]
[see_also ncgi]
[keywords checkbox]
[keywords checkbutton]
[keywords form]
[keywords html]
236
237
238
239
240
241
242




243



























244
245

246
247
248
249
250
251
252

[call [cmd ::html::mailto] [arg email] [opt [arg subject]]]

Generate a hypertext link to a mailto: URL.

[call [cmd ::html::meta] [arg args]]





[emph {Side effect only}].  Call this before [cmd ::html::head] to



























define a [term meta] tag for the page.  The [arg args] is a Tcl-style name,
value list that is used for the name= and value= parameters for the

[term meta] tag.  The [term meta] tag is included in the result of
[cmd ::html::head].

[call [cmd ::html::css] [arg href]]

[emph {Side effect only}].  Call this before [cmd ::html::head] to
define a [term link] tag for a linked CSS document.  The [arg href] 







>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>







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

[call [cmd ::html::mailto] [arg email] [opt [arg subject]]]

Generate a hypertext link to a mailto: URL.

[call [cmd ::html::meta] [arg args]]

Compatibility name for [cmd html::meta_name].

[call [cmd ::html::meta_name] [arg args]]

[emph {Side effect only}].

Call this before [cmd ::html::head] to define a [term meta] tag for
the page.

The arguments ([arg args]) are a Tcl-style name, value list that is
used for the [const name=] and [const content=] attributes of the
[term meta] tag.  The [term meta] tag is included in the result of
[cmd ::html::head].


[call [cmd ::html::meta_equiv] [arg args]]

[emph {Side effect only}].

Call this before [cmd ::html::head] to define a [term meta] tag for
the page.

The arguments ([arg args]) are a Tcl-style name, value list that is
used for the [const http-equiv=] and [const content=] attributes of
the [term meta] tag.  The [term meta] tag is included in the result of
[cmd ::html::head].

[call [cmd ::html::meta_charset] [arg charset]]

[emph {Side effect only}].

Call this before [cmd ::html::head] to
define a [term meta] tag for the page.

The [arg charset] is used with the [const charset=] attribute of the
[term meta] tag.  The [term meta] tag is included in the result of
[cmd ::html::head].

[call [cmd ::html::css] [arg href]]

[emph {Side effect only}].  Call this before [cmd ::html::head] to
define a [term link] tag for a linked CSS document.  The [arg href] 
385
386
387
388
389
390
391
392
393
394





395
396
397
398
399
400
401
[call [cmd ::html::set] [arg {var val}]]

This procedure is similar to the built-in Tcl [cmd set] command.  The
main difference is that it returns "" so it can be called from an HTML
template file without appending unwanted results.  The other
difference is that it must take two arguments.

[call [cmd ::html::submit] [arg label] [opt [arg name]]]

Generate an [term input] tag of type [term submit]. [arg name] defaults to "submit".






[call [cmd ::html::tableFromArray] [arg arrname] [opt [arg param]] [opt [arg pat]]]

Generate a two-column [term table] and nested rows to display a Tcl array. The
table gets a heading that matches the array name, and each generated row
contains a name, value pair. The array names are sorted ([cmd lsort] without
special options). The argument [arg param] is for the [term table] tag and has







|

|
>
>
>
>
>







417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
[call [cmd ::html::set] [arg {var val}]]

This procedure is similar to the built-in Tcl [cmd set] command.  The
main difference is that it returns "" so it can be called from an HTML
template file without appending unwanted results.  The other
difference is that it must take two arguments.

[call [cmd ::html::submit] [arg label] [opt [arg name]] [opt [arg title]]]

Generate an [term input] tag of type [term submit].

The [arg name] defaults to "submit".

When a non-empty [arg title] string is specified the button gains a
[const title=] attribute with that value.

[call [cmd ::html::tableFromArray] [arg arrname] [opt [arg param]] [opt [arg pat]]]

Generate a two-column [term table] and nested rows to display a Tcl array. The
table gets a heading that matches the array name, and each generated row
contains a name, value pair. The array names are sorted ([cmd lsort] without
special options). The argument [arg param] is for the [term table] tag and has
465
466
467
468
469
470
471










472
473
474
475
476
[enum] XHTML10S
[enum] XHTML10T
[enum] XHTML10F
[enum] XHTML11
[enum] XHTMLB
[list_end]











[list_end]

[vset CATEGORY html]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







>
>
>
>
>
>
>
>
>
>



|

502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
[enum] XHTML10S
[enum] XHTML10T
[enum] XHTML10F
[enum] XHTML11
[enum] XHTMLB
[list_end]

[call [cmd ::html::wrapTag] [arg tag] [opt [arg text]] [opt [arg args]]]

A helper to wrap a [arg text] in a pair of open/close [arg tag]s.

The arguments ([arg args]) are a Tcl-style name, value list that is
used to provide attributes and associated values to the opening tag.

The result is a string with the open [arg tag] along with the optional
attributes, the optional text, and the closed tag.

[list_end]

[vset CATEGORY html]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/html/html.tcl.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# Originally by Brent Welch, with help from Dan Kuchler and Melissa Chawla

package require Tcl 8.2
package require ncgi
package provide html 1.4.5

namespace eval ::html {

    # State about the current page

    variable page








|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# Originally by Brent Welch, with help from Dan Kuchler and Melissa Chawla

package require Tcl 8.2
package require ncgi
package provide html 1.5

namespace eval ::html {

    # State about the current page

    variable page

477
478
479
480
481
482
483


484

485
486










487
488
489

















490
491
492
493
494
495
496
#
# Arguments:
#	args	A name-value list of meta tag names and values.
#
# Side Effects:
#	Stores HTML for the <meta> tag for use later by html::head



proc ::html::meta {args} {

    variable page
    ::set html ""










    ::foreach {name value} $args {
	append html "<meta name=\"$name\" content=\"[quoteFormValue $value]\">"
    }

















    lappend page(meta) $html
    return ""
}

# ::html::refresh
#
#	Generate a meta refresh tag.  This tag gets bundled into the <head>







>
>

>

|
>
>
>
>
>
>
>
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
#
# Arguments:
#	args	A name-value list of meta tag names and values.
#
# Side Effects:
#	Stores HTML for the <meta> tag for use later by html::head

# Ref: https://www.w3schools.com/tags/tag_meta.asp

proc ::html::meta {args} {
    # compatibility command
    variable page
    append html ""
    ::foreach {name value} $args {
	append html "<meta name=\"$name\" content=\"[quoteFormValue $value]\">"
    }
    lappend page(meta) $html
    return ""
}

proc ::html::meta_name {args} {
    variable page
    append html ""
    ::foreach {name value} $args {
	append html "<meta name=\"$name\" content=\"[quoteFormValue $value]\">"
    }
    lappend page(meta) $html
    return ""
}

proc ::html::meta_charset {charset} {
    variable page
    append html "<meta charset=\"[quoteFormValue $charset]\">"
    lappend page(meta) $html
    return ""
}

proc ::html::meta_equiv {args} {
    variable page
    append html ""
    ::foreach {name value} $args {
	append html "<meta http-equiv=\"$name\" content=\"[quoteFormValue $value]\">"
    }
    lappend page(meta) $html
    return ""
}

# ::html::refresh
#
#	Generate a meta refresh tag.  This tag gets bundled into the <head>
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
    return ""
}

# ::html::tagParam
#
#	Return a name, value string for the tag parameters.
#	The values come from "hard-wired" values in the
#	param agrument, or from the defaults set with html::init.
#
# Arguments:
#	tag	Name of the HTML tag (case insensitive).
#	param	pname=value info that overrides any default values
#
# Results
#	A string of the form:







|







609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
    return ""
}

# ::html::tagParam
#
#	Return a name, value string for the tag parameters.
#	The values come from "hard-wired" values in the
#	param argument, or from the defaults set with html::init.
#
# Arguments:
#	tag	Name of the HTML tag (case insensitive).
#	param	pname=value info that overrides any default values
#
# Results
#	A string of the form:
920
921
922
923
924
925
926
927


928
929
930
931
932
933
934


935
936
937
938
939
940
941

# ::html::submit --
#
#	Format a submit button.
#
# Arguments:
#	label		The string to appear in the submit button.
#	name		The name for the submit button element


#
# Results:
#	The html fragment


proc ::html::submit {label {name submit}} {
    ::set html "<input type=\"submit\" name=\"$name\" value=\"$label\">\n"


}

# ::html::varEmpty --
#
#	Return true if the variable doesn't exist or is an empty string
#
# Arguments:







|
>
>




<
|
|
>
>







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

# ::html::submit --
#
#	Format a submit button.
#
# Arguments:
#	label		The string to appear in the submit button.
#	name		The name for the submit button element.
#	title		The string to appear on the submit button.
#			Optional. If not specified no title is shown.
#
# Results:
#	The html fragment


proc ::html::submit {label {name submit} {title {}}} {
    ::set html "<input type=\"submit\" name=\"$name\" value=\"$label\""
    ::if {$title != ""} { append html " title=\"$title\"" }
    append html ">\n"
}

# ::html::varEmpty --
#
#	Return true if the variable doesn't exist or is an empty string
#
# Arguments:
1009
1010
1011
1012
1013
1014
1015
























1016
1017
1018
1019
1020
1021
1022
}
proc ::html::h6 {string {param {}}} {
    html::h 6 $string $param
}
proc ::html::h {level string {param {}}} {
    return "<[string trimright "h$level [tagParam h$level $param]"]>$string</h$level>\n"
}

























# ::html::openTag
#	Remember that a tag  is opened so it can be closed later.
#	This is used to automatically clean up at the end of a page.
#
# Arguments:
#	tag	The HTML tag name







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
}
proc ::html::h6 {string {param {}}} {
    html::h 6 $string $param
}
proc ::html::h {level string {param {}}} {
    return "<[string trimright "h$level [tagParam h$level $param]"]>$string</h$level>\n"
}

# ::html::wrapTag
#   Takes an optional text and wraps it in a tag pair, along with
#   optional attributes for the tag
#
# Arguments:
#   tag      The HTML tag name 
#   text     Optional text to insert between open/close tag
#   args     List of optional attributes and values to use for the tag
#
# Results:
#   String with the text wrapped in the open/close tag

proc ::html::wrapTag {tag {text ""} args} {
    ::set html ""
    ::set params ""
    ::foreach {i j} $args {
        append params "$i=\"[quoteFormValue $j]\" "
    }
    append html [openTag $tag [string trimright $params]]
    append html $text
    append html [closeTag]
    return $html
}

# ::html::openTag
#	Remember that a tag  is opened so it can be closed later.
#	This is used to automatically clean up at the end of a page.
#
# Arguments:
#	tag	The HTML tag name

Changes to modules/html/html.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- tcl -*- Tests for the html module.
#
# This file contains a collection of tests for a module in the
# Standard Tcl Library. Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
# Copyright (c) 2006 Michael Schlenker <[email protected]>
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: html.test,v 1.23 2006/10/09 21:41:40 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]











<
<







1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
# -*- tcl -*- Tests for the html module.
#
# This file contains a collection of tests for a module in the
# Standard Tcl Library. Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
# Copyright (c) 2006 Michael Schlenker <[email protected]>
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

64
65
66
67
68
69
70



71
72
73
74
75
76
77



78
79
80
81
82
83
84
} -result "<html><head>\n\t<title>The Title</title>\n</head>\n"

test html-2.3 {html::head} -body {
    html::description "The Description"
    html::keywords key word
    html::author "Cathy Coder"
    html::meta metakey metavalue



    html::head "The Title"
} -result {<html><head>
	<title>The Title</title>
	<!-- Cathy Coder -->
	<meta name="description" content="The Description">
	<meta name="keywords" content="key, word">
	<meta name="metakey" content="metavalue">



</head>
}

test html-3.1 {html::title, not enough args} -body {
    html::title
} -returnCodes error -result {wrong # args: should be "html::title title"}








>
>
>







>
>
>







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
} -result "<html><head>\n\t<title>The Title</title>\n</head>\n"

test html-2.3 {html::head} -body {
    html::description "The Description"
    html::keywords key word
    html::author "Cathy Coder"
    html::meta metakey metavalue
    html::meta_name other value
    html::meta_charset utf-8
    html::meta_equiv refresh 30
    html::head "The Title"
} -result {<html><head>
	<title>The Title</title>
	<!-- Cathy Coder -->
	<meta name="description" content="The Description">
	<meta name="keywords" content="key, word">
	<meta name="metakey" content="metavalue">
	<meta name="other" content="value">
	<meta charset="utf-8">
	<meta http-equiv="refresh" content="30">
</head>
}

test html-3.1 {html::title, not enough args} -body {
    html::title
} -returnCodes error -result {wrong # args: should be "html::title title"}

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
    }
    ncgi::reset info=[ncgi::encode "</textarea><script>alert(1)</script>"]
    ncgi::parse
    html::textarea info
} {<textarea name="info" cols="50" rows="8">&lt;/textarea&gt;&lt;script&gt;alert(1)&lt;/script&gt;</textarea>
}


test html-24.1 {html::submit} {
    catch {html::submit}
} {1}

test html-24.2 {html::submit} {
    catch {html::submit wrong num args}
} {1}

test html-24.3 {html::submit} {
    html::submit "Push Me"
} {<input type="submit" name="submit" value="Push Me">
}

test html-24.4 {html::submit} {
    html::submit "Push Me" push
} {<input type="submit" name="push" value="Push Me">
}






test html-25.1 {html::varEmpty} {
    catch {html::varEmpty}
} 1
test html-25.2 {html::varEmpty} {
    catch {html::varEmpty wrong num args}
} 1







<
|



|
|


|




|



>
>
>
>
>







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
    }
    ncgi::reset info=[ncgi::encode "</textarea><script>alert(1)</script>"]
    ncgi::parse
    html::textarea info
} {<textarea name="info" cols="50" rows="8">&lt;/textarea&gt;&lt;script&gt;alert(1)&lt;/script&gt;</textarea>
}


test html-24.1 {html::submit, wrong args, not enough} {
    catch {html::submit}
} {1}

test html-24.2 {html::submit, wrong args, too many} {
    catch {html::submit wrong num args X}
} {1}

test html-24.3 {html::submit, label only} {
    html::submit "Push Me"
} {<input type="submit" name="submit" value="Push Me">
}

test html-24.4 {html::submit, label and name} {
    html::submit "Push Me" push
} {<input type="submit" name="push" value="Push Me">
}

test html-24.5 {html::submit, label, name, and title} {
    html::submit "Push Me" push a-title
} {<input type="submit" name="push" value="Push Me" title="a-title">
}

test html-25.1 {html::varEmpty} {
    catch {html::varEmpty}
} 1
test html-25.2 {html::varEmpty} {
    catch {html::varEmpty wrong num args}
} 1
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
	<link rel="stylesheet" type="text/css" href="http://test.css">
	<script language="javascript" type="text/javascript" src="http://test.js"></script>
</head>}

# -------------------------------------------------------------------------
# TODO: html::css-clear, html::js-clear


test html-tktafe4366e2e-38.0 {html::doctype, not enough args} -body {
    html::doctype
} -returnCodes error -result {wrong # args: should be "html::doctype arg"}

test html-tktafe4366e2e-38.1 {html::doctype, too many args} -body {
    html::doctype HTML401T X
} -returnCodes error -result {wrong # args: should be "html::doctype arg"}

test html-tktafe4366e2e-38.2 {html::doctype, unknown type} -body {
    html::doctype HTML401TXXX
} -returnCodes error -result {Unknown doctype "HTML401TXXX"}

test html-tktafe4366e2e-38.3 {html::doctype} -body {
    html::doctype HTML401T
} -result {<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">}























# -------------------------------------------------------------------------
testsuiteCleanup







<
|



|



|



|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



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
	<link rel="stylesheet" type="text/css" href="http://test.css">
	<script language="javascript" type="text/javascript" src="http://test.js"></script>
</head>}

# -------------------------------------------------------------------------
# TODO: html::css-clear, html::js-clear


test html-tkt-afe4366e2e-38.0 {html::doctype, not enough args} -body {
    html::doctype
} -returnCodes error -result {wrong # args: should be "html::doctype arg"}

test html-tkt-afe4366e2e-38.1 {html::doctype, too many args} -body {
    html::doctype HTML401T X
} -returnCodes error -result {wrong # args: should be "html::doctype arg"}

test html-tkt-afe4366e2e-38.2 {html::doctype, unknown type} -body {
    html::doctype HTML401TXXX
} -returnCodes error -result {Unknown doctype "HTML401TXXX"}

test html-tkt-afe4366e2e-38.3 {html::doctype} -body {
    html::doctype HTML401T
} -result {<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">}

# -------------------------------------------------------------------------

test html-tkt-1076403-39.0 {html::wrapTag, not enough args} -body {
    html::wrapTag
} -returnCodes error -result [tcltest::wrongNumArgs html::wrapTag {tag ?text? args} 0]

test html-tkt-1076403-39.1 {html::wrapTag, tag alone} -body {
    html::wrapTag p
} -result {<p></p>}

test html-tkt-1076403-39.2 {html::wrapTag, tag and text} -body {
    html::wrapTag p "test"
} -result {<p>test</p>}

test html-tkt-1076403-39.3 {html::wrapTag, tag, text, and attribute} -body {
    html::wrapTag p "test" align left
} -result {<p align="left">test</p>}

test html-tkt-1076403-39.4 {html::wrapTag, tag, text, and attributes} -body {
    html::wrapTag pre "test" align left width 20
} -result {<pre align="left" width="20">test</pre>}

# -------------------------------------------------------------------------
testsuiteCleanup

Changes to modules/htmlparse/htmlparse.man.

258
259
260
261
262
263
264
265
266

[cmd ::htmlparse::2tree]. It removes all nodes representing forms and
form elements. Its only argument is the name of the tree to cut down.

[list_end]

[vset CATEGORY htmlparse]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

258
259
260
261
262
263
264
265
266

[cmd ::htmlparse::2tree]. It removes all nodes representing forms and
form elements. Its only argument is the name of the tree to cut down.

[list_end]

[vset CATEGORY htmlparse]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/http/autoproxy.man.

208
209
210
211
212
213
214
215
216
At this time only Basic authentication (1) (2) is supported. It is
planned to add support for Digest (2) and NTLM in the future.

[section AUTHORS]
Pat Thoyts

[vset CATEGORY {http :: autoproxy}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

208
209
210
211
212
213
214
215
216
At this time only Basic authentication (1) (2) is supported. It is
planned to add support for Digest (2) and NTLM in the future.

[section AUTHORS]
Pat Thoyts

[vset CATEGORY {http :: autoproxy}]
[include ../common-text/feedback.inc]
[manpage_end]

Added modules/httpd/assets/test_cgi.tcl.





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/tclsh

puts stdout "Status: 200 OK"
if {$::env(CONTENT_LENGTH) > 0} {
  puts stdout "Content-Type: $::env(CONTENT_TYPE)"
  set dat [read stdin $::env(CONTENT_LENGTH)]
} else {
  puts stdout "Content-Type: text/plain"
  set dat "Hi!"
}
puts stdout "Content-Length: [string length $dat]"
puts stdout {}
puts stdout $dat
exit 0

Changes to modules/httpd/build/build.tcl.

1
2
3









4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

40
41
42
43


44
45
46
47
48
49
50
51
52
53


54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75







set srcdir [file dirname [file normalize [file join [pwd] [info script]]]]
set moddir [file dirname $srcdir]










set version 4.2.0
set tclversion 8.6
set module [file tail $moddir]


set fout [open [file join $moddir ${module}.tcl] w]
dict set map %module% $module
dict set map %version% $version
dict set map %tclversion% $tclversion
dict set map {    } {} ;# strip indentation
dict set map "\t" {    } ;# reduce indentation (see cleanup)

puts $fout [string map $map {###
    # Amalgamated package for %module%
    # Do not edit directly, tweak the source in src/ and rerun
    # build.tcl
    ###
    package require Tcl %tclversion%
    package provide %module% %version%
    namespace eval ::%module% {}
    set ::%module%::version %version%
}]

# Track what files we have included so far
set loaded {}
lappend loaded build.tcl cgi.tcl
# These files must be loaded in a particular order
foreach file {
  core.tcl
  reply.tcl
  server.tcl
  dispatch.tcl
  file.tcl
  proxy.tcl
  cgi.tcl
  scgi.tcl
  websocket.tcl

} {
  lappend loaded $file
  set fin [open [file join $srcdir $file] r]
  puts $fout "###\n# START: [file tail $file]\n###"


  puts $fout [read $fin]
  close $fin
  puts $fout "###\n# END: [file tail $file]\n###"
}
# These files can be loaded in any order
foreach file [glob [file join $srcdir *.tcl]] {
  if {[file tail $file] in $loaded} continue
  lappend loaded $file
  set fin [open [file join $srcdir $file] r]
  puts $fout "###\n# START: [file tail $file]\n###"


  puts $fout [read $fin]
  close $fin
  puts $fout "###\n# END: [file tail $file]\n###"
}

# Provide some cleanup and our final package provide
puts $fout [string map $map {
    namespace eval ::%module% {
	namespace export *
    }
}]
close $fout

###
# Build our pkgIndex.tcl file
###
set fout [open [file join $moddir pkgIndex.tcl] w]
puts $fout [string map $map {
    if {![package vsatisfies [package provide Tcl] %tclversion%]} {return}
    package ifneeded %module% %version% [list source [file join $dir %module%.tcl]]
}]
close $fout










>
>
>
>
>
>
>
>
>
|


>

|
|
|
|
|
<

|
|
|
|
|
|
|
|
|
<





|









>


<

>
>
|
<








>
>
|
<




|










|
|
|


>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

51
52
53
54

55
56
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
set srcdir [file dirname [file normalize [file join [pwd] [info script]]]]
set moddir [file dirname $srcdir]

if {[file exists [file join $moddir .. .. scripts practcl.tcl]]} {
  source [file join $moddir .. .. scripts practcl.tcl]
} elseif {[file exists [file join $moddir .. practcl build doctool.tcl]]} {
  source [file join $moddir .. practcl build doctool.tcl]
} else {
  package require practcl 0.14
}

::practcl::doctool create AutoDoc
set version 4.3.4
set tclversion 8.6
set module [file tail $moddir]
set filename $module

set fout [open [file join $moddir ${filename}.tcl] w]
dict set modmap  %module% $module
dict set modmap  %version% $version
dict set modmap  %tclversion% $tclversion
dict set modmap  %filename% $filename


puts $fout [string map $modmap {###
# Amalgamated package for %module%
# Do not edit directly, tweak the source in src/ and rerun
# build.tcl
###
package require Tcl %tclversion%
package provide %module% %version%
namespace eval ::%module% {}
set ::%module%::version %version%}]


# Track what files we have included so far
set loaded {}
lappend loaded build.tcl cgi.tcl
# These files must be loaded in a particular order
foreach {file} {
  core.tcl
  reply.tcl
  server.tcl
  dispatch.tcl
  file.tcl
  proxy.tcl
  cgi.tcl
  scgi.tcl
  websocket.tcl
  plugin.tcl
} {
  lappend loaded $file

  puts $fout "###\n# START: [file tail $file]\n###"
  set content [::practcl::cat [file join $srcdir $file]]
  AutoDoc scan_text $content
  puts $fout [::practcl::docstrip $content]

  puts $fout "###\n# END: [file tail $file]\n###"
}
# These files can be loaded in any order
foreach file [glob [file join $srcdir *.tcl]] {
  if {[file tail $file] in $loaded} continue
  lappend loaded $file
  set fin [open [file join $srcdir $file] r]
  puts $fout "###\n# START: [file tail $file]\n###"
  set content [::practcl::cat [file join $srcdir $file]]
  AutoDoc scan_text $content
  puts $fout [::practcl::docstrip $content]

  puts $fout "###\n# END: [file tail $file]\n###"
}

# Provide some cleanup and our final package provide
puts $fout [string map $modmap {
    namespace eval ::%module% {
	namespace export *
    }
}]
close $fout

###
# Build our pkgIndex.tcl file
###
set fout [open [file join $moddir pkgIndex.tcl] w]
puts $fout [string map $modmap {
if {![package vsatisfies [package provide Tcl] %tclversion%]} {return}
package ifneeded %module% %version% [list source [file join $dir %module%.tcl]]
}]
close $fout

set manout [open [file join $moddir $filename.man] w]
puts $manout [AutoDoc manpage map $modmap \
  header [::practcl::cat [file join $srcdir manual.txt]] \
  footer [::practcl::cat [file join $srcdir footer.txt]] \
]
close $manout

Changes to modules/httpd/build/cgi.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
::tool::define ::httpd::content.cgi {
  superclass ::httpd::content.proxy

  method FileName {} {
    set uri [string trimleft [my http_info get REQUEST_URI] /]
    set path [my http_info get path]
    set prefix [my http_info get prefix]

    set fname [string range $uri [string length $prefix] end]
    if {[file exists [file join $path $fname]]} {
      return [file join $path $fname]
    }
    if {[file exists [file join $path $fname.fossil]]} {
      return [file join $path $fname.fossil]
|



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
::clay::define ::httpd::content.cgi {
  superclass ::httpd::content.proxy

  method FileName {} {
    set uri [string trimleft [my request get REQUEST_PATH] /]
    set path [my clay get path]
    set prefix [my clay get prefix]

    set fname [string range $uri [string length $prefix] end]
    if {[file exists [file join $path $fname]]} {
      return [file join $path $fname]
    }
    if {[file exists [file join $path $fname.fossil]]} {
      return [file join $path $fname.fossil]
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

  method proxy_channel {} {
    ###
    # When delivering static content, allow web caches to save
    ###
    set local_file [my FileName]
    if {$local_file eq {} || ![file exist $local_file]} {
      my log httpNotFound [my http_info get REQUEST_URI]
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    if {[file isdirectory $local_file]} {
      ###
      # Produce an index page... or error
      ###







|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

  method proxy_channel {} {
    ###
    # When delivering static content, allow web caches to save
    ###
    set local_file [my FileName]
    if {$local_file eq {} || ![file exist $local_file]} {
      my log httpNotFound [my request get REQUEST_PATH]
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    if {[file isdirectory $local_file]} {
      ###
      # Produce an index page... or error
      ###
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
    }
    foreach item $verbatim {
      set ::env($item) {}
    }
    foreach item [array names ::env HTTP_*] {
      set ::env($item) {}
    }
    set ::env(SCRIPT_NAME) [my http_info get REQUEST_PATH]
    set ::env(SERVER_PROTOCOL) HTTP/1.0
    set ::env(HOME) $::env(DOCUMENT_ROOT)
    foreach {f v} [my http_info dump] {
      if {$f in $verbatim} {
        set ::env($f) $v
      }
    }
  	set arglist $::env(QUERY_STRING)
    set pwd [pwd]
    cd [file dirname $local_file]
    foreach {f v} [my request dump] {
      if {$f in $verbatim} {
        set ::env($f) $v
      } else {
        set ::env(HTTP_$f) $v
      }
    }
    set script_file $local_file
    if {[file extension $local_file] in {.fossil .fos}} {
      if {![file exists $local_file.cgi]} {
        set fout [open $local_file.cgi w]
        chan puts $fout "#!/usr/bin/fossil"
        chan puts $fout "repository: $local_file"
        close $fout







|


|
<
|
<




<
<
<
<
<
<
<







48
49
50
51
52
53
54
55
56
57
58

59

60
61
62
63







64
65
66
67
68
69
70
    }
    foreach item $verbatim {
      set ::env($item) {}
    }
    foreach item [array names ::env HTTP_*] {
      set ::env($item) {}
    }
    set ::env(SCRIPT_NAME) [my request get REQUEST_PATH]
    set ::env(SERVER_PROTOCOL) HTTP/1.0
    set ::env(HOME) $::env(DOCUMENT_ROOT)
    foreach {f v} [my request dump] {

      set ::env($f) $v

    }
  	set arglist $::env(QUERY_STRING)
    set pwd [pwd]
    cd [file dirname $local_file]







    set script_file $local_file
    if {[file extension $local_file] in {.fossil .fos}} {
      if {![file exists $local_file.cgi]} {
        set fout [open $local_file.cgi w]
        chan puts $fout "#!/usr/bin/fossil"
        chan puts $fout "repository: $local_file"
        close $fout
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
    cd $pwd
    return $pipe
  }

  method ProxyRequest {chana chanb} {
    chan event $chanb writable {}
    my log ProxyRequest {}
    set length [my http_info get CONTENT_LENGTH]
    if {$length} {
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      ###
      # Send any POST/PUT/etc content
      ###
      chan copy $chana $chanb -size $length -command [info coroutine]
    } else {
      chan flush $chanb
      chan event $chanb readable [info coroutine]
    }


    yield

  }


  method ProxyReply {chana chanb args} {
    my log ProxyReply [list args $args]
    chan event $chana readable {}
    set replyhead [my HttpHeaders $chana]







|






|


<

>
>

<







79
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
    cd $pwd
    return $pipe
  }

  method ProxyRequest {chana chanb} {
    chan event $chanb writable {}
    my log ProxyRequest {}
    set length [my request get CONTENT_LENGTH]
    if {$length} {
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      ###
      # Send any POST/PUT/etc content
      ###
      my ChannelCopy $chana $chanb -size $length
    } else {
      chan flush $chanb

    }
    my clay refcount_incr
    chan event $chanb readable [info coroutine]
    yield

  }


  method ProxyReply {chana chanb args} {
    my log ProxyReply [list args $args]
    chan event $chana readable {}
    set replyhead [my HttpHeaders $chana]
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
    # a standard service reply line from a web server, but
    # otherwise spit out the rest of the headers verbatim
    ###
    set replybuffer "HTTP/1.0 [dict get $replydat Status]\n"
    append replybuffer $replyhead
    chan configure $chanb -translation {auto crlf} -blocking 0 -buffering full -buffersize 4096
    chan puts $chanb $replybuffer
    my log SendReply [list length $length]
    if {$length} {
      ###
      # Output the body
      ###
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      chan copy $chana $chanb -size $length -command [namespace code [list my TransferComplete $chana $chanb]]
    } else {
      my TransferComplete $chana $chanb
    }
  }

  ###
  # For most CGI applications a directory list is vorboten
  ###
  method DirectoryListing {local_file} {
    my error 403 {Not Allowed}
    tailcall my DoOutput
  }
}







<
<
|
|
|
|
|
|
<
|
<










115
116
117
118
119
120
121


122
123
124
125
126
127

128

129
130
131
132
133
134
135
136
137
138
    # a standard service reply line from a web server, but
    # otherwise spit out the rest of the headers verbatim
    ###
    set replybuffer "HTTP/1.0 [dict get $replydat Status]\n"
    append replybuffer $replyhead
    chan configure $chanb -translation {auto crlf} -blocking 0 -buffering full -buffersize 4096
    chan puts $chanb $replybuffer


    ###
    # Output the body. With no -size flag, channel will copy until EOF
    ###
    chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
    chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
    my ChannelCopy $chana $chanb -chunk 4096

    my clay refcount_decr

  }

  ###
  # For most CGI applications a directory list is vorboten
  ###
  method DirectoryListing {local_file} {
    my error 403 {Not Allowed}
    tailcall my DoOutput
  }
}

Changes to modules/httpd/build/core.tcl.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30



31
32
33















































34
35
36
37
38
39



40

41
42
43

44
45
46
47
48
49
50
# support the SCGI module
###

package require uri
package require dns
package require cron
package require coroutine
package require tool
package require mime
package require fileutil
package require websocket
package require Markdown
package require uuid
package require fileutil::magic::filetype

namespace eval httpd::content {}

namespace eval ::url {}
namespace eval ::httpd {}
namespace eval ::scgi {}




tool::define ::httpd::mime {

















































  method html_header {{title {}} args} {
    set result {}
    append result "<HTML><HEAD>"
    if {$title ne {}} {
      append result "<TITLE>$title</TITLE>"
    }



    append result "<link rel=\"stylesheet\" href=\"/style.css\">"

    append result "</HEAD><BODY>"
    return $result
  }

  method html_footer {args} {
    return "</BODY></HTML>"
  }

  method http_code_string code {
    set codes {
      200 {Data follows}







<




|
|







>
>
>
|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|



>
>
>
|
>



>







10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# support the SCGI module
###

package require uri
package require dns
package require cron
package require coroutine

package require mime
package require fileutil
package require websocket
package require Markdown
package require fileutil::magic::filetype
package require clay 0.7

namespace eval httpd::content {}

namespace eval ::url {}
namespace eval ::httpd {}
namespace eval ::scgi {}

###
# A metaclass for MIME handling behavior across a live socket
###
clay::define ::httpd::mime {


  method ChannelCopy {in out args} {
    try {
      my clay refcount_incr
      set chunk 4096
      set size -1
      foreach {f v} $args {
        set [string trim $f -] $v
      }
      dict set info coroutine [info coroutine]
      if {$size>0 && $chunk>$size} {
          set chunk $size
      }
      set bytes 0
      set sofar 0
      set method [self method]
      while 1 {
        set command {}
        set error {}
        if {$size>=0} {
          incr sofar $bytes
          set remaining [expr {$size-$sofar}]
          if {$remaining <= 0} {
            break
          } elseif {$chunk > $remaining} {
            set chunk $remaining
          }
        }
        lassign [yieldto chan copy $in $out -size $chunk \
          -command [list [info coroutine] $method]] \
          command bytes error
        if {$command ne $method} {
          error "Subroutine $method interrupted"
        }
        if {[string length $error]} {
          error $error
        }
        if {[chan eof $in]} {
          break
        }
      }
    } finally {
      my clay refcount_decr
    }
  }

  ###
  # Returns a block of HTML
  method html_header {{title {}} args} {
    set result {}
    append result "<!DOCTYPE html>\n<HTML><HEAD>"
    if {$title ne {}} {
      append result "<TITLE>$title</TITLE>"
    }
    if {[dict exists $args stylesheet]} {
      append result "<link rel=\"stylesheet\" href=\"[dict get $args stylesheet]\">"
    } else {
      append result "<link rel=\"stylesheet\" href=\"/style.css\">"
    }
    append result "</HEAD><BODY>"
    return $result
  }

  method html_footer {args} {
    return "</BODY></HTML>"
  }

  method http_code_string code {
    set codes {
      200 {Data follows}
105
106
107
108
109
110
111
112










113
114



115
116
117
118
119
120
121
  method HttpHeaders_Default {} {
    return {Status {200 OK}
Content-Size 0
Content-Type {text/html; charset=UTF-8}
Cache-Control {no-cache}
Connection close}
  }











  ###
  # Minimalist MIME Header Parser



  ###
  method MimeParse mimetext {
    set data(mimeorder) {}
    foreach line [split $mimetext \n] {
      # This regexp picks up
      # key: value
      # MIME headers.  MIME headers may be continue with a line








>
>
>
>
>
>
>
>
>
>

<
>
>
>







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
  method HttpHeaders_Default {} {
    return {Status {200 OK}
Content-Size 0
Content-Type {text/html; charset=UTF-8}
Cache-Control {no-cache}
Connection close}
  }

  method HttpServerHeaders {} {
    return {
      CONTENT_LENGTH CONTENT_TYPE QUERY_STRING REMOTE_USER AUTH_TYPE
      REQUEST_METHOD REMOTE_ADDR REMOTE_HOST REQUEST_URI REQUEST_PATH
      REQUEST_VERSION  DOCUMENT_ROOT QUERY_STRING REQUEST_RAW
      GATEWAY_INTERFACE SERVER_PORT SERVER_HTTPS_PORT
      SERVER_NAME  SERVER_SOFTWARE SERVER_PROTOCOL
    }
  }

  ###

  # Converts a block of mime encoded text to a key/value list. If an exception is encountered,
  # the method will generate its own call to the [cmd error] method, and immediately invoke
  # the [cmd output] method to produce an error code and close the connection.
  ###
  method MimeParse mimetext {
    set data(mimeorder) {}
    foreach line [split $mimetext \n] {
      # This regexp picks up
      # key: value
      # MIME headers.  MIME headers may be continue with a line
193
194
195
196
197
198
199

200
201
202
203
204
205
206
        }
      }
      dict set result $ckey $data(mime,$key)
    }
    return $result
  }


  method Url_Decode data {
    regsub -all {\+} $data " " data
    regsub -all {([][$\\])} $data {\\\1} data
    regsub -all {%([0-9a-fA-F][0-9a-fA-F])} $data  {[format %c 0x\1]} data
    return [subst $data]
  }








>







259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
        }
      }
      dict set result $ckey $data(mime,$key)
    }
    return $result
  }

  # De-httpizes a string.
  method Url_Decode data {
    regsub -all {\+} $data " " data
    regsub -all {([][$\\])} $data {\\\1} data
    regsub -all {%([0-9a-fA-F][0-9a-fA-F])} $data  {[format %c 0x\1]} data
    return [subst $data]
  }

235
236
237
238
239
240
241

242
243
244
245
246
247
248
249

250
251
252
      }
    }
    return $pathlist
  }


  method wait {mode sock} {

    if {[info coroutine] eq {}} {
      chan event $sock $mode [list set ::httpd::lock_$sock $mode]
      vwait ::httpd::lock_$sock
    } else {
      chan event $sock $mode [info coroutine]
      yield
    }
    chan event $sock $mode {}

  }

}







>








>



302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
      }
    }
    return $pathlist
  }


  method wait {mode sock} {
    my clay refcount_incr
    if {[info coroutine] eq {}} {
      chan event $sock $mode [list set ::httpd::lock_$sock $mode]
      vwait ::httpd::lock_$sock
    } else {
      chan event $sock $mode [info coroutine]
      yield
    }
    chan event $sock $mode {}
    my clay refcount_decr
  }

}

Added modules/httpd/build/cuneiform.tcl.



>
1

Changes to modules/httpd/build/dispatch.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54


55
56
57
::tool::define ::httpd::content.redirect {

  method reset {} {
    ###
    # Inject the location into the HTTP headers
    ###
    my variable reply_body
    set reply_body {}
    my reply replace    [my HttpHeaders_Default]
    my reply set Server [my <server> cget server_string]
    set msg [my http_info get LOCATION]
    my reply set Location [my http_info get LOCATION]
    set code  [my http_info getnull REDIRECT_CODE]
    if {$code eq {}} {
      set code 301
    }
    my reply set Status [list $code [my http_code_string $code]]
  }

  method content {} {
    set template [my <server> template redirect]
    set msg [my http_info get LOCATION]
    set HTTP_STATUS [my reply get Status]
    my puts [subst $msg]
  }
}

::tool::define ::httpd::content.cache {

  method dispatch {newsock datastate} {
    my http_info replace $datastate
    my request replace  [dict get $datastate http]
    my variable chan
    set chan $newsock
    chan event $chan readable {}
    try {
      my Log_Dispatched
      my wait writable $chan
      chan configure $chan  -translation {binary binary}
      chan puts -nonewline $chan [my http_info get CACHE_DATA]
    } on error {err info} {
      my <server> debug [dict get $info -errorinfo]
    } finally {
      my TransferComplete $chan
    }
  }
}

::tool::define ::httpd::content.template {

  method content {} {
    if {[my http_info getnull HTTP_STATUS] ne {}} {
      my reply set Status [my http_info getnull HTTP_STATUS]
    }


    my puts [subst [my <server> template [my http_info get template]]]
  }
}
|








|
|
|
|








|





|

|
<
<

<
<
<
<
|
|
|
<
<
<
<
|
|
|
<
|


|
|

>
>
|


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30


31




32
33
34




35
36
37

38
39
40
41
42
43
44
45
46
47
48
::clay::define ::httpd::content.redirect {

  method reset {} {
    ###
    # Inject the location into the HTTP headers
    ###
    my variable reply_body
    set reply_body {}
    my reply replace    [my HttpHeaders_Default]
    my reply set Server [my <server> clay get server/ string]
    set msg [my clay get LOCATION]
    my reply set Location [my clay get LOCATION]
    set code  [my clay get REDIRECT_CODE]
    if {$code eq {}} {
      set code 301
    }
    my reply set Status [list $code [my http_code_string $code]]
  }

  method content {} {
    set template [my <server> template redirect]
    set msg [my clay get LOCATION]
    set HTTP_STATUS [my reply get Status]
    my puts [subst $msg]
  }
}

::clay::define ::httpd::content.cache {

  method Dispatch {} {


    my variable chan




    my wait writable $chan
    chan configure $chan  -translation {binary binary}
    chan puts -nonewline $chan [my clay get cache/ data]




  }
}


::clay::define ::httpd::content.template {

  method content {} {
    if {[my request get HTTP_STATUS] ne {}} {
      my reply set Status [my request get HTTP_STATUS]
    }
    set request [my request dump]
    dict with request {}
    my puts [subst [my <server> template [my clay get template]]]
  }
}

Changes to modules/httpd/build/file.tcl.

1
2
3
4
5
6
7
8





9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27



28
29
30
31
32
33
34
35
36
37
38
39
40
41
###
# Class to deliver Static content
# When utilized, this class is fed a local filename
# by the dispatcher
###
::tool::define ::httpd::content.file {

  method FileName {} {





    set uri [string trimleft [my http_info get REQUEST_URI] /]
    set path [my http_info get path]
    set prefix [my http_info get prefix]
    set fname [string range $uri [string length $prefix] end]
    if {$fname in "{} index.html index.md index"} {
      return $path
    }
    if {[file exists [file join $path $fname]]} {
      return [file join $path $fname]
    }
    if {[file exists [file join $path $fname.md]]} {
      return [file join $path $fname.md]
    }
    if {[file exists [file join $path $fname.html]]} {
      return [file join $path $fname.html]
    }
    if {[file exists [file join $path $fname.tml]]} {
      return [file join $path $fname.tml]
    }



    return {}
  }

  method DirectoryListing {local_file} {
    set uri [string trimleft [my http_info get REQUEST_URI] /]
    set path [my http_info get path]
    set prefix [my http_info get prefix]
    set fname [string range $uri [string length $prefix] end]
    my puts [my html_header "Listing of /$fname/"]
    my puts "Listing contents of /$fname/"
    my puts "<TABLE>"
    if {$prefix ni {/ {}}} {
      set updir [file dirname $prefix]
      if {$updir ne {}} {





|


>
>
>
>
>
|
|
|

|














>
>
>




|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
###
# Class to deliver Static content
# When utilized, this class is fed a local filename
# by the dispatcher
###
::clay::define ::httpd::content.file {

  method FileName {} {
    # Some dispatchers will inject a fully qualified name during discovery
    if {[my clay exists FILENAME] && [file exists [my clay get FILENAME]]} {
      my request set PREFIX_URI [file dirname [my clay get FILENAME]]
      return [my clay get FILENAME]
    }
    set uri [string trimleft [my request get REQUEST_PATH] /]
    set path [my clay get path]
    set prefix [my clay get prefix]
    set fname [string range $uri [string length $prefix] end]
    if {$fname in "{} index.html index.md index index.tml index.tcl"} {
      return $path
    }
    if {[file exists [file join $path $fname]]} {
      return [file join $path $fname]
    }
    if {[file exists [file join $path $fname.md]]} {
      return [file join $path $fname.md]
    }
    if {[file exists [file join $path $fname.html]]} {
      return [file join $path $fname.html]
    }
    if {[file exists [file join $path $fname.tml]]} {
      return [file join $path $fname.tml]
    }
    if {[file exists [file join $path $fname.tcl]]} {
      return [file join $path $fname.tcl]
    }
    return {}
  }

  method DirectoryListing {local_file} {
    set uri [string trimleft [my request get REQUEST_PATH] /]
    set path [my clay get path]
    set prefix [my clay get prefix]
    set fname [string range $uri [string length $prefix] end]
    my puts [my html_header "Listing of /$fname/"]
    my puts "Listing contents of /$fname/"
    my puts "<TABLE>"
    if {$prefix ni {/ {}}} {
      set updir [file dirname $prefix]
      if {$updir ne {}} {
53
54
55
56
57
58
59
60
61
62
63
64


65
66
67
68
69

70
71
72


73
74
75
76
77
78
79
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

    my puts [my html_footer]
  }

  method content {} {
    my variable reply_file
    set local_file [my FileName]
    if {$local_file eq {} || ![file exist $local_file]} {
      my log httpNotFound [my http_info get REQUEST_URI]
      my error 404 {File Not Found}
      tailcall my DoOutput
    }
    if {[file isdirectory $local_file] || [file tail $local_file] in {index index.html index.tml index.md}} {


      ###
      # Produce an index page
      ###
      set idxfound 0
      foreach name {

        index.html
        index.tml
        index.md


        content.htm
      } {
        if {[file exists [file join $local_file $name]]} {
          set idxfound 1
          set local_file [file join $local_file $name]
          break
        }
      }
      if {!$idxfound} {
        tailcall my DirectoryListing $local_file
      }



    }


    switch [file extension $local_file] {




























      .md {
        package require Markdown
        my reply set Content-Type {text/html; charset=UTF-8}
        set mdtxt  [::fileutil::cat $local_file]
        my puts [::Markdown::convert $mdtxt]
      }






















      .tml {
        my reply set Content-Type {text/html; charset=UTF-8}
        set tmltxt  [::fileutil::cat $local_file]
        set headers [my http_info dump]
        dict with headers {}
        my puts [subst $tmltxt]
      }








      default {
        ###
        # Assume we are returning a binary file
        ###
        my reply set Content-Type [::fileutil::magic::filetype $local_file]
        set reply_file $local_file
      }
    }
  }

  method dispatch {newsock datastate} {
    my variable reply_body reply_file reply_chan chan
    try {
      my http_info replace $datastate
      my request replace  [dict get $datastate http]
      my Log_Dispatched
      set chan $newsock
      chan event $chan readable {}
      chan configure $chan -translation {auto crlf} -buffering line

      my reset
      # Invoke the URL implementation.
      my content
    } on error {err errdat} {
      my error 500 $err [dict get $errdat -errorinfo]

      tailcall my DoOutput
    }

    if {$chan eq {}} return



    my wait writable $chan
    if {![info exists reply_file]} {
      tailcall my DoOutput
    }
    try {
      chan configure $chan  -translation {binary binary}
      my log HttpAccess {}
      ###
      # Return a stream of data from a file
      ###
      set size [file size $reply_file]
      my reply set Content-Length $size
      append result [my reply output] \n
      chan puts -nonewline $chan $result
      set reply_chan [open $reply_file r]

      my log SendReply [list length $size]
      chan configure $reply_chan  -translation {binary binary}
      ###
      # Send any POST/PUT/etc content
      # Note, we are terminating the coroutine at this point
      # and using the file event to wake the object back up
      #
      # We *could*:
      # chan copy $sock $chan -command [info coroutine]
      # yield
      #
      # But in the field this pegs the CPU for long transfers and locks
      # up the process
      ###



      chan copy $reply_chan $chan -command [namespace code [list my TransferComplete $reply_chan $chan]]
    } on error {err errdat} {
      my TransferComplete $reply_chan $chan
    }
  }
}








|




>
>





>



>
>











>
>
>

>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|



>
>
>
>
>
>
>
>










|


<
<
<
<
<
<
<





>
|
|
>

>
>
>
|
|
|
|
<










>

<

|
<
<
<
<
<
<
<
<
<

>
>
>
|
|
|
|
|
|
>
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
    my puts [my html_footer]
  }

  method content {} {
    my variable reply_file
    set local_file [my FileName]
    if {$local_file eq {} || ![file exist $local_file]} {
      my log httpNotFound [my request get REQUEST_PATH]
      my error 404 {File Not Found}
      tailcall my DoOutput
    }
    if {[file isdirectory $local_file] || [file tail $local_file] in {index index.html index.tml index.md}} {
      my request set PREFIX_URI [my request get REQUEST_PATH]
      my request set LOCAL_DIR $local_file
      ###
      # Produce an index page
      ###
      set idxfound 0
      foreach name {
        index.tcl
        index.html
        index.tml
        index.md
        index.info
        index.clay
        content.htm
      } {
        if {[file exists [file join $local_file $name]]} {
          set idxfound 1
          set local_file [file join $local_file $name]
          break
        }
      }
      if {!$idxfound} {
        tailcall my DirectoryListing $local_file
      }
    } else {
      my request set PREFIX_URI [file dirname [my request get REQUEST_PATH]]
      my request set LOCAL_DIR [file dirname $local_file]
    }
    my request set LOCAL_FILE $local_file

    switch [file extension $local_file] {
      .apng {
        my reply set Content-Type {image/apng}
        set reply_file $local_file
      }
      .bmp {
        my reply set Content-Type {image/bmp}
        set reply_file $local_file
      }
      .css {
        my reply set Content-Type {text/css}
        set reply_file $local_file
      }
      .gif {
        my reply set Content-Type {image/gif}
        set reply_file $local_file
      }
      .cur - .ico {
        my reply set Content-Type {image/x-icon}
        set reply_file $local_file
      }
      .jpg - .jpeg - .jfif - .pjpeg - .pjp {
        my reply set Content-Type {image/jpg}
        set reply_file $local_file
      }
      .js {
        my reply set Content-Type {text/javascript}
        set reply_file $local_file
      }
      .md {
        package require Markdown
        my reply set Content-Type {text/html; charset=UTF-8}
        set mdtxt  [::fileutil::cat $local_file]
        my puts [::Markdown::convert $mdtxt]
      }
      .png {
        my reply set Content-Type {image/png}
        set reply_file $local_file
      }
      .svgz -
      .svg {
        # FU magic screws it up
        my reply set Content-Type {image/svg+xml}
        set reply_file $local_file
      }
      .tcl {
        my reply set Content-Type {text/html; charset=UTF-8}
        try {
          source $local_file
        } on error {err errdat} {
          my error 500 {Internal Error} [dict get $errdat -errorinfo]
        }
      }
      .tiff {
        my reply set Content-Type {image/tiff}
        set reply_file $local_file
      }
      .tml {
        my reply set Content-Type {text/html; charset=UTF-8}
        set tmltxt  [::fileutil::cat $local_file]
        set headers [my request dump]
        dict with headers {}
        my puts [subst $tmltxt]
      }
      .txt {
        my reply set Content-Type {text/plain}
        set reply_file $local_file
      }
      .webp {
        my reply set Content-Type {image/webp}
        set reply_file $local_file
      }
      default {
        ###
        # Assume we are returning a binary file
        ###
        my reply set Content-Type [::fileutil::magic::filetype $local_file]
        set reply_file $local_file
      }
    }
  }

  method Dispatch {} {
    my variable reply_body reply_file reply_chan chan
    try {







      my reset
      # Invoke the URL implementation.
      my content
    } on error {err errdat} {
      my error 500 $err [dict get $errdat -errorinfo]
      catch {
        tailcall my DoOutput
      }
    }
    if {$chan eq {}} return
    catch {
      # Causing random issues. Technically a socket is always open for read and write
      # anyway
      #my wait writable $chan
      if {![info exists reply_file]} {
        tailcall my DoOutput
      }

      chan configure $chan  -translation {binary binary}
      my log HttpAccess {}
      ###
      # Return a stream of data from a file
      ###
      set size [file size $reply_file]
      my reply set Content-Length $size
      append result [my reply output] \n
      chan puts -nonewline $chan $result
      set reply_chan [open $reply_file r]
      my ChannelRegister $reply_chan
      my log SendReply [list length $size]

      ###
      # Output the file contents. With no -size flag, channel will copy until EOF









      ###
      chan configure $reply_chan -translation {binary binary} -buffersize 4096 -buffering full -blocking 0
      if {$size < 40960} {
        # Raw copy small files
        chan copy $reply_chan $chan
      } else {
        my ChannelCopy $reply_chan $chan -chunk 4096
      }
    }
  }
}

Added modules/httpd/build/footer.txt.











>
>
>
>
>
1
2
3
4
5
[section AUTHORS]
Sean Woods

[vset CATEGORY network]
[include ../common-text/feedback.inc]

Added modules/httpd/build/manual.txt.





































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
[keywords WWW]
[copyright {2018 Sean Woods <[email protected]>}]
[moddesc   {Tcl Web Server}]
[titledesc {A TclOO and coroutine based web server}]
[category  Networking]
[keywords TclOO]
[keywords http]
[keywords httpd]
[keywords httpserver]
[keywords services]
[require Tcl 8.6]
[require uuid]
[require clay]
[require coroutine]
[require fileutil]
[require fileutil::magic::filetype]
[require websocket]
[require mime]
[require cron]
[require uri]
[require Markdown]
[description]
[para]

This module implements a web server, suitable for embedding in an
application. The server is object oriented, and contains all of the
fundamentals needed for a full service website.

[para]

[section {Minimal Example}]

Starting a web service requires starting a class of type
[cmd httpd::server], and providing that server with one or more URIs
to service, and [cmd httpd::reply] derived classes to generate them.

[example {
oo::class create ::reply.hello {
  method content {} {
    my puts "<HTML><HEAD><TITLE>IRM Dispatch Server</TITLE></HEAD><BODY>"
    my puts "<h1>Hello World!</h1>"
    my puts </BODY></HTML>
  }
}
::httpd::server create HTTPD port 8015 myaddr 127.0.0.1 doc_root ~/htdocs
HTTPD plugin dispatch httpd::server::dispatch
HTTPD uri add * /hello [list mixin reply.hello]
}]

The bare module does have facilities to hose a files from a file system. Files that end in a .tml will be substituted in the style of Tclhttpd:

[example {
<!-- hello.tml -->
[my html_header {Hello World!}]
Your Server is running.
<p>
The time is now [clock format [clock seconds]]
[my html_footer]
}]

A complete example of an httpd server is in the /examples directory of Tcllib. It also show how to dispatch URIs to other processes via SCGI and HTTP proxies.

[example {
cd ~/tcl/sandbox/tcllib
tclsh examples/httpd.tcl
}]

Changes to modules/httpd/build/plugin.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49



50

51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

77
78
79
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
###
# httpd plugin template
###
tool::define ::httpd::plugin {
  ###
  # Any options will be saved to the local config file
  # to allow threads to pull up a snapshot of the object' configuration
  ###

  ###
  # Define a code snippet to run on plugin load
  ###
  meta set plugin load: {}

  ###
  # Define a code snippet to run within the object's Headers_Process method
  ###
  meta set plugin headers: {}

  ###
  # Define a code snippet to run within the object's dispatch method
  ###
  meta set plugin dispatch: {}

  ###
  # Define a code snippet to run within the object's writes a local config file
  ###
  meta set plugin local_config: {}

  ###
  # When after all the plugins are loaded
  # allow specially configured ones to light off a thread
  ###
  meta set plugin thread: {}

}

###
# A rudimentary plugin that dispatches URLs from a dict
# data structure
###
tool::define ::httpd::plugin.dict_dispatch {
  meta set plugin dispatch: {
    set reply [my Dispatch_Dict $data]
    if {[dict size $reply]} {
      return $reply
    }
  }




  method Dispatch_Dict {data} {

    set vhost [lindex [split [dict get $data HTTP_HOST] :] 0]
    set uri   [dict get $data REQUEST_PATH]
    foreach {host pattern info} [my uri patterns] {
      if {![string match $host $vhost]} continue

      if {![string match $pattern $uri]} continue
      set buffer $data
      foreach {f v} $info {
        dict set buffer $f $v
      }
      return $buffer
    }
    return {}
  }

  method uri::patterns {} {
    my variable url_patterns url_stream
    if {![info exists url_stream]} {
      set url_stream {}
      foreach {host hostpat} $url_patterns {
        foreach {pattern info} $hostpat {
          lappend url_stream $host $pattern $info
        }
      }
    }
    return $url_stream
  }


  method uri::add args {
    my variable url_patterns url_stream
    unset -nocomplain url_stream
    switch [llength $args] {
      2 {
        set vhosts *
        lassign $args patterns info
      }
      3 {
        lassign $args vhosts patterns info
      }
      default {
        error "Usage: add_url ?vhosts? prefix info"
      }
    }
    foreach vhost $vhosts {
      foreach pattern $patterns {
        set data $info
        if {![dict exists $data prefix]} {
           dict set data prefix [my PrefixNormalize $pattern]
        }
        dict set url_patterns $vhost [string trimleft $pattern /] $data
      }
    }
  }
}

















tool::define ::httpd::reply.memchan {
  superclass ::httpd::reply

  method output {} {
    my variable reply_body
    return $reply_body
  }

  method DoOutput {} {}

  method close {} {
    # Neuter the channel closing mechanism we need the channel to stay alive
    # until the reader sucks out the info
  }
}


tool::define ::httpd::plugin.local_memchan {

  meta set plugin load: {
package require tcl::chan::events
package require tcl::chan::memchan
  }

  method local_memchan {command args} {
    my variable sock_to_coro
    switch $command {



|








|




|




|




|





|







|
|






>
>
>

>
|
|
|

>
|
|
|
|
|
|
|
<
|
|
<
<
<
<
<
<
<
|
|
<
<
<
>
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<










|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
















|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68







69
70



71
72
73
74













75
76
77
78
79
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
###
# httpd plugin template
###
::clay::define ::httpd::plugin {
  ###
  # Any options will be saved to the local config file
  # to allow threads to pull up a snapshot of the object' configuration
  ###

  ###
  # Define a code snippet to run on plugin load
  ###
  clay set plugin/ load {}

  ###
  # Define a code snippet to run within the object's Headers_Process method
  ###
  clay set plugin/ headers {}

  ###
  # Define a code snippet to run within the object's dispatch method
  ###
  clay set plugin/ dispatch {}

  ###
  # Define a code snippet to run within the object's writes a local config file
  ###
  clay set plugin/ local_config {}

  ###
  # When after all the plugins are loaded
  # allow specially configured ones to light off a thread
  ###
  clay set plugin/ thread {}

}

###
# A rudimentary plugin that dispatches URLs from a dict
# data structure
###
::clay::define ::httpd::plugin.dict_dispatch {
  clay set plugin/ dispatch {
    set reply [my Dispatch_Dict $data]
    if {[dict size $reply]} {
      return $reply
    }
  }

  ###
  # Implementation of the dispatcher
  ###
  method Dispatch_Dict {data} {
    my variable url_patterns
    set vhost [lindex [split [dict get $data http HTTP_HOST] :] 0]
    set uri   [dict get $data http REQUEST_PATH]
    foreach {host hostpat} $url_patterns {
      if {![string match $host $vhost]} continue
      foreach {pattern info} $hostpat {
        if {![string match $pattern $uri]} continue
        set buffer $data
        foreach {f v} $info {
          dict set buffer $f $v
        }
        return $buffer
      }

    }
    return {}







  }




  ###
  #
  Ensemble uri::add {vhosts patterns info} {
    my variable url_patterns













    foreach vhost $vhosts {
      foreach pattern $patterns {
        set data $info
        if {![dict exists $data prefix]} {
           dict set data prefix [my PrefixNormalize $pattern]
        }
        dict set url_patterns $vhost [string trimleft $pattern /] $data
      }
    }
  }

  Ensemble uri::direct {vhosts patterns info body} {
    my variable url_patterns url_stream
    set cbody {}
    if {[dict exists $info superclass]} {
      append cbody \n "superclass {*}[dict get $info superclass]"
      dict unset info superclass
    }
    append cbody \n [list method content {} $body]

    set class [namespace current]::${vhosts}/${patterns}
    set class [string map {* %} $class]
    ::clay::define $class $cbody
    dict set info mixin content $class
    my uri add $vhosts $patterns $info
  }
}

::clay::define ::httpd::reply.memchan {
  superclass ::httpd::reply

  method output {} {
    my variable reply_body
    return $reply_body
  }

  method DoOutput {} {}

  method close {} {
    # Neuter the channel closing mechanism we need the channel to stay alive
    # until the reader sucks out the info
  }
}


::clay::define ::httpd::plugin.local_memchan {

  clay set plugin/ load {
package require tcl::chan::events
package require tcl::chan::memchan
  }

  method local_memchan {command args} {
    my variable sock_to_coro
    switch $command {
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

    chan configure $sock \
      -blocking 0 \
      -translation {auto crlf} \
      -buffering line
    set ip 127.0.0.1
    dict set query UUID $uuid

    dict set query HTTP_HOST       localhost
    dict set query REMOTE_ADDR     127.0.0.1
    dict set query REMOTE_HOST     localhost
    dict set query LOCALHOST 1
    my counter url_hit

    dict set query REQUEST_METHOD  [lindex $args 0]
    set uriinfo [::uri::split [lindex $args 1]]
    dict set query REQUEST_URI     [lindex $args 1]
    dict set query REQUEST_PATH    [dict get $uriinfo path]
    dict set query REQUEST_VERSION [lindex [split [lindex $args end] /] end]
    dict set query DOCUMENT_ROOT   [my cget doc_root]
    dict set query QUERY_STRING    [dict get $uriinfo query]
    dict set query REQUEST_RAW     $args
    dict set query SERVER_PORT     [my port_listening]
    my Headers_Process query
    set reply [my dispatch $query]

    if {[llength $reply]==0} {
      my log BadLocation $uuid $query
      my log BadLocation $uuid $query
      dict set query HTTP_STATUS 404
      dict set query template notfound
      dict set query mixinmap reply ::httpd::content.template
    }

    set class ::httpd::reply.memchan
    set pageobj [$class create ::httpd::object::$uuid [self]]
    if {[dict exists $reply mixinmap]} {
      set mixinmap [dict get $reply mixinmap]
    } else {
      set mixinmap {}
    }
    if {[dict exists $reply mixin]} {
      dict set mixinmap reply [dict get $reply mixin]
    }
    foreach item [dict keys $reply MIXIN_*] {
      set slot [string range $reply 6 end]
      dict set mixinmap [string tolower $slot] [dict get $reply $item]
    }
    $pageobj mixinmap {*}$mixinmap
    if {[dict exists $reply organ]} {
      $pageobj graft {*}[dict get $reply organ]
    }
    $pageobj dispatch $sock $reply
    set output [$pageobj output]
    catch {$pageobj destroy}
    return $output
  }
}








>
|
|
|
|


|

|
|
|
|
|
|
|






|

|




|
|



<
<
<




|
|
|



|




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

    chan configure $sock \
      -blocking 0 \
      -translation {auto crlf} \
      -buffering line
    set ip 127.0.0.1
    dict set query UUID $uuid
    dict set query http UUID $uuid
    dict set query http HTTP_HOST       localhost
    dict set query http REMOTE_ADDR     127.0.0.1
    dict set query http REMOTE_HOST     localhost
    dict set query http LOCALHOST 1
    my counter url_hit

    dict set query http REQUEST_METHOD  [lindex $args 0]
    set uriinfo [::uri::split [lindex $args 1]]
    dict set query http REQUEST_URI     [lindex $args 1]
    dict set query http REQUEST_PATH    [dict get $uriinfo path]
    dict set query http REQUEST_VERSION [lindex [split [lindex $args end] /] end]
    dict set query http DOCUMENT_ROOT   [my clay get server/ doc_root]
    dict set query http QUERY_STRING    [dict get $uriinfo query]
    dict set query http REQUEST_RAW     $args
    dict set query http SERVER_PORT     [my port_listening]
    my Headers_Process query
    set reply [my dispatch $query]

    if {[llength $reply]==0} {
      my log BadLocation $uuid $query
      my log BadLocation $uuid $query
      dict set query http HTTP_STATUS 404
      dict set query template notfound
      dict set query mixin reply ::httpd::content.template
    }

    set class ::httpd::reply.memchan
    set pageobj [$class create ::httpd::object::$uuid [self]]
    if {[dict exists $reply mixin]} {
      set mixinmap [dict get $reply mixin]
    } else {
      set mixinmap {}
    }



    foreach item [dict keys $reply MIXIN_*] {
      set slot [string range $reply 6 end]
      dict set mixinmap [string tolower $slot] [dict get $reply $item]
    }
    $pageobj clay mixinmap {*}$mixinmap
    if {[dict exists $reply delegate]} {
      $pageobj clay delegate {*}[dict get $reply delegate]
    }
    $pageobj dispatch $sock $reply
    set output [$pageobj output]
    $pageobj clay refcount_decr
    return $output
  }
}

Changes to modules/httpd/build/proxy.tcl.

1
2
3
4
5
6
7
8
::tool::define ::httpd::content.exec {
  variable exename [list tcl [info nameofexecutable] .tcl [info nameofexecutable]]

  method CgiExec {execname script arglist} {
    if { $::tcl_platform(platform) eq "windows"} {
      if {[file extension $script] eq ".exe"} {
        return [open "|[list $script] $arglist" r+]
      } else {
|







1
2
3
4
5
6
7
8
::clay::define ::httpd::content.exec {
  variable exename [list tcl [info nameofexecutable] .tcl [info nameofexecutable]]

  method CgiExec {execname script arglist} {
    if { $::tcl_platform(platform) eq "windows"} {
      if {[file extension $script] eq ".exe"} {
        return [open "|[list $script] $arglist" r+]
      } else {
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
        return $result
      }
    }
    if {[dict exists exename $which]} {
      return [dict get $exename $which]
    }
    if {$which eq "tcl"} {
      if {[my cget tcl_exe] ne {}} {
        dict set exename $which [my cget tcl_exe]
      } else {
        dict set exename $which [info nameofexecutable]
      }
    } else {
      if {[my cget ${which}_exe] ne {}} {
        dict set exename $which [my cget ${which}_exe]
      } elseif {"$::tcl_platform(platform)" == "windows"} {
        dict set exename $which $which.exe
      } else {
        dict set exename $which $which
      }
    }
    set result [dict get $exename $which]
    if {$ext ne {}} {
      dict set exename $ext $result
    }
    return $result
  }
}

###
# Return data from an proxy process
###
::tool::define ::httpd::content.proxy {
  superclass ::httpd::content.exec

  method proxy_channel {} {
    ###
    # This method returns a channel to the
    # proxied socket/stdout/etc
    ###
    error unimplemented
  }

  method proxy_path {} {
    set uri [string trimleft [my http_info get REQUEST_URI] /]
    set prefix [my http_info get prefix]
    return /[string range $uri [string length $prefix] end]
  }

  method ProxyRequest {chana chanb} {
    chan event $chanb writable {}
    my log ProxyRequest {}
    chan puts $chanb "[my http_info get REQUEST_METHOD] [my proxy_path]"

    chan puts $chanb [my http_info get mimetxt]
    set length [my http_info get CONTENT_LENGTH]
    if {$length} {
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      ###
      # Send any POST/PUT/etc content
      ###
      chan copy $chana $chanb -size $length -command [info coroutine]
    } else {
      chan flush $chanb
      chan event $chanb readable [info coroutine]
    }

    yield
  }

  method ProxyReply {chana chanb args} {
    my log ProxyReply [list args $args]
    chan event $chana readable {}
    set readCount [::coroutine::util::gets_safety $chana 4096 reply_status]
    set replyhead [my HttpHeaders $chana]
    set replydat  [my MimeParse $replyhead]
    if {![dict exists $replydat Content-Length]} {
      set length 0
    } else {
      set length [dict get $replydat Content-Length]
    }
    ###
    # Read the first incoming line as the HTTP reply status
    # Return the rest of the headers verbatim
    ###
    set replybuffer "$reply_status\n"
    append replybuffer $replyhead
    chan configure $chanb -translation {auto crlf} -blocking 0 -buffering full -buffersize 4096
    chan puts $chanb $replybuffer
    my log SendReply [list length $length]
    if {$length} {
      ###
      # Output the body
      ###
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      chan copy $chana $chanb -size $length -command [namespace code [list my TransferComplete $chana $chanb]]
    } else {
      my TransferComplete $chana $chanb
    }
  }

  method dispatch {newsock datastate} {
    try {
      my http_info replace $datastate
      my request replace  [dict get $datastate http]
      my Log_Dispatched
      my variable sock chan
      set chan $newsock
      chan configure $chan -translation {auto crlf} -buffering line
      # Initialize the reply
      my reset
      # Invoke the URL implementation.
    } on error {err errdat} {
      my error 500 $err [dict get $errdat -errorinfo]
      tailcall my DoOutput
    }
    if {[catch {my proxy_channel} sock errdat]} {
      my error 504 {Service Temporarily Unavailable} [dict get $errdat -errorinfo]
      tailcall my DoOutput
    }
    if {$sock eq {}} {
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    my log HttpAccess {}
    chan event $sock writable [info coroutine]
    yield

    my ProxyRequest $chan $sock
    my ProxyReply   $sock $chan
  }
}







|
|




|
|

















|











|
|






|
>
|
|






|


<

>









<
<
<
<
|








<
<
|
|
|
|
|
<
<
|
|
|
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<











>




56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
        return $result
      }
    }
    if {[dict exists exename $which]} {
      return [dict get $exename $which]
    }
    if {$which eq "tcl"} {
      if {[my clay get tcl_exe] ne {}} {
        dict set exename $which [my clay get tcl_exe]
      } else {
        dict set exename $which [info nameofexecutable]
      }
    } else {
      if {[my clay get ${which}_exe] ne {}} {
        dict set exename $which [my clay get ${which}_exe]
      } elseif {"$::tcl_platform(platform)" == "windows"} {
        dict set exename $which $which.exe
      } else {
        dict set exename $which $which
      }
    }
    set result [dict get $exename $which]
    if {$ext ne {}} {
      dict set exename $ext $result
    }
    return $result
  }
}

###
# Return data from an proxy process
###
::clay::define ::httpd::content.proxy {
  superclass ::httpd::content.exec

  method proxy_channel {} {
    ###
    # This method returns a channel to the
    # proxied socket/stdout/etc
    ###
    error unimplemented
  }

  method proxy_path {} {
    set uri [string trimleft [my request get REQUEST_URI] /]
    set prefix [my clay get prefix]
    return /[string range $uri [string length $prefix] end]
  }

  method ProxyRequest {chana chanb} {
    chan event $chanb writable {}
    my log ProxyRequest {}
    chan puts $chanb "[my request get REQUEST_METHOD] [my proxy_path]"
    set mimetxt [my clay get mimetxt]
    chan puts $chanb [my clay get mimetxt]
    set length [my request get CONTENT_LENGTH]
    if {$length} {
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      ###
      # Send any POST/PUT/etc content
      ###
      my ChannelCopy $chana $chanb -size $length
    } else {
      chan flush $chanb

    }
    chan event $chanb readable [info coroutine]
    yield
  }

  method ProxyReply {chana chanb args} {
    my log ProxyReply [list args $args]
    chan event $chana readable {}
    set readCount [::coroutine::util::gets_safety $chana 4096 reply_status]
    set replyhead [my HttpHeaders $chana]
    set replydat  [my MimeParse $replyhead]





    ###
    # Read the first incoming line as the HTTP reply status
    # Return the rest of the headers verbatim
    ###
    set replybuffer "$reply_status\n"
    append replybuffer $replyhead
    chan configure $chanb -translation {auto crlf} -blocking 0 -buffering full -buffersize 4096
    chan puts $chanb $replybuffer


    ###
    # Output the body. With no -size flag, channel will copy until EOF
    ###
    chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
    chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096


    my ChannelCopy $chana $chanb -chunk 4096
  }






  method Dispatch {} {
    my variable sock chan









    if {[catch {my proxy_channel} sock errdat]} {
      my error 504 {Service Temporarily Unavailable} [dict get $errdat -errorinfo]
      tailcall my DoOutput
    }
    if {$sock eq {}} {
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    my log HttpAccess {}
    chan event $sock writable [info coroutine]
    yield
    my ChannelRegister $sock
    my ProxyRequest $chan $sock
    my ProxyReply   $sock $chan
  }
}

Changes to modules/httpd/build/reply.man.

129
130
131
132
133
134
135





136
137
138
139
140
141
142

Terminate the transaction, and close the socket.

[call method [cmd HttpHeaders] [arg sock] [arg ?debug?]]

Stream MIME headers from the socket [arg sock], stopping at an empty line. Returns
the stream as a block of text.






[call method [cmd dispatch] [arg newsock] [arg datastate]]

Take over control of the socket [arg newsock], and store that as the [arg chan] variable
for the object. This method runs through all of the steps of reading HTTP headers, generating
content, and closing the connection. (See class writetup).








>
>
>
>
>







129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

Terminate the transaction, and close the socket.

[call method [cmd HttpHeaders] [arg sock] [arg ?debug?]]

Stream MIME headers from the socket [arg sock], stopping at an empty line. Returns
the stream as a block of text.

[call method [cmd ChannelRegister] [arg chan]]

Registers a channel that will need to be flushed and closed when the object's destructor
invokes the close method.

[call method [cmd dispatch] [arg newsock] [arg datastate]]

Take over control of the socket [arg newsock], and store that as the [arg chan] variable
for the object. This method runs through all of the steps of reading HTTP headers, generating
content, and closing the connection. (See class writetup).

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
a timeout error to the request if it has, as well as destroy the object and close the
[arg chan] socket.

[call method [cmd timestamp]]

Return the current system time in the format: [example {%a, %d %b %Y %T %Z}]

[call method [cmd TransferComplete] [arg args]]

Intended to be invoked from [cmd {chan copy}] as a callback. This closes every channel
fed to it on the command line, and then destroys the object.

[example {
    ###
    # Output the body
    ###
    chan configure $sock -translation binary -blocking 0 -buffering full -buffersize 4096
    chan configure $chan -translation binary -blocking 0 -buffering full -buffersize 4096
    if {$length} {
      ###
      # Send any POST/PUT/etc content
      ###
      chan copy $sock $chan -size $SIZE -command [info coroutine]
      yield
    }
    catch {close $sock}
    chan flush $chan
}]

[call method [cmd Url_Decode] [arg string]]

De-httpizes a string.

[list_end]







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





269
270
271
272
273
274
275






















276
277
278
279
280
a timeout error to the request if it has, as well as destroy the object and close the
[arg chan] socket.

[call method [cmd timestamp]]

Return the current system time in the format: [example {%a, %d %b %Y %T %Z}]























[call method [cmd Url_Decode] [arg string]]

De-httpizes a string.

[list_end]

Changes to modules/httpd/build/reply.tcl.

1

2































































































3
4
5

6



7




8















9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
















26
27
28



29
30
31
32
33
34
35

36




37
38
39
40
41
42
43
44
45
46
47
48










49



50
51
52
53
54


55
56
57
58
59
60
61
62
63
64
65

66



67











68
69

70
71





72
73



74
75
76
77

78




79
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
###

# Define the reply class































































































###
::tool::define ::httpd::reply {
  superclass ::httpd::mime





  variable transfer_complete 0




















  constructor {ServerObj args} {
    my variable chan dispatched_time uuid
    set uuid [namespace tail [self]]
    set dispatched_time [clock milliseconds]
    oo::objdefine [self] forward <server> $ServerObj
    foreach {field value} [::oo::meta::args_to_options {*}$args] {
      my meta set config $field: $value
    }
  }

  ###
  # clean up on exit
  ###
  destructor {
    my close
  }

















  method close {} {
    my variable chan
    if {[info exists chan] && $chan ne {}} {



      catch {chan event $chan readable {}}
      catch {chan event $chan writable {}}
      catch {chan flush $chan}
      catch {chan close $chan}
      set chan {}
    }
  }






  method Log_Dispatched {} {
    my log Dispatched [dict create \
     REMOTE_ADDR [my http_info get REMOTE_ADDR] \
     REMOTE_HOST [my http_info get REMOTE_HOST] \
     COOKIE [my request get COOKIE] \
     REFERER [my request get REFERER] \
     USER_AGENT [my request get USER_AGENT] \
     REQUEST_URI [my http_info get REQUEST_URI] \
     HTTP_HOST [my http_info getnull HTTP_HOST] \
     SESSION [my http_info getnull SESSION] \
    ]
  }














  method dispatch {newsock datastate} {
    my http_info replace $datastate
    my request replace  [dict getnull $datastate http]
    my Log_Dispatched
    my variable chan


    set chan $newsock
    try {
      chan event $chan readable {}
      chan configure $chan -translation {auto crlf} -buffering line
      my reset
      # Invoke the URL implementation.
      my content
    } on error {err errdat} {
      my error 500 $err [dict get $errdat -errorinfo]
    } finally {
      my DoOutput

    }



  }












  method html_css {} {

    set result "<link rel=\"stylesheet\" href=\"/style.css\">"
    append result \n {<style media="screen" type="text/css">





body {
	background:  url(images/etoyoc-circuit-tile.gif) repeat;



	font-family: serif;
	color:#000066;
	font-size: 12pt;
}

</style>}




  }

  method html_header {title args} {
    set result {}
    append result "<HTML><HEAD>"
    if {$title ne {}} {
      append result "<TITLE>$title</TITLE>"
    }
    append result [my html_css]
    append result "</HEAD><BODY>"
    append result \n {<div id="top-menu">}
    if {[dict exists $args banner]} {
      append result "<img src=\"[dict get $args banner]\">"
    } else {
      append result {<img src="/images/etoyoc-banner.jpg">}
    }
    append result {</div>}
    if {[dict exists $args sideimg]} {
      append result "\n<div name=\"sideimg\"><img align=right src=\"[dict get $args sideimg]\"></div>"
    }
    append result {<div id="content">}
    return $result
  }

  method html_footer {args} {
    set result {</div><div id="footer">}
    append result {</div></BODY></HTML>}
  }

  dictobj http_info http_info {
    initialize {
      CONTENT_LENGTH 0
    }
    netstring {
      set result {}
      foreach {name value} $%VARNAME% {
        append result $name \x00 $value \x00
      }
      return "[string length $result]:$result,"
    }
  }

  method error {code {msg {}} {errorInfo {}}} {
    my http_info set HTTP_ERROR $code
    my reset
    set qheaders [my http_info dump]
    set HTTP_STATUS "$code [my http_code_string $code]"
    dict with qheaders {}
    my reply replace {}
    my reply set Status $HTTP_STATUS
    my reply set Content-Type {text/html; charset=UTF-8}

    switch $code {
      301 - 302 - 303 - 307 - 308 {
        my reply set Location $msg
        set template [my <server> template redirect]
      }
      404 {
        set template [my <server> template notfound]
      }
      default {
        set template [my <server> template internal_error]
      }
    }
    my puts [subst $template]
  }


  ###
  # REPLACE ME:
  # This method is the "meat" of your application.
  # It writes to the result buffer via the "puts" method
  # and can tweak the headers via "meta put header_reply"
  ###
  method content {} {
    my puts [my html_header {Hello World!}]
    my puts "<H1>HELLO WORLD!</H1>"
    my puts [my html_footer]
  }




  method EncodeStatus {status} {
    return "HTTP/1.0 $status"
  }

  method log {type {info {}}} {
    my variable dispatched_time uuid
    my <server> log $type $uuid $info
  }

  method CoroName {} {
    if {[info coroutine] eq {}} {
      return ::httpd::object::[my http_info get UUID]
    }
  }

  ###
  # Output the result or error to the channel
  # and destroy this object
  ###
  method DoOutput {} {
    my variable reply_body chan
    if {$chan eq {}} return
    catch {


      my wait writable $chan
      chan configure $chan  -translation {binary binary}
      ###
      # Return dynamic content
      ###
      set length [string length $reply_body]
      set result {}
      if {${length} > 0} {
        my reply set Content-Length [string length $reply_body]
        append result [my reply output] \n
        append result $reply_body
      } else {
        append result [my reply output]
      }
      chan puts -nonewline $chan $result
      my log HttpAccess {}
    }
    my destroy
  }










  method FormData {} {
    my variable chan formdata
    # Run this only once
    if {[info exists formdata]} {
      return $formdata
    }
    if {![my request exists CONTENT_LENGTH]} {
      set length 0
    } else {
      set length [my request get CONTENT_LENGTH]
    }
    set formdata {}
    if {[my http_info get REQUEST_METHOD] in {"POST" "PUSH"}} {
      set rawtype [my request get CONTENT_TYPE]
      if {[string toupper [string range $rawtype 0 8]] ne "MULTIPART"} {
        set type $rawtype
      } else {
        set type multipart
      }
      switch $type {
        multipart {
          ###
          # Ok, Multipart MIME is troublesome, farm out the parsing to a dedicated tool
          ###
          set body [my http_info get mimetxt]
          append body \n [my PostData $length]
          set token [::mime::initialize -string $body]
          foreach item [::mime::getheader $token -names] {
            dict set formdata $item [::mime::getheader $token $item]
          }
          foreach item {content encoding params parts size} {
            dict set formdata MIME_[string toupper $item] [::mime::getproperty $token $item]

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|

>

>
>
>
|
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|


|
|
|










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
|
>
>
>
|
|
|
|
<

<
>
|
>
>
>
>


|
|
|
|
|
|
|
|


>
>
>
>
>
>
>
>
>
>
|
>
>
>

<
<
<
|
>
>
|
|


<
<
|
<
|
|
<
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
|
>
|
<
>
>
>
>
>
|
<
>
>
>
|
|
|
|
>
|
>
>
>
>








<




















<
<
<
<
<
<
<
<
<
<
<
<
<

|

|





<




















|







>
>
>











|




|
|





>
>
|
















<


>
>
>
>
>
>
>
>
>






<
<
<
|
<

|











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
###
# A class which shephards a request through the process of generating a
# reply.
#
# The socket associated with the reply is available at all times as the [arg chan]
# variable.
#
# The process of generating a reply begins with an [cmd httpd::server] generating a
# [cmd http::class] object, mixing in a set of behaviors and then invoking the reply
# object's [cmd dispatch] method.
#
# In normal operations the [cmd dispatch] method:
#
# [list_begin enumerated]
# [enum]
# Invokes the [cmd reset] method for the object to populate default headers.
# [enum]
# Invokes the [cmd HttpHeaders] method to stream the MIME headers out of the socket
# [enum]
# Invokes the [cmd {request parse}] method to convert the stream of MIME headers into a
# dict that can be read via the [cmd request] method.
# [enum]
# Stores the raw stream of MIME headers in the [arg rawrequest] variable of the object.
# [enum]
# Invokes the [cmd content] method for the object, generating an call to the [cmd error]
# method if an exception is raised.
# [enum]
# Invokes the [cmd output] method for the object
# [list_end]
# [para]
#
# Developers have the option of streaming output to a buffer via the [cmd puts] method of the
# reply, or simply populating the [arg reply_body] variable of the object.
# The information returned by the [cmd content] method is not interpreted in any way.
#
# If an exception is thrown (via the [cmd error] command in Tcl, for example) the caller will
# auto-generate a 500 {Internal Error} message.
#
# A typical implementation of [cmd content] look like:
#
# [example {
#
# clay::define ::test::content.file {
# 	superclass ::httpd::content.file
# 	# Return a file
# 	# Note: this is using the content.file mixin which looks for the reply_file variable
# 	# and will auto-compute the Content-Type
# 	method content {} {
# 	  my reset
#     set doc_root [my request get DOCUMENT_ROOT]
#     my variable reply_file
#     set reply_file [file join $doc_root index.html]
# 	}
# }
# clay::define ::test::content.time {
#   # return the current system time
# 	method content {} {
# 		my variable reply_body
#     my reply set Content-Type text/plain
# 		set reply_body [clock seconds]
# 	}
# }
# clay::define ::test::content.echo {
# 	method content {} {
# 		my variable reply_body
#     my reply set Content-Type [my request get CONTENT_TYPE]
# 		set reply_body [my PostData [my request get CONTENT_LENGTH]]
# 	}
# }
# clay::define ::test::content.form_handler {
# 	method content {} {
# 	  set form [my FormData]
# 	  my reply set Content-Type {text/html; charset=UTF-8}
#     my puts [my html_header {My Dynamic Page}]
#     my puts "<BODY>"
#     my puts "You Sent<p>"
#     my puts "<TABLE>"
#     foreach {f v} $form {
#       my puts "<TR><TH>$f</TH><TD><verbatim>$v</verbatim></TD>"
#     }
#     my puts "</TABLE><p>"
#     my puts "Send some info:<p>"
#     my puts "<FORM action=/[my request get REQUEST_PATH] method POST>"
#     my puts "<TABLE>"
#     foreach field {name rank serial_number} {
#       set line "<TR><TH>$field</TH><TD><input name=\"$field\" "
#       if {[dict exists $form $field]} {
#         append line " value=\"[dict get $form $field]\"""
#       }
#       append line " /></TD></TR>"
#       my puts $line
#     }
#     my puts "</TABLE>"
#     my puts [my html footer]
# 	}
# }
#
# }]
###
::clay::define ::httpd::reply {
  superclass ::httpd::mime
  Variable ChannelRegister {}

  Delegate <server> {
    description {The server object which spawned this reply}
  }

  ###
  # A dictionary which will converted into the MIME headers of the reply
  ###
  Dict reply {}

  ###
  # A dictionary containing the SCGI transformed HTTP headers for the request
  ###
  Dict request {
    CONTENT_LENGTH 0
    COOKIE {}
    HTTP_HOST {}
    REFERER {}
    REQUEST_URI {}
    REMOTE_ADDR {}
    REMOTE_HOST {}
    USER_AGENT {}
    SESSION {}
  }

  constructor {ServerObj args} {
    my variable dispatched_time uuid
    set uuid [namespace tail [self]]
    set dispatched_time [clock milliseconds]
    my clay delegate <server> $ServerObj
    foreach {field value} [::clay::args_to_options {*}$args] {
      my clay set config $field: $value
    }
  }

  ###
  # clean up on exit
  ###
  destructor {
    my close
  }

  # Registers a channel to be closed by the close method
  method ChannelRegister args {
    my variable ChannelRegister
    if {![info exists ChannelRegister]} {
      set ChannelRegister {}
    }
    foreach c $args {
      if {$c ni $ChannelRegister} {
        lappend ChannelRegister $c
      }
    }
  }

  ###
  # Close channels opened by this object
  ###
  method close {} {
    my variable ChannelRegister
    if {![info exists ChannelRegister]} {
      return
    }
    foreach c $ChannelRegister {
      catch {chan event $c readable {}}
      catch {chan event $c writable {}}
      catch {chan flush $c}
      catch {chan close $c}

    }

    set ChannelRegister {}
  }

  ###
  # Record a dispatch event
  ###
  method Log_Dispatched {} {
    my log Dispatched [dict create \
     REMOTE_ADDR [my request get REMOTE_ADDR] \
     REMOTE_HOST [my request get REMOTE_HOST] \
     COOKIE [my request get HTTP_COOKIE] \
     REFERER [my request get HTTP_REFERER] \
     USER_AGENT [my request get HTTP_USER_AGENT] \
     REQUEST_URI [my request get REQUEST_URI] \
     HTTP_HOST [my request get HTTP_HOST] \
     SESSION [my request get SESSION] \
    ]
  }

  ###
  # Accept the handoff from the server object of the socket
  # [emph newsock] and feed it the state [emph datastate].
  # Fields the [emph datastate] are looking for in particular are:
  # [para]
  # * [const mixin] - A key/value list of slots and classes to be mixed into the
  # object prior to invoking [cmd Dispatch].
  # [para]
  # * [const http] - A key/value list of values to populate the object's [emph request]
  # ensemble
  # [para]
  # All other fields are passed along to the [method clay] structure of the object.
  ###
  method dispatch {newsock datastate} {



    my variable chan request
    try {
      my clay refcount_incr
      set chan $newsock
      my ChannelRegister $chan
      chan event $chan readable {}
      chan configure $chan -translation {auto crlf} -buffering line


      if {[dict exists $datastate mixin]} {

        set mixinmap [dict get $datastate mixin]
      } else {

        set mixinmap {}
      }
      foreach item [dict keys $datastate MIXIN_*] {
        set slot [string range $item 6 end]
        dict set mixinmap [string tolower $slot] [dict get $datastate $item]
      }
      my clay mixinmap {*}$mixinmap
      if {[dict exists $datastate delegate]} {
        my clay delegate {*}[dict get $datastate delegate]
      }
      my reset
      set request [my clay get dict/ request]
      foreach {f v} $datastate {
        if {[string index $f end] eq "/"} {
          catch {my clay merge $f $v}
        } else {
          my clay set $f $v
        }
        if {$f eq "http"} {
          foreach {ff vf} $v {
            dict set request $ff $vf

          }
        }
      }
      my Session_Load
      my Log_Dispatched
      my Dispatch

    } on error {err errdat} {
      my error 500 $err [dict get $errdat -errorinfo]
      my DoOutput
    } finally {
      my close
      my clay refcount_decr
    }
  }

  method Dispatch {} {
    # Invoke the URL implementation.
    my content
    my DoOutput
  }

  method html_header {title args} {
    set result {}
    append result "<HTML><HEAD>"
    if {$title ne {}} {
      append result "<TITLE>$title</TITLE>"
    }

    append result "</HEAD><BODY>"
    append result \n {<div id="top-menu">}
    if {[dict exists $args banner]} {
      append result "<img src=\"[dict get $args banner]\">"
    } else {
      append result {<img src="/images/etoyoc-banner.jpg">}
    }
    append result {</div>}
    if {[dict exists $args sideimg]} {
      append result "\n<div name=\"sideimg\"><img align=right src=\"[dict get $args sideimg]\"></div>"
    }
    append result {<div id="content">}
    return $result
  }

  method html_footer {args} {
    set result {</div><div id="footer">}
    append result {</div></BODY></HTML>}
  }














  method error {code {msg {}} {errorInfo {}}} {
    my clay set  HTTP_ERROR $code
    my reset
    set qheaders [my clay dump]
    set HTTP_STATUS "$code [my http_code_string $code]"
    dict with qheaders {}
    my reply replace {}
    my reply set Status $HTTP_STATUS
    my reply set Content-Type {text/html; charset=UTF-8}

    switch $code {
      301 - 302 - 303 - 307 - 308 {
        my reply set Location $msg
        set template [my <server> template redirect]
      }
      404 {
        set template [my <server> template notfound]
      }
      default {
        set template [my <server> template internal_error]
      }
    }
    my puts [subst $template]
  }


  ###
  # REPLACE ME:
  # This method is the "meat" of your application.
  # It writes to the result buffer via the "puts" method
  # and can tweak the headers via "clay put header_reply"
  ###
  method content {} {
    my puts [my html_header {Hello World!}]
    my puts "<H1>HELLO WORLD!</H1>"
    my puts [my html_footer]
  }

  ###
  # Formulate a standard HTTP status header from he string provided.
  ###
  method EncodeStatus {status} {
    return "HTTP/1.0 $status"
  }

  method log {type {info {}}} {
    my variable dispatched_time uuid
    my <server> log $type $uuid $info
  }

  method CoroName {} {
    if {[info coroutine] eq {}} {
      return ::httpd::object::[my clay get UUID]
    }
  }

  ###
  # Generates the the HTTP reply, streams that reply back across [arg chan],
  # and destroys the object.
  ###
  method DoOutput {} {
    my variable reply_body chan
    if {$chan eq {}} return
    catch {
      # Causing random issues. Technically a socket is always open for read and write
      # anyway
      #my wait writable $chan
      chan configure $chan  -translation {binary binary}
      ###
      # Return dynamic content
      ###
      set length [string length $reply_body]
      set result {}
      if {${length} > 0} {
        my reply set Content-Length [string length $reply_body]
        append result [my reply output] \n
        append result $reply_body
      } else {
        append result [my reply output]
      }
      chan puts -nonewline $chan $result
      my log HttpAccess {}
    }

  }

  ###
  # For GET requests, converts the QUERY_DATA header into a key/value list.
  #
  # For POST requests, reads the Post data and converts that information to
  # a key/value list for application/x-www-form-urlencoded posts. For multipart
  # posts, it composites all of the MIME headers of the post to a singular key/value
  # list, and provides MIME_* information as computed by the [cmd mime] package, including
  # the MIME_TOKEN, which can be fed back into the mime package to read out the contents.
  ###
  method FormData {} {
    my variable chan formdata
    # Run this only once
    if {[info exists formdata]} {
      return $formdata
    }



    set length [my request get CONTENT_LENGTH]

    set formdata {}
    if {[my request get REQUEST_METHOD] in {"POST" "PUSH"}} {
      set rawtype [my request get CONTENT_TYPE]
      if {[string toupper [string range $rawtype 0 8]] ne "MULTIPART"} {
        set type $rawtype
      } else {
        set type multipart
      }
      switch $type {
        multipart {
          ###
          # Ok, Multipart MIME is troublesome, farm out the parsing to a dedicated tool
          ###
          set body [my clay get mimetxt]
          append body \n [my PostData $length]
          set token [::mime::initialize -string $body]
          foreach item [::mime::getheader $token -names] {
            dict set formdata $item [::mime::getheader $token $item]
          }
          foreach item {content encoding params parts size} {
            dict set formdata MIME_[string toupper $item] [::mime::getproperty $token $item]
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
            foreach {name value} [split $pair "="] {
              lappend formdata [my Url_Decode $name] [my Url_Decode $value]
            }
          }
        }
      }
    } else {
      foreach pair [split [my http_info getnull QUERY_STRING] "&"] {
        foreach {name value} [split $pair "="] {
          lappend formdata [my Url_Decode $name] [my Url_Decode $value]
        }
      }
    }
    return $formdata
  }



  method PostData {length} {
    my variable postdata
    # Run this only once
    if {[info exists postdata]} {
      return $postdata
    }
    set postdata {}
    if {[my http_info get REQUEST_METHOD] in {"POST" "PUSH"}} {
      my variable chan
      chan configure $chan -translation binary -blocking 0 -buffering full -buffersize 4096
      set postdata [::coroutine::util::read $chan $length]
    }
    return $postdata
  }


  method TransferComplete args {
    my variable chan transfer_complete
    set transfer_complete 1
    my log TransferComplete
    set chan {}
    foreach c $args {
      catch {chan event $c readable {}}
      catch {chan event $c writable {}}
      catch {chan flush $c}
      catch {chan close $c}
    }
    my destroy
  }

  ###
  # Append to the result buffer
  ###
  method puts line {
    my variable reply_body
    append reply_body $line \n
  }

  method RequestFind {field} {
    my variable request
    if {[dict exists $request $field]} {
      return $field
    }
    foreach item [dict keys $request] {
      if {[string tolower $item] eq [string tolower $field]} {
        return $item
      }
    }
    return $field
  }


  dictobj request request {




    field {
      tailcall my RequestFind [lindex $args 0]
    }
    get {
      set field [my RequestFind [lindex $args 0]]
      if {![dict exists $request $field]} {
        return {}
      }
      tailcall dict get $request $field
    }
    getnull {
      set field [my RequestFind [lindex $args 0]]
      if {![dict exists $request $field]} {
        return {}
      }
      tailcall dict get $request $field

    }
    exists {
      set field [my RequestFind [lindex $args 0]]
      tailcall dict exists $request $field
    }
    parse {
      if {[catch {my MimeParse [lindex $args 0]} result]} {
        my error 400 $result
        tailcall my DoOutput
      }
      set request $result
    }


  }








  dictobj reply reply {

























    output {
      set result {}
      if {![dict exists $reply Status]} {
        set status {200 OK}
      } else {
        set status [dict get $reply Status]
      }
      set result "[my EncodeStatus $status]\n"
      foreach {f v} $reply {
        if {$f in {Status}} continue
        append result "[string trimright $f :]: $v\n"
      }
      #append result \n
      return $result
    }


  }





  ###
  # Reset the result
  ###


  method reset {} {
    my variable reply_body
    my reply replace    [my HttpHeaders_Default]
    my reply set Server [my <server> cget server_string]
    my reply set Date [my timestamp]
    set reply_body {}
  }

  ###
  # Return true of this class as waited too long to respond
  ###

  method timeOutCheck {} {
    my variable dispatched_time
    if {([clock seconds]-$dispatched_time)>120} {
      ###
      # Something has lasted over 2 minutes. Kill this
      ###
      catch {
        my error 408 {Request Timed out}
        my DoOutput
      }
    }
  }

  ###
  # Return a timestamp
  ###
  method timestamp {} {
    return [clock format [clock seconds] -format {%a, %d %b %Y %T %Z}]
  }
}







|








>
>







|







>
|
<
<
<
<
<
<
<
<
<
|
<
<
|
|
<
<


















>
|
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|
|
|
|
|
|
>
>
|
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
>
>
|
|
>
|
<
<
>
>



|




|
|
|
>














|





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
            foreach {name value} [split $pair "="] {
              lappend formdata [my Url_Decode $name] [my Url_Decode $value]
            }
          }
        }
      }
    } else {
      foreach pair [split [my request get QUERY_STRING] "&"] {
        foreach {name value} [split $pair "="] {
          lappend formdata [my Url_Decode $name] [my Url_Decode $value]
        }
      }
    }
    return $formdata
  }

  # Stream [arg length] bytes from the [arg chan] socket, but only of the request is a
  # POST or PUSH. Returns an empty string otherwise.
  method PostData {length} {
    my variable postdata
    # Run this only once
    if {[info exists postdata]} {
      return $postdata
    }
    set postdata {}
    if {[my request get REQUEST_METHOD] in {"POST" "PUSH"}} {
      my variable chan
      chan configure $chan -translation binary -blocking 0 -buffering full -buffersize 4096
      set postdata [::coroutine::util::read $chan $length]
    }
    return $postdata
  }

  # Manage session data
  method Session_Load {} {}












  # Appends the value of [arg string] to the end of [arg reply_body], as well as a trailing newline
  # character.


  method puts line {
    my variable reply_body
    append reply_body $line \n
  }

  method RequestFind {field} {
    my variable request
    if {[dict exists $request $field]} {
      return $field
    }
    foreach item [dict keys $request] {
      if {[string tolower $item] eq [string tolower $field]} {
        return $item
      }
    }
    return $field
  }

  method request {subcommand args} {
    my variable request
    switch $subcommand {
      dump {
        return $request
      }
      field {
        tailcall my RequestFind [lindex $args 0]
      }
      get {
        set field [my RequestFind [lindex $args 0]]
        if {![dict exists $request $field]} {
          return {}
        }
        tailcall dict get $request $field
      }
      getnull {
        set field [my RequestFind [lindex $args 0]]
        if {![dict exists $request $field]} {
          return {}
        }
        tailcall dict get $request $field
      }

      exists {
        set field [my RequestFind [lindex $args 0]]
        tailcall dict exists $request $field
      }
      parse {
        if {[catch {my MimeParse [lindex $args 0]} result]} {
          my error 400 $result
          tailcall my DoOutput
        }
        set request $result
      }
      replace {
        set request [lindex $args 0]
      }
      set {
        dict set request {*}$args
      }
      default {
        error "Unknown command $subcommand. Valid: field, get, getnull, exists, parse, replace, set"
      }
    }
  }

  method reply {subcommand args} {
    my variable reply
    switch $subcommand {
      dump {
        return $reply
      }
      exists {
        return [dict exists $reply {*}$args]
      }
      get -
      getnull {
        return [dict getnull $reply {*}$args]
      }
      replace {
        set reply [my HttpHeaders_Default]
        if {[llength $args]==1} {
          foreach {f v} [lindex $args 0] {
            dict set reply $f $v
          }
        } else {
          foreach {f v} $args {
            dict set reply $f $v
          }
        }
      }
      output {
        set result {}
        if {![dict exists $reply Status]} {
          set status {200 OK}
        } else {
          set status [dict get $reply Status]
        }
        set result "[my EncodeStatus $status]\n"
        foreach {f v} $reply {
          if {$f in {Status}} continue
          append result "[string trimright $f :]: $v\n"
        }
        #append result \n
        return $result
      }
      set {
        dict set reply {*}$args
      }
      default {
        error "Unknown command $subcommand. Valid: exists, get, getnull, output, replace, set"
      }
    }
  }



  # Clear the contents of the [arg reply_body] variable, and reset all headers in the [cmd reply]
  # structure back to the defaults for this object.
  method reset {} {
    my variable reply_body
    my reply replace    [my HttpHeaders_Default]
    my reply set Server [my <server> clay get server/ string]
    my reply set Date [my timestamp]
    set reply_body {}
  }

  # Called from the [cmd http::server] object which spawned this reply. Checks to see
  # if too much time has elapsed while waiting for data or generating a reply, and issues
  # a timeout error to the request if it has, as well as destroy the object and close the
  # [arg chan] socket.
  method timeOutCheck {} {
    my variable dispatched_time
    if {([clock seconds]-$dispatched_time)>120} {
      ###
      # Something has lasted over 2 minutes. Kill this
      ###
      catch {
        my error 408 {Request Timed out}
        my DoOutput
      }
    }
  }

  ###
  # Return the current system time in the format: [example {%a, %d %b %Y %T %Z}]
  ###
  method timestamp {} {
    return [clock format [clock seconds] -format {%a, %d %b %Y %T %Z}]
  }
}

Changes to modules/httpd/build/scgi.tcl.

1
2
3







4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

55
56
57
58
59

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
###
# Return data from an SCGI process
###







::tool::define ::httpd::content.scgi {
  superclass ::httpd::content.proxy


  method scgi_info {} {
    ###
    # This method should check if a process is launched
    # or launch it if needed, and return a list of
    # HOST PORT SCRIPT_NAME
    ###
    # return {localhost 8016 /some/path}
    error unimplemented
  }

  method proxy_channel {} {
    set sockinfo [my scgi_info]
    if {$sockinfo eq {}} {
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    lassign $sockinfo scgihost scgiport scgiscript
    my http_info set SCRIPT_NAME $scgiscript
    if {![string is integer $scgiport]} {
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    return [::socket $scgihost $scgiport]
  }

  method ProxyRequest {chana chanb} {
    chan event $chanb writable {}
    my log ProxyRequest {}
    chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
    chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
    set info [dict create CONTENT_LENGTH 0 SCGI 1.0 SCRIPT_NAME [my http_info get SCRIPT_NAME]]
    foreach {f v} [my http_info dump] {
      dict set info $f $v
    }
    set length [dict get $info CONTENT_LENGTH]
    set block {}
    foreach {f v} $info {
      append block [string toupper $f] \x00 $v \x00
    }
    chan puts -nonewline $chanb "[string length $block]:$block,"
    # Light off another coroutine
    #set cmd [list coroutine [my CoroName] {*}[namespace code [list my ProxyReply $chanb $chana]]]
    if {$length} {
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      ###
      # Send any POST/PUT/etc content
      ###

      chan copy $chana $chanb -size $length -command [info coroutine]
    } else {
      chan flush $chanb
      chan event $chanb readable [info coroutine]
    }

    yield
  }

  method ProxyReply {chana chanb args} {
    my log ProxyReply [list args $args]
    chan event $chana readable {}
    set replyhead [my HttpHeaders $chana]
    set replydat  [my MimeParse $replyhead]
    if {![dict exists $replydat Content-Length]} {
      set length 0
    } else {
      set length [dict get $replydat Content-Length]
    }
    ###
    # Convert the Status: header from the CGI process to
    # a standard service reply line from a web server, but
    # otherwise spit out the rest of the headers verbatim
    ###
    set replybuffer "HTTP/1.0 [dict get $replydat Status]\n"
    append replybuffer $replyhead
    chan configure $chanb -translation {auto crlf} -blocking 0 -buffering full -buffersize 4096
    chan puts $chanb $replybuffer
    my log SendReply [list length $length]
    if {$length} {
      ###
      # Output the body
      ###
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      chan copy $chana $chanb -size $length -command [namespace code [list my TransferComplete $chana $chanb]]
    } else {
      my TransferComplete $chan $chanb
    }
  }
}

tool::define ::httpd::reply.scgi {
  superclass ::httpd::reply

  method EncodeStatus {status} {
    return "Status: $status"
  }
}

###
# Act as an  SCGI Server
###
tool::define ::httpd::server.scgi {
  superclass ::httpd::server

  property socket buffersize   32768
  property socket blocking     0
  property socket translation  {binary binary}

  property reply_class ::httpd::reply.scgi



  method Connect {uuid sock ip} {
    yield [info coroutine]
    chan event $sock readable {}
    chan configure $sock \
        -blocking 1 \
        -translation {binary binary} \
        -buffersize 4096 \
        -buffering none
    my counter url_hit
    try {
      # Read the SCGI request on byte at a time until we reach a ":"
      dict set query REQUEST_URI /

      dict set query REMOTE_ADDR     $ip


      set size {}
      while 1 {
        set char [::coroutine::util::read $sock 1]
        if {[chan eof $sock]} {
          catch {close $sock}
          return
        }
        if {$char eq ":"} break
        append size $char
      }
      # With length in hand, read the netstring encoded headers
      set inbuffer [::coroutine::util::read $sock [expr {$size+1}]]
      chan configure $sock -blocking 0 -buffersize 4096 -buffering full
      foreach {f v} [lrange [split [string range $inbuffer 0 end-1] \0] 0 end-1] {
        dict set query $f $v
        if {$f in {CONTENT_LENGTH CONTENT_TYPE}} {
          dict set query http $f $v
        } elseif {[string range $f 0 4] eq "HTTP_"} {
          dict set query http [string range $f 5 end] $v
        }
      }
      if {![dict exists $query REQUEST_PATH]} {
        set uri [dict get $query REQUEST_URI]
        set uriinfo [::uri::split $uri]
        dict set query REQUEST_PATH    [dict get $uriinfo path]
      }
      set reply [my dispatch $query]
      dict with query {}
      if {[llength $reply]} {
        if {[dict exists $reply class]} {
          set class [dict get $reply class]


        } else {
          set class [my cget reply_class]
        }
        set pageobj [$class create [namespace current]::reply$uuid [self]]
        if {[dict exists $reply mixin]} {



          oo::objdefine $pageobj mixin [dict get $reply mixin]
        }
        $pageobj dispatch $sock $reply
        my log HttpAccess $REQUEST_URI
      } else {
        try {
          my log HttpMissing $REQUEST_URI
          chan puts $sock "Status: 404 NOT FOUND"
          dict with query {}
          set body [subst [my template notfound]]
          chan puts $sock "Content-Length: [string length $body]"
          chan puts $sock {}
          chan puts $sock $body
        } on error {err errdat} {
          my <server> debug "FAILED ON 404: $err [dict get $errdat -errorinfo]"
        } finally {
          catch {chan event readable $sock {}}
          catch {chan event writeable $sock {}}
          catch {chan close $sock}
        }
      }
    } on error {err errdat} {
      try {
        my <server> debug [dict get $errdat -errorinfo]
        chan puts $sock "Status: 500 INTERNAL ERROR - scgi 298"

        dict with query {}
        set body [subst [my template internal_error]]
        chan puts $sock "Content-Length: [string length $body]"
        chan puts $sock {}
        chan puts $sock $body
        my log HttpError [list error [my http_info get REMOTE_ADDR] errorinfo [dict get $errdat -errorinfo]]
      } on error {err errdat} {
        my log HttpFatal [list error [my http_info get REMOTE_ADDR] errorinfo [dict get $errdat -errorinfo]]
        my <server> debug "Failed on 500: [dict get $errdat -errorinfo]""
      } finally {
        catch {chan event readable $sock {}}
        catch {chan event writeable $sock {}}
        catch {chan close $sock}
      }

    }
  }
}



>
>
>
>
>
>
>
|

>


















|












|
|
















>
|


<

>








<
<
<
<
<









<
<
|
|
|
|
|
<
<
<
<
<
<
|
<
<
<
<
<






|


|
|
|

|
>
>












|
>
|
>
>












|

<
<
|
<
<
|
<
|
|

|


|
|
|
|
>
>
|
|
|
<
|
>
>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
>
|
<
<
<
|
<
|
|
|
|
|
|
|
<
>



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76





77
78
79
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
###
# Return data from an SCGI process
###
::clay::define ::httpd::protocol.scgi {

  method EncodeStatus {status} {
    return "Status: $status"
  }
}

::clay::define ::httpd::content.scgi {
  superclass ::httpd::content.proxy


  method scgi_info {} {
    ###
    # This method should check if a process is launched
    # or launch it if needed, and return a list of
    # HOST PORT SCRIPT_NAME
    ###
    # return {localhost 8016 /some/path}
    error unimplemented
  }

  method proxy_channel {} {
    set sockinfo [my scgi_info]
    if {$sockinfo eq {}} {
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    lassign $sockinfo scgihost scgiport scgiscript
    my clay set  SCRIPT_NAME $scgiscript
    if {![string is integer $scgiport]} {
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    return [::socket $scgihost $scgiport]
  }

  method ProxyRequest {chana chanb} {
    chan event $chanb writable {}
    my log ProxyRequest {}
    chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
    chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
    set info [dict create CONTENT_LENGTH 0 SCGI 1.0 SCRIPT_NAME [my clay get SCRIPT_NAME]]
    foreach {f v} [my request dump] {
      dict set info $f $v
    }
    set length [dict get $info CONTENT_LENGTH]
    set block {}
    foreach {f v} $info {
      append block [string toupper $f] \x00 $v \x00
    }
    chan puts -nonewline $chanb "[string length $block]:$block,"
    # Light off another coroutine
    #set cmd [list coroutine [my CoroName] {*}[namespace code [list my ProxyReply $chanb $chana]]]
    if {$length} {
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      ###
      # Send any POST/PUT/etc content
      ###
      my ChannelCopy $chana $chanb -size $length
      #chan copy $chana $chanb -size $length -command [info coroutine]
    } else {
      chan flush $chanb

    }
    chan event $chanb readable [info coroutine]
    yield
  }

  method ProxyReply {chana chanb args} {
    my log ProxyReply [list args $args]
    chan event $chana readable {}
    set replyhead [my HttpHeaders $chana]
    set replydat  [my MimeParse $replyhead]





    ###
    # Convert the Status: header from the CGI process to
    # a standard service reply line from a web server, but
    # otherwise spit out the rest of the headers verbatim
    ###
    set replybuffer "HTTP/1.0 [dict get $replydat Status]\n"
    append replybuffer $replyhead
    chan configure $chanb -translation {auto crlf} -blocking 0 -buffering full -buffersize 4096
    chan puts $chanb $replybuffer


    ###
    # Output the body. With no -size flag, channel will copy until EOF
    ###
    chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
    chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096






    my ChannelCopy $chana $chanb -chunk 4096





  }
}

###
# Act as an  SCGI Server
###
::clay::define ::httpd::server.scgi {
  superclass ::httpd::server

  clay set socket/ buffersize   32768
  clay set socket/ blocking     0
  clay set socket/ translation  {binary binary}

  method debug args {
    puts $args
  }

  method Connect {uuid sock ip} {
    yield [info coroutine]
    chan event $sock readable {}
    chan configure $sock \
        -blocking 1 \
        -translation {binary binary} \
        -buffersize 4096 \
        -buffering none
    my counter url_hit
    try {
      # Read the SCGI request on byte at a time until we reach a ":"
      dict set query http HTTP_HOST {}
      dict set query http CONTENT_LENGTH 0
      dict set query http REQUEST_URI /
      dict set query http REMOTE_ADDR $ip
      dict set query http DOCUMENT_ROOT [my clay get server/ doc_root]
      set size {}
      while 1 {
        set char [::coroutine::util::read $sock 1]
        if {[chan eof $sock]} {
          catch {close $sock}
          return
        }
        if {$char eq ":"} break
        append size $char
      }
      # With length in hand, read the netstring encoded headers
      set inbuffer [::coroutine::util::read $sock [expr {$size+1}]]
      chan configure $sock -translation {auto crlf} -blocking 0 -buffersize 4096 -buffering full
      foreach {f v} [lrange [split [string range $inbuffer 0 end-1] \0] 0 end-1] {


        dict set query http $f $v


      }

      if {![dict exists $query http REQUEST_PATH]} {
        set uri [dict get $query http REQUEST_URI]
        set uriinfo [::uri::split $uri]
        dict set query http REQUEST_PATH    [dict get $uriinfo path]
      }
      set reply [my dispatch $query]
    } on error {err errdat} {
      my debug [list uri: [dict getnull $query http REQUEST_URI] ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      my log BadRequest $uuid [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      catch {chan puts $sock "HTTP/1.0 400 Bad Request (The data is invalid)"}
      catch {chan event readable $sock {}}
      catch {chan event writeable $sock {}}
      catch {chan close $sock}
      return
    }

    if {[dict size $reply]==0} {
      my log BadLocation $uuid $query
      dict set query http HTTP_STATUS 404
      dict set query template notfound
      dict set query mixin reply ::httpd::content.template
    }




















    try {


      set pageobj [::httpd::reply create ::httpd::object::$uuid [self]]
      dict set reply mixin protocol ::httpd::protocol.scgi



      $pageobj dispatch $sock $reply

    } on error {err errdat} {
      my debug [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      my log BadRequest $uuid [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      $pageobj clay refcount_decr
      catch {chan event readable $sock {}}
      catch {chan event writeable $sock {}}
      catch {chan close $sock}

      return
    }
  }
}

Changes to modules/httpd/build/server.tcl.

1
2
3



4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27

















28
29
30
31
32
33
34




35
36
37
38
39
40
41
42
43
44
45
46
47
48











































49

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
###
# An httpd server with a template engine
# and a shim to insert URL domains



###
namespace eval ::httpd::object {}
namespace eval ::httpd::coro {}

::tool::define ::httpd::server {
  superclass ::httpd::mime

  option port  {default: auto}
  option myaddr {default: 127.0.0.1}
  option server_string [list default: [list TclHttpd $::httpd::version]]
  option server_name [list default: [list [info hostname]]]
  option doc_root {default {}}
  option reverse_dns {type boolean default 0}
  option configuration_file {type filename default {}}


  property socket buffersize   32768
  property socket translation  {auto crlf}
  property reply_class ::httpd::reply

  array template
  variable url_patterns {}

  constructor {args} {
    my configure {*}$args

















    my start
  }

  destructor {
    my stop
  }





  method connect {sock ip port} {
    ###
    # If an IP address is blocked
    # send a "go to hell" message
    ###
    if {[my Validate_Connection $sock $ip]} {
      catch {close $sock}
      return
    }
    set uuid [my Uuid_Generate]
    set coro [coroutine ::httpd::coro::$uuid {*}[namespace code [list my Connect $uuid $sock $ip]]]
    chan event $sock readable $coro
  }












































  method Connect {uuid sock ip} {

    yield [info coroutine]
    chan event $sock readable {}

    chan configure $sock \
      -blocking 0 \
      -translation {auto crlf} \
      -buffering line

    my counter url_hit
    set line {}
    try {
      set readCount [::coroutine::util::gets_safety $sock 4096 line]
      dict set query UUID $uuid
      dict set query REMOTE_ADDR     $ip
      dict set query REMOTE_HOST     [my HostName $ip]
      dict set query REQUEST_METHOD  [lindex $line 0]
      set uriinfo [::uri::split [lindex $line 1]]
      dict set query REQUEST_URI     [lindex $line 1]
      dict set query REQUEST_PATH    [dict get $uriinfo path]
      dict set query REQUEST_VERSION [lindex [split [lindex $line end] /] end]
      dict set query DOCUMENT_ROOT   [my cget doc_root]
      dict set query QUERY_STRING    [dict get $uriinfo query]
      dict set query REQUEST_RAW     $line
      dict set query SERVER_PORT     [my port_listening]
      set mimetxt [my HttpHeaders $sock]
      dict set query mimetxt $mimetxt
      foreach {f v} [my MimeParse $mimetxt] {
        set fld [string toupper [string map {- _} $f]]
        if {$fld in {CONTENT_LENGTH CONTENT_TYPE}} {
          set qfld $fld
        } else {
          set qfld HTTP_$fld
        }
        dict set query $qfld $v
        dict set query http $fld $v
      }
      if {[string match 127.* $ip]} {
        dict set query LOCALHOST [expr {[lindex [split [dict getnull $query HTTP_HOST] :] 0] eq "localhost"}]
      }
      my Headers_Process query
      set reply [my dispatch $query]
    } on error {err errdat} {
      my debug [list uri: [dict getnull $query REQUEST_URI] ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      my log BadRequest $uuid [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      catch {chan puts $sock "HTTP/1.0 400 Bad Request (The data is invalid)"}
      catch {chan close $sock}
      return
    }
    if {[llength $reply]==0} {
      my log BadLocation $uuid $query
      my log BadLocation $uuid $query
      dict set query HTTP_STATUS 404
      dict set query template notfound
      dict set query mixinmap reply ::httpd::content.template
    }
    try {
      if {[dict exists $reply class]} {
        set class [dict get $reply class]
      } else {
        set class [my cget reply_class]
      }
      set pageobj [$class create ::httpd::object::$uuid [self]]
      if {[dict exists $reply mixinmap]} {
        set mixinmap [dict get $reply mixinmap]
      } else {
        set mixinmap {}
      }
      if {[dict exists $reply mixin]} {
        dict set mixinmap reply [dict get $reply mixin]
      }
      foreach item [dict keys $reply MIXIN_*] {
        set slot [string range $reply 6 end]
        dict set mixinmap [string tolower $slot] [dict get $reply $item]
      }
      $pageobj mixinmap {*}$mixinmap
      if {[dict exists $reply organ]} {
        $pageobj graft {*}[dict get $reply organ]
      }
    } on error {err errdat} {
      my debug [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      my log BadRequest $uuid [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      catch {$pageobj destroy}
      catch {chan close $sock}
    }
    try {
      $pageobj dispatch $sock $reply
    } on error {err errdat} {
      my debug [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      my log BadRequest $uuid [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      catch {$pageobj destroy}
      catch {chan close $sock}
    }
  }

  method counter which {
    my variable counters
    incr counters($which)
  }

  ###
  # Clean up any process that has gone out for lunch

  ###
  method CheckTimeout {} {
    foreach obj [info commands ::httpd::object::*] {
      try {
        $obj timeOutCheck
      } on error {} {
        catch {$obj destroy}
      }
    }

  }

  method debug args {}

  ###

  # Route a request to the appropriate handler
  ###
  method dispatch {data} {




    return [my Dispatch_Default $data]
  }






  method Dispatch_Default {reply} {
    ###
    # Fallback to docroot handling
    ###
    set doc_root [dict get $reply DOCUMENT_ROOT]
    if {$doc_root ne {}} {
      ###
      # Fall back to doc_root handling
      ###
      dict set reply prefix {}
      dict set reply path $doc_root
      dict set reply mixinmap reply httpd::content.file
      return $reply
    }
    return {}
  }



















  method Headers_Process varname {}






  method HostName ipaddr {
    if {![my cget reverse_dns]} {
      return $ipaddr
    }
    set t [::dns::resolve $ipaddr]
    set result [::dns::name $t]
    ::dns::cleanup $t
    return $result
  }





  method log args {
    # Do nothing for now
  }















  method plugin {slot {class {}}} {
    if {$class eq {}} {
      set class ::httpd::plugin.$slot
    }
    if {[info command $class] eq {}} {
      error "Class $class for plugin $slot does not exist"
    }
    my mixinmap $slot $class
    my variable mixinmap

    ###
    # Perform action on load
    ###
    eval [$class meta getnull plugin load:]


    ###
    # rebuild the dispatch method
    ###
    set body "\n try \{"





    foreach {slot class} $mixinmap {
      set script [$class meta getnull plugin dispatch:]
      if {[string length $script]} {
        append body \n "# SLOT $slot"
        append body \n $script
      }
    }
    append body \n {  return [my Dispatch_Default $data]}
    append body \n "\} on error \{err errdat\} \{"
    append body \n {  puts [list DISPATCH ERROR [dict get $errdat -errorinfo]] ; return {}}
    append body \n "\}"
    oo::objdefine [self] method dispatch data $body
    ###
    # rebuild the Headers_Process method
    ###
    set body "\n try \{"
    append body \n "  upvar 1 \$varname query"

    foreach {slot class} $mixinmap {
      set script [$class meta getnull plugin headers:]
      if {[string length $script]} {
        append body \n "# SLOT $slot"
        append body \n $script
      }
    }
    append body \n "\} on error \{err errdat\} \{"
    append body \n {  puts [list HEADERS ERROR [dict get $errdat -errorinfo]] ; return {}}
    append body \n "\}"

    oo::objdefine [self] method Headers_Process varname $body

    ###
    # rebuild the Threads_Start method
    ###
    set body "\n try \{"
    foreach {slot class} $mixinmap {
      set script [$class meta getnull plugin thread:]
      if {[string length $script]} {
        append body \n "# SLOT $slot"
        append body \n $script
      }
    }
    append body \n "\} on error \{err errdat\} \{"
    append body \n {  puts [list THREAD START ERROR [dict get $errdat -errorinfo]] ; return {}}
    append body \n "\}"
    oo::objdefine [self] method Thread_start {} $body

  }

  method port_listening {} {
    my variable port_listening
    return $port_listening
  }




  method PrefixNormalize prefix {
    set prefix [string trimright $prefix /]
    set prefix [string trimright $prefix *]
    set prefix [string trimright $prefix /]
    return $prefix
  }

  method source {filename} {
    source $filename
  }


  method start {} {
    # Build a namespace to contain replies
    namespace eval [namespace current]::reply {}

    my variable socklist port_listening
    if {[my cget configuration_file] ne {}} {
      source [my cget configuration_file]
    }
    set port [my cget port]
    if { $port in {auto {}} } {
      package require nettool
      set port [::nettool::allocate_port 8015]
    }
    set port_listening $port
    set myaddr [my cget myaddr]
    my debug [list [self] listening on $port $myaddr]

    if {$myaddr ni {all any * {}}} {
      foreach ip $myaddr {
        lappend socklist [socket -server [namespace code [list my connect]] -myaddr $ip $port]
      }
    } else {
      lappend socklist [socket -server [namespace code [list my connect]] $port]
    }
    ::cron::every [self] 120 [namespace code {my CheckTimeout}]
    my Thread_start
  }


  method stop {} {
    my variable socklist
    if {[info exists socklist]} {
      foreach sock $socklist {
        catch {close $sock}
      }
    }
    set socklist {}
    ::cron::cancel [self]
  }









  method template page {
    my variable template
    if {[info exists template($page)]} {
      return $template($page)
    }
    set template($page) [my TemplateSearch $page]
    return $template($page)
  }





  method TemplateSearch page {
    set doc_root [my cget doc_root]
    if {$doc_root ne {} && [file exists [file join $doc_root $page.tml]]} {
      return [::fileutil::cat [file join $doc_root $page.tml]]
    }
    if {$doc_root ne {} && [file exists [file join $doc_root $page.html]]} {
      return [::fileutil::cat [file join $doc_root $page.html]]
    }
    switch $page {
      redirect {
return {
[my html header "$HTTP_STATUS"]
The page you are looking for: <b>[my http_info get REQUEST_URI]</b> has moved.
<p>
If your browser does not automatically load the new location, it is
<a href=\"$msg\">$msg</a>
[my html footer]
}
      }
      internal_error {
        return {
[my html header "$HTTP_STATUS"]
Error serving <b>[my http_info get REQUEST_URI]</b>:
<p>
The server encountered an internal server error: <pre>$msg</pre>
<pre><code>
$errorInfo
</code></pre>
[my html footer]
        }
      }
      notfound {
        return {
[my html header "$HTTP_STATUS"]
The page you are looking for: <b>[my http_info get REQUEST_URI]</b> does not exist.
[my html footer]
        }
      }
    }
  }





  method Thread_start {} {}








  method Uuid_Generate {} {
    return [::uuid::uuid generate]
  }

  ###
  # Return true if this IP address is blocked
  # The socket will be closed immediately after returning
  # This handler is welcome to send a polite error message


  ###
  method Validate_Connection {sock ip} {
    return 0
  }
}

###
# Provide a backward compadible alias
###
::tool::define ::httpd::server::dispatch {
    superclass ::httpd::server
}

|
<
>
>
>




|


|
|
|
|
|
|
|
>

|
|
|

|
|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







>
>
>
>


|
|










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>


<




<

<

|
<
<
<
<
<
<
<
<
<
<
<
<

|
<
<
<
<
<
<
<
|
|
<
<
|
<









|
|

|
|
|

<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
|
|






<
>






|


>





>
|


>
>
>
>



>
>
>
>
>




|






|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>

|








>
>
>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>







|
|




|
>





>
>
>
>
>

|















>

|








>







|









|
|
|





>
>
>











>





|
|

|





|













>











>
>
|
>
>
>
>
>









>
>
>
>

|









|
|



|




|
|





|




|
|
|





>
>
>
>


>
>
>
>
>
>
>

|



|
|
|
>
>









|


1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
###
# An httpd server with a template engine and a shim to insert URL domains.

#
# This class is the root object of the webserver. It is responsible
# for opening the socket and providing the initial connection negotiation.
###
namespace eval ::httpd::object {}
namespace eval ::httpd::coro {}

::clay::define ::httpd::server {
  superclass ::httpd::mime

  clay set server/ port auto
  clay set server/ myaddr 127.0.0.1
  clay set server/ string [list TclHttpd $::httpd::version]
  clay set server/ name [info hostname]
  clay set server/ doc_root {}
  clay set server/ reverse_dns 0
  clay set server/ configuration_file {}
  clay set server/ protocol {HTTP/1.1}

  clay set socket/ buffersize   32768
  clay set socket/ translation  {auto crlf}
  clay set reply_class ::httpd::reply

  Array template
  Dict url_patterns {}

  constructor {
  {args {
    port        {default auto      comment {Port to listen on}}
    myaddr      {default 127.0.0.1 comment {IP address to listen on. "all" means all}}
    string      {default auto      comment {Value for SERVER_SOFTWARE in HTTP headers}}
    name        {default auto      comment {Value for SERVER_NAME in HTTP headers. Defaults to [info hostname]}}
    doc_root    {default {}        comment {File path to serve.}}
    reverse_dns {default 0         comment {Perform reverse DNS to convert IPs into hostnames}}
    configuration_file {default {} comment {Configuration file to load into server namespace}}
    protocol    {default {HTTP/1.1} comment {Value for SERVER_PROTOCOL in HTTP headers}}
  }}} {
    if {[llength $args]==1} {
      set arglist [lindex $args 0]
    } else {
      set arglist $args
    }
    foreach {var val} $arglist {
      my clay set server/ $var $val
    }
    my start
  }

  destructor {
    my stop
  }

  ###
  # Reply to an open socket. This method builds a coroutine to manage the remainder
  # of the connection. The coroutine's operations are driven by the [cmd Connect] method.
  ###
  method connect {sock ip port} {
    ###
    # If an IP address is blocked drop the
    # connection
    ###
    if {[my Validate_Connection $sock $ip]} {
      catch {close $sock}
      return
    }
    set uuid [my Uuid_Generate]
    set coro [coroutine ::httpd::coro::$uuid {*}[namespace code [list my Connect $uuid $sock $ip]]]
    chan event $sock readable $coro
  }

  method ServerHeaders {ip http_request mimetxt} {
    set result {}
    dict set result HTTP_HOST {}
    dict set result CONTENT_LENGTH 0
    foreach {f v} [my MimeParse $mimetxt] {
      set fld [string toupper [string map {- _} $f]]
      if {$fld in {CONTENT_LENGTH CONTENT_TYPE}} {
        set qfld $fld
      } else {
        set qfld HTTP_$fld
      }
      dict set result $qfld $v
    }
    dict set result REMOTE_ADDR     $ip
    dict set result REMOTE_HOST     [my HostName $ip]
    dict set result REQUEST_METHOD  [lindex $http_request 0]
    set uriinfo [::uri::split [lindex $http_request 1]]
    dict set result uriinfo $uriinfo
    dict set result REQUEST_URI     [lindex $http_request 1]
    dict set result REQUEST_PATH    [dict get $uriinfo path]
    dict set result REQUEST_VERSION [lindex [split [lindex $http_request end] /] end]
    dict set result DOCUMENT_ROOT   [my clay get server/ doc_root]
    dict set result QUERY_STRING    [dict get $uriinfo query]
    dict set result REQUEST_RAW     $http_request
    dict set result SERVER_PORT     [my port_listening]
    dict set result SERVER_NAME     [my clay get server/ name]
    dict set result SERVER_PROTOCOL [my clay get server/ protocol]
    dict set result SERVER_SOFTWARE [my clay get server/ string]
    if {[string match 127.* $ip]} {
      dict set result LOCALHOST [expr {[lindex [split [dict getnull $result HTTP_HOST] :] 0] eq "localhost"}]
    }
    return $result
  }

  ###
  # This method reads HTTP headers, and then consults the [cmd dispatch] method to
  # determine if the request is valid, and/or what kind of reply to generate. Under
  # normal cases, an object of class [cmd ::http::reply] is created, and that class's
  # [cmd dispatch] method.
  # This action passes control of the socket to
  # the reply object. The reply object manages the rest of the transaction, including
  # closing the socket.
  ###
  method Connect {uuid sock ip} {
    ::clay::cleanup
    yield [info coroutine]
    chan event $sock readable {}

    chan configure $sock \
      -blocking 0 \
      -translation {auto crlf} \
      -buffering line

    my counter url_hit

    try {
      set readCount [::coroutine::util::gets_safety $sock 4096 http_request]












      set mimetxt [my HttpHeaders $sock]
      dict set query UUID $uuid







      dict set query mimetxt $mimetxt
      dict set query mixin style [my clay get server/ style]


      dict set query http [my ServerHeaders $ip $http_request $mimetxt]

      my Headers_Process query
      set reply [my dispatch $query]
    } on error {err errdat} {
      my debug [list uri: [dict getnull $query REQUEST_URI] ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      my log BadRequest $uuid [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      catch {chan puts $sock "HTTP/1.0 400 Bad Request (The data is invalid)"}
      catch {chan close $sock}
      return
    }
    if {[dict size $reply]==0} {
      set reply $query
      my log BadLocation $uuid $query
      dict set reply http HTTP_STATUS {404 Not Found}
      dict set reply template notfound
      dict set reply mixin reply ::httpd::content.template
    }






    set pageobj [::httpd::reply create ::httpd::object::$uuid [self]]























    tailcall $pageobj dispatch $sock $reply





  }

  # Increment an internal counter.
  method counter which {
    my variable counters
    incr counters($which)
  }

  ###

  # Check open connections for a time out event.
  ###
  method CheckTimeout {} {
    foreach obj [info commands ::httpd::object::*] {
      try {
        $obj timeOutCheck
      } on error {} {
        $obj clay refcount_decr
      }
    }
    ::clay::cleanup
  }

  method debug args {}

  ###
  # Given a key/value list of information, return a data structure describing how
  # the server should reply.
  ###
  method dispatch {data} {
    set reply [my Dispatch_Local $data]
    if {[dict size $reply]} {
      return $reply
    }
    return [my Dispatch_Default $data]
  }

  ###
  # Method dispatch method of last resort before returning a 404 NOT FOUND error.
  # The default behavior is to look for a file in [emph DOCUMENT_ROOT] which
  # matches the query.
  ###
  method Dispatch_Default {reply} {
    ###
    # Fallback to docroot handling
    ###
    set doc_root [dict getnull $reply http DOCUMENT_ROOT]
    if {$doc_root ne {}} {
      ###
      # Fall back to doc_root handling
      ###
      dict set reply prefix {}
      dict set reply path $doc_root
      dict set reply mixin reply httpd::content.file
      return $reply
    }
    return {}
  }

  ###
  # Method dispatch method invoked prior to invoking methods implemented by plugins.
  # If this method returns a non-empty dictionary, that structure will be passed to
  # the reply. The default is an empty implementation.
  ###
  method Dispatch_Local data {}

  ###
  # Introspect and possibly modify a data structure destined for a reply. This
  # method is invoked before invoking Header methods implemented by plugins.
  # The default implementation is empty.
  ###
  method Headers_Local {varname} {}

  ###
  # Introspect and possibly modify a data structure destined for a reply. This
  # method is built dynamically by the [cmd plugin] method.
  ###
  method Headers_Process varname {}

  ###
  # Convert an ip address to a host name. If the server/ reverse_dns flag
  # is false, this method simply returns the IP address back.
  # Internally, this method uses the [emph dns] module from tcllib.
  ###
  method HostName ipaddr {
    if {![my clay get server/ reverse_dns]} {
      return $ipaddr
    }
    set t [::dns::resolve $ipaddr]
    set result [::dns::name $t]
    ::dns::cleanup $t
    return $result
  }

  ###
  # Log an event. The input for args is free form. This method is intended
  # to be replaced by the user, and is a noop for a stock http::server object.
  ###
  method log args {
    # Do nothing for now
  }

  ###
  # Incorporate behaviors from a plugin.
  # This method dynamically rebuilds the [cmd Dispatch] and [cmd Headers]
  # method. For every plugin, the server looks for the following entries in
  # [emph "clay plugin/"]:
  # [para]
  # [emph load] - A script to invoke in the server's namespace during the [cmd plugin] method invokation.
  # [para]
  # [emph dispatch] - A script to stitch into the server's [cmd Dispatch] method.
  # [para]
  # [emph headers] - A script to stitch into the server's [cmd Headers] method.
  # [para]
  # [emph thread] - A script to stitch into the server's [cmd Thread_start] method.
  ###
  method plugin {slot {class {}}} {
    if {$class eq {}} {
      set class ::httpd::plugin.$slot
    }
    if {[info command $class] eq {}} {
      error "Class $class for plugin $slot does not exist"
    }
    my clay mixinmap $slot $class
    set mixinmap [my clay mixinmap]

    ###
    # Perform action on load
    ###
    set script [$class clay search plugin/ load]
    eval $script

    ###
    # rebuild the dispatch method
    ###
    set body "\n try \{"
    append body \n {
  set reply [my Dispatch_Local $data]
  if {[dict size $reply]} {return $reply}
}

    foreach {slot class} $mixinmap {
      set script [$class clay search plugin/ dispatch]
      if {[string length $script]} {
        append body \n "# SLOT $slot"
        append body \n $script
      }
    }
    append body \n {  return [my Dispatch_Default $data]}
    append body \n "\} on error \{err errdat\} \{"
    append body \n {  puts [list DISPATCH ERROR [dict get $errdat -errorinfo]] ; return {}}
    append body \n "\}"
    oo::objdefine [self] method dispatch data $body
    ###
    # rebuild the Headers_Process method
    ###
    set body "\n try \{"
    append body \n "  upvar 1 \$varname query"
    append body \n {  my Headers_Local query}
    foreach {slot class} $mixinmap {
      set script [$class clay search plugin/ headers]
      if {[string length $script]} {
        append body \n "# SLOT $slot"
        append body \n $script
      }
    }
    append body \n "\} on error \{err errdat\} \{"
    append body \n {  puts [list HEADERS ERROR [dict get $errdat -errorinfo]] ; return {}}
    append body \n "\}"

    oo::objdefine [self] method Headers_Process varname $body

    ###
    # rebuild the Threads_Start method
    ###
    set body "\n try \{"
    foreach {slot class} $mixinmap {
      set script [$class clay search plugin/ thread]
      if {[string length $script]} {
        append body \n "# SLOT $slot"
        append body \n $script
      }
    }
    append body \n "\} on error \{err errdat\} \{"
    append body \n {  puts [list THREAD START ERROR [dict get $errdat -errorinfo]] ; return {}}
    append body \n "\}"
    oo::objdefine [self] method Thread_start {} $body
  }

  # Return the actual port that httpd is listening on.
  method port_listening {} {
    my variable port_listening
    return $port_listening
  }

  # For the stock version, trim trailing /'s and *'s from a prefix. This
  # method can be replaced by the end user to perform any other transformations
  # needed for the application.
  method PrefixNormalize prefix {
    set prefix [string trimright $prefix /]
    set prefix [string trimright $prefix *]
    set prefix [string trimright $prefix /]
    return $prefix
  }

  method source {filename} {
    source $filename
  }

  # Open the socket listener.
  method start {} {
    # Build a namespace to contain replies
    namespace eval [namespace current]::reply {}

    my variable socklist port_listening
    if {[my clay get server/ configuration_file] ne {}} {
      source [my clay get server/ configuration_file]
    }
    set port [my clay get server/ port]
    if { $port in {auto {}} } {
      package require nettool
      set port [::nettool::allocate_port 8015]
    }
    set port_listening $port
    set myaddr [my clay get server/ myaddr]
    my debug [list [self] listening on $port $myaddr]

    if {$myaddr ni {all any * {}}} {
      foreach ip $myaddr {
        lappend socklist [socket -server [namespace code [list my connect]] -myaddr $ip $port]
      }
    } else {
      lappend socklist [socket -server [namespace code [list my connect]] $port]
    }
    ::cron::every [self] 120 [namespace code {my CheckTimeout}]
    my Thread_start
  }

  # Shut off the socket listener, and destroy any pending replies.
  method stop {} {
    my variable socklist
    if {[info exists socklist]} {
      foreach sock $socklist {
        catch {close $sock}
      }
    }
    set socklist {}
    ::cron::cancel [self]
  }

  Ensemble SubObject::db {} {
    return [namespace current]::Sqlite_db
  }
  Ensemble SubObject::default {} {
    return [namespace current]::$method
  }

  # Return a template for the string [arg page]
  method template page {
    my variable template
    if {[info exists template($page)]} {
      return $template($page)
    }
    set template($page) [my TemplateSearch $page]
    return $template($page)
  }

  # Perform a search for the template that best matches [arg page]. This
  # can include local file searches, in-memory structures, or even
  # database lookups. The stock implementation simply looks for files
  # with a .tml or .html extension in the [opt doc_root] directory.
  method TemplateSearch page {
    set doc_root [my clay get server/ doc_root]
    if {$doc_root ne {} && [file exists [file join $doc_root $page.tml]]} {
      return [::fileutil::cat [file join $doc_root $page.tml]]
    }
    if {$doc_root ne {} && [file exists [file join $doc_root $page.html]]} {
      return [::fileutil::cat [file join $doc_root $page.html]]
    }
    switch $page {
      redirect {
return {
[my html_header "$HTTP_STATUS"]
The page you are looking for: <b>[my request get REQUEST_PATH]</b> has moved.
<p>
If your browser does not automatically load the new location, it is
<a href=\"$msg\">$msg</a>
[my html_footer]
}
      }
      internal_error {
        return {
[my html_header "$HTTP_STATUS"]
Error serving <b>[my request get REQUEST_PATH]</b>:
<p>
The server encountered an internal server error: <pre>$msg</pre>
<pre><code>
$errorInfo
</code></pre>
[my html_footer]
        }
      }
      notfound {
        return {
[my html_header "$HTTP_STATUS"]
The page you are looking for: <b>[my request get REQUEST_PATH]</b> does not exist.
[my html_footer]
        }
      }
    }
  }

  ###
  # Built by the [cmd plugin] method. Called by the [cmd start] method. Intended
  # to allow plugins to spawn worker threads.
  ###
  method Thread_start {} {}

  ###
  # Generate a GUUID. Used to ensure every request has a unique ID.
  # The default implementation is:
  # [example {
  #   return [::clay::uuid generate]
  # }]
  ###
  method Uuid_Generate {} {
    return [::clay::uuid::short]
  }

  ###
  # Given a socket and an ip address, return true if this connection should
  # be terminated, or false if it should be allowed to continue. The stock
  # implementation always returns 0. This is intended for applications to
  # be able to implement black lists and/or provide security based on IP
  # address.
  ###
  method Validate_Connection {sock ip} {
    return 0
  }
}

###
# Provide a backward compadible alias
###
::clay::define ::httpd::server::dispatch {
    superclass ::httpd::server
}

Changes to modules/httpd/build/websocket.tcl.

1
2
3
4
5
6
###
# Upgrade a connection to a websocket
###
::tool::define ::httpd::content.websocket {

}



|


1
2
3
4
5
6
###
# Upgrade a connection to a websocket
###
::clay::define ::httpd::content.websocket {

}

Changes to modules/httpd/httpd.man.

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[vset VERSION 4.1.1]
[comment {-*- tcl -*- doctools manpage}]

[manpage_begin tool n [vset VERSION]]
[keywords WWW]
[copyright {2018 Sean Woods <[email protected]>}]
[moddesc   {Tcl Web Server}]
[titledesc {A TclOO and coroutine based web server}]
[category  Networking]
[keywords TclOO]
[keywords http]
[keywords httpd]
[keywords httpserver]
[keywords services]
[require Tcl 8.6]
[require httpd [opt [vset VERSION]]]
[require sha1]
[require dicttool]
[require oo::meta]
[require oo::dialect]
[require tool]
[require coroutine]
[require fileutil]
[require fileutil::magic::filetype]
[require websocket]
[require mime]
[require cron]
[require uri]
<

>
|











<
|
<
<
<
|








1
2
3
4
5
6
7
8
9
10
11
12
13
14

15



16
17
18
19
20
21
22
23

[comment {-*- tcl -*- doctools manpage}]
[vset PACKAGE_VERSION 4.3.4]
[manpage_begin httpd n [vset PACKAGE_VERSION]]
[keywords WWW]
[copyright {2018 Sean Woods <[email protected]>}]
[moddesc   {Tcl Web Server}]
[titledesc {A TclOO and coroutine based web server}]
[category  Networking]
[keywords TclOO]
[keywords http]
[keywords httpd]
[keywords httpserver]
[keywords services]
[require Tcl 8.6]

[require uuid]



[require clay]
[require coroutine]
[require fileutil]
[require fileutil::magic::filetype]
[require websocket]
[require mime]
[require cron]
[require uri]
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

53


















54
55


56




































































































































































































































































































































































































































57
58






































































































































































































































































































































































































































59
60
61
62
63

64
65

[section {Minimal Example}]

Starting a web service requires starting a class of type
[cmd httpd::server], and providing that server with one or more URIs
to service, and [cmd httpd::reply] derived classes to generate them.

[example {
tool::define ::reply.hello {
  method content {} {
    my puts "<HTML><HEAD><TITLE>IRM Dispatch Server</TITLE></HEAD><BODY>"
    my puts "<h1>Hello World!</h1>"
    my puts </BODY></HTML>
  }
}
::docserver::server create HTTPD port 8015 myaddr 127.0.0.1

HTTPD add_uri /* [list mixin reply.hello]


















}]



[include build/server.man]




































































































































































































































































































































































































































[include build/reply.man]
[include build/content.man]







































































































































































































































































































































































































































[section AUTHORS]
Sean Woods

[vset CATEGORY network]

[include ../doctools2base/include/feedback.inc]
[manpage_end]








|






|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





>
|

>
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
[section {Minimal Example}]

Starting a web service requires starting a class of type
[cmd httpd::server], and providing that server with one or more URIs
to service, and [cmd httpd::reply] derived classes to generate them.

[example {
oo::class create ::reply.hello {
  method content {} {
    my puts "<HTML><HEAD><TITLE>IRM Dispatch Server</TITLE></HEAD><BODY>"
    my puts "<h1>Hello World!</h1>"
    my puts </BODY></HTML>
  }
}
::httpd::server create HTTPD port 8015 myaddr 127.0.0.1 doc_root ~/htdocs
HTTPD plugin dispatch httpd::server::dispatch
HTTPD uri add * /hello [list mixin reply.hello]
}]

The bare module does have facilities to hose a files from a file system. Files that end in a .tml will be substituted in the style of Tclhttpd:

[example {
<!-- hello.tml -->
[my html_header {Hello World!}]
Your Server is running.
<p>
The time is now [clock format [clock seconds]]
[my html_footer]
}]

A complete example of an httpd server is in the /examples directory of Tcllib. It also show how to dispatch URIs to other processes via SCGI and HTTP proxies.

[example {
cd ~/tcl/sandbox/tcllib
tclsh examples/httpd.tcl
}]

[section Classes]
[subsection {Class  httpd::mime}]

 A metaclass for MIME handling behavior across a live socket



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "ChannelCopy"] [arg in] [arg out] [opt "[arg args]"]]


[call method [cmd "html_header"] [opt "[arg title] [const ""]"] [opt "[arg args]"]]

 Returns a block of HTML



[call method [cmd "html_footer"] [opt "[arg args]"]]


[call method [cmd "http_code_string"] [arg code]]


[call method [cmd "HttpHeaders"] [arg sock] [opt "[arg debug] [const ""]"]]


[call method [cmd "HttpHeaders_Default"]]


[call method [cmd "HttpServerHeaders"]]


[call method [cmd "MimeParse"] [arg mimetext]]

 Converts a block of mime encoded text to a key/value list. If an exception is encountered,
 the method will generate its own call to the [cmd error] method, and immediately invoke
 the [cmd output] method to produce an error code and close the connection.




[call method [cmd "Url_Decode"] [arg data]]
 De-httpizes a string.



[call method [cmd "Url_PathCheck"] [arg urlsuffix]]


[call method [cmd "wait"] [arg mode] [arg sock]]


[list_end]
[para]

[subsection {Class  httpd::reply}]
[emph "ancestors"]: [class httpd::mime]
[para]

 A class which shephards a request through the process of generating a
 reply.

 The socket associated with the reply is available at all times as the [arg chan]
 variable.

 The process of generating a reply begins with an [cmd httpd::server] generating a
 [cmd http::class] object, mixing in a set of behaviors and then invoking the reply
 object's [cmd dispatch] method.

 In normal operations the [cmd dispatch] method:

 [list_begin enumerated]
 [enum]
 Invokes the [cmd reset] method for the object to populate default headers.
 [enum]
 Invokes the [cmd HttpHeaders] method to stream the MIME headers out of the socket
 [enum]
 Invokes the [cmd {request parse}] method to convert the stream of MIME headers into a
 dict that can be read via the [cmd request] method.
 [enum]
 Stores the raw stream of MIME headers in the [arg rawrequest] variable of the object.
 [enum]
 Invokes the [cmd content] method for the object, generating an call to the [cmd error]
 method if an exception is raised.
 [enum]
 Invokes the [cmd output] method for the object
 [list_end]
 [para]

 Developers have the option of streaming output to a buffer via the [cmd puts] method of the
 reply, or simply populating the [arg reply_body] variable of the object.
 The information returned by the [cmd content] method is not interpreted in any way.

 If an exception is thrown (via the [cmd error] command in Tcl, for example) the caller will
 auto-generate a 500 {Internal Error} message.

 A typical implementation of [cmd content] look like:

 [example {

 clay::define ::test::content.file {
 	superclass ::httpd::content.file
 	# Return a file
 	# Note: this is using the content.file mixin which looks for the reply_file variable
 	# and will auto-compute the Content-Type
 	method content {} {
 	  my reset
     set doc_root [my request get DOCUMENT_ROOT]
     my variable reply_file
     set reply_file [file join $doc_root index.html]
 	}
 }
 clay::define ::test::content.time {
   # return the current system time
 	method content {} {
 		my variable reply_body
     my reply set Content-Type text/plain
 		set reply_body [clock seconds]
 	}
 }
 clay::define ::test::content.echo {
 	method content {} {
 		my variable reply_body
     my reply set Content-Type [my request get CONTENT_TYPE]
 		set reply_body [my PostData [my request get CONTENT_LENGTH]]
 	}
 }
 clay::define ::test::content.form_handler {
 	method content {} {
 	  set form [my FormData]
 	  my reply set Content-Type {text/html; charset=UTF-8}
     my puts [my html_header {My Dynamic Page}]
     my puts "<BODY>"
     my puts "You Sent<p>"
     my puts "<TABLE>"
     foreach {f v} $form {
       my puts "<TR><TH>$f</TH><TD><verbatim>$v</verbatim></TD>"
     }
     my puts "</TABLE><p>"
     my puts "Send some info:<p>"
     my puts "<FORM action=/[my request get REQUEST_PATH] method POST>"
     my puts "<TABLE>"
     foreach field {name rank serial_number} {
       set line "<TR><TH>$field</TH><TD><input name=\"$field\" "
       if {[dict exists $form $field]} {
         append line " value=\"[dict get $form $field]\"""
       }
       append line " /></TD></TR>"
       my puts $line
     }
     my puts "</TABLE>"
     my puts [my html footer]
 	}
 }

 }]



[para]
[class {Variable}]
[list_begin definitions]
[call variable [cmd ChannelRegister]]

[call variable [cmd reply]]
 A dictionary which will converted into the MIME headers of the reply




[call variable [cmd request]]
 A dictionary containing the SCGI transformed HTTP headers for the request




[list_end]
[para]
[class {Delegate}]
[list_begin definitions]
[call delegate [cmd <server>]]The server object which spawned this reply

[list_end]
[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "constructor"] [arg ServerObj] [opt "[arg args]"]]


[call method [cmd "destructor"] [opt "[arg dictargs]"]]

 clean up on exit




[call method [cmd "ChannelRegister"] [opt "[arg args]"]]
 Registers a channel to be closed by the close method



[call method [cmd "close"]]

 Close channels opened by this object




[call method [cmd "Log_Dispatched"]]

 Record a dispatch event




[call method [cmd "dispatch"] [arg newsock] [arg datastate]]

 Accept the handoff from the server object of the socket
 [emph newsock] and feed it the state [emph datastate].
 Fields the [emph datastate] are looking for in particular are:
 [para]
 * [const mixin] - A key/value list of slots and classes to be mixed into the
 object prior to invoking [cmd Dispatch].
 [para]
 * [const http] - A key/value list of values to populate the object's [emph request]
 ensemble
 [para]
 All other fields are passed along to the [method clay] structure of the object.




[call method [cmd "Dispatch"]]


[call method [cmd "html_header"] [arg title] [opt "[arg args]"]]


[call method [cmd "html_footer"] [opt "[arg args]"]]


[call method [cmd "error"] [arg code] [opt "[arg msg] [const ""]"] [opt "[arg errorInfo] [const ""]"]]


[call method [cmd "content"]]

 REPLACE ME:
 This method is the "meat" of your application.
 It writes to the result buffer via the "puts" method
 and can tweak the headers via "clay put header_reply"




[call method [cmd "EncodeStatus"] [arg status]]

 Formulate a standard HTTP status header from he string provided.




[call method [cmd "log"] [arg type] [opt "[arg info] [const ""]"]]


[call method [cmd "CoroName"]]


[call method [cmd "DoOutput"]]

 Generates the the HTTP reply, streams that reply back across [arg chan],
 and destroys the object.




[call method [cmd "FormData"]]

 For GET requests, converts the QUERY_DATA header into a key/value list.

 For POST requests, reads the Post data and converts that information to
 a key/value list for application/x-www-form-urlencoded posts. For multipart
 posts, it composites all of the MIME headers of the post to a singular key/value
 list, and provides MIME_* information as computed by the [cmd mime] package, including
 the MIME_TOKEN, which can be fed back into the mime package to read out the contents.




[call method [cmd "PostData"] [arg length]]
 Stream [arg length] bytes from the [arg chan] socket, but only of the request is a
 POST or PUSH. Returns an empty string otherwise.



[call method [cmd "Session_Load"]]
 Manage session data



[call method [cmd "puts"] [arg line]]
 Appends the value of [arg string] to the end of [arg reply_body], as well as a trailing newline
 character.



[call method [cmd "RequestFind"] [arg field]]


[call method [cmd "request"] [arg subcommand] [opt "[arg args]"]]


[call method [cmd "reply"] [arg subcommand] [opt "[arg args]"]]


[call method [cmd "reset"]]
 Clear the contents of the [arg reply_body] variable, and reset all headers in the [cmd reply]
 structure back to the defaults for this object.



[call method [cmd "timeOutCheck"]]
 Called from the [cmd http::server] object which spawned this reply. Checks to see
 if too much time has elapsed while waiting for data or generating a reply, and issues
 a timeout error to the request if it has, as well as destroy the object and close the
 [arg chan] socket.



[call method [cmd "timestamp"]]

 Return the current system time in the format: [example {%a, %d %b %Y %T %Z}]




[list_end]
[para]

[subsection {Class  httpd::server}]
[emph "ancestors"]: [class httpd::mime]
[para]

[para]
[class {Variable}]
[list_begin definitions]
[call variable [cmd template]]

[call variable [cmd url_patterns]]

[list_end]
[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "constructor"] [arg args] [opt "[arg port] [const "auto"]"] [opt "[arg myaddr] [const "127.0.0.1"]"] [opt "[arg string] [const "auto"]"] [opt "[arg name] [const "auto"]"] [opt "[arg doc_root] [const ""]"] [opt "[arg reverse_dns] [const "0"]"] [opt "[arg configuration_file] [const ""]"] [opt "[arg protocol] [const "HTTP/1.1"]"]]


[call method [cmd "destructor"] [opt "[arg dictargs]"]]


[call method [cmd "connect"] [arg sock] [arg ip] [arg port]]

 Reply to an open socket. This method builds a coroutine to manage the remainder
 of the connection. The coroutine's operations are driven by the [cmd Connect] method.




[call method [cmd "ServerHeaders"] [arg ip] [arg http_request] [arg mimetxt]]


[call method [cmd "Connect"] [arg uuid] [arg sock] [arg ip]]

 This method reads HTTP headers, and then consults the [cmd dispatch] method to
 determine if the request is valid, and/or what kind of reply to generate. Under
 normal cases, an object of class [cmd ::http::reply] is created, and that class's
 [cmd dispatch] method.
 This action passes control of the socket to
 the reply object. The reply object manages the rest of the transaction, including
 closing the socket.




[call method [cmd "counter"] [arg which]]
 Increment an internal counter.



[call method [cmd "CheckTimeout"]]

 Check open connections for a time out event.




[call method [cmd "debug"] [opt "[arg args]"]]


[call method [cmd "dispatch"] [arg data]]

 Given a key/value list of information, return a data structure describing how
 the server should reply.




[call method [cmd "Dispatch_Default"] [arg reply]]

 Method dispatch method of last resort before returning a 404 NOT FOUND error.
 The default behavior is to look for a file in [emph DOCUMENT_ROOT] which
 matches the query.




[call method [cmd "Dispatch_Local"] [arg data]]

 Method dispatch method invoked prior to invoking methods implemented by plugins.
 If this method returns a non-empty dictionary, that structure will be passed to
 the reply. The default is an empty implementation.




[call method [cmd "Headers_Local"] [arg varname]]

 Introspect and possibly modify a data structure destined for a reply. This
 method is invoked before invoking Header methods implemented by plugins.
 The default implementation is empty.




[call method [cmd "Headers_Process"] [arg varname]]

 Introspect and possibly modify a data structure destined for a reply. This
 method is built dynamically by the [cmd plugin] method.




[call method [cmd "HostName"] [arg ipaddr]]

 Convert an ip address to a host name. If the server/ reverse_dns flag
 is false, this method simply returns the IP address back.
 Internally, this method uses the [emph dns] module from tcllib.




[call method [cmd "log"] [opt "[arg args]"]]

 Log an event. The input for args is free form. This method is intended
 to be replaced by the user, and is a noop for a stock http::server object.




[call method [cmd "plugin"] [arg slot] [opt "[arg class] [const ""]"]]

 Incorporate behaviors from a plugin.
 This method dynamically rebuilds the [cmd Dispatch] and [cmd Headers]
 method. For every plugin, the server looks for the following entries in
 [emph "clay plugin/"]:
 [para]
 [emph load] - A script to invoke in the server's namespace during the [cmd plugin] method invokation.
 [para]
 [emph dispatch] - A script to stitch into the server's [cmd Dispatch] method.
 [para]
 [emph headers] - A script to stitch into the server's [cmd Headers] method.
 [para]
 [emph thread] - A script to stitch into the server's [cmd Thread_start] method.




[call method [cmd "port_listening"]]
 Return the actual port that httpd is listening on.



[call method [cmd "PrefixNormalize"] [arg prefix]]
 For the stock version, trim trailing /'s and *'s from a prefix. This
 method can be replaced by the end user to perform any other transformations
 needed for the application.



[call method [cmd "source"] [arg filename]]


[call method [cmd "start"]]
 Open the socket listener.



[call method [cmd "stop"]]
 Shut off the socket listener, and destroy any pending replies.



[call method [cmd "SubObject {} db"]]


[call method [cmd "SubObject {} default"]]


[call method [cmd "template"] [arg page]]
 Return a template for the string [arg page]



[call method [cmd "TemplateSearch"] [arg page]]
 Perform a search for the template that best matches [arg page]. This
 can include local file searches, in-memory structures, or even
 database lookups. The stock implementation simply looks for files
 with a .tml or .html extension in the [opt doc_root] directory.



[call method [cmd "Thread_start"]]

 Built by the [cmd plugin] method. Called by the [cmd start] method. Intended
 to allow plugins to spawn worker threads.




[call method [cmd "Uuid_Generate"]]

 Generate a GUUID. Used to ensure every request has a unique ID.
 The default implementation is:
 [example {
   return [::clay::uuid generate]
 }]




[call method [cmd "Validate_Connection"] [arg sock] [arg ip]]

 Given a socket and an ip address, return true if this connection should
 be terminated, or false if it should be allowed to continue. The stock
 implementation always returns 0. This is intended for applications to
 be able to implement black lists and/or provide security based on IP
 address.




[list_end]
[para]

[subsection {Class  httpd::server::dispatch}]
[emph "ancestors"]: [class httpd::server]
[para]

 Provide a backward compadible alias



[para]

[subsection {Class  httpd::content.redirect}]

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "reset"]]


[call method [cmd "content"]]


[list_end]
[para]

[subsection {Class  httpd::content.cache}]

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "Dispatch"]]


[list_end]
[para]

[subsection {Class  httpd::content.template}]

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "content"]]


[list_end]
[para]

[subsection {Class  httpd::content.file}]

 Class to deliver Static content
 When utilized, this class is fed a local filename
 by the dispatcher



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "FileName"]]


[call method [cmd "DirectoryListing"] [arg local_file]]


[call method [cmd "content"]]


[call method [cmd "Dispatch"]]


[list_end]
[para]

[subsection {Class  httpd::content.exec}]

[para]
[class {Variable}]
[list_begin definitions]
[call variable [cmd exename]]

[list_end]
[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "CgiExec"] [arg execname] [arg script] [arg arglist]]


[call method [cmd "Cgi_Executable"] [arg script]]


[list_end]
[para]

[subsection {Class  httpd::content.proxy}]
[emph "ancestors"]: [class httpd::content.exec]
[para]

 Return data from an proxy process



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "proxy_channel"]]


[call method [cmd "proxy_path"]]


[call method [cmd "ProxyRequest"] [arg chana] [arg chanb]]


[call method [cmd "ProxyReply"] [arg chana] [arg chanb] [opt "[arg args]"]]


[call method [cmd "Dispatch"]]


[list_end]
[para]

[subsection {Class  httpd::content.cgi}]
[emph "ancestors"]: [class httpd::content.proxy]
[para]

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "FileName"]]


[call method [cmd "proxy_channel"]]


[call method [cmd "ProxyRequest"] [arg chana] [arg chanb]]


[call method [cmd "ProxyReply"] [arg chana] [arg chanb] [opt "[arg args]"]]


[call method [cmd "DirectoryListing"] [arg local_file]]

 For most CGI applications a directory list is vorboten




[list_end]
[para]

[subsection {Class  httpd::protocol.scgi}]

 Return data from an SCGI process



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "EncodeStatus"] [arg status]]


[list_end]
[para]

[subsection {Class  httpd::content.scgi}]
[emph "ancestors"]: [class httpd::content.proxy]
[para]

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "scgi_info"]]


[call method [cmd "proxy_channel"]]


[call method [cmd "ProxyRequest"] [arg chana] [arg chanb]]


[call method [cmd "ProxyReply"] [arg chana] [arg chanb] [opt "[arg args]"]]


[list_end]
[para]

[subsection {Class  httpd::server.scgi}]
[emph "ancestors"]: [class httpd::server]
[para]

 Act as an  SCGI Server



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "debug"] [opt "[arg args]"]]


[call method [cmd "Connect"] [arg uuid] [arg sock] [arg ip]]


[list_end]
[para]

[subsection {Class  httpd::content.websocket}]

 Upgrade a connection to a websocket



[para]

[subsection {Class  httpd::plugin}]

 httpd plugin template



[para]

[subsection {Class  httpd::plugin.dict_dispatch}]

 A rudimentary plugin that dispatches URLs from a dict
 data structure



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "Dispatch_Dict"] [arg data]]

 Implementation of the dispatcher




[call method [cmd "uri {} add"] [arg vhosts] [arg patterns] [arg info]]





[call method [cmd "uri {} direct"] [arg vhosts] [arg patterns] [arg info] [arg body]]


[list_end]
[para]

[subsection {Class  httpd::reply.memchan}]
[emph "ancestors"]: [class httpd::reply]
[para]

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "output"]]


[call method [cmd "DoOutput"]]


[call method [cmd "close"]]


[list_end]
[para]

[subsection {Class  httpd::plugin.local_memchan}]

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "local_memchan"] [arg command] [opt "[arg args]"]]


[call method [cmd "Connect_Local"] [arg uuid] [arg sock] [opt "[arg args]"]]

 A modified connection method that passes simple GET request to an object
 and pulls data directly from the reply_body data variable in the object

 Needed because memchan is bidirectional, and we can't seem to communicate that
 the server is one side of the link and the reply is another




[list_end]
[para]

[section AUTHORS]
Sean Woods

[vset CATEGORY network]
[include ../common-text/feedback.inc]

[manpage_end]

Changes to modules/httpd/httpd.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

41

42
43
44







45



46
































47
48
49
50
51
52



53

54
55
56
57
58
59
60
61
62
63
64
65
66
67
###
# Amalgamated package for httpd
# Do not edit directly, tweak the source in src/ and rerun
# build.tcl
###
package require Tcl 8.6
package provide httpd 4.2.0
namespace eval ::httpd {}
set ::httpd::version 4.2.0

###
# START: core.tcl
###
###
# Author: Sean Woods, [email protected]
##
# Adapted from the "minihttpd.tcl" file distributed with Tclhttpd
#
# The working elements have been updated to operate as a TclOO object
# running with Tcl 8.6+. Global variables and hard coded tables are
# now resident with the object, allowing this server to be more easily
# embedded another program, as well as be adapted and extended to
# support the SCGI module
###

package require uri
package require dns
package require cron
package require coroutine
package require tool
package require mime
package require fileutil
package require websocket
package require Markdown
package require uuid
package require fileutil::magic::filetype

namespace eval httpd::content {}

namespace eval ::url {}

namespace eval ::httpd {}

namespace eval ::scgi {}

tool::define ::httpd::mime {












































  method html_header {{title {}} args} {
    set result {}
    append result "<HTML><HEAD>"
    if {$title ne {}} {
      append result "<TITLE>$title</TITLE>"
    }



    append result "<link rel=\"stylesheet\" href=\"/style.css\">"

    append result "</HEAD><BODY>"
    return $result
  }
  method html_footer {args} {
    return "</BODY></HTML>"
  }

  method http_code_string code {
    set codes {
      200 {Data follows}
      204 {No Content}
      301 {Moved Permanently}
      302 {Found}
      303 {Moved Temporarily}






|

|
<



<
<
<
<
<
<
<
<
<
<
<
<




<




|
|
<
|
|
|
>
|
>
|
|
|
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|



>
>
>
|
>






<







1
2
3
4
5
6
7
8
9

10
11
12












13
14
15
16

17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
###
# Amalgamated package for httpd
# Do not edit directly, tweak the source in src/ and rerun
# build.tcl
###
package require Tcl 8.6
package provide httpd 4.3.4
namespace eval ::httpd {}
set ::httpd::version 4.3.4

###
# START: core.tcl
###












package require uri
package require dns
package require cron
package require coroutine

package require mime
package require fileutil
package require websocket
package require Markdown
package require fileutil::magic::filetype
package require clay 0.7

namespace eval httpd::content {
}
namespace eval ::url {
}
namespace eval ::httpd {
}
namespace eval ::scgi {
}
clay::define ::httpd::mime {
  method ChannelCopy {in out args} {
    try {
      my clay refcount_incr
      set chunk 4096
      set size -1
      foreach {f v} $args {
        set [string trim $f -] $v
      }
      dict set info coroutine [info coroutine]
      if {$size>0 && $chunk>$size} {
          set chunk $size
      }
      set bytes 0
      set sofar 0
      set method [self method]
      while 1 {
        set command {}
        set error {}
        if {$size>=0} {
          incr sofar $bytes
          set remaining [expr {$size-$sofar}]
          if {$remaining <= 0} {
            break
          } elseif {$chunk > $remaining} {
            set chunk $remaining
          }
        }
        lassign [yieldto chan copy $in $out -size $chunk \
          -command [list [info coroutine] $method]] \
          command bytes error
        if {$command ne $method} {
          error "Subroutine $method interrupted"
        }
        if {[string length $error]} {
          error $error
        }
        if {[chan eof $in]} {
          break
        }
      }
    } finally {
      my clay refcount_decr
    }
  }
  method html_header {{title {}} args} {
    set result {}
    append result "<!DOCTYPE html>\n<HTML><HEAD>"
    if {$title ne {}} {
      append result "<TITLE>$title</TITLE>"
    }
    if {[dict exists $args stylesheet]} {
      append result "<link rel=\"stylesheet\" href=\"[dict get $args stylesheet]\">"
    } else {
      append result "<link rel=\"stylesheet\" href=\"/style.css\">"
    }
    append result "</HEAD><BODY>"
    return $result
  }
  method html_footer {args} {
    return "</BODY></HTML>"
  }

  method http_code_string code {
    set codes {
      200 {Data follows}
      204 {No Content}
      301 {Moved Permanently}
      302 {Found}
      303 {Moved Temporarily}
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
      505 {HTTP Version Not Supported}
    }
    if {[dict exists $codes $code]} {
      return [dict get $codes $code]
    }
    return {Unknown Http Code}
  }

  method HttpHeaders {sock {debug {}}} {
    set result {}
    set LIMIT 8192
    ###
    # Set up a channel event to stream the data from the socket line by
    # line. When a blank line is read, the HttpHeaderLine method will send
    # a flag which will terminate the vwait.







<







114
115
116
117
118
119
120

121
122
123
124
125
126
127
      505 {HTTP Version Not Supported}
    }
    if {[dict exists $codes $code]} {
      return [dict get $codes $code]
    }
    return {Unknown Http Code}
  }

  method HttpHeaders {sock {debug {}}} {
    set result {}
    set LIMIT 8192
    ###
    # Set up a channel event to stream the data from the socket line by
    # line. When a blank line is read, the HttpHeaderLine method will send
    # a flag which will terminate the vwait.
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
      }
    }
    ###
    # Return our buffer
    ###
    return $result
  }

  method HttpHeaders_Default {} {
    return {Status {200 OK}
Content-Size 0
Content-Type {text/html; charset=UTF-8}
Cache-Control {no-cache}
Connection close}
  }








  ###
  # Minimalist MIME Header Parser
  ###

  method MimeParse mimetext {
    set data(mimeorder) {}
    foreach line [split $mimetext \n] {
      # This regexp picks up
      # key: value
      # MIME headers.  MIME headers may be continue with a line
      # that starts with spaces or a tab







<







>
>
>
>
>
>
>
|
<
<
<
>







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
      }
    }
    ###
    # Return our buffer
    ###
    return $result
  }

  method HttpHeaders_Default {} {
    return {Status {200 OK}
Content-Size 0
Content-Type {text/html; charset=UTF-8}
Cache-Control {no-cache}
Connection close}
  }
  method HttpServerHeaders {} {
    return {
      CONTENT_LENGTH CONTENT_TYPE QUERY_STRING REMOTE_USER AUTH_TYPE
      REQUEST_METHOD REMOTE_ADDR REMOTE_HOST REQUEST_URI REQUEST_PATH
      REQUEST_VERSION  DOCUMENT_ROOT QUERY_STRING REQUEST_RAW
      GATEWAY_INTERFACE SERVER_PORT SERVER_HTTPS_PORT
      SERVER_NAME  SERVER_SOFTWARE SERVER_PROTOCOL
    }



  }
  method MimeParse mimetext {
    set data(mimeorder) {}
    foreach line [split $mimetext \n] {
      # This regexp picks up
      # key: value
      # MIME headers.  MIME headers may be continue with a line
      # that starts with spaces or a tab
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
          set ckey Referer
        }
      }
      dict set result $ckey $data(mime,$key)
    }
    return $result
  }

  method Url_Decode data {
    regsub -all {\+} $data " " data
    regsub -all {([][$\\])} $data {\\\1} data
    regsub -all {%([0-9a-fA-F][0-9a-fA-F])} $data  {[format %c 0x\1]} data
    return [subst $data]
  }

  method Url_PathCheck {urlsuffix} {
    set pathlist ""
    foreach part  [split $urlsuffix /] {
      if {[string length $part] == 0} {
        # It is important *not* to "continue" here and skip
        # an empty component because it could be the last thing,
        # /a/b/c/







<






<







240
241
242
243
244
245
246

247
248
249
250
251
252

253
254
255
256
257
258
259
          set ckey Referer
        }
      }
      dict set result $ckey $data(mime,$key)
    }
    return $result
  }

  method Url_Decode data {
    regsub -all {\+} $data " " data
    regsub -all {([][$\\])} $data {\\\1} data
    regsub -all {%([0-9a-fA-F][0-9a-fA-F])} $data  {[format %c 0x\1]} data
    return [subst $data]
  }

  method Url_PathCheck {urlsuffix} {
    set pathlist ""
    foreach part  [split $urlsuffix /] {
      if {[string length $part] == 0} {
        # It is important *not* to "continue" here and skip
        # an empty component because it could be the last thing,
        # /a/b/c/
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
        default {
          lappend pathlist $part
        }
      }
    }
    return $pathlist
  }


  method wait {mode sock} {

    if {[info coroutine] eq {}} {
      chan event $sock $mode [list set ::httpd::lock_$sock $mode]
      vwait ::httpd::lock_$sock
    } else {
      chan event $sock $mode [info coroutine]
      yield
    }
    chan event $sock $mode {}

  }

}

###
# END: core.tcl
###
###
# START: reply.tcl
###
###
# Define the reply class
###
::tool::define ::httpd::reply {
  superclass ::httpd::mime




  variable transfer_complete 0











  constructor {ServerObj args} {
    my variable chan dispatched_time uuid
    set uuid [namespace tail [self]]
    set dispatched_time [clock milliseconds]
    oo::objdefine [self] forward <server> $ServerObj
    foreach {field value} [::oo::meta::args_to_options {*}$args] {
      my meta set config $field: $value
    }
  }

  ###
  # clean up on exit
  ###
  destructor {
    my close
  }











  method close {} {
    my variable chan
    if {[info exists chan] && $chan ne {}} {



      catch {chan event $chan readable {}}
      catch {chan event $chan writable {}}
      catch {chan flush $chan}
      catch {chan close $chan}
      set chan {}
    }

  }

  method Log_Dispatched {} {
    my log Dispatched [dict create \
     REMOTE_ADDR [my http_info get REMOTE_ADDR] \
     REMOTE_HOST [my http_info get REMOTE_HOST] \
     COOKIE [my request get COOKIE] \
     REFERER [my request get REFERER] \
     USER_AGENT [my request get USER_AGENT] \
     REQUEST_URI [my http_info get REQUEST_URI] \
     HTTP_HOST [my http_info getnull HTTP_HOST] \
     SESSION [my http_info getnull SESSION] \
    ]
  }

  method dispatch {newsock datastate} {
    my http_info replace $datastate
    my request replace  [dict getnull $datastate http]
    my Log_Dispatched
    my variable chan


    set chan $newsock
    try {
      chan event $chan readable {}
      chan configure $chan -translation {auto crlf} -buffering line













      my reset













      # Invoke the URL implementation.

      my content
    } on error {err errdat} {
      my error 500 $err [dict get $errdat -errorinfo]

    } finally {
      my DoOutput

    }
  }

  method html_css {} {
    set result "<link rel=\"stylesheet\" href=\"/style.css\">"
    append result \n {<style media="screen" type="text/css">
body {
	background:  url(images/etoyoc-circuit-tile.gif) repeat;
	font-family: serif;
	color:#000066;
	font-size: 12pt;
}
</style>}
  }

  method html_header {title args} {
    set result {}
    append result "<HTML><HEAD>"
    if {$title ne {}} {
      append result "<TITLE>$title</TITLE>"
    }
    append result [my html_css]
    append result "</HEAD><BODY>"
    append result \n {<div id="top-menu">}
    if {[dict exists $args banner]} {
      append result "<img src=\"[dict get $args banner]\">"
    } else {
      append result {<img src="/images/etoyoc-banner.jpg">}
    }
    append result {</div>}
    if {[dict exists $args sideimg]} {
      append result "\n<div name=\"sideimg\"><img align=right src=\"[dict get $args sideimg]\"></div>"
    }
    append result {<div id="content">}
    return $result
  }

  method html_footer {args} {
    set result {</div><div id="footer">}
    append result {</div></BODY></HTML>}
  }

  dictobj http_info http_info {
    initialize {
      CONTENT_LENGTH 0
    }
    netstring {
      set result {}
      foreach {name value} $%VARNAME% {
        append result $name \x00 $value \x00
      }
      return "[string length $result]:$result,"
    }
  }

  method error {code {msg {}} {errorInfo {}}} {
    my http_info set HTTP_ERROR $code
    my reset
    set qheaders [my http_info dump]
    set HTTP_STATUS "$code [my http_code_string $code]"
    dict with qheaders {}
    my reply replace {}
    my reply set Status $HTTP_STATUS
    my reply set Content-Type {text/html; charset=UTF-8}

    switch $code {
      301 - 302 - 303 - 307 - 308 {
        my reply set Location $msg
        set template [my <server> template redirect]
      }
      404 {
        set template [my <server> template notfound]
      }
      default {
        set template [my <server> template internal_error]
      }
    }
    my puts [subst $template]
  }


  ###
  # REPLACE ME:
  # This method is the "meat" of your application.
  # It writes to the result buffer via the "puts" method
  # and can tweak the headers via "meta put header_reply"
  ###
  method content {} {
    my puts [my html_header {Hello World!}]
    my puts "<H1>HELLO WORLD!</H1>"
    my puts [my html_footer]
  }

  method EncodeStatus {status} {
    return "HTTP/1.0 $status"
  }

  method log {type {info {}}} {
    my variable dispatched_time uuid
    my <server> log $type $uuid $info
  }

  method CoroName {} {
    if {[info coroutine] eq {}} {
      return ::httpd::object::[my http_info get UUID]
    }
  }

  ###
  # Output the result or error to the channel
  # and destroy this object
  ###
  method DoOutput {} {
    my variable reply_body chan
    if {$chan eq {}} return
    catch {


      my wait writable $chan
      chan configure $chan  -translation {binary binary}
      ###
      # Return dynamic content
      ###
      set length [string length $reply_body]
      set result {}
      if {${length} > 0} {
        my reply set Content-Length [string length $reply_body]
        append result [my reply output] \n
        append result $reply_body
      } else {
        append result [my reply output]
      }
      chan puts -nonewline $chan $result
      my log HttpAccess {}
    }
    my destroy
  }

  method FormData {} {
    my variable chan formdata
    # Run this only once
    if {[info exists formdata]} {
      return $formdata
    }
    if {![my request exists CONTENT_LENGTH]} {
      set length 0
    } else {
      set length [my request get CONTENT_LENGTH]
    }
    set formdata {}
    if {[my http_info get REQUEST_METHOD] in {"POST" "PUSH"}} {
      set rawtype [my request get CONTENT_TYPE]
      if {[string toupper [string range $rawtype 0 8]] ne "MULTIPART"} {
        set type $rawtype
      } else {
        set type multipart
      }
      switch $type {
        multipart {
          ###
          # Ok, Multipart MIME is troublesome, farm out the parsing to a dedicated tool
          ###
          set body [my http_info get mimetxt]
          append body \n [my PostData $length]
          set token [::mime::initialize -string $body]
          foreach item [::mime::getheader $token -names] {
            dict set formdata $item [::mime::getheader $token $item]
          }
          foreach item {content encoding params parts size} {
            dict set formdata MIME_[string toupper $item] [::mime::getproperty $token $item]







<
<

>








>

<








<
<
<
|

>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
|

|


|
|
|


<
<
<
<



>
>
>
>
|
>
>
>
>
>
>

|
|
>
>
>
|
|
|
|
<

>

<


|
|
|
|
|
|
|
|


<

<
<
<
|
>
>
|
|


>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|


>

|
>


<
|
<
|
|
<
<
<
<
<
|

<






<














<




<
<
<
<
<
<
<
<
<
<
<
<
<
<

|

|





<














<
<
<
<
<
<
<
<





<



<




<


|


<
<
<
<
<




>
>
|
















<

<






<
<
<
|
<

|











|







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
        default {
          lappend pathlist $part
        }
      }
    }
    return $pathlist
  }


  method wait {mode sock} {
    my clay refcount_incr
    if {[info coroutine] eq {}} {
      chan event $sock $mode [list set ::httpd::lock_$sock $mode]
      vwait ::httpd::lock_$sock
    } else {
      chan event $sock $mode [info coroutine]
      yield
    }
    chan event $sock $mode {}
    my clay refcount_decr
  }

}

###
# END: core.tcl
###
###
# START: reply.tcl
###



::clay::define ::httpd::reply {
  superclass ::httpd::mime
  Variable ChannelRegister {}
  Delegate <server> {
    description {The server object which spawned this reply}
  }
  Dict reply {}
  Dict request {
    CONTENT_LENGTH 0
    COOKIE {}
    HTTP_HOST {}
    REFERER {}
    REQUEST_URI {}
    REMOTE_ADDR {}
    REMOTE_HOST {}
    USER_AGENT {}
    SESSION {}
  }
  constructor {ServerObj args} {
    my variable dispatched_time uuid
    set uuid [namespace tail [self]]
    set dispatched_time [clock milliseconds]
    my clay delegate <server> $ServerObj
    foreach {field value} [::clay::args_to_options {*}$args] {
      my clay set config $field: $value
    }
  }




  destructor {
    my close
  }
  method ChannelRegister args {
    my variable ChannelRegister
    if {![info exists ChannelRegister]} {
      set ChannelRegister {}
    }
    foreach c $args {
      if {$c ni $ChannelRegister} {
        lappend ChannelRegister $c
      }
    }
  }
  method close {} {
    my variable ChannelRegister
    if {![info exists ChannelRegister]} {
      return
    }
    foreach c $ChannelRegister {
      catch {chan event $c readable {}}
      catch {chan event $c writable {}}
      catch {chan flush $c}
      catch {chan close $c}

    }
    set ChannelRegister {}
  }

  method Log_Dispatched {} {
    my log Dispatched [dict create \
     REMOTE_ADDR [my request get REMOTE_ADDR] \
     REMOTE_HOST [my request get REMOTE_HOST] \
     COOKIE [my request get HTTP_COOKIE] \
     REFERER [my request get HTTP_REFERER] \
     USER_AGENT [my request get HTTP_USER_AGENT] \
     REQUEST_URI [my request get REQUEST_URI] \
     HTTP_HOST [my request get HTTP_HOST] \
     SESSION [my request get SESSION] \
    ]
  }

  method dispatch {newsock datastate} {



    my variable chan request
    try {
      my clay refcount_incr
      set chan $newsock
      my ChannelRegister $chan
      chan event $chan readable {}
      chan configure $chan -translation {auto crlf} -buffering line
      if {[dict exists $datastate mixin]} {
        set mixinmap [dict get $datastate mixin]
      } else {
        set mixinmap {}
      }
      foreach item [dict keys $datastate MIXIN_*] {
        set slot [string range $item 6 end]
        dict set mixinmap [string tolower $slot] [dict get $datastate $item]
      }
      my clay mixinmap {*}$mixinmap
      if {[dict exists $datastate delegate]} {
        my clay delegate {*}[dict get $datastate delegate]
      }
      my reset
      set request [my clay get dict/ request]
      foreach {f v} $datastate {
        if {[string index $f end] eq "/"} {
          catch {my clay merge $f $v}
        } else {
          my clay set $f $v
        }
        if {$f eq "http"} {
          foreach {ff vf} $v {
            dict set request $ff $vf
          }
        }
      }
      my Session_Load
      my Log_Dispatched
      my Dispatch
    } on error {err errdat} {
      my error 500 $err [dict get $errdat -errorinfo]
      my DoOutput
    } finally {
      my close
      my clay refcount_decr
    }
  }

  method Dispatch {} {

    # Invoke the URL implementation.
    my content





    my DoOutput
  }

  method html_header {title args} {
    set result {}
    append result "<HTML><HEAD>"
    if {$title ne {}} {
      append result "<TITLE>$title</TITLE>"
    }

    append result "</HEAD><BODY>"
    append result \n {<div id="top-menu">}
    if {[dict exists $args banner]} {
      append result "<img src=\"[dict get $args banner]\">"
    } else {
      append result {<img src="/images/etoyoc-banner.jpg">}
    }
    append result {</div>}
    if {[dict exists $args sideimg]} {
      append result "\n<div name=\"sideimg\"><img align=right src=\"[dict get $args sideimg]\"></div>"
    }
    append result {<div id="content">}
    return $result
  }

  method html_footer {args} {
    set result {</div><div id="footer">}
    append result {</div></BODY></HTML>}
  }














  method error {code {msg {}} {errorInfo {}}} {
    my clay set  HTTP_ERROR $code
    my reset
    set qheaders [my clay dump]
    set HTTP_STATUS "$code [my http_code_string $code]"
    dict with qheaders {}
    my reply replace {}
    my reply set Status $HTTP_STATUS
    my reply set Content-Type {text/html; charset=UTF-8}

    switch $code {
      301 - 302 - 303 - 307 - 308 {
        my reply set Location $msg
        set template [my <server> template redirect]
      }
      404 {
        set template [my <server> template notfound]
      }
      default {
        set template [my <server> template internal_error]
      }
    }
    my puts [subst $template]
  }








  method content {} {
    my puts [my html_header {Hello World!}]
    my puts "<H1>HELLO WORLD!</H1>"
    my puts [my html_footer]
  }

  method EncodeStatus {status} {
    return "HTTP/1.0 $status"
  }

  method log {type {info {}}} {
    my variable dispatched_time uuid
    my <server> log $type $uuid $info
  }

  method CoroName {} {
    if {[info coroutine] eq {}} {
      return ::httpd::object::[my clay get UUID]
    }
  }





  method DoOutput {} {
    my variable reply_body chan
    if {$chan eq {}} return
    catch {
      # Causing random issues. Technically a socket is always open for read and write
      # anyway
      #my wait writable $chan
      chan configure $chan  -translation {binary binary}
      ###
      # Return dynamic content
      ###
      set length [string length $reply_body]
      set result {}
      if {${length} > 0} {
        my reply set Content-Length [string length $reply_body]
        append result [my reply output] \n
        append result $reply_body
      } else {
        append result [my reply output]
      }
      chan puts -nonewline $chan $result
      my log HttpAccess {}
    }

  }

  method FormData {} {
    my variable chan formdata
    # Run this only once
    if {[info exists formdata]} {
      return $formdata
    }



    set length [my request get CONTENT_LENGTH]

    set formdata {}
    if {[my request get REQUEST_METHOD] in {"POST" "PUSH"}} {
      set rawtype [my request get CONTENT_TYPE]
      if {[string toupper [string range $rawtype 0 8]] ne "MULTIPART"} {
        set type $rawtype
      } else {
        set type multipart
      }
      switch $type {
        multipart {
          ###
          # Ok, Multipart MIME is troublesome, farm out the parsing to a dedicated tool
          ###
          set body [my clay get mimetxt]
          append body \n [my PostData $length]
          set token [::mime::initialize -string $body]
          foreach item [::mime::getheader $token -names] {
            dict set formdata $item [::mime::getheader $token $item]
          }
          foreach item {content encoding params parts size} {
            dict set formdata MIME_[string toupper $item] [::mime::getproperty $token $item]
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
            foreach {name value} [split $pair "="] {
              lappend formdata [my Url_Decode $name] [my Url_Decode $value]
            }
          }
        }
      }
    } else {
      foreach pair [split [my http_info getnull QUERY_STRING] "&"] {
        foreach {name value} [split $pair "="] {
          lappend formdata [my Url_Decode $name] [my Url_Decode $value]
        }
      }
    }
    return $formdata
  }

  method PostData {length} {
    my variable postdata
    # Run this only once
    if {[info exists postdata]} {
      return $postdata
    }
    set postdata {}
    if {[my http_info get REQUEST_METHOD] in {"POST" "PUSH"}} {
      my variable chan
      chan configure $chan -translation binary -blocking 0 -buffering full -buffersize 4096
      set postdata [::coroutine::util::read $chan $length]
    }
    return $postdata
  }

  method TransferComplete args {
    my variable chan transfer_complete
    set transfer_complete 1
    my log TransferComplete
    set chan {}
    foreach c $args {
      catch {chan event $c readable {}}
      catch {chan event $c writable {}}
      catch {chan flush $c}
      catch {chan close $c}
    }
    my destroy
  }

  ###
  # Append to the result buffer
  ###
  method puts line {
    my variable reply_body
    append reply_body $line \n
  }

  method RequestFind {field} {
    my variable request
    if {[dict exists $request $field]} {
      return $field
    }
    foreach item [dict keys $request] {
      if {[string tolower $item] eq [string tolower $field]} {
        return $item
      }
    }
    return $field
  }






  dictobj request request {
    field {
      tailcall my RequestFind [lindex $args 0]
    }
    get {
      set field [my RequestFind [lindex $args 0]]
      if {![dict exists $request $field]} {
        return {}
      }
      tailcall dict get $request $field
    }
    getnull {
      set field [my RequestFind [lindex $args 0]]
      if {![dict exists $request $field]} {
        return {}
      }
      tailcall dict get $request $field

    }
    exists {
      set field [my RequestFind [lindex $args 0]]
      tailcall dict exists $request $field
    }
    parse {
      if {[catch {my MimeParse [lindex $args 0]} result]} {
        my error 400 $result
        tailcall my DoOutput
      }
      set request $result
    }


  }








  dictobj reply reply {
























    output {
      set result {}
      if {![dict exists $reply Status]} {
        set status {200 OK}
      } else {
        set status [dict get $reply Status]
      }
      set result "[my EncodeStatus $status]\n"
      foreach {f v} $reply {
        if {$f in {Status}} continue
        append result "[string trimright $f :]: $v\n"
      }
      #append result \n
      return $result
    }


  }




  ###
  # Reset the result
  ###

  method reset {} {
    my variable reply_body
    my reply replace    [my HttpHeaders_Default]
    my reply set Server [my <server> cget server_string]
    my reply set Date [my timestamp]
    set reply_body {}
  }

  ###
  # Return true of this class as waited too long to respond
  ###
  method timeOutCheck {} {
    my variable dispatched_time
    if {([clock seconds]-$dispatched_time)>120} {
      ###
      # Something has lasted over 2 minutes. Kill this
      ###
      catch {
        my error 408 {Request Timed out}
        my DoOutput
      }
    }
  }

  ###
  # Return a timestamp
  ###
  method timestamp {} {
    return [clock format [clock seconds] -format {%a, %d %b %Y %T %Z}]
  }
}

###
# END: reply.tcl
###
###
# START: server.tcl
###
###
# An httpd server with a template engine
# and a shim to insert URL domains
###
namespace eval ::httpd::object {}

namespace eval ::httpd::coro {}

::tool::define ::httpd::server {
  superclass ::httpd::mime

  option port  {default: auto}
  option myaddr {default: 127.0.0.1}
  option server_string [list default: [list TclHttpd $::httpd::version]]
  option server_name [list default: [list [info hostname]]]
  option doc_root {default {}}
  option reverse_dns {type boolean default 0}
  option configuration_file {type filename default {}}

  property socket buffersize   32768
  property socket translation  {auto crlf}
  property reply_class ::httpd::reply

  array template
  variable url_patterns {}
















  constructor {args} {
    my configure {*}$args
    my start
  }


  destructor {
    my stop
  }

  method connect {sock ip port} {
    ###
    # If an IP address is blocked
    # send a "go to hell" message
    ###
    if {[my Validate_Connection $sock $ip]} {
      catch {close $sock}
      return
    }
    set uuid [my Uuid_Generate]
    set coro [coroutine ::httpd::coro::$uuid {*}[namespace code [list my Connect $uuid $sock $ip]]]
    chan event $sock readable $coro
  }

































  method Connect {uuid sock ip} {

    yield [info coroutine]
    chan event $sock readable {}

    chan configure $sock \
      -blocking 0 \
      -translation {auto crlf} \
      -buffering line

    my counter url_hit
    set line {}
    try {
      set readCount [::coroutine::util::gets_safety $sock 4096 line]
      dict set query UUID $uuid
      dict set query REMOTE_ADDR     $ip
      dict set query REMOTE_HOST     [my HostName $ip]
      dict set query REQUEST_METHOD  [lindex $line 0]
      set uriinfo [::uri::split [lindex $line 1]]
      dict set query REQUEST_URI     [lindex $line 1]
      dict set query REQUEST_PATH    [dict get $uriinfo path]
      dict set query REQUEST_VERSION [lindex [split [lindex $line end] /] end]
      dict set query DOCUMENT_ROOT   [my cget doc_root]
      dict set query QUERY_STRING    [dict get $uriinfo query]
      dict set query REQUEST_RAW     $line
      dict set query SERVER_PORT     [my port_listening]
      set mimetxt [my HttpHeaders $sock]
      dict set query mimetxt $mimetxt
      foreach {f v} [my MimeParse $mimetxt] {
        set fld [string toupper [string map {- _} $f]]
        if {$fld in {CONTENT_LENGTH CONTENT_TYPE}} {
          set qfld $fld
        } else {
          set qfld HTTP_$fld
        }
        dict set query $qfld $v
        dict set query http $fld $v
      }
      if {[string match 127.* $ip]} {
        dict set query LOCALHOST [expr {[lindex [split [dict getnull $query HTTP_HOST] :] 0] eq "localhost"}]
      }
      my Headers_Process query
      set reply [my dispatch $query]
    } on error {err errdat} {
      my debug [list uri: [dict getnull $query REQUEST_URI] ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      my log BadRequest $uuid [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      catch {chan puts $sock "HTTP/1.0 400 Bad Request (The data is invalid)"}
      catch {chan close $sock}
      return
    }
    if {[llength $reply]==0} {
      my log BadLocation $uuid $query
      my log BadLocation $uuid $query
      dict set query HTTP_STATUS 404
      dict set query template notfound
      dict set query mixinmap reply ::httpd::content.template
    }
    try {
      if {[dict exists $reply class]} {
        set class [dict get $reply class]
      } else {
        set class [my cget reply_class]
      }
      set pageobj [$class create ::httpd::object::$uuid [self]]
      if {[dict exists $reply mixinmap]} {
        set mixinmap [dict get $reply mixinmap]
      } else {
        set mixinmap {}
      }
      if {[dict exists $reply mixin]} {
        dict set mixinmap reply [dict get $reply mixin]
      }
      foreach item [dict keys $reply MIXIN_*] {
        set slot [string range $reply 6 end]
        dict set mixinmap [string tolower $slot] [dict get $reply $item]
      }
      $pageobj mixinmap {*}$mixinmap
      if {[dict exists $reply organ]} {
        $pageobj graft {*}[dict get $reply organ]
      }
    } on error {err errdat} {
      my debug [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      my log BadRequest $uuid [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      catch {$pageobj destroy}
      catch {chan close $sock}
    }
    try {
      $pageobj dispatch $sock $reply
    } on error {err errdat} {
      my debug [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      my log BadRequest $uuid [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      catch {$pageobj destroy}
      catch {chan close $sock}
    }
  }

  method counter which {
    my variable counters
    incr counters($which)
  }

  ###
  # Clean up any process that has gone out for lunch
  ###
  method CheckTimeout {} {
    foreach obj [info commands ::httpd::object::*] {
      try {
        $obj timeOutCheck
      } on error {} {
        catch {$obj destroy}
      }
    }

  }

  method debug args {}

  ###
  # Route a request to the appropriate handler
  ###
  method dispatch {data} {


    return [my Dispatch_Default $data]
  }


  method Dispatch_Default {reply} {
    ###
    # Fallback to docroot handling
    ###
    set doc_root [dict get $reply DOCUMENT_ROOT]
    if {$doc_root ne {}} {
      ###
      # Fall back to doc_root handling
      ###
      dict set reply prefix {}
      dict set reply path $doc_root
      dict set reply mixinmap reply httpd::content.file
      return $reply
    }
    return {}
  }


  method Headers_Process varname {}

  method HostName ipaddr {
    if {![my cget reverse_dns]} {
      return $ipaddr
    }
    set t [::dns::resolve $ipaddr]
    set result [::dns::name $t]
    ::dns::cleanup $t
    return $result
  }

  method log args {
    # Do nothing for now
  }

  method plugin {slot {class {}}} {
    if {$class eq {}} {
      set class ::httpd::plugin.$slot
    }
    if {[info command $class] eq {}} {
      error "Class $class for plugin $slot does not exist"
    }
    my mixinmap $slot $class
    my variable mixinmap

    ###
    # Perform action on load
    ###
    eval [$class meta getnull plugin load:]


    ###
    # rebuild the dispatch method
    ###
    set body "\n try \{"





    foreach {slot class} $mixinmap {
      set script [$class meta getnull plugin dispatch:]
      if {[string length $script]} {
        append body \n "# SLOT $slot"
        append body \n $script
      }
    }
    append body \n {  return [my Dispatch_Default $data]}
    append body \n "\} on error \{err errdat\} \{"
    append body \n {  puts [list DISPATCH ERROR [dict get $errdat -errorinfo]] ; return {}}
    append body \n "\}"
    oo::objdefine [self] method dispatch data $body
    ###
    # rebuild the Headers_Process method
    ###
    set body "\n try \{"
    append body \n "  upvar 1 \$varname query"

    foreach {slot class} $mixinmap {
      set script [$class meta getnull plugin headers:]
      if {[string length $script]} {
        append body \n "# SLOT $slot"
        append body \n $script
      }
    }
    append body \n "\} on error \{err errdat\} \{"
    append body \n {  puts [list HEADERS ERROR [dict get $errdat -errorinfo]] ; return {}}
    append body \n "\}"

    oo::objdefine [self] method Headers_Process varname $body

    ###
    # rebuild the Threads_Start method
    ###
    set body "\n try \{"
    foreach {slot class} $mixinmap {
      set script [$class meta getnull plugin thread:]
      if {[string length $script]} {
        append body \n "# SLOT $slot"
        append body \n $script
      }
    }
    append body \n "\} on error \{err errdat\} \{"
    append body \n {  puts [list THREAD START ERROR [dict get $errdat -errorinfo]] ; return {}}
    append body \n "\}"
    oo::objdefine [self] method Thread_start {} $body

  }

  method port_listening {} {
    my variable port_listening
    return $port_listening
  }

  method PrefixNormalize prefix {
    set prefix [string trimright $prefix /]
    set prefix [string trimright $prefix *]
    set prefix [string trimright $prefix /]
    return $prefix
  }

  method source {filename} {
    source $filename
  }

  method start {} {
    # Build a namespace to contain replies
    namespace eval [namespace current]::reply {}

    my variable socklist port_listening
    if {[my cget configuration_file] ne {}} {
      source [my cget configuration_file]
    }
    set port [my cget port]
    if { $port in {auto {}} } {
      package require nettool
      set port [::nettool::allocate_port 8015]
    }
    set port_listening $port
    set myaddr [my cget myaddr]
    my debug [list [self] listening on $port $myaddr]

    if {$myaddr ni {all any * {}}} {
      foreach ip $myaddr {
        lappend socklist [socket -server [namespace code [list my connect]] -myaddr $ip $port]
      }
    } else {
      lappend socklist [socket -server [namespace code [list my connect]] $port]
    }
    ::cron::every [self] 120 [namespace code {my CheckTimeout}]
    my Thread_start
  }

  method stop {} {
    my variable socklist
    if {[info exists socklist]} {
      foreach sock $socklist {
        catch {close $sock}
      }
    }
    set socklist {}
    ::cron::cancel [self]
  }






  method template page {
    my variable template
    if {[info exists template($page)]} {
      return $template($page)
    }
    set template($page) [my TemplateSearch $page]
    return $template($page)
  }

  method TemplateSearch page {
    set doc_root [my cget doc_root]
    if {$doc_root ne {} && [file exists [file join $doc_root $page.tml]]} {
      return [::fileutil::cat [file join $doc_root $page.tml]]
    }
    if {$doc_root ne {} && [file exists [file join $doc_root $page.html]]} {
      return [::fileutil::cat [file join $doc_root $page.html]]
    }
    switch $page {
      redirect {
return {
[my html header "$HTTP_STATUS"]
The page you are looking for: <b>[my http_info get REQUEST_URI]</b> has moved.
<p>
If your browser does not automatically load the new location, it is
<a href=\"$msg\">$msg</a>
[my html footer]
}
      }
      internal_error {
        return {
[my html header "$HTTP_STATUS"]
Error serving <b>[my http_info get REQUEST_URI]</b>:
<p>
The server encountered an internal server error: <pre>$msg</pre>
<pre><code>
$errorInfo
</code></pre>
[my html footer]
        }
      }
      notfound {
        return {
[my html header "$HTTP_STATUS"]
The page you are looking for: <b>[my http_info get REQUEST_URI]</b> does not exist.
[my html footer]
        }
      }
    }
  }

  method Thread_start {} {}

  method Uuid_Generate {} {
    return [::uuid::uuid generate]
  }

  ###
  # Return true if this IP address is blocked
  # The socket will be closed immediately after returning
  # This handler is welcome to send a polite error message
  ###
  method Validate_Connection {sock ip} {
    return 0
  }
}

###
# Provide a backward compadible alias
###
::tool::define ::httpd::server::dispatch {
    superclass ::httpd::server
}

###
# END: server.tcl
###
###
# START: dispatch.tcl
###
::tool::define ::httpd::content.redirect {

  method reset {} {
    ###
    # Inject the location into the HTTP headers
    ###
    my variable reply_body
    set reply_body {}
    my reply replace    [my HttpHeaders_Default]
    my reply set Server [my <server> cget server_string]
    set msg [my http_info get LOCATION]
    my reply set Location [my http_info get LOCATION]
    set code  [my http_info getnull REDIRECT_CODE]
    if {$code eq {}} {
      set code 301
    }
    my reply set Status [list $code [my http_code_string $code]]
  }

  method content {} {
    set template [my <server> template redirect]
    set msg [my http_info get LOCATION]
    set HTTP_STATUS [my reply get Status]
    my puts [subst $msg]
  }
}

::tool::define ::httpd::content.cache {

  method dispatch {newsock datastate} {
    my http_info replace $datastate
    my request replace  [dict get $datastate http]
    my variable chan
    set chan $newsock
    chan event $chan readable {}
    try {
      my Log_Dispatched
      my wait writable $chan
      chan configure $chan  -translation {binary binary}
      chan puts -nonewline $chan [my http_info get CACHE_DATA]
    } on error {err info} {
      my <server> debug [dict get $info -errorinfo]
    } finally {
      my TransferComplete $chan
    }
  }
}

::tool::define ::httpd::content.template {

  method content {} {
    if {[my http_info getnull HTTP_STATUS] ne {}} {
      my reply set Status [my http_info getnull HTTP_STATUS]
    }


    my puts [subst [my <server> template [my http_info get template]]]
  }
}

###
# END: dispatch.tcl
###
###
# START: file.tcl
###
###
# Class to deliver Static content
# When utilized, this class is fed a local filename
# by the dispatcher
###
::tool::define ::httpd::content.file {

  method FileName {} {





    set uri [string trimleft [my http_info get REQUEST_URI] /]
    set path [my http_info get path]
    set prefix [my http_info get prefix]
    set fname [string range $uri [string length $prefix] end]
    if {$fname in "{} index.html index.md index"} {
      return $path
    }
    if {[file exists [file join $path $fname]]} {
      return [file join $path $fname]
    }
    if {[file exists [file join $path $fname.md]]} {
      return [file join $path $fname.md]
    }
    if {[file exists [file join $path $fname.html]]} {
      return [file join $path $fname.html]
    }
    if {[file exists [file join $path $fname.tml]]} {
      return [file join $path $fname.tml]
    }

    return {}
  }


  method DirectoryListing {local_file} {
    set uri [string trimleft [my http_info get REQUEST_URI] /]
    set path [my http_info get path]
    set prefix [my http_info get prefix]
    set fname [string range $uri [string length $prefix] end]
    my puts [my html_header "Listing of /$fname/"]
    my puts "Listing contents of /$fname/"
    my puts "<TABLE>"
    if {$prefix ni {/ {}}} {
      set updir [file dirname $prefix]
      if {$updir ne {}} {
        my puts "<TR><TD><a href=\"/$updir\">..</a></TD><TD></TD></TR>"
      }
    }
    foreach file [glob -nocomplain [file join $local_file *]] {
      if {[file isdirectory $file]} {
        my puts "<TR><TD><a href=\"[file join / $uri [file tail $file]]\">[file tail $file]/</a></TD><TD></TD></TR>"
      } else {
        my puts "<TR><TD><a href=\"[file join / $uri [file tail $file]]\">[file tail $file]</a></TD><TD>[file size $file]</TD></TR>"
      }
    }
    my puts "</TABLE>"
    my puts [my html_footer]
  }

  method content {} {
    my variable reply_file
    set local_file [my FileName]
    if {$local_file eq {} || ![file exist $local_file]} {
      my log httpNotFound [my http_info get REQUEST_URI]
      my error 404 {File Not Found}
      tailcall my DoOutput
    }
    if {[file isdirectory $local_file] || [file tail $local_file] in {index index.html index.tml index.md}} {


      ###
      # Produce an index page
      ###
      set idxfound 0
      foreach name {

        index.html
        index.tml
        index.md


        content.htm
      } {
        if {[file exists [file join $local_file $name]]} {
          set idxfound 1
          set local_file [file join $local_file $name]
          break
        }
      }
      if {!$idxfound} {
        tailcall my DirectoryListing $local_file
      }



    }


    switch [file extension $local_file] {




























      .md {
        package require Markdown
        my reply set Content-Type {text/html; charset=UTF-8}
        set mdtxt  [::fileutil::cat $local_file]
        my puts [::Markdown::convert $mdtxt]
      }






















      .tml {
        my reply set Content-Type {text/html; charset=UTF-8}
        set tmltxt  [::fileutil::cat $local_file]
        set headers [my http_info dump]
        dict with headers {}
        my puts [subst $tmltxt]
      }








      default {
        ###
        # Assume we are returning a binary file
        ###
        my reply set Content-Type [::fileutil::magic::filetype $local_file]
        set reply_file $local_file
      }
    }
  }

  method dispatch {newsock datastate} {
    my variable reply_body reply_file reply_chan chan
    try {
      my http_info replace $datastate
      my request replace  [dict get $datastate http]
      my Log_Dispatched
      set chan $newsock
      chan event $chan readable {}
      chan configure $chan -translation {auto crlf} -buffering line

      my reset
      # Invoke the URL implementation.
      my content
    } on error {err errdat} {
      my error 500 $err [dict get $errdat -errorinfo]

      tailcall my DoOutput
    }

    if {$chan eq {}} return



    my wait writable $chan
    if {![info exists reply_file]} {
      tailcall my DoOutput
    }
    try {
      chan configure $chan  -translation {binary binary}
      my log HttpAccess {}
      ###
      # Return a stream of data from a file
      ###
      set size [file size $reply_file]
      my reply set Content-Length $size
      append result [my reply output] \n
      chan puts -nonewline $chan $result
      set reply_chan [open $reply_file r]

      my log SendReply [list length $size]
      chan configure $reply_chan  -translation {binary binary}
      ###
      # Send any POST/PUT/etc content
      # Note, we are terminating the coroutine at this point
      # and using the file event to wake the object back up
      #
      # We *could*:
      # chan copy $sock $chan -command [info coroutine]
      # yield
      #
      # But in the field this pegs the CPU for long transfers and locks
      # up the process
      ###



      chan copy $reply_chan $chan -command [namespace code [list my TransferComplete $reply_chan $chan]]
    } on error {err errdat} {
      my TransferComplete $reply_chan $chan

    }
  }
}

###
# END: file.tcl
###
###
# START: proxy.tcl
###
::tool::define ::httpd::content.exec {
  variable exename [list tcl [info nameofexecutable] .tcl [info nameofexecutable]]

  method CgiExec {execname script arglist} {
    if { $::tcl_platform(platform) eq "windows"} {
      if {[file extension $script] eq ".exe"} {
        return [open "|[list $script] $arglist" r+]
      } else {
        if {$execname eq {}} {
          set execname [my Cgi_Executable $script]
        }
        return [open "|[list $execname $script] $arglist" r+]
      }
    } else {
      if {$execname eq {}} {
        return [open "|[list $script] $arglist 2>@1" r+]
      } else {
        return [open "|[list $execname $script] $arglist 2>@1" r+]
      }
    }
    error "CGI Not supported"
  }

  method Cgi_Executable {script} {
    if {[string tolower [file extension $script]] eq ".exe"} {
      return $script
    }
    my variable exename
    set ext [file extension $script]
    if {$ext eq {}} {







|







<







|






|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




<












>
>
>
>
>
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|
|
|
|
|
|
>
>
|
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
>
>
|
|
<
<
<
>



|



<
<
<
<












<
<
<
<











<
<
<
<
|
>
|
|
|

|
<
|
|
|
|
|
|
|
|
|
|
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
|
|
|
>
|



<


|
|









>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>


<




<

<

|
<
<
<
<
<
<
<
<
<
<
<
<

|
<
<
<
<
<
<
<
|
|
<
<
|
<









|
|

|
|
|

<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<




<
<
<
<





|


>

<

<
<
<
<

>
>
|
|
>
|




|






|




|
>

<

|







<



<







|
|




|
>





>
>
>
>
>

|















>

|








>







|









|
<
<




<






<



<





|
|

|





|












<










>
>
|
>
>
|








<

|









|
|



|




|
|





|




|
|
|




<

<

|

<
<
<
<
<
<




<
<
<
<
|









|
<







|
|
|
|





<


|




<
|
|
<
<
<

<
<
<
<
|
|
|
<
<
<
<
|
|
<
<
|
<

|
|

>
>
|









<
<
<
<
<
|
<

>
>
>
>
>
|
|
|

|














>
|
|
>
|

|
|
|




















<




|




>
>





>



>
>











>
>
>

>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|



>
>
>
>
>
>
>
>









|
<


<
<
<
<
<
<
<





>
|
|
>

>
>
>
|
|
|
|
<










>

<

|
<
<
<
<
<
<
<
<
<

>
>
>
|
|
|
>










|

<



















<







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
            foreach {name value} [split $pair "="] {
              lappend formdata [my Url_Decode $name] [my Url_Decode $value]
            }
          }
        }
      }
    } else {
      foreach pair [split [my request get QUERY_STRING] "&"] {
        foreach {name value} [split $pair "="] {
          lappend formdata [my Url_Decode $name] [my Url_Decode $value]
        }
      }
    }
    return $formdata
  }

  method PostData {length} {
    my variable postdata
    # Run this only once
    if {[info exists postdata]} {
      return $postdata
    }
    set postdata {}
    if {[my request get REQUEST_METHOD] in {"POST" "PUSH"}} {
      my variable chan
      chan configure $chan -translation binary -blocking 0 -buffering full -buffersize 4096
      set postdata [::coroutine::util::read $chan $length]
    }
    return $postdata
  }
  method Session_Load {} {}

















  method puts line {
    my variable reply_body
    append reply_body $line \n
  }

  method RequestFind {field} {
    my variable request
    if {[dict exists $request $field]} {
      return $field
    }
    foreach item [dict keys $request] {
      if {[string tolower $item] eq [string tolower $field]} {
        return $item
      }
    }
    return $field
  }
  method request {subcommand args} {
    my variable request
    switch $subcommand {
      dump {
        return $request
      }

      field {
        tailcall my RequestFind [lindex $args 0]
      }
      get {
        set field [my RequestFind [lindex $args 0]]
        if {![dict exists $request $field]} {
          return {}
        }
        tailcall dict get $request $field
      }
      getnull {
        set field [my RequestFind [lindex $args 0]]
        if {![dict exists $request $field]} {
          return {}
        }
        tailcall dict get $request $field
      }

      exists {
        set field [my RequestFind [lindex $args 0]]
        tailcall dict exists $request $field
      }
      parse {
        if {[catch {my MimeParse [lindex $args 0]} result]} {
          my error 400 $result
          tailcall my DoOutput
        }
        set request $result
      }
      replace {
        set request [lindex $args 0]
      }
      set {
        dict set request {*}$args
      }
      default {
        error "Unknown command $subcommand. Valid: field, get, getnull, exists, parse, replace, set"
      }
    }
  }
  method reply {subcommand args} {
    my variable reply
    switch $subcommand {
      dump {
        return $reply
      }
      exists {
        return [dict exists $reply {*}$args]
      }
      get -
      getnull {
        return [dict getnull $reply {*}$args]
      }
      replace {
        set reply [my HttpHeaders_Default]
        if {[llength $args]==1} {
          foreach {f v} [lindex $args 0] {
            dict set reply $f $v
          }
        } else {
          foreach {f v} $args {
            dict set reply $f $v
          }
        }
      }
      output {
        set result {}
        if {![dict exists $reply Status]} {
          set status {200 OK}
        } else {
          set status [dict get $reply Status]
        }
        set result "[my EncodeStatus $status]\n"
        foreach {f v} $reply {
          if {$f in {Status}} continue
          append result "[string trimright $f :]: $v\n"
        }
        #append result \n
        return $result
      }
      set {
        dict set reply {*}$args
      }
      default {
        error "Unknown command $subcommand. Valid: exists, get, getnull, output, replace, set"
      }
    }



  }
  method reset {} {
    my variable reply_body
    my reply replace    [my HttpHeaders_Default]
    my reply set Server [my <server> clay get server/ string]
    my reply set Date [my timestamp]
    set reply_body {}
  }




  method timeOutCheck {} {
    my variable dispatched_time
    if {([clock seconds]-$dispatched_time)>120} {
      ###
      # Something has lasted over 2 minutes. Kill this
      ###
      catch {
        my error 408 {Request Timed out}
        my DoOutput
      }
    }
  }




  method timestamp {} {
    return [clock format [clock seconds] -format {%a, %d %b %Y %T %Z}]
  }
}

###
# END: reply.tcl
###
###
# START: server.tcl
###




namespace eval ::httpd::object {
}
namespace eval ::httpd::coro {
}
::clay::define ::httpd::server {
  superclass ::httpd::mime
  clay set server/ port auto

  clay set server/ myaddr 127.0.0.1
  clay set server/ string [list TclHttpd $::httpd::version]
  clay set server/ name [info hostname]
  clay set server/ doc_root {}
  clay set server/ reverse_dns 0
  clay set server/ configuration_file {}
  clay set server/ protocol {HTTP/1.1}
  clay set socket/ buffersize   32768
  clay set socket/ translation  {auto crlf}
  clay set reply_class ::httpd::reply

  Array template
  Dict url_patterns {}
  constructor {
  {args {
    port        {default auto      comment {Port to listen on}}
    myaddr      {default 127.0.0.1 comment {IP address to listen on. "all" means all}}
    string      {default auto      comment {Value for SERVER_SOFTWARE in HTTP headers}}
    name        {default auto      comment {Value for SERVER_NAME in HTTP headers. Defaults to [info hostname]}}
    doc_root    {default {}        comment {File path to serve.}}
    reverse_dns {default 0         comment {Perform reverse DNS to convert IPs into hostnames}}
    configuration_file {default {} comment {Configuration file to load into server namespace}}
    protocol    {default {HTTP/1.1} comment {Value for SERVER_PROTOCOL in HTTP headers}}
  }}} {
    if {[llength $args]==1} {
      set arglist [lindex $args 0]
    } else {
      set arglist $args
    }

    foreach {var val} $arglist {
      my clay set server/ $var $val
    }
    my start
  }
  destructor {
    my stop
  }

  method connect {sock ip port} {
    ###
    # If an IP address is blocked drop the
    # connection
    ###
    if {[my Validate_Connection $sock $ip]} {
      catch {close $sock}
      return
    }
    set uuid [my Uuid_Generate]
    set coro [coroutine ::httpd::coro::$uuid {*}[namespace code [list my Connect $uuid $sock $ip]]]
    chan event $sock readable $coro
  }
  method ServerHeaders {ip http_request mimetxt} {
    set result {}
    dict set result HTTP_HOST {}
    dict set result CONTENT_LENGTH 0
    foreach {f v} [my MimeParse $mimetxt] {
      set fld [string toupper [string map {- _} $f]]
      if {$fld in {CONTENT_LENGTH CONTENT_TYPE}} {
        set qfld $fld
      } else {
        set qfld HTTP_$fld
      }
      dict set result $qfld $v
    }
    dict set result REMOTE_ADDR     $ip
    dict set result REMOTE_HOST     [my HostName $ip]
    dict set result REQUEST_METHOD  [lindex $http_request 0]
    set uriinfo [::uri::split [lindex $http_request 1]]
    dict set result uriinfo $uriinfo
    dict set result REQUEST_URI     [lindex $http_request 1]
    dict set result REQUEST_PATH    [dict get $uriinfo path]
    dict set result REQUEST_VERSION [lindex [split [lindex $http_request end] /] end]
    dict set result DOCUMENT_ROOT   [my clay get server/ doc_root]
    dict set result QUERY_STRING    [dict get $uriinfo query]
    dict set result REQUEST_RAW     $http_request
    dict set result SERVER_PORT     [my port_listening]
    dict set result SERVER_NAME     [my clay get server/ name]
    dict set result SERVER_PROTOCOL [my clay get server/ protocol]
    dict set result SERVER_SOFTWARE [my clay get server/ string]
    if {[string match 127.* $ip]} {
      dict set result LOCALHOST [expr {[lindex [split [dict getnull $result HTTP_HOST] :] 0] eq "localhost"}]
    }
    return $result
  }
  method Connect {uuid sock ip} {
    ::clay::cleanup
    yield [info coroutine]
    chan event $sock readable {}

    chan configure $sock \
      -blocking 0 \
      -translation {auto crlf} \
      -buffering line

    my counter url_hit

    try {
      set readCount [::coroutine::util::gets_safety $sock 4096 http_request]












      set mimetxt [my HttpHeaders $sock]
      dict set query UUID $uuid







      dict set query mimetxt $mimetxt
      dict set query mixin style [my clay get server/ style]


      dict set query http [my ServerHeaders $ip $http_request $mimetxt]

      my Headers_Process query
      set reply [my dispatch $query]
    } on error {err errdat} {
      my debug [list uri: [dict getnull $query REQUEST_URI] ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      my log BadRequest $uuid [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      catch {chan puts $sock "HTTP/1.0 400 Bad Request (The data is invalid)"}
      catch {chan close $sock}
      return
    }
    if {[dict size $reply]==0} {
      set reply $query
      my log BadLocation $uuid $query
      dict set reply http HTTP_STATUS {404 Not Found}
      dict set reply template notfound
      dict set reply mixin reply ::httpd::content.template
    }






    set pageobj [::httpd::reply create ::httpd::object::$uuid [self]]























    tailcall $pageobj dispatch $sock $reply





  }


  method counter which {
    my variable counters
    incr counters($which)
  }




  method CheckTimeout {} {
    foreach obj [info commands ::httpd::object::*] {
      try {
        $obj timeOutCheck
      } on error {} {
        $obj clay refcount_decr
      }
    }
    ::clay::cleanup
  }

  method debug args {}




  method dispatch {data} {
    set reply [my Dispatch_Local $data]
    if {[dict size $reply]} {
      return $reply
    }
    return [my Dispatch_Default $data]
  }
  method Dispatch_Default {reply} {
    ###
    # Fallback to docroot handling
    ###
    set doc_root [dict getnull $reply http DOCUMENT_ROOT]
    if {$doc_root ne {}} {
      ###
      # Fall back to doc_root handling
      ###
      dict set reply prefix {}
      dict set reply path $doc_root
      dict set reply mixin reply httpd::content.file
      return $reply
    }
    return {}
  }
  method Dispatch_Local data {}
  method Headers_Local {varname} {}
  method Headers_Process varname {}

  method HostName ipaddr {
    if {![my clay get server/ reverse_dns]} {
      return $ipaddr
    }
    set t [::dns::resolve $ipaddr]
    set result [::dns::name $t]
    ::dns::cleanup $t
    return $result
  }

  method log args {
    # Do nothing for now
  }

  method plugin {slot {class {}}} {
    if {$class eq {}} {
      set class ::httpd::plugin.$slot
    }
    if {[info command $class] eq {}} {
      error "Class $class for plugin $slot does not exist"
    }
    my clay mixinmap $slot $class
    set mixinmap [my clay mixinmap]

    ###
    # Perform action on load
    ###
    set script [$class clay search plugin/ load]
    eval $script

    ###
    # rebuild the dispatch method
    ###
    set body "\n try \{"
    append body \n {
  set reply [my Dispatch_Local $data]
  if {[dict size $reply]} {return $reply}
}

    foreach {slot class} $mixinmap {
      set script [$class clay search plugin/ dispatch]
      if {[string length $script]} {
        append body \n "# SLOT $slot"
        append body \n $script
      }
    }
    append body \n {  return [my Dispatch_Default $data]}
    append body \n "\} on error \{err errdat\} \{"
    append body \n {  puts [list DISPATCH ERROR [dict get $errdat -errorinfo]] ; return {}}
    append body \n "\}"
    oo::objdefine [self] method dispatch data $body
    ###
    # rebuild the Headers_Process method
    ###
    set body "\n try \{"
    append body \n "  upvar 1 \$varname query"
    append body \n {  my Headers_Local query}
    foreach {slot class} $mixinmap {
      set script [$class clay search plugin/ headers]
      if {[string length $script]} {
        append body \n "# SLOT $slot"
        append body \n $script
      }
    }
    append body \n "\} on error \{err errdat\} \{"
    append body \n {  puts [list HEADERS ERROR [dict get $errdat -errorinfo]] ; return {}}
    append body \n "\}"

    oo::objdefine [self] method Headers_Process varname $body

    ###
    # rebuild the Threads_Start method
    ###
    set body "\n try \{"
    foreach {slot class} $mixinmap {
      set script [$class clay search plugin/ thread]
      if {[string length $script]} {
        append body \n "# SLOT $slot"
        append body \n $script
      }
    }
    append body \n "\} on error \{err errdat\} \{"
    append body \n {  puts [list THREAD START ERROR [dict get $errdat -errorinfo]] ; return {}}
    append body \n "\}"
    oo::objdefine [self] method Thread_start {} $body
  }


  method port_listening {} {
    my variable port_listening
    return $port_listening
  }

  method PrefixNormalize prefix {
    set prefix [string trimright $prefix /]
    set prefix [string trimright $prefix *]
    set prefix [string trimright $prefix /]
    return $prefix
  }

  method source {filename} {
    source $filename
  }

  method start {} {
    # Build a namespace to contain replies
    namespace eval [namespace current]::reply {}

    my variable socklist port_listening
    if {[my clay get server/ configuration_file] ne {}} {
      source [my clay get server/ configuration_file]
    }
    set port [my clay get server/ port]
    if { $port in {auto {}} } {
      package require nettool
      set port [::nettool::allocate_port 8015]
    }
    set port_listening $port
    set myaddr [my clay get server/ myaddr]
    my debug [list [self] listening on $port $myaddr]

    if {$myaddr ni {all any * {}}} {
      foreach ip $myaddr {
        lappend socklist [socket -server [namespace code [list my connect]] -myaddr $ip $port]
      }
    } else {
      lappend socklist [socket -server [namespace code [list my connect]] $port]
    }
    ::cron::every [self] 120 [namespace code {my CheckTimeout}]
    my Thread_start
  }

  method stop {} {
    my variable socklist
    if {[info exists socklist]} {
      foreach sock $socklist {
        catch {close $sock}
      }
    }
    set socklist {}
    ::cron::cancel [self]
  }
  Ensemble SubObject::db {} {
    return [namespace current]::Sqlite_db
  }
  Ensemble SubObject::default {} {
    return [namespace current]::$method
  }
  method template page {
    my variable template
    if {[info exists template($page)]} {
      return $template($page)
    }
    set template($page) [my TemplateSearch $page]
    return $template($page)
  }

  method TemplateSearch page {
    set doc_root [my clay get server/ doc_root]
    if {$doc_root ne {} && [file exists [file join $doc_root $page.tml]]} {
      return [::fileutil::cat [file join $doc_root $page.tml]]
    }
    if {$doc_root ne {} && [file exists [file join $doc_root $page.html]]} {
      return [::fileutil::cat [file join $doc_root $page.html]]
    }
    switch $page {
      redirect {
return {
[my html_header "$HTTP_STATUS"]
The page you are looking for: <b>[my request get REQUEST_PATH]</b> has moved.
<p>
If your browser does not automatically load the new location, it is
<a href=\"$msg\">$msg</a>
[my html_footer]
}
      }
      internal_error {
        return {
[my html_header "$HTTP_STATUS"]
Error serving <b>[my request get REQUEST_PATH]</b>:
<p>
The server encountered an internal server error: <pre>$msg</pre>
<pre><code>
$errorInfo
</code></pre>
[my html_footer]
        }
      }
      notfound {
        return {
[my html_header "$HTTP_STATUS"]
The page you are looking for: <b>[my request get REQUEST_PATH]</b> does not exist.
[my html_footer]
        }
      }
    }
  }

  method Thread_start {} {}

  method Uuid_Generate {} {
    return [::clay::uuid::short]
  }






  method Validate_Connection {sock ip} {
    return 0
  }
}




::clay::define ::httpd::server::dispatch {
    superclass ::httpd::server
}

###
# END: server.tcl
###
###
# START: dispatch.tcl
###
::clay::define ::httpd::content.redirect {

  method reset {} {
    ###
    # Inject the location into the HTTP headers
    ###
    my variable reply_body
    set reply_body {}
    my reply replace    [my HttpHeaders_Default]
    my reply set Server [my <server> clay get server/ string]
    set msg [my clay get LOCATION]
    my reply set Location [my clay get LOCATION]
    set code  [my clay get REDIRECT_CODE]
    if {$code eq {}} {
      set code 301
    }
    my reply set Status [list $code [my http_code_string $code]]
  }

  method content {} {
    set template [my <server> template redirect]
    set msg [my clay get LOCATION]
    set HTTP_STATUS [my reply get Status]
    my puts [subst $msg]
  }
}

::clay::define ::httpd::content.cache {
  method Dispatch {} {



    my variable chan




    my wait writable $chan
    chan configure $chan  -translation {binary binary}
    chan puts -nonewline $chan [my clay get cache/ data]




  }
}


::clay::define ::httpd::content.template {

  method content {} {
    if {[my request get HTTP_STATUS] ne {}} {
      my reply set Status [my request get HTTP_STATUS]
    }
    set request [my request dump]
    dict with request {}
    my puts [subst [my <server> template [my clay get template]]]
  }
}

###
# END: dispatch.tcl
###
###
# START: file.tcl
###





::clay::define ::httpd::content.file {

  method FileName {} {
    # Some dispatchers will inject a fully qualified name during discovery
    if {[my clay exists FILENAME] && [file exists [my clay get FILENAME]]} {
      my request set PREFIX_URI [file dirname [my clay get FILENAME]]
      return [my clay get FILENAME]
    }
    set uri [string trimleft [my request get REQUEST_PATH] /]
    set path [my clay get path]
    set prefix [my clay get prefix]
    set fname [string range $uri [string length $prefix] end]
    if {$fname in "{} index.html index.md index index.tml index.tcl"} {
      return $path
    }
    if {[file exists [file join $path $fname]]} {
      return [file join $path $fname]
    }
    if {[file exists [file join $path $fname.md]]} {
      return [file join $path $fname.md]
    }
    if {[file exists [file join $path $fname.html]]} {
      return [file join $path $fname.html]
    }
    if {[file exists [file join $path $fname.tml]]} {
      return [file join $path $fname.tml]
    }
    if {[file exists [file join $path $fname.tcl]]} {
      return [file join $path $fname.tcl]
    }
    return {}
  }
  method DirectoryListing {local_file} {
    set uri [string trimleft [my request get REQUEST_PATH] /]
    set path [my clay get path]
    set prefix [my clay get prefix]
    set fname [string range $uri [string length $prefix] end]
    my puts [my html_header "Listing of /$fname/"]
    my puts "Listing contents of /$fname/"
    my puts "<TABLE>"
    if {$prefix ni {/ {}}} {
      set updir [file dirname $prefix]
      if {$updir ne {}} {
        my puts "<TR><TD><a href=\"/$updir\">..</a></TD><TD></TD></TR>"
      }
    }
    foreach file [glob -nocomplain [file join $local_file *]] {
      if {[file isdirectory $file]} {
        my puts "<TR><TD><a href=\"[file join / $uri [file tail $file]]\">[file tail $file]/</a></TD><TD></TD></TR>"
      } else {
        my puts "<TR><TD><a href=\"[file join / $uri [file tail $file]]\">[file tail $file]</a></TD><TD>[file size $file]</TD></TR>"
      }
    }
    my puts "</TABLE>"
    my puts [my html_footer]
  }

  method content {} {
    my variable reply_file
    set local_file [my FileName]
    if {$local_file eq {} || ![file exist $local_file]} {
      my log httpNotFound [my request get REQUEST_PATH]
      my error 404 {File Not Found}
      tailcall my DoOutput
    }
    if {[file isdirectory $local_file] || [file tail $local_file] in {index index.html index.tml index.md}} {
      my request set PREFIX_URI [my request get REQUEST_PATH]
      my request set LOCAL_DIR $local_file
      ###
      # Produce an index page
      ###
      set idxfound 0
      foreach name {
        index.tcl
        index.html
        index.tml
        index.md
        index.info
        index.clay
        content.htm
      } {
        if {[file exists [file join $local_file $name]]} {
          set idxfound 1
          set local_file [file join $local_file $name]
          break
        }
      }
      if {!$idxfound} {
        tailcall my DirectoryListing $local_file
      }
    } else {
      my request set PREFIX_URI [file dirname [my request get REQUEST_PATH]]
      my request set LOCAL_DIR [file dirname $local_file]
    }
    my request set LOCAL_FILE $local_file

    switch [file extension $local_file] {
      .apng {
        my reply set Content-Type {image/apng}
        set reply_file $local_file
      }
      .bmp {
        my reply set Content-Type {image/bmp}
        set reply_file $local_file
      }
      .css {
        my reply set Content-Type {text/css}
        set reply_file $local_file
      }
      .gif {
        my reply set Content-Type {image/gif}
        set reply_file $local_file
      }
      .cur - .ico {
        my reply set Content-Type {image/x-icon}
        set reply_file $local_file
      }
      .jpg - .jpeg - .jfif - .pjpeg - .pjp {
        my reply set Content-Type {image/jpg}
        set reply_file $local_file
      }
      .js {
        my reply set Content-Type {text/javascript}
        set reply_file $local_file
      }
      .md {
        package require Markdown
        my reply set Content-Type {text/html; charset=UTF-8}
        set mdtxt  [::fileutil::cat $local_file]
        my puts [::Markdown::convert $mdtxt]
      }
      .png {
        my reply set Content-Type {image/png}
        set reply_file $local_file
      }
      .svgz -
      .svg {
        # FU magic screws it up
        my reply set Content-Type {image/svg+xml}
        set reply_file $local_file
      }
      .tcl {
        my reply set Content-Type {text/html; charset=UTF-8}
        try {
          source $local_file
        } on error {err errdat} {
          my error 500 {Internal Error} [dict get $errdat -errorinfo]
        }
      }
      .tiff {
        my reply set Content-Type {image/tiff}
        set reply_file $local_file
      }
      .tml {
        my reply set Content-Type {text/html; charset=UTF-8}
        set tmltxt  [::fileutil::cat $local_file]
        set headers [my request dump]
        dict with headers {}
        my puts [subst $tmltxt]
      }
      .txt {
        my reply set Content-Type {text/plain}
        set reply_file $local_file
      }
      .webp {
        my reply set Content-Type {image/webp}
        set reply_file $local_file
      }
      default {
        ###
        # Assume we are returning a binary file
        ###
        my reply set Content-Type [::fileutil::magic::filetype $local_file]
        set reply_file $local_file
      }
    }
  }
  method Dispatch {} {

    my variable reply_body reply_file reply_chan chan
    try {







      my reset
      # Invoke the URL implementation.
      my content
    } on error {err errdat} {
      my error 500 $err [dict get $errdat -errorinfo]
      catch {
        tailcall my DoOutput
      }
    }
    if {$chan eq {}} return
    catch {
      # Causing random issues. Technically a socket is always open for read and write
      # anyway
      #my wait writable $chan
      if {![info exists reply_file]} {
        tailcall my DoOutput
      }

      chan configure $chan  -translation {binary binary}
      my log HttpAccess {}
      ###
      # Return a stream of data from a file
      ###
      set size [file size $reply_file]
      my reply set Content-Length $size
      append result [my reply output] \n
      chan puts -nonewline $chan $result
      set reply_chan [open $reply_file r]
      my ChannelRegister $reply_chan
      my log SendReply [list length $size]

      ###
      # Output the file contents. With no -size flag, channel will copy until EOF









      ###
      chan configure $reply_chan -translation {binary binary} -buffersize 4096 -buffering full -blocking 0
      if {$size < 40960} {
        # Raw copy small files
        chan copy $reply_chan $chan
      } else {
        my ChannelCopy $reply_chan $chan -chunk 4096
      }
    }
  }
}

###
# END: file.tcl
###
###
# START: proxy.tcl
###
::clay::define ::httpd::content.exec {
  variable exename [list tcl [info nameofexecutable] .tcl [info nameofexecutable]]

  method CgiExec {execname script arglist} {
    if { $::tcl_platform(platform) eq "windows"} {
      if {[file extension $script] eq ".exe"} {
        return [open "|[list $script] $arglist" r+]
      } else {
        if {$execname eq {}} {
          set execname [my Cgi_Executable $script]
        }
        return [open "|[list $execname $script] $arglist" r+]
      }
    } else {
      if {$execname eq {}} {
        return [open "|[list $script] $arglist 2>@1" r+]
      } else {
        return [open "|[list $execname $script] $arglist 2>@1" r+]
      }
    }
    error "CGI Not supported"
  }

  method Cgi_Executable {script} {
    if {[string tolower [file extension $script]] eq ".exe"} {
      return $script
    }
    my variable exename
    set ext [file extension $script]
    if {$ext eq {}} {
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
        return $result
      }
    }
    if {[dict exists exename $which]} {
      return [dict get $exename $which]
    }
    if {$which eq "tcl"} {
      if {[my cget tcl_exe] ne {}} {
        dict set exename $which [my cget tcl_exe]
      } else {
        dict set exename $which [info nameofexecutable]
      }
    } else {
      if {[my cget ${which}_exe] ne {}} {
        dict set exename $which [my cget ${which}_exe]
      } elseif {"$::tcl_platform(platform)" == "windows"} {
        dict set exename $which $which.exe
      } else {
        dict set exename $which $which
      }
    }
    set result [dict get $exename $which]
    if {$ext ne {}} {
      dict set exename $ext $result
    }
    return $result
  }
}

###
# Return data from an proxy process
###
::tool::define ::httpd::content.proxy {
  superclass ::httpd::content.exec

  method proxy_channel {} {
    ###
    # This method returns a channel to the
    # proxied socket/stdout/etc
    ###
    error unimplemented
  }

  method proxy_path {} {
    set uri [string trimleft [my http_info get REQUEST_URI] /]
    set prefix [my http_info get prefix]
    return /[string range $uri [string length $prefix] end]
  }

  method ProxyRequest {chana chanb} {
    chan event $chanb writable {}
    my log ProxyRequest {}
    chan puts $chanb "[my http_info get REQUEST_METHOD] [my proxy_path]"

    chan puts $chanb [my http_info get mimetxt]
    set length [my http_info get CONTENT_LENGTH]
    if {$length} {
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      ###
      # Send any POST/PUT/etc content
      ###
      chan copy $chana $chanb -size $length -command [info coroutine]
    } else {
      chan flush $chanb
      chan event $chanb readable [info coroutine]
    }

    yield
  }

  method ProxyReply {chana chanb args} {
    my log ProxyReply [list args $args]
    chan event $chana readable {}
    set readCount [::coroutine::util::gets_safety $chana 4096 reply_status]
    set replyhead [my HttpHeaders $chana]
    set replydat  [my MimeParse $replyhead]
    if {![dict exists $replydat Content-Length]} {
      set length 0
    } else {
      set length [dict get $replydat Content-Length]
    }
    ###
    # Read the first incoming line as the HTTP reply status
    # Return the rest of the headers verbatim
    ###
    set replybuffer "$reply_status\n"
    append replybuffer $replyhead
    chan configure $chanb -translation {auto crlf} -blocking 0 -buffering full -buffersize 4096
    chan puts $chanb $replybuffer
    my log SendReply [list length $length]
    if {$length} {
      ###
      # Output the body
      ###
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      chan copy $chana $chanb -size $length -command [namespace code [list my TransferComplete $chana $chanb]]
    } else {
      my TransferComplete $chana $chanb
    }
  }

  method dispatch {newsock datastate} {
    try {
      my http_info replace $datastate
      my request replace  [dict get $datastate http]
      my Log_Dispatched
      my variable sock chan
      set chan $newsock
      chan configure $chan -translation {auto crlf} -buffering line
      # Initialize the reply
      my reset
      # Invoke the URL implementation.
    } on error {err errdat} {
      my error 500 $err [dict get $errdat -errorinfo]
      tailcall my DoOutput
    }
    if {[catch {my proxy_channel} sock errdat]} {
      my error 504 {Service Temporarily Unavailable} [dict get $errdat -errorinfo]
      tailcall my DoOutput
    }
    if {$sock eq {}} {
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    my log HttpAccess {}
    chan event $sock writable [info coroutine]
    yield

    my ProxyRequest $chan $sock
    my ProxyReply   $sock $chan
  }
}

###
# END: proxy.tcl
###
###
# START: cgi.tcl
###
::tool::define ::httpd::content.cgi {
  superclass ::httpd::content.proxy

  method FileName {} {
    set uri [string trimleft [my http_info get REQUEST_URI] /]
    set path [my http_info get path]
    set prefix [my http_info get prefix]

    set fname [string range $uri [string length $prefix] end]
    if {[file exists [file join $path $fname]]} {
      return [file join $path $fname]
    }
    if {[file exists [file join $path $fname.fossil]]} {
      return [file join $path $fname.fossil]
    }
    if {[file exists [file join $path $fname.fos]]} {
      return [file join $path $fname.fos]
    }
    if {[file extension $fname] in {.exe .cgi .tcl .pl .py .php}} {
      return $fname
    }
    return {}
  }

  method proxy_channel {} {
    ###
    # When delivering static content, allow web caches to save
    ###
    set local_file [my FileName]
    if {$local_file eq {} || ![file exist $local_file]} {
      my log httpNotFound [my http_info get REQUEST_URI]
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    if {[file isdirectory $local_file]} {
      ###
      # Produce an index page... or error
      ###







|
|




|
|













<
<
<
<
|

<







<

|
|


<



|
>
|
|






|


<

>


<






<
<
<
<
|








<
<
|
|
|
|
|
<
<
|
|
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<











>











|

<

|
|
|
















<






|







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
        return $result
      }
    }
    if {[dict exists exename $which]} {
      return [dict get $exename $which]
    }
    if {$which eq "tcl"} {
      if {[my clay get tcl_exe] ne {}} {
        dict set exename $which [my clay get tcl_exe]
      } else {
        dict set exename $which [info nameofexecutable]
      }
    } else {
      if {[my clay get ${which}_exe] ne {}} {
        dict set exename $which [my clay get ${which}_exe]
      } elseif {"$::tcl_platform(platform)" == "windows"} {
        dict set exename $which $which.exe
      } else {
        dict set exename $which $which
      }
    }
    set result [dict get $exename $which]
    if {$ext ne {}} {
      dict set exename $ext $result
    }
    return $result
  }
}




::clay::define ::httpd::content.proxy {
  superclass ::httpd::content.exec

  method proxy_channel {} {
    ###
    # This method returns a channel to the
    # proxied socket/stdout/etc
    ###
    error unimplemented
  }

  method proxy_path {} {
    set uri [string trimleft [my request get REQUEST_URI] /]
    set prefix [my clay get prefix]
    return /[string range $uri [string length $prefix] end]
  }

  method ProxyRequest {chana chanb} {
    chan event $chanb writable {}
    my log ProxyRequest {}
    chan puts $chanb "[my request get REQUEST_METHOD] [my proxy_path]"
    set mimetxt [my clay get mimetxt]
    chan puts $chanb [my clay get mimetxt]
    set length [my request get CONTENT_LENGTH]
    if {$length} {
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      ###
      # Send any POST/PUT/etc content
      ###
      my ChannelCopy $chana $chanb -size $length
    } else {
      chan flush $chanb

    }
    chan event $chanb readable [info coroutine]
    yield
  }

  method ProxyReply {chana chanb args} {
    my log ProxyReply [list args $args]
    chan event $chana readable {}
    set readCount [::coroutine::util::gets_safety $chana 4096 reply_status]
    set replyhead [my HttpHeaders $chana]
    set replydat  [my MimeParse $replyhead]





    ###
    # Read the first incoming line as the HTTP reply status
    # Return the rest of the headers verbatim
    ###
    set replybuffer "$reply_status\n"
    append replybuffer $replyhead
    chan configure $chanb -translation {auto crlf} -blocking 0 -buffering full -buffersize 4096
    chan puts $chanb $replybuffer


    ###
    # Output the body. With no -size flag, channel will copy until EOF
    ###
    chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
    chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096


    my ChannelCopy $chana $chanb -chunk 4096
  }






  method Dispatch {} {
    my variable sock chan









    if {[catch {my proxy_channel} sock errdat]} {
      my error 504 {Service Temporarily Unavailable} [dict get $errdat -errorinfo]
      tailcall my DoOutput
    }
    if {$sock eq {}} {
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    my log HttpAccess {}
    chan event $sock writable [info coroutine]
    yield
    my ChannelRegister $sock
    my ProxyRequest $chan $sock
    my ProxyReply   $sock $chan
  }
}

###
# END: proxy.tcl
###
###
# START: cgi.tcl
###
::clay::define ::httpd::content.cgi {
  superclass ::httpd::content.proxy

  method FileName {} {
    set uri [string trimleft [my request get REQUEST_PATH] /]
    set path [my clay get path]
    set prefix [my clay get prefix]

    set fname [string range $uri [string length $prefix] end]
    if {[file exists [file join $path $fname]]} {
      return [file join $path $fname]
    }
    if {[file exists [file join $path $fname.fossil]]} {
      return [file join $path $fname.fossil]
    }
    if {[file exists [file join $path $fname.fos]]} {
      return [file join $path $fname.fos]
    }
    if {[file extension $fname] in {.exe .cgi .tcl .pl .py .php}} {
      return $fname
    }
    return {}
  }

  method proxy_channel {} {
    ###
    # When delivering static content, allow web caches to save
    ###
    set local_file [my FileName]
    if {$local_file eq {} || ![file exist $local_file]} {
      my log httpNotFound [my request get REQUEST_PATH]
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    if {[file isdirectory $local_file]} {
      ###
      # Produce an index page... or error
      ###
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
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713

1714
1715
1716
1717
1718

1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773

1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786

1787


1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818


1819
1820
1821
1822
1823



1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848

1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862

1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935

1936
1937
1938
1939

1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987






1988

1989







1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048

2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103



2104




2105
2106
2107
2108
    }
    foreach item $verbatim {
      set ::env($item) {}
    }
    foreach item [array names ::env HTTP_*] {
      set ::env($item) {}
    }
    set ::env(SCRIPT_NAME) [my http_info get REQUEST_PATH]
    set ::env(SERVER_PROTOCOL) HTTP/1.0
    set ::env(HOME) $::env(DOCUMENT_ROOT)
    foreach {f v} [my http_info dump] {
      if {$f in $verbatim} {
        set ::env($f) $v
      }
    }
  	set arglist $::env(QUERY_STRING)
    set pwd [pwd]
    cd [file dirname $local_file]
    foreach {f v} [my request dump] {
      if {$f in $verbatim} {
        set ::env($f) $v
      } else {
        set ::env(HTTP_$f) $v
      }
    }
    set script_file $local_file
    if {[file extension $local_file] in {.fossil .fos}} {
      if {![file exists $local_file.cgi]} {
        set fout [open $local_file.cgi w]
        chan puts $fout "#!/usr/bin/fossil"
        chan puts $fout "repository: $local_file"
        close $fout
      }
      set script_file $local_file.cgi
      set EXE [my Cgi_Executable fossil]
    } else {
      set EXE [my Cgi_Executable $local_file]
    }
    set ::env(PATH_TRANSLATED) $script_file
    set pipe [my CgiExec $EXE $script_file $arglist]
    cd $pwd
    return $pipe
  }

  method ProxyRequest {chana chanb} {
    chan event $chanb writable {}
    my log ProxyRequest {}
    set length [my http_info get CONTENT_LENGTH]
    if {$length} {
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      ###
      # Send any POST/PUT/etc content
      ###
      chan copy $chana $chanb -size $length -command [info coroutine]
    } else {
      chan flush $chanb
      chan event $chanb readable [info coroutine]
    }


    yield

  }


  method ProxyReply {chana chanb args} {
    my log ProxyReply [list args $args]
    chan event $chana readable {}
    set replyhead [my HttpHeaders $chana]
    set replydat  [my MimeParse $replyhead]
    if {![dict exists $replydat Content-Length]} {
      set length 0
    } else {
      set length [dict get $replydat Content-Length]
    }
    ###
    # Convert the Status: header from the CGI process to
    # a standard service reply line from a web server, but
    # otherwise spit out the rest of the headers verbatim
    ###
    set replybuffer "HTTP/1.0 [dict get $replydat Status]\n"
    append replybuffer $replyhead
    chan configure $chanb -translation {auto crlf} -blocking 0 -buffering full -buffersize 4096
    chan puts $chanb $replybuffer
    my log SendReply [list length $length]
    if {$length} {
      ###
      # Output the body
      ###
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      chan copy $chana $chanb -size $length -command [namespace code [list my TransferComplete $chana $chanb]]
    } else {
      my TransferComplete $chana $chanb
    }
  }

  ###
  # For most CGI applications a directory list is vorboten
  ###
  method DirectoryListing {local_file} {
    my error 403 {Not Allowed}
    tailcall my DoOutput
  }
}

###
# END: cgi.tcl
###
###
# START: scgi.tcl
###
###


# Return data from an SCGI process
###


::tool::define ::httpd::content.scgi {
  superclass ::httpd::content.proxy

  method scgi_info {} {
    ###
    # This method should check if a process is launched
    # or launch it if needed, and return a list of
    # HOST PORT SCRIPT_NAME
    ###
    # return {localhost 8016 /some/path}
    error unimplemented
  }

  method proxy_channel {} {
    set sockinfo [my scgi_info]
    if {$sockinfo eq {}} {
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    lassign $sockinfo scgihost scgiport scgiscript
    my http_info set SCRIPT_NAME $scgiscript
    if {![string is integer $scgiport]} {
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    return [::socket $scgihost $scgiport]
  }

  method ProxyRequest {chana chanb} {
    chan event $chanb writable {}
    my log ProxyRequest {}
    chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
    chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
    set info [dict create CONTENT_LENGTH 0 SCGI 1.0 SCRIPT_NAME [my http_info get SCRIPT_NAME]]
    foreach {f v} [my http_info dump] {
      dict set info $f $v
    }
    set length [dict get $info CONTENT_LENGTH]
    set block {}
    foreach {f v} $info {
      append block [string toupper $f] \x00 $v \x00
    }
    chan puts -nonewline $chanb "[string length $block]:$block,"
    # Light off another coroutine
    #set cmd [list coroutine [my CoroName] {*}[namespace code [list my ProxyReply $chanb $chana]]]
    if {$length} {
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      ###
      # Send any POST/PUT/etc content
      ###

      chan copy $chana $chanb -size $length -command [info coroutine]
    } else {
      chan flush $chanb
      chan event $chanb readable [info coroutine]
    }

    yield
  }

  method ProxyReply {chana chanb args} {
    my log ProxyReply [list args $args]
    chan event $chana readable {}
    set replyhead [my HttpHeaders $chana]
    set replydat  [my MimeParse $replyhead]
    if {![dict exists $replydat Content-Length]} {
      set length 0
    } else {
      set length [dict get $replydat Content-Length]
    }
    ###
    # Convert the Status: header from the CGI process to
    # a standard service reply line from a web server, but
    # otherwise spit out the rest of the headers verbatim
    ###
    set replybuffer "HTTP/1.0 [dict get $replydat Status]\n"
    append replybuffer $replyhead
    chan configure $chanb -translation {auto crlf} -blocking 0 -buffering full -buffersize 4096
    chan puts $chanb $replybuffer
    my log SendReply [list length $length]
    if {$length} {
      ###
      # Output the body
      ###
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      chan copy $chana $chanb -size $length -command [namespace code [list my TransferComplete $chana $chanb]]
    } else {
      my TransferComplete $chan $chanb
    }
  }
}

tool::define ::httpd::reply.scgi {
  superclass ::httpd::reply

  method EncodeStatus {status} {
    return "Status: $status"
  }
}

###
# Act as an  SCGI Server
###
tool::define ::httpd::server.scgi {
  superclass ::httpd::server

  property socket buffersize   32768
  property socket blocking     0
  property socket translation  {binary binary}

  property reply_class ::httpd::reply.scgi


  method Connect {uuid sock ip} {
    yield [info coroutine]
    chan event $sock readable {}
    chan configure $sock \
        -blocking 1 \
        -translation {binary binary} \
        -buffersize 4096 \
        -buffering none
    my counter url_hit
    try {
      # Read the SCGI request on byte at a time until we reach a ":"
      dict set query REQUEST_URI /

      dict set query REMOTE_ADDR     $ip


      set size {}
      while 1 {
        set char [::coroutine::util::read $sock 1]
        if {[chan eof $sock]} {
          catch {close $sock}
          return
        }
        if {$char eq ":"} break
        append size $char
      }
      # With length in hand, read the netstring encoded headers
      set inbuffer [::coroutine::util::read $sock [expr {$size+1}]]
      chan configure $sock -blocking 0 -buffersize 4096 -buffering full
      foreach {f v} [lrange [split [string range $inbuffer 0 end-1] \0] 0 end-1] {
        dict set query $f $v
        if {$f in {CONTENT_LENGTH CONTENT_TYPE}} {
          dict set query http $f $v
        } elseif {[string range $f 0 4] eq "HTTP_"} {
          dict set query http [string range $f 5 end] $v
        }
      }
      if {![dict exists $query REQUEST_PATH]} {
        set uri [dict get $query REQUEST_URI]
        set uriinfo [::uri::split $uri]
        dict set query REQUEST_PATH    [dict get $uriinfo path]
      }
      set reply [my dispatch $query]
      dict with query {}
      if {[llength $reply]} {
        if {[dict exists $reply class]} {
          set class [dict get $reply class]


        } else {
          set class [my cget reply_class]
        }
        set pageobj [$class create [namespace current]::reply$uuid [self]]
        if {[dict exists $reply mixin]} {



          oo::objdefine $pageobj mixin [dict get $reply mixin]
        }
        $pageobj dispatch $sock $reply
        my log HttpAccess $REQUEST_URI
      } else {
        try {
          my log HttpMissing $REQUEST_URI
          chan puts $sock "Status: 404 NOT FOUND"
          dict with query {}
          set body [subst [my template notfound]]
          chan puts $sock "Content-Length: [string length $body]"
          chan puts $sock {}
          chan puts $sock $body
        } on error {err errdat} {
          my <server> debug "FAILED ON 404: $err [dict get $errdat -errorinfo]"
        } finally {
          catch {chan event readable $sock {}}
          catch {chan event writeable $sock {}}
          catch {chan close $sock}
        }
      }
    } on error {err errdat} {
      try {
        my <server> debug [dict get $errdat -errorinfo]
        chan puts $sock "Status: 500 INTERNAL ERROR - scgi 298"

        dict with query {}
        set body [subst [my template internal_error]]
        chan puts $sock "Content-Length: [string length $body]"
        chan puts $sock {}
        chan puts $sock $body
        my log HttpError [list error [my http_info get REMOTE_ADDR] errorinfo [dict get $errdat -errorinfo]]
      } on error {err errdat} {
        my log HttpFatal [list error [my http_info get REMOTE_ADDR] errorinfo [dict get $errdat -errorinfo]]
        my <server> debug "Failed on 500: [dict get $errdat -errorinfo]""
      } finally {
        catch {chan event readable $sock {}}
        catch {chan event writeable $sock {}}
        catch {chan close $sock}
      }

    }
  }
}

###
# END: scgi.tcl
###
###
# START: websocket.tcl
###
###
# Upgrade a connection to a websocket
###
::tool::define ::httpd::content.websocket {

}

###
# END: websocket.tcl
###
###
# START: plugin.tcl
###
###
# httpd plugin template
###
tool::define ::httpd::plugin {
  ###
  # Any options will be saved to the local config file
  # to allow threads to pull up a snapshot of the object' configuration
  ###

  ###
  # Define a code snippet to run on plugin load
  ###
  meta set plugin load: {}

  ###
  # Define a code snippet to run within the object's Headers_Process method
  ###
  meta set plugin headers: {}

  ###
  # Define a code snippet to run within the object's dispatch method
  ###
  meta set plugin dispatch: {}

  ###
  # Define a code snippet to run within the object's writes a local config file
  ###
  meta set plugin local_config: {}

  ###
  # When after all the plugins are loaded
  # allow specially configured ones to light off a thread
  ###
  meta set plugin thread: {}

}

###
# A rudimentary plugin that dispatches URLs from a dict
# data structure
###
tool::define ::httpd::plugin.dict_dispatch {
  meta set plugin dispatch: {
    set reply [my Dispatch_Dict $data]
    if {[dict size $reply]} {
      return $reply
    }
  }

  method Dispatch_Dict {data} {

    set vhost [lindex [split [dict get $data HTTP_HOST] :] 0]
    set uri   [dict get $data REQUEST_PATH]
    foreach {host pattern info} [my uri patterns] {
      if {![string match $host $vhost]} continue

      if {![string match $pattern $uri]} continue
      set buffer $data
      foreach {f v} $info {
        dict set buffer $f $v
      }
      return $buffer
    }
    return {}
  }

  method uri::patterns {} {
    my variable url_patterns url_stream
    if {![info exists url_stream]} {
      set url_stream {}
      foreach {host hostpat} $url_patterns {
        foreach {pattern info} $hostpat {
          lappend url_stream $host $pattern $info
        }
      }
    }
    return $url_stream
  }

  method uri::add args {
    my variable url_patterns url_stream
    unset -nocomplain url_stream
    switch [llength $args] {
      2 {
        set vhosts *
        lassign $args patterns info
      }
      3 {
        lassign $args vhosts patterns info
      }
      default {
        error "Usage: add_url ?vhosts? prefix info"
      }
    }
    foreach vhost $vhosts {
      foreach pattern $patterns {
        set data $info
        if {![dict exists $data prefix]} {
           dict set data prefix [my PrefixNormalize $pattern]
        }
        dict set url_patterns $vhost [string trimleft $pattern /] $data
      }
    }
  }






}









tool::define ::httpd::reply.memchan {
  superclass ::httpd::reply

  method output {} {
    my variable reply_body
    return $reply_body
  }

  method DoOutput {} {}

  method close {} {
    # Neuter the channel closing mechanism we need the channel to stay alive
    # until the reader sucks out the info
  }
}


tool::define ::httpd::plugin.local_memchan {

  meta set plugin load: {
package require tcl::chan::events
package require tcl::chan::memchan
  }

  method local_memchan {command args} {
    my variable sock_to_coro
    switch $command {
      geturl {
        ###
        # Hook to allow a local process to ask for data without a socket
        ###
        set uuid [my Uuid_Generate]
        set ip 127.0.0.1
        set sock [::tcl::chan::memchan]
        set output [coroutine ::httpd::coro::$uuid {*}[namespace code [list my Connect_Local $uuid $sock GET {*}$args]]]
        return $output
      }
      default {
        error "Valid: connect geturl"
      }
    }
  }

  ###
  # A modified connection method that passes simple GET request to an object
  # and pulls data directly from the reply_body data variable in the object
  #
  # Needed because memchan is bidirectional, and we can't seem to communicate that
  # the server is one side of the link and the reply is another
  ###
  method Connect_Local {uuid sock args} {
    chan event $sock readable {}

    chan configure $sock \
      -blocking 0 \
      -translation {auto crlf} \
      -buffering line
    set ip 127.0.0.1
    dict set query UUID $uuid

    dict set query HTTP_HOST       localhost
    dict set query REMOTE_ADDR     127.0.0.1
    dict set query REMOTE_HOST     localhost
    dict set query LOCALHOST 1
    my counter url_hit

    dict set query REQUEST_METHOD  [lindex $args 0]
    set uriinfo [::uri::split [lindex $args 1]]
    dict set query REQUEST_URI     [lindex $args 1]
    dict set query REQUEST_PATH    [dict get $uriinfo path]
    dict set query REQUEST_VERSION [lindex [split [lindex $args end] /] end]
    dict set query DOCUMENT_ROOT   [my cget doc_root]
    dict set query QUERY_STRING    [dict get $uriinfo query]
    dict set query REQUEST_RAW     $args
    dict set query SERVER_PORT     [my port_listening]
    my Headers_Process query
    set reply [my dispatch $query]

    if {[llength $reply]==0} {
      my log BadLocation $uuid $query
      my log BadLocation $uuid $query
      dict set query HTTP_STATUS 404
      dict set query template notfound
      dict set query mixinmap reply ::httpd::content.template
    }

    set class ::httpd::reply.memchan
    set pageobj [$class create ::httpd::object::$uuid [self]]
    if {[dict exists $reply mixinmap]} {
      set mixinmap [dict get $reply mixinmap]
    } else {
      set mixinmap {}
    }
    if {[dict exists $reply mixin]} {
      dict set mixinmap reply [dict get $reply mixin]
    }
    foreach item [dict keys $reply MIXIN_*] {
      set slot [string range $reply 6 end]
      dict set mixinmap [string tolower $slot] [dict get $reply $item]
    }
    $pageobj mixinmap {*}$mixinmap
    if {[dict exists $reply organ]} {
      $pageobj graft {*}[dict get $reply organ]
    }
    $pageobj dispatch $sock $reply
    set output [$pageobj output]
    catch {$pageobj destroy}
    return $output
  }
}


###
# END: plugin.tcl
###








namespace eval ::httpd {
    namespace export *
}








|


|
<
|
<




<
<
<
<
<
<
<


















<



|






|


<

>
>

|
<
<
<



















<
<
|
|
|
|
|
|
<
|
|
<
<
<
<
<












<
>
>
|
<
>
>
|

<









<







|






<





|
|
















>
|


<

>


<





<
<
<
<
<









<
<
|
|
|
|
|
<
<
<
<
<
<
|
<
<
|
<
<
|
<
<
<
<
<
|

<
|
|
|
|
<
>
|











|
>
|
>
>












|

<
<
|
<
<
|
<
|
|

|


|
|
|
|
>
>
|
|
|
<
|
>
>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
>
|
<
<
<
|
<
|
|
|
|
|
|
|
<
>










<
<
<
|
<








<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
|
|
<
<
<
<
<
<
|
|





<

>
|
|
|

>
|
|
|
|
|
|
|
<
|
<
<
<
<
<
<
<
<
<
<
<
|

|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<










>
>
>
>
>
>
|
>

>
>
>
>
>
>
>
|

<




<

<





<
<
|
<
|



<


















<
<
<
<
<
<
<
<









>
|
|
|
|


|

|
|
|
|
|
|
|






|

|




|
|



<
<
<




|
|
|



|




<



>
>
>

>
>
>
>
|
|
|

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
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717

1718
1719
1720
1721

1722
1723
1724
1725
1726





1727
1728
1729
1730
1731
1732
1733
1734
1735


1736
1737
1738
1739
1740






1741


1742


1743





1744
1745

1746
1747
1748
1749

1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781


1782


1783

1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798

1799
1800
1801
1802
1803
1804




















1805


1806
1807



1808

1809
1810
1811
1812
1813
1814
1815

1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826



1827

1828
1829
1830
1831
1832
1833
1834
1835



1836








1837




1838




1839




1840





1841
1842






1843
1844
1845
1846
1847
1848
1849

1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863

1864











1865
1866
1867

1868













1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896

1897
1898
1899
1900

1901

1902
1903
1904
1905
1906


1907

1908
1909
1910
1911

1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929








1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972



1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987

1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
    }
    foreach item $verbatim {
      set ::env($item) {}
    }
    foreach item [array names ::env HTTP_*] {
      set ::env($item) {}
    }
    set ::env(SCRIPT_NAME) [my request get REQUEST_PATH]
    set ::env(SERVER_PROTOCOL) HTTP/1.0
    set ::env(HOME) $::env(DOCUMENT_ROOT)
    foreach {f v} [my request dump] {

      set ::env($f) $v

    }
  	set arglist $::env(QUERY_STRING)
    set pwd [pwd]
    cd [file dirname $local_file]







    set script_file $local_file
    if {[file extension $local_file] in {.fossil .fos}} {
      if {![file exists $local_file.cgi]} {
        set fout [open $local_file.cgi w]
        chan puts $fout "#!/usr/bin/fossil"
        chan puts $fout "repository: $local_file"
        close $fout
      }
      set script_file $local_file.cgi
      set EXE [my Cgi_Executable fossil]
    } else {
      set EXE [my Cgi_Executable $local_file]
    }
    set ::env(PATH_TRANSLATED) $script_file
    set pipe [my CgiExec $EXE $script_file $arglist]
    cd $pwd
    return $pipe
  }

  method ProxyRequest {chana chanb} {
    chan event $chanb writable {}
    my log ProxyRequest {}
    set length [my request get CONTENT_LENGTH]
    if {$length} {
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      ###
      # Send any POST/PUT/etc content
      ###
      my ChannelCopy $chana $chanb -size $length
    } else {
      chan flush $chanb

    }
    my clay refcount_incr
    chan event $chanb readable [info coroutine]
    yield
  }



  method ProxyReply {chana chanb args} {
    my log ProxyReply [list args $args]
    chan event $chana readable {}
    set replyhead [my HttpHeaders $chana]
    set replydat  [my MimeParse $replyhead]
    if {![dict exists $replydat Content-Length]} {
      set length 0
    } else {
      set length [dict get $replydat Content-Length]
    }
    ###
    # Convert the Status: header from the CGI process to
    # a standard service reply line from a web server, but
    # otherwise spit out the rest of the headers verbatim
    ###
    set replybuffer "HTTP/1.0 [dict get $replydat Status]\n"
    append replybuffer $replyhead
    chan configure $chanb -translation {auto crlf} -blocking 0 -buffering full -buffersize 4096
    chan puts $chanb $replybuffer


    ###
    # Output the body. With no -size flag, channel will copy until EOF
    ###
    chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
    chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
    my ChannelCopy $chana $chanb -chunk 4096

    my clay refcount_decr
  }





  method DirectoryListing {local_file} {
    my error 403 {Not Allowed}
    tailcall my DoOutput
  }
}

###
# END: cgi.tcl
###
###
# START: scgi.tcl
###

::clay::define ::httpd::protocol.scgi {
  method EncodeStatus {status} {
    return "Status: $status"

  }
}
::clay::define ::httpd::content.scgi {
  superclass ::httpd::content.proxy

  method scgi_info {} {
    ###
    # This method should check if a process is launched
    # or launch it if needed, and return a list of
    # HOST PORT SCRIPT_NAME
    ###
    # return {localhost 8016 /some/path}
    error unimplemented
  }

  method proxy_channel {} {
    set sockinfo [my scgi_info]
    if {$sockinfo eq {}} {
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    lassign $sockinfo scgihost scgiport scgiscript
    my clay set  SCRIPT_NAME $scgiscript
    if {![string is integer $scgiport]} {
      my error 404 {Not Found}
      tailcall my DoOutput
    }
    return [::socket $scgihost $scgiport]
  }

  method ProxyRequest {chana chanb} {
    chan event $chanb writable {}
    my log ProxyRequest {}
    chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
    chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
    set info [dict create CONTENT_LENGTH 0 SCGI 1.0 SCRIPT_NAME [my clay get SCRIPT_NAME]]
    foreach {f v} [my request dump] {
      dict set info $f $v
    }
    set length [dict get $info CONTENT_LENGTH]
    set block {}
    foreach {f v} $info {
      append block [string toupper $f] \x00 $v \x00
    }
    chan puts -nonewline $chanb "[string length $block]:$block,"
    # Light off another coroutine
    #set cmd [list coroutine [my CoroName] {*}[namespace code [list my ProxyReply $chanb $chana]]]
    if {$length} {
      chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
      chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096
      ###
      # Send any POST/PUT/etc content
      ###
      my ChannelCopy $chana $chanb -size $length
      #chan copy $chana $chanb -size $length -command [info coroutine]
    } else {
      chan flush $chanb

    }
    chan event $chanb readable [info coroutine]
    yield
  }

  method ProxyReply {chana chanb args} {
    my log ProxyReply [list args $args]
    chan event $chana readable {}
    set replyhead [my HttpHeaders $chana]
    set replydat  [my MimeParse $replyhead]





    ###
    # Convert the Status: header from the CGI process to
    # a standard service reply line from a web server, but
    # otherwise spit out the rest of the headers verbatim
    ###
    set replybuffer "HTTP/1.0 [dict get $replydat Status]\n"
    append replybuffer $replyhead
    chan configure $chanb -translation {auto crlf} -blocking 0 -buffering full -buffersize 4096
    chan puts $chanb $replybuffer


    ###
    # Output the body. With no -size flag, channel will copy until EOF
    ###
    chan configure $chana -translation binary -blocking 0 -buffering full -buffersize 4096
    chan configure $chanb -translation binary -blocking 0 -buffering full -buffersize 4096






    my ChannelCopy $chana $chanb -chunk 4096


  }


}





::clay::define ::httpd::server.scgi {
  superclass ::httpd::server

  clay set socket/ buffersize   32768
  clay set socket/ blocking     0
  clay set socket/ translation  {binary binary}
  method debug args {

    puts $args
  }
  method Connect {uuid sock ip} {
    yield [info coroutine]
    chan event $sock readable {}
    chan configure $sock \
        -blocking 1 \
        -translation {binary binary} \
        -buffersize 4096 \
        -buffering none
    my counter url_hit
    try {
      # Read the SCGI request on byte at a time until we reach a ":"
      dict set query http HTTP_HOST {}
      dict set query http CONTENT_LENGTH 0
      dict set query http REQUEST_URI /
      dict set query http REMOTE_ADDR $ip
      dict set query http DOCUMENT_ROOT [my clay get server/ doc_root]
      set size {}
      while 1 {
        set char [::coroutine::util::read $sock 1]
        if {[chan eof $sock]} {
          catch {close $sock}
          return
        }
        if {$char eq ":"} break
        append size $char
      }
      # With length in hand, read the netstring encoded headers
      set inbuffer [::coroutine::util::read $sock [expr {$size+1}]]
      chan configure $sock -translation {auto crlf} -blocking 0 -buffersize 4096 -buffering full
      foreach {f v} [lrange [split [string range $inbuffer 0 end-1] \0] 0 end-1] {


        dict set query http $f $v


      }

      if {![dict exists $query http REQUEST_PATH]} {
        set uri [dict get $query http REQUEST_URI]
        set uriinfo [::uri::split $uri]
        dict set query http REQUEST_PATH    [dict get $uriinfo path]
      }
      set reply [my dispatch $query]
    } on error {err errdat} {
      my debug [list uri: [dict getnull $query http REQUEST_URI] ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      my log BadRequest $uuid [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      catch {chan puts $sock "HTTP/1.0 400 Bad Request (The data is invalid)"}
      catch {chan event readable $sock {}}
      catch {chan event writeable $sock {}}
      catch {chan close $sock}
      return
    }

    if {[dict size $reply]==0} {
      my log BadLocation $uuid $query
      dict set query http HTTP_STATUS 404
      dict set query template notfound
      dict set query mixin reply ::httpd::content.template
    }




















    try {


      set pageobj [::httpd::reply create ::httpd::object::$uuid [self]]
      dict set reply mixin protocol ::httpd::protocol.scgi



      $pageobj dispatch $sock $reply

    } on error {err errdat} {
      my debug [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      my log BadRequest $uuid [list ip: $ip error: $err errorinfo: [dict get $errdat -errorinfo]]
      $pageobj clay refcount_decr
      catch {chan event readable $sock {}}
      catch {chan event writeable $sock {}}
      catch {chan close $sock}

      return
    }
  }
}

###
# END: scgi.tcl
###
###
# START: websocket.tcl
###



::clay::define ::httpd::content.websocket {

}

###
# END: websocket.tcl
###
###
# START: plugin.tcl
###



::clay::define ::httpd::plugin {








  clay set plugin/ load {}




  clay set plugin/ headers {}




  clay set plugin/ dispatch {}




  clay set plugin/ local_config {}





  clay set plugin/ thread {}
}






::clay::define ::httpd::plugin.dict_dispatch {
  clay set plugin/ dispatch {
    set reply [my Dispatch_Dict $data]
    if {[dict size $reply]} {
      return $reply
    }
  }

  method Dispatch_Dict {data} {
    my variable url_patterns
    set vhost [lindex [split [dict get $data http HTTP_HOST] :] 0]
    set uri   [dict get $data http REQUEST_PATH]
    foreach {host hostpat} $url_patterns {
      if {![string match $host $vhost]} continue
      foreach {pattern info} $hostpat {
        if {![string match $pattern $uri]} continue
        set buffer $data
        foreach {f v} $info {
          dict set buffer $f $v
        }
        return $buffer
      }

    }











    return {}
  }
  Ensemble uri::add {vhosts patterns info} {

    my variable url_patterns













    foreach vhost $vhosts {
      foreach pattern $patterns {
        set data $info
        if {![dict exists $data prefix]} {
           dict set data prefix [my PrefixNormalize $pattern]
        }
        dict set url_patterns $vhost [string trimleft $pattern /] $data
      }
    }
  }
  Ensemble uri::direct {vhosts patterns info body} {
    my variable url_patterns url_stream
    set cbody {}
    if {[dict exists $info superclass]} {
      append cbody \n "superclass {*}[dict get $info superclass]"
      dict unset info superclass
    }
    append cbody \n [list method content {} $body]

    set class [namespace current]::${vhosts}/${patterns}
    set class [string map {* %} $class]
    ::clay::define $class $cbody
    dict set info mixin content $class
    my uri add $vhosts $patterns $info
  }
}
::clay::define ::httpd::reply.memchan {
  superclass ::httpd::reply

  method output {} {
    my variable reply_body
    return $reply_body
  }

  method DoOutput {} {}

  method close {} {
    # Neuter the channel closing mechanism we need the channel to stay alive
    # until the reader sucks out the info
  }
}


::clay::define ::httpd::plugin.local_memchan {

  clay set plugin/ load {
package require tcl::chan::events
package require tcl::chan::memchan
  }

  method local_memchan {command args} {
    my variable sock_to_coro
    switch $command {
      geturl {
        ###
        # Hook to allow a local process to ask for data without a socket
        ###
        set uuid [my Uuid_Generate]
        set ip 127.0.0.1
        set sock [::tcl::chan::memchan]
        set output [coroutine ::httpd::coro::$uuid {*}[namespace code [list my Connect_Local $uuid $sock GET {*}$args]]]
        return $output
      }
      default {
        error "Valid: connect geturl"
      }
    }
  }








  method Connect_Local {uuid sock args} {
    chan event $sock readable {}

    chan configure $sock \
      -blocking 0 \
      -translation {auto crlf} \
      -buffering line
    set ip 127.0.0.1
    dict set query UUID $uuid
    dict set query http UUID $uuid
    dict set query http HTTP_HOST       localhost
    dict set query http REMOTE_ADDR     127.0.0.1
    dict set query http REMOTE_HOST     localhost
    dict set query http LOCALHOST 1
    my counter url_hit

    dict set query http REQUEST_METHOD  [lindex $args 0]
    set uriinfo [::uri::split [lindex $args 1]]
    dict set query http REQUEST_URI     [lindex $args 1]
    dict set query http REQUEST_PATH    [dict get $uriinfo path]
    dict set query http REQUEST_VERSION [lindex [split [lindex $args end] /] end]
    dict set query http DOCUMENT_ROOT   [my clay get server/ doc_root]
    dict set query http QUERY_STRING    [dict get $uriinfo query]
    dict set query http REQUEST_RAW     $args
    dict set query http SERVER_PORT     [my port_listening]
    my Headers_Process query
    set reply [my dispatch $query]

    if {[llength $reply]==0} {
      my log BadLocation $uuid $query
      my log BadLocation $uuid $query
      dict set query http HTTP_STATUS 404
      dict set query template notfound
      dict set query mixin reply ::httpd::content.template
    }

    set class ::httpd::reply.memchan
    set pageobj [$class create ::httpd::object::$uuid [self]]
    if {[dict exists $reply mixin]} {
      set mixinmap [dict get $reply mixin]
    } else {
      set mixinmap {}
    }



    foreach item [dict keys $reply MIXIN_*] {
      set slot [string range $reply 6 end]
      dict set mixinmap [string tolower $slot] [dict get $reply $item]
    }
    $pageobj clay mixinmap {*}$mixinmap
    if {[dict exists $reply delegate]} {
      $pageobj clay delegate {*}[dict get $reply delegate]
    }
    $pageobj dispatch $sock $reply
    set output [$pageobj output]
    $pageobj clay refcount_decr
    return $output
  }
}


###
# END: plugin.tcl
###
###
# START: cuneiform.tcl
###

###
# END: cuneiform.tcl
###

    namespace eval ::httpd {
	namespace export *
    }

Changes to modules/httpd/httpd.test.

1
2
3







4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47


48
49
50
51
52
53
54
55

56
57
58
59
60
61







62






























































































63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# httpd.test - Copyright (c) 2015 Sean Woods

# -------------------------------------------------------------------------








source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.6 ;# tool requires 8.6
testsNeedTcltest 2

testsNeed TclOO 1

support {
  use fileutil/fileutil.tcl fileutil
  use fumagic/rtcore.tcl fileutil::magic::rt
  use fumagic/filetypes.tcl fileutil::magic::filetype

  use textutil/string.tcl   textutil::string
  use textutil/repeat.tcl   textutil::repeat
  use textutil/tabify.tcl   textutil::tabify
  use markdown/markdown.tcl Markdown



  use cmdline/cmdline.tcl cmdline
  use fileutil/fileutil.tcl fileutil
  use sha1/sha1.tcl sha1
  use uri/uri.tcl uri
  use ncgi/ncgi.tcl ncgi
  use log/logger.tcl logger
  use base64/base64.tcl base64
  use md5/md5x.tcl md5
  use mime/mime.tcl mime
  use dns/ip.tcl ip
  use nettool/nettool.tcl nettool
  use coroutine/coroutine.tcl coroutine
  use uuid/uuid.tcl uuid

  use websocket/websocket.tcl websocket

  use dicttool/dicttool.tcl dicttool
  use cron/cron.tcl cron
  use oodialect/oodialect.tcl oo::dialect
  use oometa/oometa.tcl oo::meta
  use tool/tool.tcl tool
  use virtchannel_core/core.tcl tcl::chan::core
  use virtchannel_core/events.tcl tcl::chan::events
  use virtchannel_base/memchan.tcl tcl::chan::memchan


}

testing {
  useLocal httpd.tcl httpd
}

# Set to true for debugging and traces
set ::DEBUG 0


proc DEBUG args {
  if {$::DEBUG} {
    uplevel 1 $args
  }
}






































































































# -------------------------------------------------------------------------

namespace eval ::httpd {}
namespace eval ::httpd::test {}

###
# Minimal test harness for the .tests
# Not intended for public consumption
# (But if you find it handy, please steal!)
proc ::httpd::test::compare {actual correct} {
	set result {}
	set cbuf [split $correct \n]
	set abuf [split $actual \n]
	for {set i 0} {$i < [llength $cbuf]} {incr i} {
		set cline [string trim [lindex $cbuf $i]]
		set aline [string trim [lindex $abuf $i]]
		if {![string match $cline $aline]} {
			if {$cline ne $aline} {
				append result "Line $i differs [list $aline] != [list $cline]" \n
			}
		}
	}
  if {[llength $result]} {
  	puts [list ACTUAL $actual]
	  puts [list CORRECT $correct]
  }
	return $result
}

proc ::httpd::test::send {port http headers body} {
  set sock [socket localhost $port]
  variable reply
  set reply($sock) {}
  chan configure $sock -translation {crlf crlf} -blocking 0 -buffering full -buffersize 4096
  chan event $sock readable [list ::httpd::test::get_reply $sock]

	puts $sock $http
	if {![dict exists $headers Host]} {
	  dict set headers Host localhost
	}
	if {[string length $body]} {
		if {![dict exists $headers Content-Type]} {
			dict set headers Content_Type text/plain
		}
		dict set headers Content-Length [string length $body]
	}
	foreach {f v} $headers {
		puts $sock "${f}: $v"
	}
  puts $sock {}
	if {[string length $body]} {
    chan configure $sock -translation binary -blocking 0 -buffering full -buffersize 4096
		puts -nonewline $sock $body
	}
  flush $sock
  while {$reply($sock) eq {}} {
    update
  }
  #vwait [namespace current]::reply($sock)


  return $reply($sock)
}

proc ::httpd::test::get_reply {sock} {
  variable buffer
  set data [read $sock]
  append buffer($sock) $data
  if {[eof $sock]} {
    chan event $sock readable {}
    set [namespace current]::reply($sock) $buffer($sock)
    unset buffer($sock)
  }
}


tool::define ::httpd::server {
  method log args {}


  method TemplateSearch page {
    set doc_root [my cget doc_root]
    if {$doc_root ne {} && [file exists [file join $doc_root $page.tml]]} {
      return [::fileutil::cat [file join $doc_root $page.tml]]
    }
    if {$doc_root ne {} && [file exists [file join $doc_root $page.html]]} {
      return [::fileutil::cat [file join $doc_root $page.html]]
    }
    switch $page {
      redirect {



        return {404 Not Found}
      }
      internal_error {
        return {500 Server Internal Error}
      }
    }
  }


  ::DEBUG method debug args {
    puts stderr $args
  }

  ::DEBUG method log args {
    puts stdout $args
  }
}


###
# Modify the reply class to return plain text
###
tool::define ::httpd::reply {

  method HttpHeaders_Default {} {
    return {Status {200 OK}

    Content-Type {text/plain}
		Connection close}

  }

  method reset {} {
    my variable reply_body
    my reply replace [my HttpHeaders_Default]
    set reply_body {}
  }

  method error {code {msg {}} {errorInfo {}}} {
    my http_info set HTTP_ERROR $code
    my reset
    set errorstring [my http_code_string $code]
    set qheaders [my http_info dump]
    dict with qheaders {}
    my reply replace {}
    my reply set Status "$code $errorstring"
    my reply set Content-Type text/plain
    my puts "$code $errorstring"
  }
}

tool::define ::test::content.echo {
	method content {} {
		my variable reply_body
		set reply_body [my PostData [my request get CONTENT_LENGTH]]
		#puts [list REPLY BODY WAS $reply_body]
	}
}
tool::define ::test::content.file {
	superclass ::httpd::content.file
	method content {} {
	  my reset
    set doc_root [my http_info get doc_root]
    my variable reply_file
    set reply_file [file join $doc_root pkgIndex.tcl]
	}
}
tool::define ::test::content.time {
	method content {} {
		my variable reply_body
		set reply_body [clock seconds]
	}
}
tool::define ::test::content.error {
	method content {} {
		error {The programmer asked me to die this way}
	}
}
tool::define ::test::content.cgi {
	superclass ::httpd::content.cgi





}

tool::define ::httpd::test::reply {
	superclass ::httpd::reply ::test::content.echo
}

###
# Build the server
###
set DIR [file dirname [file normalize [info script]]]
set ::DEMOROOT $DIR

::httpd::server create TESTAPP port 10001
TESTAPP plugin dict_dispatch
TESTAPP uri add /     [list mixin ::test::content.echo]
TESTAPP uri add /echo [list mixin ::test::content.echo]
TESTAPP uri add /file [list mixin ::test::content.file doc_root $::DEMOROOT]
TESTAPP uri add /time [list mixin ::test::content.time]
TESTAPP uri add /error [list mixin ::test::content.error]


# Catch all
#TESTAPP uri add * [list mixin httpd::content.echo]

::DEBUG puts httpd-client-0001
test httpd-client-0001 {Do an echo request} {

set reply [::httpd::test::send 10001 {POST /echo HTTP/1.0} {} {THIS IS MY CODE}]
::httpd::test::compare $reply {HTTP/1.0 200 OK
Content-Type: text/plain
Connection: close
Content-Length: *

THIS IS MY CODE}
} {}

::DEBUG puts httpd-client-0002
test httpd-client-0002 {Do another echo request} {
set reply [::httpd::test::send 10001 {POST /echo HTTP/1.0} {} {THOUGH THERE ARE MANY LIKE IT}]
::httpd::test::compare $reply {HTTP/1.0 200 OK
Content-Type: text/plain
Connection: close
Content-Length: 29

THOUGH THERE ARE MANY LIKE IT}
} {}

::DEBUG puts httpd-client-0003
test httpd-client-0003 {Do another echo request} {
set reply [::httpd::test::send 10001 {POST /echo HTTP/1.0} {} {THIS ONE ALONE IS MINE}]
::httpd::test::compare $reply {HTTP/1.0 200 OK
Content-Type: text/plain
Connection: close
Content-Length: *

THIS ONE ALONE IS MINE}
}  {}

::DEBUG puts httpd-client-0004
test httpd-client-0004 {URL Generates Error} {

set reply [::httpd::test::send 10001 {POST /error HTTP/1.0} {} {THIS ONE ALONE IS MINE}]

::httpd::test::compare $reply {HTTP/1.0 500 Server Internal Error
Content-Type: text/plain
Connection: close
Content-Length: *

500 Server Internal Error}
} {}

set checkreply [subst {HTTP/1.0 200 OK
Content-Type: text/plain
Connection: close
Content-Length: *

[clock seconds]}]

::DEBUG puts httpd-client-0005
test httpd-client-0005 {URL Different output with a different request} {
set reply [::httpd::test::send 10001 {POST /time HTTP/1.0} {} {THIS ONE ALONE IS MINE}]
::httpd::test::compare $reply $checkreply
} {}

set fin [open [file join $DEMOROOT pkgIndex.tcl] r]
set replyfile [read $fin]
close $fin
set checkreply "HTTP/1.0 200 OK
Content-Type: text/plain
Connection: close
Content-Length: [string length $replyfile]

$replyfile"

::DEBUG puts httpd-client-0006
test httpd-client-0006 {Return a file} {
set reply [::httpd::test::send 10001 {GET /file HTTP/1.0} {} {}]
::httpd::test::compare $reply $checkreply
} {}










# -------------------------------------------------------------------------
# Test proxies

tool::define ::test::content.proxy {
	superclass ::httpd::content.proxy


  method proxy_channel {} {
    return [::socket localhost [my http_info get proxy_port]]
  }
}


::httpd::server create TESTPROXY port 10002
TESTAPP   uri add /proxy*     [list mixin ::test::content.proxy proxy_port [TESTPROXY port_listening]]
TESTPROXY plugin dict_dispatch
TESTPROXY uri add /     [list mixin ::test::content.echo]
TESTPROXY uri add /echo [list mixin ::test::content.echo]
TESTPROXY uri add /file [list mixin ::test::content.file doc_root $::DEMOROOT]
TESTPROXY uri add /time [list mixin ::test::content.time]
TESTPROXY uri add /error [list mixin ::test::content.error]













::DEBUG puts httpd-proxy-0001
test httpd-proxy-0001 {Do an echo request} {

set reply [::httpd::test::send 10001 {POST /proxy/echo HTTP/1.0} {} {THIS IS MY CODE}]
::httpd::test::compare $reply {HTTP/1.0 200 OK
Content-Type: text/plain
Connection: close
Content-Length: *

THIS IS MY CODE}
} {}

::DEBUG puts httpd-proxy-0002
test httpd-proxy-0002 {Do another echo request} {
set reply [::httpd::test::send 10001 {POST /proxy/echo HTTP/1.0} {} {THOUGH THERE ARE MANY LIKE IT}]
::httpd::test::compare $reply {HTTP/1.0 200 OK
Content-Type: text/plain
Connection: close
Content-Length: 29

THOUGH THERE ARE MANY LIKE IT}
} {}

::DEBUG puts httpd-proxy-0003
test httpd-proxy-0003 {Do another echo request} {
set reply [::httpd::test::send 10001 {POST /proxy/echo HTTP/1.0} {} {THIS ONE ALONE IS MINE}]
::httpd::test::compare $reply {HTTP/1.0 200 OK
Content-Type: text/plain
Connection: close
Content-Length: *

THIS ONE ALONE IS MINE}
}  {}

::DEBUG puts httpd-proxy-0004
test httpd-proxy-0004 {URL Generates Error} {

set reply [::httpd::test::send 10001 {POST /proxy/error HTTP/1.0} {} {THIS ONE ALONE IS MINE}]

::httpd::test::compare $reply {HTTP/1.0 500 Server Internal Error
Content-Type: text/plain
Connection: close
Content-Length: *

500 Server Internal Error}
} {}

set checkreply [subst {HTTP/1.0 200 OK
Content-Type: text/plain
Connection: close
Content-Length: *

[clock seconds]}]

::DEBUG puts httpd-proxy-0005
test httpd-proxy-0005 {URL Different output with a different request} {
set reply [::httpd::test::send 10001 {POST /proxy/time HTTP/1.0} {} {THIS ONE ALONE IS MINE}]
::httpd::test::compare $reply $checkreply
} {}

set fin [open [file join $DEMOROOT pkgIndex.tcl] r]
set replyfile [read $fin]
close $fin
set checkreply "HTTP/1.0 200 OK
Content-Type: text/plain
Connection: close
Content-Length: [string length $replyfile]

$replyfile"

::DEBUG puts httpd-proxy-0006
test httpd-proxy-0006 {Return a file} {
set reply [::httpd::test::send 10001 {GET /proxy/file HTTP/1.0} {} {}]
::httpd::test::compare $reply $checkreply
} {}





# -------------------------------------------------------------------------
# cgi
TESTAPP plugin local_memchan

TESTAPP uri add /cgi-bin* [list mixin ::test::content.cgi path $::DEMOROOT]

set fout [open [file join $DIR test.tcl] w]
puts $fout {#!/usr/bin/tclsh

puts stdout "Status: 200 OK"
if {$::env(CONTENT_LENGTH) > 0} {
  puts stdout "Content-Type: $::env(CONTENT_TYPE)"
  set dat [read stdin $::env(CONTENT_LENGTH)]
} else {
  puts stdout "Content-Type: text/plain"
  set dat "Hi!"
}
puts stdout "Content-Length: [string length $dat]"
puts stdout {}
puts stdout $dat
exit 0
}
close $fout

::DEBUG puts httpd-cgi-0001
test httpd-cgi-0001 {CGI Post} {

set reply [::httpd::test::send 10001 {POST /cgi-bin/test.tcl HTTP/1.0} {} {THIS IS MY CODE}]
::httpd::test::compare $reply {HTTP/1.0 200 OK
Status: 200 OK
Content-Type: text/plain
Content-Length: *

THIS IS MY CODE}
} {}

::DEBUG puts httpd-cgi-0002
test httpd-cgi-0002 {CGI Get} {

set reply [::httpd::test::send 10001 {GET /cgi-bin/test.tcl HTTP/1.0} {} {}]
::httpd::test::compare $reply {HTTP/1.0 200 OK
Status: 200 OK
Content-Type: text/plain
Content-Length: *

Hi!}
} {}

###
# Test the local geturl method
###
set now [clock seconds]
set dat [TESTAPP local_memchan geturl /time]
test httpd-memchan-0001 {Memchan GET} {
  TESTAPP local_memchan geturl /time
} $now

# -------------------------------------------------------------------------
namespace eval ::scgi {}
namespace eval ::scgi::test {}

###
# Minimal test harness for the .tests
# Not intended for public consumption
# (But if you find it handy, please steal!)
namespace eval ::scgi::test {}

proc ::scgi::encode_request {headers body info} {
  variable server_block

  dict set outdict CONTENT_LENGTH [string length $body]
  set outdict [dict merge $outdict $server_block $info]
  dict set outdict PWD [pwd]

  foreach {key value} $headers {
    if {$key in {
      DOCUMENT_ROOT
      HTTPS
      PATH
      REQUEST_METHOD REQUEST_URI
      REMOTE_HOST REMOTE_ADDR REMOTE_PORT
      SCRIPT_NAME
    } || [string range $key 0 5] eq "HTTP_"} {
      dict set outdict $key $value
    } else {
      dict set outdict HTTP_[string map {"-" "_"} [string toupper $key]] $value
    }
  }
  set result {}
  foreach {name value} $outdict {
    append result $name \x00 $value \x00
  }
  return "[string length $result]:$result,"
}

proc ::scgi::test::send {port headers body} {
  set sock [socket localhost $port]
  variable reply
  set reply($sock) {}

  if {![dict exists $headers HOST]} {
    dict set headers HOST localhost
  }
  dict set headers REMOTE_IP 127.0.0.1
  dict set headers REMOTE_HOST localhost

  chan configure $sock -translation binary -blocking 0 -buffering full -buffersize 4096
  chan event $sock readable [list ::scgi::test::get_reply $sock]

  set block [::scgi::encode_request $headers $body {}]

  puts -nonewline $sock $block
  flush $sock
  puts -nonewline $sock $body
  flush $sock

  while {$reply($sock) eq {}} {
    update
  }

  #vwait [namespace current]::reply($sock)


  return $reply($sock)
}

proc ::scgi::test::get_reply {sock} {
  variable buffer
  set data [read $sock]
  append buffer($sock) $data
  if {[eof $sock]} {
    chan event $sock readable {}
    set [namespace current]::reply($sock) $buffer($sock)
    unset buffer($sock)
  }
}

namespace eval ::scgi {
  variable server_block {SCGI 1.0 SERVER_SOFTWARE {TclScgiServer/0.1}}
}

###
# Build the reply class
###

tool::class create ::scgi::test::reply {
  superclass ::httpd::reply.scgi

  method reset {} {
    my variable reply_body
    my reply replace [my HttpHeaders_Default]
    set reply_body {}
  }
}

###
# Build the server
###

tool::class create scgi::test::app {
  superclass ::httpd::server.scgi

  property reply_class ::scgi::test::reply
}



scgi::test::app create TESTSCGI port 10003

TESTSCGI plugin dict_dispatch
TESTSCGI uri add /     [list mixin ::test::content.echo]
TESTSCGI uri add /echo [list mixin ::test::content.echo]
TESTSCGI uri add /file [list mixin ::test::content.file doc_root $::DEMOROOT]
TESTSCGI uri add /time [list mixin ::test::content.time]
TESTSCGI uri add /error [list mixin ::test::content.error]


::DEBUG puts scgi-client-0001
test scgi-client-0001 {Do an echo request} {

set reply [::scgi::test::send 10003 {REQUEST_METHOD POST REQUEST_URI /echo} {THIS IS MY CODE}]
set checkreply {Status: 200 OK
Content-Type: text/plain
Connection: close
Content-Length: *

THIS IS MY CODE}
::httpd::test::compare $reply $checkreply
} {}

::DEBUG puts scgi-client-0002
test scgi-client-0002 {Do another echo request} {
set reply [::scgi::test::send 10003 {REQUEST_METHOD POST REQUEST_URI /echo} {THOUGH THERE ARE MANY LIKE IT}]
set checkreply {Status: 200 OK
Content-Type: text/plain
Connection: close
Content-Length: *

THOUGH THERE ARE MANY LIKE IT}
::httpd::test::compare $reply $checkreply
} {}

::DEBUG puts scgi-client-0003
test scgi-client-0003 {Do another echo request} {
set reply [::scgi::test::send 10003 {REQUEST_METHOD POST REQUEST_URI /echo} {THIS ONE ALONE IS MINE}]
set checkreply {Status: 200 OK
Content-Type: text/plain
Connection: close
Content-Length: *

THIS ONE ALONE IS MINE}
::httpd::test::compare $reply $checkreply
} {}

::DEBUG puts scgi-client-0004
test scgi-client-0004 {URL Generates Error} {

set reply [::scgi::test::send 10003 {REQUEST_METHOD POST REQUEST_URI /error} {THIS ONE ALONE IS MINE}]

set checkreply {Status: 500 Server Internal Error
Content-Type: text/plain
Connection: close
Content-Length: *

500 Server Internal Error
}
::httpd::test::compare $reply $checkreply
} {}

set checkreply [subst {Status: 200 OK
Content-Type: text/plain
Connection: close
Content-Length: *

[clock seconds]}]

::DEBUG puts scgi-client-0005
test scgi-client-0005 {URL Different output with a different request} {
set reply [::scgi::test::send 10003 {REQUEST_METHOD POST REQUEST_URI /time} {THIS ONE ALONE IS MINE}]

::httpd::test::compare $reply $checkreply
} {}

set fin [open [file join $DEMOROOT pkgIndex.tcl] r]
set checkfile [read $fin]
close $fin

::DEBUG puts scgi-client-0006
test scgi-client-0006 {Return a file} {
set reply [::scgi::test::send 10003 {REQUEST_METHOD GET REQUEST_URI /file} {}]


set checkreply "Status: 200 OK
Content-Type: text/plain
Connection: close
Content-Length: [string length $checkfile]









$checkfile"
::httpd::test::compare $reply $checkreply
} {}

::DEBUG puts all-tests-finished
file delete test.tcl
# -------------------------------------------------------------------------

testsuiteCleanup

# Local variables:
# mode: tcl
# indent-tabs-mode: nil



>
>
>
>
>
>
>
|
|
<
<



|



<
|
|
|
<
|
|
|
|
>
>
|
|
|
|
|
|
|
|
<
|
<
<
<
|
<
|
|
|
<
<
<
|
|
|
>
>



|




>


|

|
|
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|



|
|
|
|
|
|
|
|


<
|
|

<
|
|
|
|
|
|
|
|
|
|
>
>
>
|
|
|
|
|
|
|

>
|
|
|

|
|
|






|

|
|
>
|
|
>
|

|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|


|
|
|
|
|
|

|
|
|
|
|
|
|
|

|
|
|
|
|

|
|
|
|

|
|
|
>
>
>
>
|
|
|
|





<
<

|

|
|
|
|
|
>


|


|
<
|
<
<
<
<
<
|
<



|
<
<
<
<
<
|
<


|
|
<
<
<
<
<
|
<


|
<
|
|
<
<
<
<

<
<
<
<
<
<
<
<
<
<

|
|
<
<
|
<
<
<
<
<
<
<
<
<


|
|
<
|

>
>
>
>

>
>
>
>



|
|

<
|
|
|


<
|
|

|
|
|
|
|
>

>
>
>
>
>
>
>
>
>
>
>

|
<
|
<
<
<
<
<
|
<


|
|
<
<
<
<
<
|
<


|
|
<
<
<
<
<
|
<


|
<
|
|
<
<
<
<

<
<
<
<
<
<
<
<
<
<

|
|
<
<
|
<
<
<
<
<
<
<
<
<


|
|
<
|

|
|
>
>


<

<
|
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<

|
<
|
<
<
<
<
<
|
|


|
<
|
<
<
<
<
|
|
<




<
<

|
|









<


|

|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|



|
|
|
>
|
|
|
|
|

|
|
>
|
>
|
|
|
|
>
|
|
|
>
|
>
>
|



|
|
|
|
|
|
|
|









>
|
|

|
|
|
|
|





>
|
|

|


>
>
|
>

|
|
|
|
|
>


|
<
|
<
<
<
<
<
|
<
<


|
|
<
<
<
<
<
|
<
<


|
|
<
<
<
<
<
|
<
<


|
<
|
|
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<

|
|
|
<
<
<
<
<
<


|
|
>

<
<
<
<

>
>
>
>
>
>
>
>
|
|
|


<







1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19

20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
35
36

37



38

39
40
41



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# httpd.test - Copyright (c) 2015 Sean Woods

# -------------------------------------------------------------------------
set TESTDIR [file dirname [file normalize [info script]]]
set MODDIR [file dirname $TESTDIR]
if {[file exists [file join $MODDIR devtools testutilities.tcl]]} {
  # Running inside tcllib
  set TCLLIBMOD $MODDIR
} else {
  set TCLLIBMOD [file join $MODDIR .. .. tcllib modules]
}
source [file join $TCLLIBMOD devtools testutilities.tcl]



testsNeedTcl     8.6 ;# tool requires 8.6
testsNeedTcltest 2
set NOW [clock seconds]
testsNeed TclOO 1

support {

    use [file join ${TCLLIBMOD} fumagic rtcore.tcl]       fileutil::magic::rt
    use [file join ${TCLLIBMOD} fumagic filetypes.tcl]    fileutil::magic::filetype
    use [file join ${TCLLIBMOD} textutil string.tcl]      textutil::string

    use [file join ${TCLLIBMOD} textutil repeat.tcl]      textutil::repeat
    use [file join ${TCLLIBMOD} textutil tabify.tcl]      textutil::tabify
    use [file join ${TCLLIBMOD} markdown markdown.tcl]    Markdown
    use [file join ${TCLLIBMOD} ncgi ncgi.tcl]            ncgi
    use [file join ${TCLLIBMOD} log logger.tcl]           logger
    use [file join ${TCLLIBMOD} base64 base64.tcl]        base64
    use [file join ${TCLLIBMOD} md5 md5x.tcl]             md5
    use [file join ${TCLLIBMOD} mime mime.tcl]            mime
    use [file join ${TCLLIBMOD} uuid uuid.tcl]            uuid
    use [file join ${TCLLIBMOD} cmdline cmdline.tcl]      cmdline
    use [file join ${TCLLIBMOD} fileutil fileutil.tcl]    fileutil
    use [file join ${TCLLIBMOD} sha1 sha1.tcl]            sha1
    use [file join ${TCLLIBMOD} uri uri.tcl]              uri
    use [file join ${TCLLIBMOD} ncgi ncgi.tcl]            ncgi

    use [file join ${TCLLIBMOD} dns ip.tcl]               ip



    use [file join ${TCLLIBMOD} nettool nettool.tcl]      nettool

    use [file join ${TCLLIBMOD} coroutine coroutine.tcl]  coroutine
    use [file join ${TCLLIBMOD} dicttool dicttool.tcl]    dicttool
    use [file join ${TCLLIBMOD} cron cron.tcl]            cron



    use [file join ${TCLLIBMOD} virtchannel_core core.tcl] tcl::chan::core
    use [file join ${TCLLIBMOD} virtchannel_core events.tcl] tcl::chan::events
    use [file join ${TCLLIBMOD} virtchannel_base memchan.tcl] tcl::chan::memchan
    use [file join ${TCLLIBMOD} websocket websocket.tcl]  websocket
    use [file join ${MODDIR} clay clay.tcl]               clay
}

testing {
    useLocal httpd.tcl httpd
}

# Set to true for debugging and traces
set ::DEBUG 0
set ::clay::debug $::DEBUG

proc DEBUG args {
    if {!$::DEBUG} return
    uplevel 1 $args
}

# -------------------------------------------------------------------------
# Constructors for various expected replies.
proc IndexReply {{head {HTTP/1.0}}} {
   global TESTDIR
   set fin       [open [file join $TESTDIR pkgIndex.tcl] r]
   set replyfile [read $fin]
   close $fin

   append checkreply "$head 200 OK" \n
   append checkreply "Content-Type: text/plain" \n
   append checkreply "Connection: close" \n
   append checkreply "Content-Length: [string length $replyfile]" \n
   append checkreply \n
   append checkreply $replyfile

   return $checkreply
}

proc 404 {} {
    lappend map "        " ""
    lappend map "    "     ""
    # The map removes the indentation of the value
    return [string map $map {HTTP/1.0 404 Not Found
        Content-Type: text/plain
        Connection: close
        Content-Length: *

        404 Not Found
    }]
}

proc 200 {text {len *}} {
    lappend map "        " ""
    # The map removes the indentation of the value
    # and inserts the dynamic parts
    lappend map @C $text
    lappend map @L $len
    return [string map $map {HTTP/1.0 200 OK
        Content-Type: text/plain
        Connection: close
        Content-Length: @L

        @C}]
}

proc 200+status-head {text {len *}} {
    lappend map "        " ""
    # The map removes the indentation of the value
    # and inserts the dynamic parts
    lappend map @C $text
    lappend map @L $len
    return [string map $map {Status: 200 OK
        Content-Type: text/plain
        Connection: close
        Content-Length: @L

        @C}]
}

proc 200+status-conn {text {len *}} {
    lappend map "        " ""
    # The map removes the indentation of the value
    # and inserts the dynamic parts
    lappend map @C $text
    lappend map @L $len
    return [string map $map {HTTP/1.0 200 OK
        Status: 200 OK
        Content-Type: text/plain
        Content-Length: @L

        @C}]
}

proc 500 {} {
    lappend map "        " ""
    lappend map "    "     ""
    # The map removes the indentation of the value
    return [string map $map {HTTP/1.0 500 Server Internal Error
        Content-Type: text/plain
        Connection: close
        Content-Length: *

        500 Server Internal Error
    }]
}

proc 500+status-head {} {
    lappend map "        " ""
    lappend map "    "     ""
    # The map removes the indentation of the value
    return [string map $map {Status: 500 Server Internal Error
        Content-Type: text/plain
        Connection: close
        Content-Length: *

        500 Server Internal Error
    }]
}

# Likely a band aid, see AKU
proc norm-eol {x} { string map [list "\r\n" "\n"] $x }

# -------------------------------------------------------------------------

namespace eval ::httpd {}
namespace eval ::httpd::test {}

























proc ::httpd::test::send {port http headers body} {
    set sock [socket localhost $port]
    variable reply
    set reply($sock) {}
    chan configure $sock -translation {crlf crlf} -blocking 0 -buffering full -buffersize 4096
    chan event $sock readable [list ::httpd::test::get_reply $sock]

    puts $sock $http
    if {![dict exists $headers Host]} {
        dict set headers Host localhost
    }
    if {[string length $body]} {
        if {![dict exists $headers Content-Type]} {
            dict set headers Content_Type text/plain
        }
        dict set headers Content-Length [string length $body]
    }
    foreach {f v} $headers {
        puts $sock "${f}: $v"
    }
    puts $sock {}
    if {[string length $body]} {
        chan configure $sock -translation binary -blocking 0 -buffering full -buffersize 4096
        puts -nonewline $sock $body
    }
    flush $sock
    while {$reply($sock) eq {}} {
        update
    }
    #vwait [namespace current]::reply($sock)

    #puts ZZ\t[join [split $reply($sock) \n] "|\nZZ\t"]|
    return $reply($sock)
}

proc ::httpd::test::get_reply {sock} {
    variable buffer
    set data [read $sock]
    append buffer($sock) $data
    if {[eof $sock]} {
        chan event $sock readable {}
        set [namespace current]::reply($sock) $buffer($sock)
        unset buffer($sock)
    }
}


clay::define ::httpd::server {
    method log args {}


    method TemplateSearch page {
        set doc_root [my clay get server/ doc_root]
        if {$doc_root ne {} && [file exists [file join $doc_root $page.tml]]} {
            return [::fileutil::cat [file join $doc_root $page.tml]]
        }
        if {$doc_root ne {} && [file exists [file join $doc_root $page.html]]} {
            return [::fileutil::cat [file join $doc_root $page.html]]
        }
        switch $page {
            redirect {
                return {300 Redirect}
            }
            notfound {
                return {404 Not Found}
            }
            internal_error {
                return {500 Server Internal Error}
            }
        }
    }


    ::DEBUG method debug args {
        puts stderr $args
    }

    ::DEBUG method log args {
        puts stdout $args
    }
}


###
# Modify the reply class to return plain text
###
clay::define ::httpd::reply {

    method HttpHeaders_Default {} {
        return {
            Status       {200 OK}
            Content-Type {text/plain}
            Connection   close
        }
    }

    method reset {} {
        my variable reply_body
        my reply replace [my HttpHeaders_Default]
        set reply_body {}
    }

    method error {code {msg {}} {errorInfo {}}} {
        my clay set HTTP_ERROR $code
        my reset
        set errorstring [my http_code_string $code]
        set qheaders [my clay dump]
        dict with qheaders {}
        my reply replace {}
        my reply set Status "$code $errorstring"
        my reply set Content-Type text/plain
        my puts "$code $errorstring"
    }
}

clay::define ::test::content.echo {
    method content {} {
        my variable reply_body
        set reply_body [my PostData [my request get CONTENT_LENGTH]]
        #puts [list REPLY BODY WAS $reply_body]
    }
}
clay::define ::test::content.file {
    superclass ::httpd::content.file
    method content {} {
        my reset
        set doc_root  [my clay get path]
        my variable reply_file
        set reply_file [file join $doc_root pkgIndex.tcl]
    }
}
clay::define ::test::content.time {
    method content {} {
        my variable reply_body
        set reply_body $::NOW
    }
}
clay::define ::test::content.error {
    method content {} {
        error {The programmer asked me to die this way}
    }
}
clay::define ::test::content.cgi {
    superclass ::httpd::content.cgi
}
clay::define ::test::content.string {
    method content {} {
        my variable reply_body
        set reply_body [my clay get hardcoded_string]
    }
}
clay::define ::httpd::test::reply {
    superclass ::httpd::reply ::test::content.echo
}

###
# Build the server
###



::httpd::server create TESTAPP port 10001 doc_root $::TESTDIR
TESTAPP plugin dict_dispatch
TESTAPP uri add * /      [list mixin {reply ::test::content.echo}]
TESTAPP uri add * /echo  [list mixin {reply ::test::content.echo}]
TESTAPP uri add * /file  [list mixin {reply ::test::content.file} path $::TESTDIR]
TESTAPP uri add * /time  [list mixin {reply ::test::content.time}]
TESTAPP uri add * /error [list mixin {reply ::test::content.error}]
TESTAPP uri add * /string  [list mixin {reply ::test::content.string} hardcoded_string apple]

# Catch all
#TESTAPP uri add * * [list mixin {reply httpd::content.echo}]

::DEBUG puts httpd-client-0001
test httpd-client-0001 {Do an echo request} -body {

    ::httpd::test::send 10001 {POST /echo HTTP/1.0} {} {THIS IS MY CODE}





} -match glob -result [200 {THIS IS MY CODE}]


::DEBUG puts httpd-client-0002
test httpd-client-0002 {Do another echo request} {
    ::httpd::test::send 10001 {POST /echo HTTP/1.0} {} {THOUGH THERE ARE MANY LIKE IT}





} [200 {THOUGH THERE ARE MANY LIKE IT} 29]


::DEBUG puts httpd-client-0003
test httpd-client-0003 {Do another echo request} -body {
    ::httpd::test::send 10001 {POST /echo HTTP/1.0} {} {THIS ONE ALONE IS MINE}





} -match glob -result [200 {THIS ONE ALONE IS MINE}]


::DEBUG puts httpd-client-0004
test httpd-client-0004 {URL Generates Error} -body {

    ::httpd::test::send 10001 {POST /error HTTP/1.0} {} {THIS ONE ALONE IS MINE}
} -match glob -result [500]















::DEBUG puts httpd-client-0005
test httpd-client-0005 {URL Different output with a different request} -body {
    ::httpd::test::send 10001 {POST /time HTTP/1.0} {} {THIS ONE ALONE IS MINE}


} -match glob -result [200 $::NOW]










::DEBUG puts httpd-client-0006
test httpd-client-0006 {Return a file} -body {
    ::httpd::test::send 10001 {GET /file HTTP/1.0} {} {}

} -result [IndexReply]

::DEBUG puts httpd-client-0007
test httpd-client-0007 {URL Generates Not Found} -body {
    ::httpd::test::send 10001 {POST /doesnotexist HTTP/1.0} {} {THIS ONE ALONE IS MINE}
} -match glob -result [404]

::DEBUG puts httpd-client-0008
test httpd-client-0008 {Pull a constant string} -body {
    ::httpd::test::send 10001 {GET /string HTTP/1.0} {} {}
} -match glob -result [200 apple]
# -------------------------------------------------------------------------
# Test proxies

clay::define ::test::content.proxy {
    superclass ::httpd::content.proxy


    method proxy_channel {} {
        return [::socket localhost [my clay get proxy_port]]
    }
}


::httpd::server create TESTPROXY port 10002 doc_root $::TESTDIR
TESTAPP   uri add * /proxy* [list mixin {reply ::test::content.proxy} proxy_port [TESTPROXY port_listening]]
TESTPROXY plugin dict_dispatch
TESTPROXY uri add * /       [list mixin {reply ::test::content.echo}]
TESTPROXY uri add * /echo   [list mixin {reply ::test::content.echo}]
TESTPROXY uri add * /file   [list mixin {reply ::test::content.file} path $::TESTDIR]
TESTPROXY uri add * /time   [list mixin {reply ::test::content.time}]
TESTPROXY uri add * /error  [list mixin {reply ::test::content.error}]
TESTPROXY uri add * /string   [list mixin {reply ::test::content.string} hardcoded_string banana]

## AKU ##
#
# Note: Proxy replies are not normalized to \n. They contain \r\n
# endings.  The old test::compare was ok with that due to running a
# trim on the lines it was comparing. Here we properly normalize
# before feeding into the comparison.
#
# Note 2: I suspect that this leakage / non-normalization of of \r\n
#         in the server is a bug which should be fixed. If so, norm-eol
#         becomes superfluous. Right now it feels like a band-aid

::DEBUG puts httpd-proxy-0001
test httpd-proxy-0001 {Do an echo request} -body {

    norm-eol [::httpd::test::send 10001 {POST /proxy/echo HTTP/1.0} {} {THIS IS MY CODE}]





} -match glob -result [200 {THIS IS MY CODE}]


::DEBUG puts httpd-proxy-0002
test httpd-proxy-0002 {Do another echo request} -body {
    norm-eol [::httpd::test::send 10001 {POST /proxy/echo HTTP/1.0} {} {THOUGH THERE ARE MANY LIKE IT}]





} -result [200 {THOUGH THERE ARE MANY LIKE IT} 29]


::DEBUG puts httpd-proxy-0003
test httpd-proxy-0003 {Do another echo request} -body {
    norm-eol [::httpd::test::send 10001 {POST /proxy/echo HTTP/1.0} {} {THIS ONE ALONE IS MINE}]





} -match glob -result [200 {THIS ONE ALONE IS MINE}]


::DEBUG puts httpd-proxy-0004
test httpd-proxy-0004 {URL Generates Error} -body {

    norm-eol [::httpd::test::send 10001 {POST /proxy/error HTTP/1.0} {} {THIS ONE ALONE IS MINE}]
} -match glob -result [500]















::DEBUG puts httpd-proxy-0005
test httpd-proxy-0005 {URL Different output with a different request} -body {
    norm-eol [::httpd::test::send 10001 {POST /proxy/time HTTP/1.0} {} {THIS ONE ALONE IS MINE}]


} -match glob -result [200 $::NOW]










::DEBUG puts httpd-proxy-0006
test httpd-proxy-0006 {Return a file} -body {
    norm-eol [::httpd::test::send 10001 {GET /proxy/file HTTP/1.0} {} {}]

} -result [IndexReply]

::DEBUG puts httpd-proxy-0008
test httpd-proxy-0008 {Pull a constant string} -body {
    norm-eol [::httpd::test::send 10001 {GET /proxy/string HTTP/1.0} {} {}]
} -result [200 banana 6]
# -------------------------------------------------------------------------
# cgi



TESTAPP plugin local_memchan


TESTAPP uri add * /cgi-bin* [list mixin {reply ::test::content.cgi} path $::TESTDIR/assets]















::DEBUG puts httpd-cgi-0001
test httpd-cgi-0001 {CGI Post} -body {

    norm-eol [::httpd::test::send 10001 {POST /cgi-bin/test_cgi.tcl HTTP/1.0} {} {THIS IS MY CODE}]





} -match glob -result [200+status-conn {THIS IS MY CODE
}]

::DEBUG puts httpd-cgi-0002
test httpd-cgi-0002 {CGI Get} -body {

    ::httpd::test::send 10001 {GET /cgi-bin/test_cgi.tcl HTTP/1.0} {} {}




} -match glob -result [200+status-conn {Hi!
}]


###
# Test the local geturl method
###


test httpd-memchan-0001 {Memchan GET} {
    TESTAPP local_memchan geturl /time
} $NOW

# -------------------------------------------------------------------------
namespace eval ::scgi {}
namespace eval ::scgi::test {}

###
# Minimal test harness for the .tests
# Not intended for public consumption
# (But if you find it handy, please steal!)


proc ::scgi::encode_request {headers body info} {
    variable server_block

    dict set outdict CONTENT_LENGTH [string length $body]
    set outdict [dict merge $outdict $server_block $info]
    dict set outdict PWD [pwd]

    foreach {key value} $headers {
        if {$key in {
            DOCUMENT_ROOT
            HTTPS
            PATH
            REQUEST_METHOD REQUEST_URI
            REMOTE_HOST REMOTE_ADDR REMOTE_PORT
            SCRIPT_NAME
        } || [string range $key 0 5] eq "HTTP_"} {
            dict set outdict $key $value
        } else {
            dict set outdict HTTP_[string map {"-" "_"} [string toupper $key]] $value
        }
    }
    set result {}
    foreach {name value} $outdict {
        append result $name \x00 $value \x00
    }
    return "[string length $result]:$result,"
}

proc ::scgi::test::send {port headers body} {
    set sock [socket localhost $port]
    variable reply
    set reply($sock) {}

    if {![dict exists $headers HOST]} {
        dict set headers HOST localhost
    }
    dict set headers REMOTE_IP   127.0.0.1
    dict set headers REMOTE_HOST localhost

    chan configure $sock -translation binary -blocking 0 -buffering full -buffersize 4096
    chan event     $sock readable [list ::scgi::test::get_reply $sock]

    set block [::scgi::encode_request $headers $body {}]

    puts -nonewline $sock $block
    flush $sock
    puts -nonewline $sock $body
    flush $sock

    while {$reply($sock) eq {}} {
        update
    }

    #vwait [namespace current]::reply($sock)

    #puts ZZ\t[join [split $reply($sock) \n] "|\nZZ\t"]|
    return $reply($sock)
}

proc ::scgi::test::get_reply {sock} {
    variable buffer
    set data [read $sock]
    append buffer($sock) $data
    if {[eof $sock]} {
        chan event $sock readable {}
        set [namespace current]::reply($sock) $buffer($sock)
        unset buffer($sock)
    }
}

namespace eval ::scgi {
  variable server_block {SCGI 1.0 SERVER_SOFTWARE {TclScgiServer/0.1}}
}

###
# Build the reply class
###

::clay::define ::scgi::test::reply {
    superclass ::httpd::reply

    method reset {} {
        my variable reply_body
        my reply replace [my HttpHeaders_Default]
        set reply_body {}
    }
}

###
# Build the server
###

::clay::define scgi::test::app {
    superclass ::httpd::server.scgi

    clay set reply_class ::scgi::test::reply
}

::DEBUG puts [list ::test::content.file [info commands ::test::content.file]]

scgi::test::app create TESTSCGI port 10003 doc_root $::TESTDIR

TESTSCGI plugin dict_dispatch
TESTSCGI uri add * /      [list mixin {reply ::test::content.echo}]
TESTSCGI uri add * /echo  [list mixin {reply ::test::content.echo}]
TESTSCGI uri add * /file  [list mixin {reply ::test::content.file} path $::TESTDIR]
TESTSCGI uri add * /time  [list mixin {reply ::test::content.time}]
TESTSCGI uri add * /error [list mixin {reply ::test::content.error}]
TESTSCGI uri add * /string  [list mixin {reply ::test::content.string} hardcoded_string cherry]

::DEBUG puts scgi-client-0001
test scgi-client-0001 {Do an echo request} -body {

    ::scgi::test::send 10003 {REQUEST_METHOD POST REQUEST_URI /echo} {THIS IS MY CODE}





} -match glob -result [200+status-head {THIS IS MY CODE}]



::DEBUG puts scgi-client-0002
test scgi-client-0002 {Do another echo request} -body {
    ::scgi::test::send 10003 {REQUEST_METHOD POST REQUEST_URI /echo} {THOUGH THERE ARE MANY LIKE IT}





} -match glob -result [200+status-head {THOUGH THERE ARE MANY LIKE IT}]



::DEBUG puts scgi-client-0003
test scgi-client-0003 {Do another echo request} -body {
    ::scgi::test::send 10003 {REQUEST_METHOD POST REQUEST_URI /echo} {THIS ONE ALONE IS MINE}





} -match glob -result [200+status-head {THIS ONE ALONE IS MINE}]



::DEBUG puts scgi-client-0004
test scgi-client-0004 {URL Generates Error} -body {

    ::scgi::test::send 10003 {REQUEST_METHOD POST REQUEST_URI /error} {THIS ONE ALONE IS MINE}
} -match glob -result [500+status-head]

















::DEBUG puts scgi-client-0005
test scgi-client-0005 {URL Different output with a different request} -body {
    ::scgi::test::send 10003 {REQUEST_METHOD POST REQUEST_URI /time} {THIS ONE ALONE IS MINE}
} -match glob -result [200+status-head $::NOW]







::DEBUG puts scgi-client-0006
test scgi-client-0006 {Return a file} -body {
    ::scgi::test::send 10003 {REQUEST_METHOD GET REQUEST_URI /file} {}
} -result [IndexReply Status:]






::DEBUG puts scgi-client-0008
test scgi-client-0008 {Pull a constant string} -body {
    ::scgi::test::send 10003 {REQUEST_METHOD GET REQUEST_URI /string} {}
} -match glob -result [200+status-head cherry]
###
# Test the all object have been destroyed after ::clay::cleanup
###
test httpd-garbage-collection {Test that garbage collection leaves nothing behind} -body {
  ::clay::cleanup
  info commands ::httpd::object::*
} -result {}

::DEBUG puts all-tests-finished

# -------------------------------------------------------------------------

testsuiteCleanup

# Local variables:
# mode: tcl
# indent-tabs-mode: nil

Changes to modules/httpd/pkgIndex.tcl.

1
2
3
4

if {![package vsatisfies [package provide Tcl] 8.6]} {return}
package ifneeded httpd 4.2.0 [list source [file join $dir httpd.tcl]]



|

1
2
3
4

if {![package vsatisfies [package provide Tcl] 8.6]} {return}
package ifneeded httpd 4.3.4 [list source [file join $dir httpd.tcl]]

Changes to modules/ident/ident.man.

46
47
48
49
50
51
52
53
54
to the RFC. A detailed error message is returned under the
[const error] key.

[list_end]
[list_end]

[vset CATEGORY ident]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

46
47
48
49
50
51
52
53
54
to the RFC. A detailed error message is returned under the
[const error] key.

[list_end]
[list_end]

[vset CATEGORY ident]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/imap4/imap4.man.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

[manpage_begin imap4 n 0.5.3]
[see_also ftp]
[see_also http]
[see_also imap]
[see_also mime]
[see_also pop3]
[see_also tls]
[keywords email]
[keywords imap]
[keywords internet]
[keywords mail]
[keywords net]
[keywords rfc3501]
[keywords ssl]
[keywords tls]
[moddesc   {imap client}]
[titledesc {imap client-side tcl implementation of imap protocol}]

[require Tcl 8.5]
[require imap4 [opt 0.5.2]]

[description]

The [package imap4] library package provides the client side of the
[emph "Internet Message Access Protocol"] (IMAP) using standard
sockets or secure connection via TLS/SSL.
The package is fully implemented in Tcl.
>
|
















|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[vset VERSION 0.5.3]
[manpage_begin imap4 n [vset VERSION]]
[see_also ftp]
[see_also http]
[see_also imap]
[see_also mime]
[see_also pop3]
[see_also tls]
[keywords email]
[keywords imap]
[keywords internet]
[keywords mail]
[keywords net]
[keywords rfc3501]
[keywords ssl]
[keywords tls]
[moddesc   {imap client}]
[titledesc {imap client-side tcl implementation of imap protocol}]
[category Networking]
[require Tcl 8.5]
[require imap4 [opt [vset VERSION]]]

[description]

The [package imap4] library package provides the client side of the
[emph "Internet Message Access Protocol"] (IMAP) using standard
sockets or secure connection via TLS/SSL.
The package is fully implemented in Tcl.
357
358
359
360
361
362
363
364
365
366
367
Mark R. Crispin, "INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1",
RFC 3501, March 2003, [uri http://www.rfc-editor.org/rfc/rfc3501.txt]

[para]
OpenSSL, [uri http://www.openssl.org/]

[vset CATEGORY imap4]
[include ../doctools2base/include/feedback.inc]

Only a small part of rfc3501 implemented.
[manpage_end]







|



358
359
360
361
362
363
364
365
366
367
368
Mark R. Crispin, "INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1",
RFC 3501, March 2003, [uri http://www.rfc-editor.org/rfc/rfc3501.txt]

[para]
OpenSSL, [uri http://www.openssl.org/]

[vset CATEGORY imap4]
[include ../common-text/feedback.inc]

Only a small part of rfc3501 implemented.
[manpage_end]

Changes to modules/inifile/ini.man.

92
93
94
95
96
97
98
99
100
Reads and sets the comment character. Lines that begin with this character are treated as
comments. When comments are written out each line is preceded by this character. The default
is [const \;].

[list_end]

[vset CATEGORY inifile]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

92
93
94
95
96
97
98
99
100
Reads and sets the comment character. Lines that begin with this character are treated as
comments. When comments are written out each line is preceded by this character. The default
is [const \;].

[list_end]

[vset CATEGORY inifile]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/inifile/inifile.test.

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
testing {
    useLocal ini.tcl inifile
}

#---------------------------------------------------------------------

set inifile [localPath ini.tcl]
set testini [localPath test.ini]
set sampini [localPath sample.ini]

#---------------------------------------------------------------------

test inifile-1.1 {ini::open} {
    set res [ini::open $testini r]
    ini::close $res
    set res







|
|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
testing {
    useLocal ini.tcl inifile
}

#---------------------------------------------------------------------

set inifile [localPath ini.tcl]
set testini [asset test.ini]
set sampini [asset sample.ini]

#---------------------------------------------------------------------

test inifile-1.1 {ini::open} {
    set res [ini::open $testini r]
    ini::close $res
    set res

Deleted modules/inifile/sample.ini.

1
2
3
4
5
[General]   
 key=value
key2=value2 

  ; ....  
<
<
<
<
<










Added modules/inifile/test-assets/sample.ini.











>
>
>
>
>
1
2
3
4
5
[General]   
 key=value
key2=value2 

  ; ....  

Added modules/inifile/test-assets/test.ini.































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[emptysection]

; a comment for section 1

[section1]
key=value
testkey=hi

[section2]
; key comment
key=othervalue


[{test]
}key   =    $blah

Deleted modules/inifile/test.ini.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[emptysection]

; a comment for section 1

[section1]
key=value
testkey=hi

[section2]
; key comment
key=othervalue


[{test]
}key   =    $blah
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























Changes to modules/interp/deleg_method.man.

41
42
43
44
45
46
47
48
49
returns the result from the remote method as its own result. If
however the option [option -async] was specified then the generated
method will not wait for a result and return immediately.

[list_end]

[vset CATEGORY interp]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

41
42
43
44
45
46
47
48
49
returns the result from the remote method as its own result. If
however the option [option -async] was specified then the generated
method will not wait for a result and return immediately.

[list_end]

[vset CATEGORY interp]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/interp/deleg_proc.man.

39
40
41
42
43
44
45
46
47
returns the result from the remote procedure as its own result. If
however the option [option -async] was specified then the generated
procedure will not wait for a result and return immediately.

[list_end]

[vset CATEGORY interp]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

39
40
41
42
43
44
45
46
47
returns the result from the remote procedure as its own result. If
however the option [option -async] was specified then the generated
procedure will not wait for a result and return immediately.

[list_end]

[vset CATEGORY interp]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/interp/tcllib_interp.man.

66
67
68
69
70
71
72
73
74
[para]

The result of the command is the empty string.

[list_end]

[vset CATEGORY interp]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

66
67
68
69
70
71
72
73
74
[para]

The result of the command is the empty string.

[list_end]

[vset CATEGORY interp]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/irc/irc.man.

232
233
234
235
236
237
238
239
240
[call [cmd msg]]

Returns the message portion of the command (the part after the :).

[list_end]

[vset CATEGORY irc]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

232
233
234
235
236
237
238
239
240
[call [cmd msg]]

Returns the message portion of the command (the part after the :).

[list_end]

[vset CATEGORY irc]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/javascript/javascript.man.

88
89
90
91
92
93
94
95
96
checked.  The [arg parentName] argument is the name of the child's
parent html checkbox object.  The [arg childName] argument is the name
of child html checkbox object to create.

[list_end]

[vset CATEGORY javascript]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

88
89
90
91
92
93
94
95
96
checked.  The [arg parentName] argument is the name of the child's
parent html checkbox object.  The [arg childName] argument is the name
of child html checkbox object to create.

[list_end]

[vset CATEGORY javascript]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/jpeg/jpeg.man.

188
189
190
191
192
193
194
195
196

can only work with files
cant write exif data
gps exif data not parsed
makernote data not yet implemented

[vset CATEGORY jpeg]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

188
189
190
191
192
193
194
195
196

can only work with files
cant write exif data
gps exif data not parsed
makernote data not yet implemented

[vset CATEGORY jpeg]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/jpeg/jpeg.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# -*- tcl -*-
# jpeg.test:  Tests for the JPEG utilities.
#
# Copyright (c) 2008-2013 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# JPEG: @(#) $Id: jpeg.test,v 1.2 2011/05/06 13:39:27 patthoyts Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]






<
<







1
2
3
4
5


6
7
8
9
10
11
12
# -*- tcl -*-
# jpeg.test:  Tests for the JPEG utilities.
#
# Copyright (c) 2008-2013 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
test jpeg-1.1 {isJPEG error, wrong#args, too many} -body {
    ::jpeg::isJPEG foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::isJPEG} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*JPG*] {
    test jpeg-2.$n "isJPEG, ok, [file tail $f]" -body {
	::jpeg::isJPEG $f
    } -result 1
    incr n
}

test jpeg-2.$n "isJPEG, fail, [file tail [info script]]" -body {







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
test jpeg-1.1 {isJPEG error, wrong#args, too many} -body {
    ::jpeg::isJPEG foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::isJPEG} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*JPG*] {
    test jpeg-2.$n "isJPEG, ok, [file tail $f]" -body {
	::jpeg::isJPEG $f
    } -result 1
    incr n
}

test jpeg-2.$n "isJPEG, fail, [file tail [info script]]" -body {
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
test jpeg-2.1 {imageInfo error, wrong#args, too many} -body {
    ::jpeg::imageInfo foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::imageInfo} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.JPG] {
    test jpeg-3.$n "imageInfo regular, [file tail $f]" -body {
	::jpeg::imageInfo $f
    } -result [string trim [fileutil::cat [file rootname $f].info.txt]]
    incr n
}

set n 0
foreach f [TestFilesGlob testimages/*.thumb] {
    test jpeg-4.$n "imageInfo thumbnails, [file tail $f]" -body {
	::jpeg::imageInfo $f
    } -result {}
    incr n
}

test jpeg-5.0 "imageInfo, fail, [file tail [info script]]" -body {







|







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
test jpeg-2.1 {imageInfo error, wrong#args, too many} -body {
    ::jpeg::imageInfo foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::imageInfo} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.JPG] {
    test jpeg-3.$n "imageInfo regular, [file tail $f]" -body {
	::jpeg::imageInfo $f
    } -result [string trim [fileutil::cat [file rootname $f].info.txt]]
    incr n
}

set n 0
foreach f [TestFilesGlob test-assets/*.thumb] {
    test jpeg-4.$n "imageInfo thumbnails, [file tail $f]" -body {
	::jpeg::imageInfo $f
    } -result {}
    incr n
}

test jpeg-5.0 "imageInfo, fail, [file tail [info script]]" -body {
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
test jpeg-6.1 {dimensions error, wrong#args, too many} -body {
    ::jpeg::dimensions foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::dimensions} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.JPG] {
    test jpeg-7.$n "dimensions regular, [file tail $f]" -body {
	::jpeg::dimensions $f
    } -result [string trim [fileutil::cat [file rootname $f].WxH.txt]]
    incr n
}

set n 0
foreach f [TestFilesGlob testimages/*.thumb] {
    test jpeg-8.$n "dimensions thumbnails, [file tail $f]" -body {
	::jpeg::dimensions $f
    } -result {160 120}
    incr n
}

test jpeg-9.0 "dimensions, fail, [file tail [info script]]" -body {







|







|







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
test jpeg-6.1 {dimensions error, wrong#args, too many} -body {
    ::jpeg::dimensions foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::dimensions} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.JPG] {
    test jpeg-7.$n "dimensions regular, [file tail $f]" -body {
	::jpeg::dimensions $f
    } -result [string trim [fileutil::cat [file rootname $f].WxH.txt]]
    incr n
}

set n 0
foreach f [TestFilesGlob test-assets/*.thumb] {
    test jpeg-8.$n "dimensions thumbnails, [file tail $f]" -body {
	::jpeg::dimensions $f
    } -result {160 120}
    incr n
}

test jpeg-9.0 "dimensions, fail, [file tail [info script]]" -body {
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
test jpeg-10.1 {getThumbnail error, wrong#args, too many} -body {
    ::jpeg::getThumbnail foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::getThumbnail} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.JPG] {
    if {![file exists $f.thumb]} {
	test jpeg-11.$n "getThumbnail - no thumbnail, [file tail $f]" -body {
	    ::jpeg::getThumbnail $f
	} -result {}
    } else {
	test jpeg-11.$n "getThumbnail regular, [file tail $f]" -body {
	    #fileutil::writeFile -translation binary ${f}.x.jpg [::jpeg::getThumbnail $f]
	    # Note: The .thumb files were created from the .JPG files
	    # using 'jhead -st', version 2.6.
	    set expected [fileutil::cat -translation binary ${f}.thumb]
	    set have     [::jpeg::getThumbnail $f]
	    list [string equal $expected $have] [strdiff $expected $have]
	} -result {1 -}
    }

    incr n
}

set n 0
foreach f [TestFilesGlob testimages/*.thumb] {
    test jpeg-12.$n "getThumbnail thumbnails, [file tail $f]" -body {
	::jpeg::getThumbnail $f
    } -result {}
    incr n
}

test jpeg-13.0 "getThumbnail, fail, [file tail [info script]]" -body {







|



















|







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
test jpeg-10.1 {getThumbnail error, wrong#args, too many} -body {
    ::jpeg::getThumbnail foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::getThumbnail} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.JPG] {
    if {![file exists $f.thumb]} {
	test jpeg-11.$n "getThumbnail - no thumbnail, [file tail $f]" -body {
	    ::jpeg::getThumbnail $f
	} -result {}
    } else {
	test jpeg-11.$n "getThumbnail regular, [file tail $f]" -body {
	    #fileutil::writeFile -translation binary ${f}.x.jpg [::jpeg::getThumbnail $f]
	    # Note: The .thumb files were created from the .JPG files
	    # using 'jhead -st', version 2.6.
	    set expected [fileutil::cat -translation binary ${f}.thumb]
	    set have     [::jpeg::getThumbnail $f]
	    list [string equal $expected $have] [strdiff $expected $have]
	} -result {1 -}
    }

    incr n
}

set n 0
foreach f [TestFilesGlob test-assets/*.thumb] {
    test jpeg-12.$n "getThumbnail thumbnails, [file tail $f]" -body {
	::jpeg::getThumbnail $f
    } -result {}
    incr n
}

test jpeg-13.0 "getThumbnail, fail, [file tail [info script]]" -body {
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
test jpeg-16.1 {getComments error, wrong#args, too many} -body {
    ::jpeg::getComments foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::getComments} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.JPG] {
    test jpeg-17.$n "getComments regular, [file tail $f]" -body {
	::jpeg::getComments $f
    } -result {}
    incr n
}

set n 0
foreach f [TestFilesGlob testimages/*.thumb] {
    test jpeg-18.$n "getComments thumbnails, [file tail $f]" -body {
	::jpeg::getComments $f
    } -result {}
    incr n
}

test jpeg-19.0 "getComments, fail, [file tail [info script]]" -body {







|







|







209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
test jpeg-16.1 {getComments error, wrong#args, too many} -body {
    ::jpeg::getComments foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::getComments} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.JPG] {
    test jpeg-17.$n "getComments regular, [file tail $f]" -body {
	::jpeg::getComments $f
    } -result {}
    incr n
}

set n 0
foreach f [TestFilesGlob test-assets/*.thumb] {
    test jpeg-18.$n "getComments thumbnails, [file tail $f]" -body {
	::jpeg::getComments $f
    } -result {}
    incr n
}

test jpeg-19.0 "getComments, fail, [file tail [info script]]" -body {
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
test jpeg-20.1 {addComment error, wrong#args, not enough} -body {
    ::jpeg::addComment foo
} -returnCodes error -result [tcltest::wrongNumArgs {::jpeg::addComment} {file comment args} 1]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*JPG*] {
    test jpeg-21.$n "addComment regular, [file tail $f]" -setup {
	file copy -force $f [set fx [makeFile {} jtmp]]
	::jpeg::addComment $fx {a b} {c d}
    } -body {
	::jpeg::getComments $fx
    } -cleanup {
	removeFile $fx







|







241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
test jpeg-20.1 {addComment error, wrong#args, not enough} -body {
    ::jpeg::addComment foo
} -returnCodes error -result [tcltest::wrongNumArgs {::jpeg::addComment} {file comment args} 1]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*JPG*] {
    test jpeg-21.$n "addComment regular, [file tail $f]" -setup {
	file copy -force $f [set fx [makeFile {} jtmp]]
	::jpeg::addComment $fx {a b} {c d}
    } -body {
	::jpeg::getComments $fx
    } -cleanup {
	removeFile $fx
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
test jpeg-23.1 {removeComments error, wrong#args, too many} -body {
    ::jpeg::removeComments foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::removeComments} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*JPG*] {
    test jpeg-24.$n "removeComments regular, [file tail $f]" -setup {
	file copy -force $f [set fx [makeFile {} jtmp]]
	::jpeg::addComment     $fx {a b} {c d}
    } -body {
	::jpeg::removeComments $fx
	::jpeg::getComments $fx
    } -cleanup {







|







271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
test jpeg-23.1 {removeComments error, wrong#args, too many} -body {
    ::jpeg::removeComments foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::removeComments} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*JPG*] {
    test jpeg-24.$n "removeComments regular, [file tail $f]" -setup {
	file copy -force $f [set fx [makeFile {} jtmp]]
	::jpeg::addComment     $fx {a b} {c d}
    } -body {
	::jpeg::removeComments $fx
	::jpeg::getComments $fx
    } -cleanup {
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
test jpeg-26.2 {replaceComment error, wrong#args, too many} -body {
    ::jpeg::replaceComment foo bar barf
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::replaceComment} {file comment}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*JPG*] {
    test jpeg-27.$n "replaceComment regular, [file tail $f]" -setup {
	file copy -force $f [set fx [makeFile {} jtmp]]
	::jpeg::addComment      $fx {a b} {c d}
    } -body {
	::jpeg::replaceComment $fx new
	::jpeg::getComments $fx
    } -cleanup {







|







306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
test jpeg-26.2 {replaceComment error, wrong#args, too many} -body {
    ::jpeg::replaceComment foo bar barf
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::replaceComment} {file comment}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*JPG*] {
    test jpeg-27.$n "replaceComment regular, [file tail $f]" -setup {
	file copy -force $f [set fx [makeFile {} jtmp]]
	::jpeg::addComment      $fx {a b} {c d}
    } -body {
	::jpeg::replaceComment $fx new
	::jpeg::getComments $fx
    } -cleanup {
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
} -returnCodes error -result [tcltest::wrongNumArgs {::jpeg::getExif} {file ?type?} 0]

test jpeg-29.1 {getExif error, wrong#args, too many} -body {
    ::jpeg::getExif foo bar barf
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::getExif} {file ?type?}]

test jpeg-29.2 {getExif error, bad section type} -body {
    ::jpeg::getExif [localPath testimages/IMG_7950.JPG] fufara
} -returnCodes error -result {Bad type "fufara", expected one of "main", or "thumbnail"}

test jpeg-29.3 {getExifFromChannel error, wrong#args, not enough} -body {
    ::jpeg::getExifFromChannel
} -returnCodes error -result [tcltest::wrongNumArgs {::jpeg::getExifFromChannel} {chan ?type?} 0]

test jpeg-29.4 {getExifFromChannel error, wrong#args, too many} -body {
    ::jpeg::getExifFromChannel foo bar barf
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::getExifFromChannel} {chan ?type?}]

test jpeg-29.5 {getExifFromChannel error, bad section type} -setup {
    set fd [::jpeg::openJFIF [localPath testimages/IMG_7950.JPG] r]
} -body {
    ::jpeg::getExifFromChannel $fd fufara
} -cleanup {
    close $fd
    unset fd
} -returnCodes error -result {Bad type "fufara", expected one of "main", or "thumbnail"}

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.JPG] {
    test jpeg-30.$n "getExif, main section, $f" -body {
	dictsort [fixupdata [::jpeg::formatExif [::jpeg::getExif $f]]]
    } -result [string trimright [fileutil::cat [file rootname $f].exif.txt]]
    incr n
}

set n 0
foreach f [TestFilesGlob testimages/*.thumb] {
    test jpeg-31.$n "getExif, main section, $f" -body {
	dictsort [fixupdata [::jpeg::formatExif [::jpeg::getExif $f]]]
    } -result {}
    incr n
}

set n 0
foreach f [TestFilesGlob testimages/*.JPG] {
    test jpeg-32.$n "getExif, thumbnail section, $f" -body {
	dictsort [fixupdata [::jpeg::formatExif [::jpeg::getExif $f thumbnail]]]
    } -result [string trimright [fileutil::cat [file rootname $f].thumbexif.txt]]
    incr n
}

set n 0
foreach f [TestFilesGlob testimages/*.thumb] {
    test jpeg-33.$n "getExif, thumbnail section, $f" -body {
	dictsort [fixupdata [::jpeg::formatExif [::jpeg::getExif $f thumbnail]]]
    } -result {}
    incr n
}

test jpeg-34.0 "getExif, fail, [file tail [info script]]" -body {







|











|










|







|







|







|







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
} -returnCodes error -result [tcltest::wrongNumArgs {::jpeg::getExif} {file ?type?} 0]

test jpeg-29.1 {getExif error, wrong#args, too many} -body {
    ::jpeg::getExif foo bar barf
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::getExif} {file ?type?}]

test jpeg-29.2 {getExif error, bad section type} -body {
    ::jpeg::getExif [asset IMG_7950.JPG] fufara
} -returnCodes error -result {Bad type "fufara", expected one of "main", or "thumbnail"}

test jpeg-29.3 {getExifFromChannel error, wrong#args, not enough} -body {
    ::jpeg::getExifFromChannel
} -returnCodes error -result [tcltest::wrongNumArgs {::jpeg::getExifFromChannel} {chan ?type?} 0]

test jpeg-29.4 {getExifFromChannel error, wrong#args, too many} -body {
    ::jpeg::getExifFromChannel foo bar barf
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::getExifFromChannel} {chan ?type?}]

test jpeg-29.5 {getExifFromChannel error, bad section type} -setup {
    set fd [::jpeg::openJFIF [asset IMG_7950.JPG] r]
} -body {
    ::jpeg::getExifFromChannel $fd fufara
} -cleanup {
    close $fd
    unset fd
} -returnCodes error -result {Bad type "fufara", expected one of "main", or "thumbnail"}

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.JPG] {
    test jpeg-30.$n "getExif, main section, $f" -body {
	dictsort [fixupdata [::jpeg::formatExif [::jpeg::getExif $f]]]
    } -result [string trimright [fileutil::cat [file rootname $f].exif.txt]]
    incr n
}

set n 0
foreach f [TestFilesGlob test-assets/*.thumb] {
    test jpeg-31.$n "getExif, main section, $f" -body {
	dictsort [fixupdata [::jpeg::formatExif [::jpeg::getExif $f]]]
    } -result {}
    incr n
}

set n 0
foreach f [TestFilesGlob test-assets/*.JPG] {
    test jpeg-32.$n "getExif, thumbnail section, $f" -body {
	dictsort [fixupdata [::jpeg::formatExif [::jpeg::getExif $f thumbnail]]]
    } -result [string trimright [fileutil::cat [file rootname $f].thumbexif.txt]]
    incr n
}

set n 0
foreach f [TestFilesGlob test-assets/*.thumb] {
    test jpeg-33.$n "getExif, thumbnail section, $f" -body {
	dictsort [fixupdata [::jpeg::formatExif [::jpeg::getExif $f thumbnail]]]
    } -result {}
    incr n
}

test jpeg-34.0 "getExif, fail, [file tail [info script]]" -body {
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
test jpeg-34.1 {removeExif error, wrong#args, too many} -body {
    ::jpeg::removeExif foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::removeExif} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*JPG*] {
    test jpeg-35.$n "removeExif ok, [file tail $f]" -setup {
	file copy -force $f [set fx [makeFile {} jtmp]]
	::jpeg::addComment $fx {a b} {c d}
    } -body {
	::jpeg::removeExif $fx
	set res [list [::jpeg::getComments $fx] [::jpeg::getExif $fx] [::jpeg::getExif $fx thumbnail]]
    } -cleanup {







|







417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
test jpeg-34.1 {removeExif error, wrong#args, too many} -body {
    ::jpeg::removeExif foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::removeExif} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*JPG*] {
    test jpeg-35.$n "removeExif ok, [file tail $f]" -setup {
	file copy -force $f [set fx [makeFile {} jtmp]]
	::jpeg::addComment $fx {a b} {c d}
    } -body {
	::jpeg::removeExif $fx
	set res [list [::jpeg::getComments $fx] [::jpeg::getExif $fx] [::jpeg::getExif $fx thumbnail]]
    } -cleanup {
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
test jpeg-37.1 {stripJPEG error, wrong#args, too many} -body {
    ::jpeg::stripJPEG foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::stripJPEG} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*JPG*] {
    test jpeg-38.$n "stripJPEG ok, [file tail $f]" -setup {
	file copy -force $f [set fx [makeFile {} jtmp]]
	::jpeg::addComment $fx {a b} {c d}
    } -body {
	::jpeg::stripJPEG $fx
	set res [list [::jpeg::getComments $fx] [::jpeg::getExif $fx] [::jpeg::getExif $fx thumbnail]]
    } -cleanup {







|







448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
test jpeg-37.1 {stripJPEG error, wrong#args, too many} -body {
    ::jpeg::stripJPEG foo bar
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::stripJPEG} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*JPG*] {
    test jpeg-38.$n "stripJPEG ok, [file tail $f]" -setup {
	file copy -force $f [set fx [makeFile {} jtmp]]
	::jpeg::addComment $fx {a b} {c d}
    } -body {
	::jpeg::stripJPEG $fx
	set res [list [::jpeg::getComments $fx] [::jpeg::getExif $fx] [::jpeg::getExif $fx thumbnail]]
    } -cleanup {
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::debug} {file}]

# -------------------------------------------------------------------------
# We do not try to actually run 'debug', because it prints its results
# to stdout. This may change when we can capture stdout as test result

set n 0
foreach f [TestFilesGlob testimages/*JPG*] {
    test jpeg-41.$n "debug ok, [file tail $f]" -constraints donotrun -body {
	::jpeg::debug $f
    } -result {}
    incr n
}

test jpeg-42.0 "debug, fail, [file tail [info script]]" -body {
    ::jpeg::debug [info script]
} -returnCodes error -result {not a jpg file}

# -------------------------------------------------------------------------
rename strdiff {}
testsuiteCleanup







|













481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
} -returnCodes error -result [tcltest::tooManyArgs {::jpeg::debug} {file}]

# -------------------------------------------------------------------------
# We do not try to actually run 'debug', because it prints its results
# to stdout. This may change when we can capture stdout as test result

set n 0
foreach f [TestFilesGlob test-assets/*JPG*] {
    test jpeg-41.$n "debug ok, [file tail $f]" -constraints donotrun -body {
	::jpeg::debug $f
    } -result {}
    incr n
}

test jpeg-42.0 "debug, fail, [file tail [info script]]" -body {
    ::jpeg::debug [info script]
} -returnCodes error -result {not a jpg file}

# -------------------------------------------------------------------------
rename strdiff {}
testsuiteCleanup

Added modules/jpeg/test-assets/1000.JPG.

cannot compute difference between binary files

Added modules/jpeg/test-assets/1000.WxH.txt.



>
1
1000 1000

Added modules/jpeg/test-assets/1000.exif.txt.



>
1
ExifByteOrder little ExifOffset 30

Added modules/jpeg/test-assets/1000.info.txt.



>
1
version 1.1 units 1 xdensity 96 ydensity 96 xthumb 0 ythumb 0

Added modules/jpeg/test-assets/1000.thumbexif.txt.

Added modules/jpeg/test-assets/IMG_7898.JPG.

cannot compute difference between binary files

Added modules/jpeg/test-assets/IMG_7898.JPG.thumb.

cannot compute difference between binary files

Added modules/jpeg/test-assets/IMG_7898.WxH.txt.



>
1
320 240

Added modules/jpeg/test-assets/IMG_7898.exif.txt.



>
1
ApertureValue 4.0 ColorSpace sRGB ComponentsConfiguration 1,2,3,0 CompressedBitsPerPixel 5 CustomRendered normal DateTime {2008:03:14 15:40:06} DateTimeDigitized {2008:03:14 15:40:06} DateTimeOriginal {2008:03:14 15:40:06} DigitalZoomRatio 1 ExifByteOrder little ExifImageHeight 2448 ExifImageWidth 3264 ExifOffset 30 ExifVersion 2.2 ExposureBiasValue 0 ExposureMode auto ExposureTime 1/60 FNumber 4.0 FileSource {digital still camera} Flash {flash did not fire, compulsory flash mode} FlashpixVersion {Flashpix Format Version 1.0} FocalLength 6 FocalPlaneResolutionUnit inch FocalPlaneXResolution 14506.67 FocalPlaneYResolution 14485.21 ISOSpeedRatings 80 InteroperabilityIndex R98 InteroperabilityVersion 0100 Make Canon MaxApertureValue 3.0 MeteringMode multi-segment Model {Canon PowerShot S5 IS} Orientation normal RelatedImageLength 2448 RelatedImageWidth 3264 ResolutionUnit inch SceneCaptureType standard SensingMethod {one chip color area sensor} ShutterSpeedValue 1/60 UserComment {} WhiteBalance auto XResolution 180 YCbCrPositioning centered YResolution 180

Added modules/jpeg/test-assets/IMG_7898.info.txt.



>
1
version 1.1 units 1 xdensity 180 ydensity 180 xthumb 0 ythumb 0

Added modules/jpeg/test-assets/IMG_7898.thumbexif.txt.



>
1
Compression JPEG ExifByteOrder little ExifOffset 30 JPEGInterchangeFormat 5108 JPEGInterchangeFormatLength 6496 ResolutionUnit inch XResolution 180 YResolution 180

Added modules/jpeg/test-assets/IMG_7917.JPG.

cannot compute difference between binary files

Added modules/jpeg/test-assets/IMG_7917.JPG.thumb.

cannot compute difference between binary files

Added modules/jpeg/test-assets/IMG_7917.WxH.txt.



>
1
320 240

Added modules/jpeg/test-assets/IMG_7917.exif.txt.



>
1
ApertureValue 3.5 ColorSpace sRGB ComponentsConfiguration 1,2,3,0 CompressedBitsPerPixel 5 CustomRendered normal DateTime {2008:03:14 16:20:16} DateTimeDigitized {2008:03:14 16:20:16} DateTimeOriginal {2008:03:14 16:20:16} DigitalZoomRatio 1 ExifByteOrder little ExifImageHeight 2448 ExifImageWidth 3264 ExifOffset 30 ExifVersion 2.2 ExposureBiasValue 0 ExposureMode auto ExposureTime 1/60 FNumber 3.2 FileSource {digital still camera} Flash {flash did not fire, compulsory flash mode} FlashpixVersion {Flashpix Format Version 1.0} FocalLength 6 FocalPlaneResolutionUnit inch FocalPlaneXResolution 14506.67 FocalPlaneYResolution 14485.21 ISOSpeedRatings 80 InteroperabilityIndex R98 InteroperabilityVersion 0100 Make Canon MaxApertureValue 3.0 MeteringMode multi-segment Model {Canon PowerShot S5 IS} Orientation normal RelatedImageLength 2448 RelatedImageWidth 3264 ResolutionUnit inch SceneCaptureType standard SensingMethod {one chip color area sensor} ShutterSpeedValue 1/60 UserComment {} WhiteBalance auto XResolution 180 YCbCrPositioning centered YResolution 180

Added modules/jpeg/test-assets/IMG_7917.info.txt.



>
1
version 1.1 units 1 xdensity 180 ydensity 180 xthumb 0 ythumb 0

Added modules/jpeg/test-assets/IMG_7917.thumbexif.txt.



>
1
Compression JPEG ExifByteOrder little ExifOffset 30 JPEGInterchangeFormat 5108 JPEGInterchangeFormatLength 5219 ResolutionUnit inch XResolution 180 YResolution 180

Added modules/jpeg/test-assets/IMG_7950.JPG.

cannot compute difference between binary files

Added modules/jpeg/test-assets/IMG_7950.JPG.thumb.

cannot compute difference between binary files

Added modules/jpeg/test-assets/IMG_7950.WxH.txt.



>
1
320 240

Added modules/jpeg/test-assets/IMG_7950.exif.txt.



>
1
ApertureValue 3.7 ColorSpace sRGB ComponentsConfiguration 1,2,3,0 CompressedBitsPerPixel 5 CustomRendered normal DateTime {2008:03:14 16:54:36} DateTimeDigitized {2008:03:14 16:54:36} DateTimeOriginal {2008:03:14 16:54:36} DigitalZoomRatio 1 ExifByteOrder little ExifImageHeight 2448 ExifImageWidth 3264 ExifOffset 30 ExifVersion 2.2 ExposureBiasValue 0 ExposureMode auto ExposureTime 1/60 FNumber 3.5 FileSource {digital still camera} Flash {flash did not fire, compulsory flash mode} FlashpixVersion {Flashpix Format Version 1.0} FocalLength 6 FocalPlaneResolutionUnit inch FocalPlaneXResolution 14506.67 FocalPlaneYResolution 14485.21 ISOSpeedRatings 80 InteroperabilityIndex R98 InteroperabilityVersion 0100 Make Canon MaxApertureValue 3.0 MeteringMode multi-segment Model {Canon PowerShot S5 IS} Orientation normal RelatedImageLength 2448 RelatedImageWidth 3264 ResolutionUnit inch SceneCaptureType standard SensingMethod {one chip color area sensor} ShutterSpeedValue 1/60 UserComment {} WhiteBalance auto XResolution 180 YCbCrPositioning centered YResolution 180

Added modules/jpeg/test-assets/IMG_7950.info.txt.



>
1
version 1.1 units 1 xdensity 180 ydensity 180 xthumb 0 ythumb 0

Added modules/jpeg/test-assets/IMG_7950.thumbexif.txt.



>
1
Compression JPEG ExifByteOrder little ExifOffset 30 JPEGInterchangeFormat 5108 JPEGInterchangeFormatLength 4181 ResolutionUnit inch XResolution 180 YResolution 180

Added modules/jpeg/test-assets/IMG_7950_none.JPG.

cannot compute difference between binary files

Added modules/jpeg/test-assets/IMG_7950_none.WxH.txt.



>
1
320 240

Added modules/jpeg/test-assets/IMG_7950_none.exif.txt.

Added modules/jpeg/test-assets/IMG_7950_none.info.txt.



>
1
version 1.1 units 1 xdensity 300 ydensity 300 xthumb 0 ythumb 0

Added modules/jpeg/test-assets/IMG_7950_none.thumbexif.txt.

Deleted modules/jpeg/testimages/1000.JPG.

cannot compute difference between binary files

Deleted modules/jpeg/testimages/1000.WxH.txt.

1
1000 1000
<


Deleted modules/jpeg/testimages/1000.exif.txt.

1
ExifByteOrder little ExifOffset 30
<


Deleted modules/jpeg/testimages/1000.info.txt.

1
version 1.1 units 1 xdensity 96 ydensity 96 xthumb 0 ythumb 0
<


Deleted modules/jpeg/testimages/1000.thumbexif.txt.

Deleted modules/jpeg/testimages/IMG_7898.JPG.

cannot compute difference between binary files

Deleted modules/jpeg/testimages/IMG_7898.JPG.thumb.

cannot compute difference between binary files

Deleted modules/jpeg/testimages/IMG_7898.WxH.txt.

1
320 240
<


Deleted modules/jpeg/testimages/IMG_7898.exif.txt.

1
ApertureValue 4.0 ColorSpace sRGB ComponentsConfiguration 1,2,3,0 CompressedBitsPerPixel 5 CustomRendered normal DateTime {2008:03:14 15:40:06} DateTimeDigitized {2008:03:14 15:40:06} DateTimeOriginal {2008:03:14 15:40:06} DigitalZoomRatio 1 ExifByteOrder little ExifImageHeight 2448 ExifImageWidth 3264 ExifOffset 30 ExifVersion 2.2 ExposureBiasValue 0 ExposureMode auto ExposureTime 1/60 FNumber 4.0 FileSource {digital still camera} Flash {flash did not fire, compulsory flash mode} FlashpixVersion {Flashpix Format Version 1.0} FocalLength 6 FocalPlaneResolutionUnit inch FocalPlaneXResolution 14506.67 FocalPlaneYResolution 14485.21 ISOSpeedRatings 80 InteroperabilityIndex R98 InteroperabilityVersion 0100 Make Canon MaxApertureValue 3.0 MeteringMode multi-segment Model {Canon PowerShot S5 IS} Orientation normal RelatedImageLength 2448 RelatedImageWidth 3264 ResolutionUnit inch SceneCaptureType standard SensingMethod {one chip color area sensor} ShutterSpeedValue 1/60 UserComment {} WhiteBalance auto XResolution 180 YCbCrPositioning centered YResolution 180
<


Deleted modules/jpeg/testimages/IMG_7898.info.txt.

1
version 1.1 units 1 xdensity 180 ydensity 180 xthumb 0 ythumb 0
<


Deleted modules/jpeg/testimages/IMG_7898.thumbexif.txt.

1
Compression JPEG ExifByteOrder little ExifOffset 30 JPEGInterchangeFormat 5108 JPEGInterchangeFormatLength 6496 ResolutionUnit inch XResolution 180 YResolution 180
<


Deleted modules/jpeg/testimages/IMG_7917.JPG.

cannot compute difference between binary files

Deleted modules/jpeg/testimages/IMG_7917.JPG.thumb.

cannot compute difference between binary files

Deleted modules/jpeg/testimages/IMG_7917.WxH.txt.

1
320 240
<


Deleted modules/jpeg/testimages/IMG_7917.exif.txt.

1
ApertureValue 3.5 ColorSpace sRGB ComponentsConfiguration 1,2,3,0 CompressedBitsPerPixel 5 CustomRendered normal DateTime {2008:03:14 16:20:16} DateTimeDigitized {2008:03:14 16:20:16} DateTimeOriginal {2008:03:14 16:20:16} DigitalZoomRatio 1 ExifByteOrder little ExifImageHeight 2448 ExifImageWidth 3264 ExifOffset 30 ExifVersion 2.2 ExposureBiasValue 0 ExposureMode auto ExposureTime 1/60 FNumber 3.2 FileSource {digital still camera} Flash {flash did not fire, compulsory flash mode} FlashpixVersion {Flashpix Format Version 1.0} FocalLength 6 FocalPlaneResolutionUnit inch FocalPlaneXResolution 14506.67 FocalPlaneYResolution 14485.21 ISOSpeedRatings 80 InteroperabilityIndex R98 InteroperabilityVersion 0100 Make Canon MaxApertureValue 3.0 MeteringMode multi-segment Model {Canon PowerShot S5 IS} Orientation normal RelatedImageLength 2448 RelatedImageWidth 3264 ResolutionUnit inch SceneCaptureType standard SensingMethod {one chip color area sensor} ShutterSpeedValue 1/60 UserComment {} WhiteBalance auto XResolution 180 YCbCrPositioning centered YResolution 180
<


Deleted modules/jpeg/testimages/IMG_7917.info.txt.

1
version 1.1 units 1 xdensity 180 ydensity 180 xthumb 0 ythumb 0
<


Deleted modules/jpeg/testimages/IMG_7917.thumbexif.txt.

1
Compression JPEG ExifByteOrder little ExifOffset 30 JPEGInterchangeFormat 5108 JPEGInterchangeFormatLength 5219 ResolutionUnit inch XResolution 180 YResolution 180
<


Deleted modules/jpeg/testimages/IMG_7950.JPG.

cannot compute difference between binary files

Deleted modules/jpeg/testimages/IMG_7950.JPG.thumb.

cannot compute difference between binary files

Deleted modules/jpeg/testimages/IMG_7950.WxH.txt.

1
320 240
<


Deleted modules/jpeg/testimages/IMG_7950.exif.txt.

1
ApertureValue 3.7 ColorSpace sRGB ComponentsConfiguration 1,2,3,0 CompressedBitsPerPixel 5 CustomRendered normal DateTime {2008:03:14 16:54:36} DateTimeDigitized {2008:03:14 16:54:36} DateTimeOriginal {2008:03:14 16:54:36} DigitalZoomRatio 1 ExifByteOrder little ExifImageHeight 2448 ExifImageWidth 3264 ExifOffset 30 ExifVersion 2.2 ExposureBiasValue 0 ExposureMode auto ExposureTime 1/60 FNumber 3.5 FileSource {digital still camera} Flash {flash did not fire, compulsory flash mode} FlashpixVersion {Flashpix Format Version 1.0} FocalLength 6 FocalPlaneResolutionUnit inch FocalPlaneXResolution 14506.67 FocalPlaneYResolution 14485.21 ISOSpeedRatings 80 InteroperabilityIndex R98 InteroperabilityVersion 0100 Make Canon MaxApertureValue 3.0 MeteringMode multi-segment Model {Canon PowerShot S5 IS} Orientation normal RelatedImageLength 2448 RelatedImageWidth 3264 ResolutionUnit inch SceneCaptureType standard SensingMethod {one chip color area sensor} ShutterSpeedValue 1/60 UserComment {} WhiteBalance auto XResolution 180 YCbCrPositioning centered YResolution 180
<


Deleted modules/jpeg/testimages/IMG_7950.info.txt.

1
version 1.1 units 1 xdensity 180 ydensity 180 xthumb 0 ythumb 0
<


Deleted modules/jpeg/testimages/IMG_7950.thumbexif.txt.

1
Compression JPEG ExifByteOrder little ExifOffset 30 JPEGInterchangeFormat 5108 JPEGInterchangeFormatLength 4181 ResolutionUnit inch XResolution 180 YResolution 180
<


Deleted modules/jpeg/testimages/IMG_7950_none.JPG.

cannot compute difference between binary files

Deleted modules/jpeg/testimages/IMG_7950_none.WxH.txt.

1
320 240
<


Deleted modules/jpeg/testimages/IMG_7950_none.exif.txt.

Deleted modules/jpeg/testimages/IMG_7950_none.info.txt.

1
version 1.1 units 1 xdensity 300 ydensity 300 xthumb 0 ythumb 0
<


Deleted modules/jpeg/testimages/IMG_7950_none.thumbexif.txt.

Changes to modules/json/json.man.

106
107
108
109
110
111
112
113
114
}]

[section RELATED]

To write json, instead of parsing it, see package [package json::write].

[vset CATEGORY json]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

106
107
108
109
110
111
112
113
114
}]

[section RELATED]

To write json, instead of parsing it, see package [package json::write].

[vset CATEGORY json]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/json/json_write.man.

84
85
86
87
88
89
90
91
92
[para]

[section RELATED]

To parse json, instead of writing it, see package [package json].

[vset CATEGORY json]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

84
85
86
87
88
89
90
91
92
[para]

[section RELATED]

To parse json, instead of writing it, see package [package json].

[vset CATEGORY json]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/lambda/lambda.man.

81
82
83
84
85
86
87
88
89

[list_end]

[section AUTHORS]
Andreas Kupries

[vset CATEGORY lambda]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

81
82
83
84
85
86
87
88
89

[list_end]

[section AUTHORS]
Andreas Kupries

[vset CATEGORY lambda]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/lazyset/lazyset.man.

72
73
74
75
76
77
78
79
80
	puts $simple
}]

[section AUTHORS]
Roy Keene

[vset CATEGORY utility]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

72
73
74
75
76
77
78
79
80
	puts $simple
}]

[section AUTHORS]
Roy Keene

[vset CATEGORY utility]
[include ../common-text/feedback.inc]
[manpage_end]

Deleted modules/ldap/data/d6c9cfba.ldif.

1
2
3
4
5
6

dn: group #0
FILES: aaaaaaa
 bbbbbbbbb
  ccccccccccc
   dddddddddddd
<
<
<
<
<
<












Changes to modules/ldap/ldap.man.

541
542
543
544
545
546
547
548
549
	puts ""
    }
    ldap::unbind $handle
    ldap::disconnect $handle
}]

[vset CATEGORY ldap]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

541
542
543
544
545
546
547
548
549
	puts ""
    }
    ldap::unbind $handle
    ldap::disconnect $handle
}]

[vset CATEGORY ldap]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/ldap/ldap.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# ldap.test - Copyright (C) 2006 Michael Schlenker <[email protected]>
#
# Tests for the Tcllib ldap package
#
# -------------------------------------------------------------------------
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# -------------------------------------------------------------------------
# RCS: @(#) $Id: ldap.test,v 1.5 2008/07/20 19:50:55 mic42 Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2.0

testing {
    useLocal ldap.tcl ldap
    useLocal ../asn/asn.tcl asn
}


namespace import ::asn::*

# -------------------------------------------------------------------------
# Tests








<












|







1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# ldap.test - Copyright (C) 2006 Michael Schlenker <[email protected]>
#
# Tests for the Tcllib ldap package
#
# -------------------------------------------------------------------------
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# -------------------------------------------------------------------------


# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2.0

testing {
    useLocal ldap.tcl ldap
    use      asn/asn.tcl asn
}


namespace import ::asn::*

# -------------------------------------------------------------------------
# Tests

Changes to modules/ldap/ldapx.man.

766
767
768
769
770
771
772
773
774
    liout destroy
    liin destroy
}]

[section References]

[vset CATEGORY ldap]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

766
767
768
769
770
771
772
773
774
    liout destroy
    liin destroy
}]

[section References]

[vset CATEGORY ldap]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/ldap/ldapx.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# -*- tcl -*-
# ldapx.test:  tests for the ldapx module.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2006 by Pierre David <[email protected]>
# All rights reserved.
#
# $Id: ldapx.test,v 1.6 2007/08/19 20:20:43 pdav Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]









<
<







1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
# -*- tcl -*-
# ldapx.test:  tests for the ldapx module.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2006 by Pierre David <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
} {}


# -------------------------------------------------------------------------

test ldax-d6c9cfba {ldapx continuation line handling} {
    ::ldapx::ldif create ldin
    ldin channel [open $::tcltest::testsDirectory/data/d6c9cfba.ldif r]
    ::ldapx::entry create entr

    ldin read entr
    set r [entr get1 files]

    entr destroy
    ldin destroy







|







369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
} {}


# -------------------------------------------------------------------------

test ldax-d6c9cfba {ldapx continuation line handling} {
    ::ldapx::ldif create ldin
    ldin channel [open [asset d6c9cfba.ldif] r]
    ::ldapx::entry create entr

    ldin read entr
    set r [entr get1 files]

    entr destroy
    ldin destroy

Added modules/ldap/test-assets/d6c9cfba.ldif.













>
>
>
>
>
>
1
2
3
4
5
6

dn: group #0
FILES: aaaaaaa
 bbbbbbbbb
  ccccccccccc
   dddddddddddd

Changes to modules/log/log.man.

281
282
283
284
285
286
287
288
289

[emph Note] that by default all messages with levels [const warning] down to
[const debug] are suppressed. This is done intentionally, because (we believe
that) in most situations debugging output is not wanted. Most people wish to
have such output only when actually debugging an application.

[vset CATEGORY log]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

281
282
283
284
285
286
287
288
289

[emph Note] that by default all messages with levels [const warning] down to
[const debug] are suppressed. This is done intentionally, because (we believe
that) in most situations debugging output is not wanted. Most people wish to
have such output only when actually debugging an application.

[vset CATEGORY log]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/log/log.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# -*- tcl -*-
# Tests for the log facility
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2001 by ActiveState Tool Corp.
# All rights reserved.
#
# RCS: @(#) $Id: log.test,v 1.10 2008/09/25 21:52:57 eee Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]









<
<







1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
# -*- tcl -*-
# Tests for the log facility
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2001 by ActiveState Tool Corp.
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

438
439
440
441
442
443
444


445
446
447

	set log [join [split [viewFile test.log] \n]]
	removeFile test.log
	list [string match *__data__* $log] [string match *__NOT__* $log]
    } {1 0}
}
::log::lvChannelForall {}



testsuiteCleanup
return







>
>



436
437
438
439
440
441
442
443
444
445
446
447

	set log [join [split [viewFile test.log] \n]]
	removeFile test.log
	list [string match *__data__* $log] [string match *__NOT__* $log]
    } {1 0}
}
::log::lvChannelForall {}

# -------------------------------------------------------------------------

testsuiteCleanup
return

Changes to modules/log/logger.man.

1
2
3

4
5
6
7
8
9
10
[comment {-*- tcl -*- doctools manpage}]
[comment {$Id: logger.man,v 1.26 2012/07/10 03:34:47 andreas_kupries Exp $}]
[vset VERSION 0.9.4]

[manpage_begin logger n [vset VERSION]]
[keywords log]
[keywords {log level}]
[keywords logger]
[keywords service]
[moddesc {Object Oriented logging facility}]
[titledesc {System to control logging of events.}]
<
<

>









1
2
3
4
5
6
7
8
9


[vset VERSION 0.9.4]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin logger n [vset VERSION]]
[keywords log]
[keywords {log level}]
[keywords logger]
[keywords service]
[moddesc {Object Oriented logging facility}]
[titledesc {System to control logging of events.}]
389
390
391
392
393
394
395
396
397

     # install as logproc
     ${log}::logproc debug log_local_var
     }
]

[vset CATEGORY logger]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

388
389
390
391
392
393
394
395
396

     # install as logproc
     ${log}::logproc debug log_local_var
     }
]

[vset CATEGORY logger]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/log/logger.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# -*- tcl -*-
# Tests for the logger facility.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2002 by David N. Welton <[email protected]>.
# Copyright (c) 2004,2005 by Michael Schlenker <[email protected]>.
#
# $Id: logger.test,v 1.33 2011/12/21 21:28:50 mic42 Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]









<
<







1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
# -*- tcl -*-
# Tests for the logger facility.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2002 by David N. Welton <[email protected]>.
# Copyright (c) 2004,2005 by Michael Schlenker <[email protected]>.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

Changes to modules/log/loggerAppender.man.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

[comment {-*- tcl -*- doctools manpage}]
[comment {$Id: loggerAppender.man,v 1.6 2009/01/29 06:16:19 andreas_kupries Exp $}]
[manpage_begin logger::appender n 1.2]
[keywords appender]
[keywords logger]
[copyright {2005 Aamer Akhter <[email protected]>}]
[moddesc {Object Oriented logging facility}]
[titledesc {Collection of predefined appenders for logger}]
[category  {Programming tools}]
[require Tcl 8.2]
[require logger::appender [opt 1.2]]
[description]

This package provides a predefined set of logger templates.

[list_begin definitions]

[call [cmd ::logger::appender::console] \
>

<
|







|







1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[vset VERSION 1.2]
[comment {-*- tcl -*- doctools manpage}]

[manpage_begin logger::appender n [vset VERSION]]
[keywords appender]
[keywords logger]
[copyright {2005 Aamer Akhter <[email protected]>}]
[moddesc {Object Oriented logging facility}]
[titledesc {Collection of predefined appenders for logger}]
[category  {Programming tools}]
[require Tcl 8.2]
[require logger::appender [opt [vset VERSION]]]
[description]

This package provides a predefined set of logger templates.

[list_begin definitions]

[call [cmd ::logger::appender::console] \
57
58
59
60
61
62
63
64
65

See [cmd ::logger::appender::colorConsole] for a description of the
applicable options.

[list_end]

[vset CATEGORY logger]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

57
58
59
60
61
62
63
64
65

See [cmd ::logger::appender::colorConsole] for a description of the
applicable options.

[list_end]

[vset CATEGORY logger]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/log/loggerAppender.tcl.

1
2
3
4
5
6
7
8
9
10
##Library Header
#
# $Id: loggerAppender.tcl,v 1.4 2007/02/08 22:09:54 mic42 Exp $
# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::appender
#
# Purpose:
#	collection of appenders for tcllib logger


<







1
2

3
4
5
6
7
8
9
##Library Header
#

# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::appender
#
# Purpose:
#	collection of appenders for tcllib logger
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
	emergency red-bold
    }
}



##Procedure Header
# $Id: loggerAppender.tcl,v 1.4 2007/02/08 22:09:54 mic42 Exp $
# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::appender::console
#
# Purpose:
#	 







<







68
69
70
71
72
73
74

75
76
77
78
79
80
81
	emergency red-bold
    }
}



##Procedure Header

# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::appender::console
#
# Purpose:
#	 
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
    set myProcNameVar $procName
    return $procText
}



##Procedure Header
# $Id: loggerAppender.tcl,v 1.4 2007/02/08 22:09:54 mic42 Exp $
# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::appender::colorConsole
#
# Purpose:
#	 







<







170
171
172
173
174
175
176

177
178
179
180
181
182
183
    set myProcNameVar $procName
    return $procText
}



##Procedure Header

# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::appender::colorConsole
#
# Purpose:
#	 
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
	      -category $service \
	      -priority $level ]
    set myProcNameVar $procName
    return $procText
}

##Procedure Header
# $Id: loggerAppender.tcl,v 1.4 2007/02/08 22:09:54 mic42 Exp $
# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#       ::logger::appender::fileAppend
#
# Purpose:
#







<







276
277
278
279
280
281
282

283
284
285
286
287
288
289
	      -category $service \
	      -priority $level ]
    set myProcNameVar $procName
    return $procText
}

##Procedure Header

# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#       ::logger::appender::fileAppend
#
# Purpose:
#
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
    return $procText
}
  	 



##Internal Procedure Header
# $Id: loggerAppender.tcl,v 1.4 2007/02/08 22:09:54 mic42 Exp $
# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#       ::logger::appender::genProcName
#
# Purpose:
#        







<







387
388
389
390
391
392
393

394
395
396
397
398
399
400
    return $procText
}
  	 



##Internal Procedure Header

# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#       ::logger::appender::genProcName
#
# Purpose:
#        

Changes to modules/log/loggerUtils.man.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

[comment {-*- tcl -*- doctools manpage}]
[comment {$Id: loggerUtils.man,v 1.7 2009/01/29 06:16:19 andreas_kupries Exp $}]
[manpage_begin logger::utils n 1.3]
[keywords appender]
[keywords logger]
[copyright {2005 Aamer Akhter <[email protected]>}]
[moddesc {Object Oriented logging facility}]
[titledesc {Utilities for logger}]
[category  {Programming tools}]
[require Tcl 8.4]
[require logger::utils [opt 1.3]]
[description]

This package adds template based [term appenders].

[list_begin definitions]

[call [cmd ::logger::utils::createFormatCmd] [arg formatString]]
>

<
|







|







1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[vset VERSION 1.3.1]
[comment {-*- tcl -*- doctools manpage}]

[manpage_begin logger::utils n [vset VERSION]]
[keywords appender]
[keywords logger]
[copyright {2005 Aamer Akhter <[email protected]>}]
[moddesc {Object Oriented logging facility}]
[titledesc {Utilities for logger}]
[category  {Programming tools}]
[require Tcl 8.4]
[require logger::utils [opt [vset VERSION]]]
[description]

This package adds template based [term appenders].

[list_begin definitions]

[call [cmd ::logger::utils::createFormatCmd] [arg formatString]]
141
142
143
144
145
146
147
148
149
  logger::utils::applyAppender -appender console
  set log [logger::init applyAppender-3]
  ${log}::error "this is an error"
}]
[list_end]

[vset CATEGORY logger]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

141
142
143
144
145
146
147
148
149
  logger::utils::applyAppender -appender console
  set log [logger::init applyAppender-3]
  ${log}::error "this is an error"
}]
[list_end]

[vset CATEGORY logger]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/log/loggerUtils.tcl.

1
2
3
4
5
6
7
8
9
10
##Library Header
#
# $Id: loggerUtils.tcl,v 1.6 2007/03/20 16:22:16 andreas_kupries Exp $
# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::utils::
#
# Purpose:
#	an extension to the tcllib logger module


<







1
2

3
4
5
6
7
8
9
##Library Header
#

# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::utils::
#
# Purpose:
#	an extension to the tcllib logger module
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
    logger::import -force -namespace log logger::utils

    # @mdgen OWNER: msgs/*.msg
    ::msgcat::mcload [file join $packageDir msgs]
}

##Internal Procedure Header
# $Id: loggerUtils.tcl,v 1.6 2007/03/20 16:22:16 andreas_kupries Exp $
# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::utils::createFormatCmd
#
# Purpose:
#







<







54
55
56
57
58
59
60

61
62
63
64
65
66
67
    logger::import -force -namespace log logger::utils

    # @mdgen OWNER: msgs/*.msg
    ::msgcat::mcload [file join $packageDir msgs]
}

##Internal Procedure Header

# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::utils::createFormatCmd
#
# Purpose:
#
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

    return $text
}



##Procedure Header
# $Id: loggerUtils.tcl,v 1.6 2007/03/20 16:22:16 andreas_kupries Exp $
# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::utils::createLogProc
#
# Purpose:
#







<







158
159
160
161
162
163
164

165
166
167
168
169
170
171

    return $text
}



##Procedure Header

# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::utils::createLogProc
#
# Purpose:
#
266
267
268
269
270
271
272



273
274
275
276
277
278
279
280
281
282
283
	}


	if {[regexp {%M} $text]} {
	    set methodText {
		if {[info level] < 2} {
		    set method "global"



		} else {
		    set method [lindex [info level -1] 0]
		}

	    }

	    regsub -all -- \
		{%M} \
		$text \
		{$method} \
		text







>
>
>



<







263
264
265
266
267
268
269
270
271
272
273
274
275

276
277
278
279
280
281
282
	}


	if {[regexp {%M} $text]} {
	    set methodText {
		if {[info level] < 2} {
		    set method "global"
		} elseif {[uplevel 1 {namespace which self}] == "::oo::Helpers::self"} {
		    set    method    [uplevel 1 {self class}]
		    append method :: [uplevel 1 {self method}]
		} else {
		    set method [lindex [info level -1] 0]
		}

	    }

	    regsub -all -- \
		{%M} \
		$text \
		{$method} \
		text
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329

    set procText [subst $procText]
    return $procText
}


##Procedure Header
# $Id: loggerUtils.tcl,v 1.6 2007/03/20 16:22:16 andreas_kupries Exp $
# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::utils::applyAppender
#
# Purpose:
#







<







314
315
316
317
318
319
320

321
322
323
324
325
326
327

    set procText [subst $procText]
    return $procText
}


##Procedure Header

# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::utils::applyAppender
#
# Purpose:
#
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
	    ${srvCmd}::logproc $lvl $procName
	}
    }
}


##Internal Procedure Header
# $Id: loggerUtils.tcl,v 1.6 2007/03/20 16:22:16 andreas_kupries Exp $
# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::utils::autoApplyAppender
#
# Purpose:
#







<







448
449
450
451
452
453
454

455
456
457
458
459
460
461
	    ${srvCmd}::logproc $lvl $procName
	}
    }
}


##Internal Procedure Header

# Copyright (c) 2005 Cisco Systems, Inc.
#
# Name:
#	::logger::utils::autoApplyAppender
#
# Purpose:
#
530
531
532
533
534
535
536
537
538
539
540
541
    }
    logger::utils::applyAppender -appender $appender -serviceCmd $log \
	-levels $levels -appenderArgs $appenderArgs
    return $log
}


package provide logger::utils 1.3

# ;;; Local Variables: ***
# ;;; mode: tcl ***
# ;;; End: ***







|




527
528
529
530
531
532
533
534
535
536
537
538
    }
    logger::utils::applyAppender -appender $appender -serviceCmd $log \
	-levels $levels -appenderArgs $appenderArgs
    return $log
}


package provide logger::utils 1.3.1

# ;;; Local Variables: ***
# ;;; mode: tcl ***
# ;;; End: ***

Changes to modules/log/loggerUtils.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# -*- tcl -*-
# Tests for the utilities to the logger facility.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2005 by Aamer Aahkter
#
# $Id: loggerUtils.test,v 1.7 2006/10/09 21:41:41 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]








<
<







1
2
3
4
5
6
7


8
9
10
11
12
13
14
# -*- tcl -*-
# Tests for the utilities to the logger facility.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2005 by Aamer Aahkter



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
testing {
    useLocal loggerUtils.tcl logger::utils
}

# -------------------------------------------------------------------------

logger::setlevel debug

# -------------------------------------------------------------------------

namespace eval ::loggerExtension::test {

    ::tcltest::test load {} -setup {
    } -constraints {
    } -cleanup {
    } -body {
    } -returnCodes {
        ok
    } -result {}



    ::tcltest::test createFormatCmd-1 {
    check for %d
    } -setup {
    } -constraints {
    } -cleanup {
    } -body {
    set a [logger::utils::createFormatCmd %d]
    set b [subst $a]
    regexp {\d\d\d\d/\d\d/\d\d \d\d:\d\d:\d\d} $b
    } -result {1}

    ::tcltest::test createFormatCmd-2 {
    check for %P
    } -setup {
    } -constraints {
    } -cleanup {
    } -body {
    set a [logger::utils::createFormatCmd %P]
    set b [subst $a]
    } -returnCodes {
        ok
    } -result [pid]

    ::tcltest::test createFormatCmd-3 {
    check for %H
    } -setup {
    } -constraints {
    } -cleanup {
    } -body {
    set a [logger::utils::createFormatCmd %H]
    set b [subst $a]
    } -returnCodes {
        ok
    } -result [info hostname]

    ::tcltest::test createFormatCmd-4 {
    check for %c
    } -setup {
    } -constraints {
    } -cleanup {
    } -body {
    set a [logger::utils::createFormatCmd %c -category test::cat ] 
    set b [subst $a]
    } -returnCodes {
        ok
    } -result test::cat

    ::tcltest::test createFormatCmd-5 {
    check for %C
    } -setup {
    } -constraints {
    } -cleanup {
    } -body {
    set a [logger::utils::createFormatCmd %C -category test::cat ] 
    set b [subst $a]
    } -returnCodes {
        ok
    } -result test

    ::tcltest::test createFormatCmd-6 {
    check for %p
    } -setup {
    } -constraints {
    } -cleanup {
    } -body {
    set a [logger::utils::createFormatCmd %p -category test::cat -priority error] 
    set b [subst $a]
    } -returnCodes {
        ok
    } -result error


    ::tcltest::test createLogProc-1 {
    create a proc and test it
    } -setup {
    } -constraints {
    } -cleanup {

    } -body {
    set a [logger::utils::createLogProc \
           -category catTest \
           -priority critical \
           -procName ::bobo \
           -conversionPattern {\[%d\] \[%c\] \[%M\] \[%p\] %m}]
    eval $a
    ::bobo test


    } -returnCodes {ls
























    ok
    }  -match regexp \
    -output {\[[\d:\/ ]+\] \[catTest\] \[namespace\] \[critical\] test}

    ::tcltest::test applyAppender-1 {
    apply an appender 
    } -setup {
    } -constraints {
    } -cleanup {
    ${log}::delete
    unset log

    } -body {
    set log [logger::init testLog]
    logger::utils::applyAppender -appender console -serviceCmd $log

    ${log}::error "this is error"
    } -returnCodes {
        ok

    }  -match regexp \
    -output {\[[\d:\/ ]+\] \[testLog\] \[namespace\] \[error\] this is error}

    ::tcltest::test applyAppender-2 {
    apply an appender, to 2 loggers
    } -setup {
    } -constraints {
    } -cleanup {
    ${log1}::delete
    ${log2}::delete
    unset log1
    unset log2

    } -body {
    set log1 [logger::init testLog1]
    set log2 [logger::init testLog2]
    logger::utils::applyAppender -appender console -serviceCmd [list $log1 $log2]

    ${log1}::error "this is error1"
    ${log2}::error "this is error2"
    } -returnCodes {
        ok
    }  -match regexp \
    -output {\[[\d:\/ ]+\] \[testLog1\] \[namespace\] \[error\] this is error1\n\[[\d:\/ ]+\] \[testLog2\] \[namespace\] \[error\] this is error2}



    ::tcltest::test applyAppender-3 {
    auto apply

    } -setup {
    } -constraints {
    } -cleanup {

    } -body {
    logger::utils::applyAppender -appender console
    set log [logger::init applyAppender-3]

    ${log}::error "this is error"
    } -returnCodes {
        ok

    } -match regexp \
    -output {\[[\d:\/ ]+\] \[applyAppender-3\] \[namespace\] \[error\] this is error}

    ::tcltest::test applyAppender-4 {
    auto apply

    } -setup {
    } -constraints {
    } -cleanup {

    } -body {
    logger::utils::applyAppender -appender colorConsole
    set log [logger::init applyAppender-4]

    ${log}::error "this is error"
    } -returnCodes {
        ok

    } -match regexp \
    -output {\[[\d:\/ ]+\] \[applyAppender-4\] \[namespace\] \[error\] this is error}

    ::tcltest::test applyAppender-5 {
    auto apply fileAppend
    } -setup {
    } -constraints {
    } -cleanup {

    } -body {
    logger::utils::applyAppender \

        -appender fileAppend -appenderArgs {-outputChannel stderr}
    set log [logger::init applyAppender-5]

    ${log}::error "this is error"
    } -returnCodes {
    ok
    } -match regexp \
    -errorOutput {\[[\d:\/ ]+\] \[applyAppender-5\] \[namespace\] \[error\] this is error}
    

}


testsuiteCleanup

# ;;; Local Variables: ***
# ;;; mode: tcl ***
# ;;; End: ***








|
|
|
|
<
<
<
<
<
<
<

>

|
<
|
<
<
|

|

|

|
<
|
<
<
|


<
<
|

|
<
|
<
<
|


<
<
|

|
<
|
<
<
|


<
<
|

|
<
|
<
<
|


<
<
|

|
<
|
<
<
|


<
<
|

<
|
<
|
<
<
>
|
|
|
|
|
|
|
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
|
<

|
<
<
<
<


>
|


>
|
<
<
>
|
<

|
<
<
<
<




>
|



>
|
|
<
<
<
<
|
>

|
<
>
|
<
<
>
|


>
|
<
<
>
|
<

|
<
>
|
<
<
>
|


>
|
<
<
>
|
<

|
|
|
<
<
>
|

>
|

>
|
<
<
<
<
|
|
|
|


|



22
23
24
25
26
27
28
29
30
31
32
33







34
35
36
37

38


39
40
41
42
43
44
45

46


47
48
49


50
51
52

53


54
55
56


57
58
59

60


61
62
63


64
65
66

67


68
69
70


71
72
73

74


75
76
77


78
79

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
testing {
    useLocal loggerUtils.tcl logger::utils
}

# -------------------------------------------------------------------------

logger::setlevel debug

proc msg {name {suffix {}}} {
    lappend map @ $name ! $suffix
    return [string map $map {\[[\d:\/ ]+\] \[@\] \[namespace\] \[error\] this is error!}]
}








# -------------------------------------------------------------------------

::tcltest::test createFormatCmd-1 {check for %d} -cleanup {

    unset a b


} -body {
    set a [logger::utils::createFormatCmd %d]
    set b [subst $::a]
    regexp {\d\d\d\d/\d\d/\d\d \d\d:\d\d:\d\d} $b
} -result {1}

::tcltest::test createFormatCmd-2 {check for %P} -cleanup {

    unset a b


} -body {
    set a [logger::utils::createFormatCmd %P]
    set b [subst $a]


} -result [pid]

::tcltest::test createFormatCmd-3 {check for %H} -cleanup {

    unset a b


} -body {
    set a [logger::utils::createFormatCmd %H]
    set b [subst $a]


} -result [info hostname]

::tcltest::test createFormatCmd-4 {check for %c} -cleanup {

    unset a b


} -body {
    set a [logger::utils::createFormatCmd %c -category test::cat ] 
    set b [subst $a]


} -result test::cat

::tcltest::test createFormatCmd-5 {check for %C} -cleanup {

    unset a b


} -body {
    set a [logger::utils::createFormatCmd %C -category test::cat ] 
    set b [subst $a]


} -result test

::tcltest::test createFormatCmd-6 {check for %p} -cleanup {

    unset a b


} -body {
    set a [logger::utils::createFormatCmd %p -category test::cat -priority error] 
    set b [subst $a]


} -result error


::tcltest::test createLogProc-1 {create a proc and test it} -cleanup {

    rename ::bobo {}


    namespace delete ::loggerExtension::test
} -body {
    eval [logger::utils::createLogProc \
	      -category catTest \
	      -priority critical \
	      -procName ::bobo \
	      -conversionPattern {\[%d\] \[%c\] \[%M\] \[%p\] %m}]
    namespace eval ::loggerExtension::test {
	::bobo test
    }
}  -match regexp -output {\[[\d:\/ ]+\] \[catTest\] \[namespace\] \[critical\] test}


::tcltest::test createLogProc-2 {tkt e4d5ef01e7, %M OO context} -constraints tcl8.5plus -setup {
    package require TclOO
    ::oo::class create Main {
	variable log
	constructor {} {
	    set this_inst [namespace current]
	    set this_klaz [info object class $this_inst]
	    set log [::logger::init $this_klaz]
	    ::logger::utils::applyAppender \
		-appender "console" \
		-appenderArgs {-conversionPattern {%d \[%p\] \[%M\] %m}} \
		-serviceCmd $log
	}
	method invoke {} {
	    ${log}::info "hello"
	}
    }
    set main [Main new]
} -cleanup {
    $main destroy
    unset main
    Main destroy
} -body {
    $main invoke
} -match regexp -output {[\d:\/ ]+ \[info\] \[::Main::invoke\] hello}


::tcltest::test applyAppender-1 {apply an appender} -cleanup {




    ${log}::delete
    unset log
    namespace delete ::loggerExtension::test
} -body {
    set log [logger::init testLog]
    logger::utils::applyAppender -appender console -serviceCmd $log
    namespace eval ::loggerExtension::test {
	${::log}::error "this is error"


    }
} -match regexp -output [msg testLog]


::tcltest::test applyAppender-2 {apply an appender, to 2 loggers} -cleanup {




    ${log1}::delete
    ${log2}::delete
    unset log1
    unset log2
    namespace delete ::loggerExtension::test
} -body {
    set log1 [logger::init testLog1]
    set log2 [logger::init testLog2]
    logger::utils::applyAppender -appender console -serviceCmd [list $log1 $log2]
    namespace eval ::loggerExtension::test {
	${::log1}::error "this is error1"
	${::log2}::error "this is error2"




    }
} -match regexp -output [msg testLog1 1]\n[msg testLog2 2]

::tcltest::test applyAppender-3 {auto apply} -cleanup {

    ${log}::delete
    unset log


    namespace delete ::loggerExtension::test
} -body {
    logger::utils::applyAppender -appender console
    set log [logger::init applyAppender-3]
    namespace eval ::loggerExtension::test {
	${::log}::error "this is error"


    }
} -match regexp -output [msg applyAppender-3]


::tcltest::test applyAppender-4 {auto apply} -cleanup {

    ${log}::delete
    unset log


    namespace delete ::loggerExtension::test
} -body {
    logger::utils::applyAppender -appender colorConsole
    set log [logger::init applyAppender-4]
    namespace eval ::loggerExtension::test {
	${::log}::error "this is error"


    }
} -match regexp -output [msg applyAppender-4]


::tcltest::test applyAppender-5 {auto apply fileAppend} -cleanup {
    ${log}::delete
    unset log


    namespace delete ::loggerExtension::test
} -body {
    logger::utils::applyAppender \
	-appender fileAppend \
	-appenderArgs {-outputChannel stderr}
    set log [logger::init applyAppender-5]
    namespace eval ::loggerExtension::test {
	${::log}::error "this is error"




    }
} -match regexp -errorOutput [msg applyAppender-5]

# -------------------------------------------------------------------------

testsuiteCleanup
return
# ;;; Local Variables: ***
# ;;; mode: tcl ***
# ;;; End: ***

Changes to modules/log/logger_trace.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# -*- tcl -*-
# Tests for the logger facility.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2002 by David N. Welton <[email protected]>.
# Copyright (c) 2004,2005 by Michael Schlenker <[email protected]>.
#
# $Id: logger_trace.test,v 1.2 2006/10/09 21:41:41 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]









<
<







1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
# -*- tcl -*-
# Tests for the logger facility.
#
# Sourcing this file into Tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# Copyright (c) 2002 by David N. Welton <[email protected]>.
# Copyright (c) 2004,2005 by Michael Schlenker <[email protected]>.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

Changes to modules/log/loggerperformance.

1
2
3
4
5
6
7
8
9
10
11
12
# -*- tcl -*-
# loggerperformance.tcl

# $Id: loggerperformance,v 1.2 2004/01/15 06:36:13 andreas_kupries Exp $

# This code is for benchmarking the performance of the log tools.

set auto_path "[file dirname [info script]] $auto_path"
package require logger
package require log

# Set up logger


|
<
<







1
2
3


4
5
6
7
8
9
10
# -*- tcl -*-
# loggerperformance.tcl
#


# This code is for benchmarking the performance of the log tools.

set auto_path "[file dirname [info script]] $auto_path"
package require logger
package require log

# Set up logger

Changes to modules/log/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
if {![package vsatisfies [package provide Tcl] 8]} {return}
package ifneeded log 1.4 [list source [file join $dir log.tcl]]

if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded logger           0.9.4 [list source [file join $dir logger.tcl]]
package ifneeded logger::appender 1.3   [list source [file join $dir loggerAppender.tcl]]

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded logger::utils    1.3   [list source [file join $dir loggerUtils.tcl]]








|
1
2
3
4
5
6
7
8
9
if {![package vsatisfies [package provide Tcl] 8]} {return}
package ifneeded log 1.4 [list source [file join $dir log.tcl]]

if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded logger           0.9.4 [list source [file join $dir logger.tcl]]
package ifneeded logger::appender 1.3   [list source [file join $dir loggerAppender.tcl]]

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded logger::utils    1.3.1 [list source [file join $dir loggerUtils.tcl]]

Changes to modules/markdown/markdown.man.

1
2
3
4
5
6
7
8
[vset VERSION 1.1]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin markdown n [vset VERSION]]
[moddesc   {Markdown to HTML Converter}]
[titledesc {Converts Markdown text to HTML}]
[category  {Text processing}]
[require Tcl 8.5]
[require Markdown [vset VERSION]]
|







1
2
3
4
5
6
7
8
[vset VERSION 1.1.1]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin markdown n [vset VERSION]]
[moddesc   {Markdown to HTML Converter}]
[titledesc {Converts Markdown text to HTML}]
[category  {Text processing}]
[require Tcl 8.5]
[require Markdown [vset VERSION]]
45
46
47
48
49
50
51
52
53
[call [cmd ::Markdown::reset_lang_counter]]

Reset the language counters.

[list_end]

[vset CATEGORY textutil]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

45
46
47
48
49
50
51
52
53
[call [cmd ::Markdown::reset_lang_counter]]

Reset the language counters.

[list_end]

[vset CATEGORY textutil]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/markdown/markdown.tcl.

249
250
251
252
253
254
255
256
257
258
259
260
261
262
263

                        if {$eoc} { break }

                        set line [lindex $lines $index]
                    }
                    set code_result [join $code_result \n]

                    append result <pre><code> $code_result \n </code></pre>
                }
                {^(?:(?:`{3,})|(?:~{3,}))\{?(\S+)?\}?\s*$} {
                    # FENCED CODE BLOCKS
                    set code_result {}
                    if {[string index $line 0] eq {`}} {
                        set end_match {^`{3,}\s*$}
                    } else {







|







249
250
251
252
253
254
255
256
257
258
259
260
261
262
263

                        if {$eoc} { break }

                        set line [lindex $lines $index]
                    }
                    set code_result [join $code_result \n]

                    append result <pre><code> $code_result </code></pre>
                }
                {^(?:(?:`{3,})|(?:~{3,}))\{?(\S+)?\}?\s*$} {
                    # FENCED CODE BLOCKS
                    set code_result {}
                    if {[string index $line 0] eq {`}} {
                        set end_match {^`{3,}\s*$}
                    } else {
804
805
806
807
808
809
810
811
812

    ## \private
    proc html_escape {text} {
        return [string map {& &amp; < &lt; > &gt; \" &quot;} $text]
    }
}

package provide Markdown 1.1








|
|
804
805
806
807
808
809
810
811
812

    ## \private
    proc html_escape {text} {
        return [string map {& &amp; < &lt; > &gt; \" &quot;} $text]
    }
}

package provide Markdown 1.1.1
return

Changes to modules/markdown/markdown.test.


1
2
3
4
5
6
7

# tool.test - Copyright (c) 2016 Sean Woods, Will DuQuette, Caius Project
# -------------------------------------------------------------------------
#-------------------------------------------------------------------------
# TITLE:
#    markdown.test
#
# PROJECT:
>







1
2
3
4
5
6
7
8
# -*- tcl -*-
# tool.test - Copyright (c) 2016 Sean Woods, Will DuQuette, Caius Project
# -------------------------------------------------------------------------
#-------------------------------------------------------------------------
# TITLE:
#    markdown.test
#
# PROJECT:
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
}

#-------------------------------------------------------------------------
# Setup

tcltest::testConstraint knownbug 0


# outdent text
#
# text   - A multi-line text string
#
# This command outdents a multi-line text string to the left margin.

proc outdent {text} {
    # FIRST, remove any leading blank lines
    regsub {\A(\s*\n)} $text "" text

    # NEXT, remove any trailing whitespace
    set text [string trimright $text]

    # NEXT, get the length of the leading on the first line.
    if {[regexp {\A(\s*)\S} $text dummy leader]} {

        # Remove the leader from the beginning of each indented
        # line, and update the string.
        regsub -all -line "^$leader" $text "" text
    }








<













|







29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
}

#-------------------------------------------------------------------------
# Setup

tcltest::testConstraint knownbug 0


# outdent text
#
# text   - A multi-line text string
#
# This command outdents a multi-line text string to the left margin.

proc outdent {text} {
    # FIRST, remove any leading blank lines
    regsub {\A(\s*\n)} $text "" text

    # NEXT, remove any trailing whitespace
    set text [string trimright $text]

    # NEXT, get the length of the leader on the first line.
    if {[regexp {\A(\s*)\S} $text dummy leader]} {

        # Remove the leader from the beginning of each indented
        # line, and update the string.
        regsub -all -line "^$leader" $text "" text
    }

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

    <h3>Heading 3</h3>

    <p>This is what he said. This is what she said. This is what
    he said. This is what she said.</p>

    <pre><code>import os
    os.path.listdir()
    </code></pre>

    <p>This is what he said. This is what she said. This is what
    he said. This is what she said.</p>
    </blockquote>

    <h2>Heading 2</h2>

    <p>This is what he said. This is what she said. This is what
    he said. This is what she said.</p>
    </blockquote>

    <p>This is a test.</p>
}



test convert-2.2 {refs} -body {
    convert {
        Find it [here][foo]!

        [foo]: http://example.com/  "Optional Title Here"
    }
} -result {
    <p>Find it <a href="http://example.com/" title="Optional Title Here">here</a>!</p>
}

















#=========================================================================
# Tests related to other processors or test suites

#-------------------------------------------------------------------------
# Caius Markdown Tests
#







|
<














<
<










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

    <h3>Heading 3</h3>

    <p>This is what he said. This is what she said. This is what
    he said. This is what she said.</p>

    <pre><code>import os
    os.path.listdir()</code></pre>


    <p>This is what he said. This is what she said. This is what
    he said. This is what she said.</p>
    </blockquote>

    <h2>Heading 2</h2>

    <p>This is what he said. This is what she said. This is what
    he said. This is what she said.</p>
    </blockquote>

    <p>This is a test.</p>
}



test convert-2.2 {refs} -body {
    convert {
        Find it [here][foo]!

        [foo]: http://example.com/  "Optional Title Here"
    }
} -result {
    <p>Find it <a href="http://example.com/" title="Optional Title Here">here</a>!</p>
}

test code-block-1.0 {basic code block render} -body {
    convert {
	pre code

	    in code

	post code
    }
} -result {
    <p>pre code</p>

    <pre><code>in code</code></pre>

    <p>post code</p>
}

#=========================================================================
# Tests related to other processors or test suites

#-------------------------------------------------------------------------
# Caius Markdown Tests
#
310
311
312
313
314
315
316

317
318
319
320
321
322
323
324
325
326

test caius-1.7 {indent test} -body {
    set md   [::tcltest::viewFile test/indent.md]
    set html [::tcltest::viewFile test/indent.html]
    cmp $html [Markdown::convert $md]
} -result {1}
}

#-------------------------------------------------------------------------
# mdtest: Bugs found while running michelf/mdtest


test mdtest-1.1 {AL: Auto links: & not escaped in URL} -body {
    convert {
        Auto-link with ampersand: <http://example.com/?foo=1&bar=2>
    }
} -result {
    <p>Auto-link with ampersand: <a href="http://example.com/?foo=1&amp;bar=2">http://example.com/?foo=1&amp;bar=2</a></p>







>


<







322
323
324
325
326
327
328
329
330
331

332
333
334
335
336
337
338

test caius-1.7 {indent test} -body {
    set md   [::tcltest::viewFile test/indent.md]
    set html [::tcltest::viewFile test/indent.html]
    cmp $html [Markdown::convert $md]
} -result {1}
}

#-------------------------------------------------------------------------
# mdtest: Bugs found while running michelf/mdtest


test mdtest-1.1 {AL: Auto links: & not escaped in URL} -body {
    convert {
        Auto-link with ampersand: <http://example.com/?foo=1&bar=2>
    }
} -result {
    <p>Auto-link with ampersand: <a href="http://example.com/?foo=1&amp;bar=2">http://example.com/?foo=1&amp;bar=2</a></p>

Changes to modules/markdown/pkgIndex.tcl.

1
package ifneeded Markdown 1.1 [list source [file join $dir markdown.tcl]]
|
1
package ifneeded Markdown 1.1.1 [list source [file join $dir markdown.tcl]]

Changes to modules/math/ChangeLog.



















































1
2
3
4
5
6
7


















































2018-08-04  Arjen Markus <[email protected]>
	* statistics.tcl: Source stat_wasserstein.tcl and stat_logit.tcl - for new commands
	* statistics.test: Add corresponding tests
	* statistics.man: Add description of these commands
	* pkgIndex.tcl: Bump the version to 1.3.0

2018-07-22  Arjen Markus <[email protected]>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
2019-11-08  Arjen Markus <[email protected]>
	* statistics.tcl: Add a new type of error message, version to 1.5.0
	* pdf_stat.tcl: Add procedures for Laplace, Kumaraswamy and negative binomial distributions, also tests for homoscedasticity
	* statistics.tcl: Corresponding tests
	* statistics.man: Documentation of the new procedures
	* pkgIndex.tcl: Bumped version of statistics package to 1.5.0

2019-11-04  Arjen Markus <[email protected]>
	* interpolate.tcl: Correct the procedure interp-linear for another pair of corner cases (thanks to Alexandru)

2019-10-29  Arjen Markus <[email protected]>
	* interpolate.tcl: Correct the procedure interp-linear for several corner cases (thanks to Alexandru)
	* pkgIndex.tcl: Bumped version of interpolation package to 1.1.2

2019-09-30  Arjen Markus <[email protected]>
	* special.tcl: Add function incomplete Beta, regularized Beta and digamma
	* special.test: Add tests for the new functions
	* special.man: Describe the new functions
	* pkgIndex.tcl: Bumped version of special functions package to 0.4

2019-08-14  Arjen Markus <[email protected]>
	* math_geometry.man: Describe several procedures that were not described yet
	* geometry.tcl: Export several procedures that were not exported yet
	* pkgIndex.tcl: Bumped version of geometry package to 1.3.1

2019-06-22  Arjen Markus <[email protected]>
	* pdf_stat.tcl: Add procedures for triangular distribution
	* statistics.man: Describe procedures for triangular distribution
	* statistics.test: Add tests for triangular distribution
	* statistics.tcl: Bumped version to 1.3.1
	* pkgIndex.tcl: Bumped version to 1.3.1
2019-05-07  Arjen Markus <[email protected]>
	* quasirandom.test: Add tests to deal with procedures in a different namespace
	* quasirandom.tcl: Deal with procedures in a different namespace

2019-04-24  Arjen Markus <[email protected]>
	* quasirandom.test: Add support code
	* numtheory.tcl: Add estimation of the number of primes between two limits
	* numtheory.test: Add tests regarding the estimated number of primes

2019-04-23  Arjen Markus <[email protected]>
	* quasirandom.tcl: New package - generate quasi-random numbers (for instance for estimating multidimensional integrals)
	* quasirandom.test: Tests for the new package
	* quasirandom.man: Documentation for the new package
	* pkgIndex.tcl: Add the new package

2019-04-18  Arjen Markus <[email protected]>
	* misc.tcl: Add double() to calculation of mean and standard deviation in proc stats (ticket 0a030f850d4e3fc05da98aa954a6ec1b16e655d9)
	* math.test: Correct the outcome of the test for stats (consequence of ticket 0a030f850d4e3fc05da98aa954a6ec1b16e655d9)

2018-08-04  Arjen Markus <[email protected]>
	* statistics.tcl: Source stat_wasserstein.tcl and stat_logit.tcl - for new commands
	* statistics.test: Add corresponding tests
	* statistics.man: Add description of these commands
	* pkgIndex.tcl: Bump the version to 1.3.0

2018-07-22  Arjen Markus <[email protected]>

Changes to modules/math/TODO.

1
2




3
4
5
6
7
8
9
This file records outstanding actions for the math module





dd. 4 september 2018
- Implement a "typical profile" for timeseries and determining residuals
  (Plus perhaps a notion of outliers)
- Implement detection of extreme values/periods with extreme values


dd. 17 june 2018


>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
This file records outstanding actions for the math module

dd. 4 november 2019
- Extend the set of test cases for linear interpolation with corner cases
  - these should fail with a clear error message.

dd. 4 september 2018
- Implement a "typical profile" for timeseries and determining residuals
  (Plus perhaps a notion of outliers)
- Implement detection of extreme values/periods with extreme values


dd. 17 june 2018

Changes to modules/math/bigfloat.man.

424
425
426
427
428
429
430
431
432
set sinProduct [lb]mul [lb]sin $angle1[rb] [lb]sin $angle2[rb][rb]
set cosProduct [lb]mul [lb]cos $angle1[rb] [lb]cos $angle2[rb][rb]
set angle3 [lb]asin [lb]add [lb]mul $sinProduct [lb]cos $opposite3[rb][rb] $cosProduct[rb][rb]
puts "angle3 : [lb]tostr [lb]rad2deg $angle3[rb][rb]"
[example_end]

[vset CATEGORY {math :: bignum :: float}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

424
425
426
427
428
429
430
431
432
set sinProduct [lb]mul [lb]sin $angle1[rb] [lb]sin $angle2[rb][rb]
set cosProduct [lb]mul [lb]cos $angle1[rb] [lb]cos $angle2[rb][rb]
set angle3 [lb]asin [lb]add [lb]mul $sinProduct [lb]cos $opposite3[rb][rb] $cosProduct[rb][rb]
puts "angle3 : [lb]tostr [lb]rad2deg $angle3[rb][rb]"
[example_end]

[vset CATEGORY {math :: bignum :: float}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/bignum.man.

220
221
222
223
224
225
226
227
228
[call [cmd ::math::bignum::bits] [arg bignum]]
Return the number of bits needed to represent bignum in radix 2.

[list_end]
[para]

[vset CATEGORY {math :: bignum}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

220
221
222
223
224
225
226
227
228
[call [cmd ::math::bignum::bits] [arg bignum]]
Return the number of bits needed to represent bignum in radix 2.

[list_end]
[para]

[vset CATEGORY {math :: bignum}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/calculus.man.

443
444
445
446
447
448
449
450
451
   set length 100.0

   set y [lb]::math::calculus::boundaryValueSecondOrder \
      coeffs force {0.0 1.0} [lb]list $length 0.0[rb] 100[rb]
[example_end]

[vset CATEGORY {math :: calculus}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

443
444
445
446
447
448
449
450
451
   set length 100.0

   set y [lb]::math::calculus::boundaryValueSecondOrder \
      coeffs force {0.0 1.0} [lb]list $length 0.0[rb] 100[rb]
[example_end]

[vset CATEGORY {math :: calculus}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/combinatorics.man.

100
101
102
103
104
105
106
107
108
Results are returned as a floating point number precise to better than
nine significant digits provided that [arg w] and [arg z] are both at
least 1.

[list_end]

[vset CATEGORY math]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

100
101
102
103
104
105
106
107
108
Results are returned as a floating point number precise to better than
nine significant digits provided that [arg w] and [arg z] are both at
least 1.

[list_end]

[vset CATEGORY math]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/constants.man.

128
129
130
131
132
133
134
135
136
[def [const onesixth]] One sixth (0.1666....)
[def [const huge]]     (Approximately) largest number
[def [const tiny]]     (Approximately) smallest number not equal zero
[def [const eps]]      Smallest number such that 1+eps != 1
[list_end]

[vset CATEGORY {math :: constants}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

128
129
130
131
132
133
134
135
136
[def [const onesixth]] One sixth (0.1666....)
[def [const huge]]     (Approximately) largest number
[def [const tiny]]     (Approximately) smallest number not equal zero
[def [const eps]]      Smallest number such that 1+eps != 1
[list_end]

[vset CATEGORY {math :: constants}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/decimal.man.

191
192
193
194
195
196
197
198
199
Rounds [emph decimal] to [emph digits] number of decimal points with the following rules: Round zero or five away from 0. The same as round-up, except that rounding up only occurs if the digit to be rounded up is 0 or 5, and after overflow
the result is the same as for round-down.

[list_end]
[para]

[vset CATEGORY decimal]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

191
192
193
194
195
196
197
198
199
Rounds [emph decimal] to [emph digits] number of decimal points with the following rules: Round zero or five away from 0. The same as round-up, except that rounding up only occurs if the digit to be rounded up is 0 or 5, and after overflow
the result is the same as for round-down.

[list_end]
[para]

[vset CATEGORY decimal]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/decimal.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# -*- tcl -*-
# Tests for decimal arithmetic package in math library  -*- tcl -*-
#
# This file contains a collection of tests for one or more of the Tcllib
# procedures.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# $Id: decimal.test,v 1.3 2011/11/09 18:33:22 andreas_kupries Exp $
#
# Copyright (c) 2011 by Mark Alston
# All rights reserved.
#

# -------------------------------------------------------------------------

source [file join \







<
<







1
2
3
4
5
6
7


8
9
10
11
12
13
14
# -*- tcl -*-
# Tests for decimal arithmetic package in math library  -*- tcl -*-
#
# This file contains a collection of tests for one or more of the Tcllib
# procedures.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#


# Copyright (c) 2011 by Mark Alston
# All rights reserved.
#

# -------------------------------------------------------------------------

source [file join \

Changes to modules/math/fourier.man.

126
127
128
129
130
131
132
133
134
[arg_def list in_data] List of data (amplitudes)
[list_end]
[para]

[list_end]

[vset CATEGORY {math :: fourier}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

126
127
128
129
130
131
132
133
134
[arg_def list in_data] List of data (amplitudes)
[list_end]
[para]

[list_end]

[vset CATEGORY {math :: fourier}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/fuzzy.man.

125
126
127
128
129
130
131
132
133
APL QUOTE QUAD 8(3):16-23, March 1978.
[para]
D. Knuth, Art of Computer Programming,

Vol. 1, Problem 1.2.4-5.

[vset CATEGORY {math :: fuzzy}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

125
126
127
128
129
130
131
132
133
APL QUOTE QUAD 8(3):16-23, March 1978.
[para]
D. Knuth, Art of Computer Programming,

Vol. 1, Problem 1.2.4-5.

[vset CATEGORY {math :: fuzzy}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/geometry.tcl.

1548
1549
1550
1551
1552
1553
1554
1555


1556
1557
1558
1559
1560
	nwse rect octant findLineSegmentIntersection \
	findLineIntersection bbox x y conjx conjy \
	calculateDistanceToLine findClosestPointOnLine \
	calculateDistanceToLineSegment findClosestPointOnLineSegment \
	calculateDistanceToPolylineSegment findClosestPointOnPolyline lengthOfPolyline \
	movePointInDirection lineSegmentsIntersect findLineSegmentIntersection findLineIntersection \
	polylinesIntersect polylinesBoundingIntersect intervalsOverlap rectanglesOverlap pointInsidePolygon pointInsidePolygonAlt \
	rectangleInsidePolygon areaPolygon translate rotate reflect degToRad radToDeg


}

source [file join [file dirname [info script]] geometry_circle.tcl]

package provide math::geometry 1.3.0







|
>
>




|
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
	nwse rect octant findLineSegmentIntersection \
	findLineIntersection bbox x y conjx conjy \
	calculateDistanceToLine findClosestPointOnLine \
	calculateDistanceToLineSegment findClosestPointOnLineSegment \
	calculateDistanceToPolylineSegment findClosestPointOnPolyline lengthOfPolyline \
	movePointInDirection lineSegmentsIntersect findLineSegmentIntersection findLineIntersection \
	polylinesIntersect polylinesBoundingIntersect intervalsOverlap rectanglesOverlap pointInsidePolygon pointInsidePolygonAlt \
	rectangleInsidePolygon areaPolygon translate rotate reflect degToRad radToDeg \
	calculateDistanceToPolyline calculateDistanceToPolygon areaParallellogram angle inproduct angleBetween

}

source [file join [file dirname [info script]] geometry_circle.tcl]

package provide math::geometry 1.3.1

Changes to modules/math/interpolate.man.

291
292
293
294
295
296
297
298
299
0.8: 4.11
0.9: 3.95675857843
1.0: 4.12
}]
As you can see, the values at the abscissae are reproduced perfectly.

[vset CATEGORY {math :: interpolate}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

291
292
293
294
295
296
297
298
299
0.8: 4.11
0.9: 3.95675857843
1.0: 4.12
}]
As you can see, the values at the abscissae are reproduced perfectly.

[vset CATEGORY {math :: interpolate}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/interpolate.tcl.

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
# Note:
#    The list xyvalues must be sorted w.r.t. the x-value
#
proc ::math::interpolate::interp-linear { xyvalues xval } {
   #
   # Border cases first
   #
   if { [lindex $xyvalues 0] > $xval } {
      return [lindex $xyvalues 1]
   }
   if { [lindex $xyvalues end-1] < $xval } {
      return [lindex $xyvalues end]
   }

   #
   # The ordinary case
   #
   set idxx -2
   set idxy -1
   foreach { x y } $xyvalues {
      if { $xval < $x } {
         break
      }
      incr idxx 2
      incr idxy 2
   }

   set x2 [lindex $xyvalues $idxx]
   set y2 [lindex $xyvalues $idxy]

   if { $x2 != $x } {
      set yval [expr {$y+($y2-$y)*($xval-$x)/($x2-$x)}]
   } else {
      set yval $y
   }
   return $yval
}

# interp-lagrange --
#    Use the Lagrange interpolation method
#







|


|




















|

|







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
# Note:
#    The list xyvalues must be sorted w.r.t. the x-value
#
proc ::math::interpolate::interp-linear { xyvalues xval } {
   #
   # Border cases first
   #
   if { [lindex $xyvalues 0]+0.0 > $xval } {
      return [lindex $xyvalues 1]
   }
   if { [lindex $xyvalues end-1]+0.0 < $xval } {
      return [lindex $xyvalues end]
   }

   #
   # The ordinary case
   #
   set idxx -2
   set idxy -1
   foreach { x y } $xyvalues {
      if { $xval < $x } {
         break
      }
      incr idxx 2
      incr idxy 2
   }

   set x2 [lindex $xyvalues $idxx]
   set y2 [lindex $xyvalues $idxy]

   if { $x2 != $x } {
      set yval [expr {$y+($y2-$y)*($xval-$x)/double($x2-$x)}]
   } else {
      set yval [expr {double($y)}]
   }
   return $yval
}

# interp-lagrange --
#    Use the Lagrange interpolation method
#
660
661
662
663
664
665
666
667
}



#
# Announce our presence
#
package provide math::interpolate 1.1.1







|
660
661
662
663
664
665
666
667
}



#
# Announce our presence
#
package provide math::interpolate 1.1.2

Changes to modules/math/linalg.man.

960
961
962
963
964
965
966
967
968
namespace eval compute {
    rename ::scale scaleTk
    scaleTk .scale ...
}
}]

[vset CATEGORY {math :: linearalgebra}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

960
961
962
963
964
965
966
967
968
namespace eval compute {
    rename ::scale scaleTk
    scaleTk .scale ...
}
}]

[vset CATEGORY {math :: linearalgebra}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/machineparameters.man.

183
184
185
186
187
188
189
190
191
[call [arg objectname] [method print]]

Print machine parameters on standard output.

[list_end]

[vset CATEGORY math]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

183
184
185
186
187
188
189
190
191
[call [arg objectname] [method print]]

Print machine parameters on standard output.

[list_end]

[vset CATEGORY math]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/math.man.

118
119
120
121
122
123
124
125
126
[call [cmd ::math::sum] [arg value] [opt [arg {value ...}]]]

Return the sum of one or more numeric values.

[list_end]

[vset CATEGORY math]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

118
119
120
121
122
123
124
125
126
[call [cmd ::math::sum] [arg value] [opt [arg {value ...}]]]

Return the sum of one or more numeric values.

[list_end]

[vset CATEGORY math]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/math.test.

214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
} [tcltest::wrongNumArgs math::stats {val1 val2 args} 1]
test math-8.3 { simple math::stats } {
     foreach {a b c} [ math::stats 100 100 100 110 ] { break }
     set a [ expr round($a) ]
     set b [ expr round($b) ]
     set c [ expr round($c) ]
     list $a $b $c
} {102 5 5}

test math-9.1 { math::integrate, insufficient data points } {
     catch { math::integrate {1 10 2 20 3 30 4 40} } msg
     set msg
} "at least 5 x,y pairs must be given"
test math-9.2 { simple math::integrate } {
     math::integrate {1 10 2 20 3 30 4 40 5 50 6 60 7 70 8 80 9 90 10 100}







|







214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
} [tcltest::wrongNumArgs math::stats {val1 val2 args} 1]
test math-8.3 { simple math::stats } {
     foreach {a b c} [ math::stats 100 100 100 110 ] { break }
     set a [ expr round($a) ]
     set b [ expr round($b) ]
     set c [ expr round($c) ]
     list $a $b $c
} {103 5 5}

test math-9.1 { math::integrate, insufficient data points } {
     catch { math::integrate {1 10 2 20 3 30 4 40} } msg
     set msg
} "at least 5 x,y pairs must be given"
test math-9.2 { simple math::integrate } {
     math::integrate {1 10 2 20 3 30 4 40 5 50 6 60 7 70 8 80 9 90 10 100}

Changes to modules/math/math_geometry.man.

167
168
169
170
171
172
173



























174
175
176
177
178
179
180
Calculate the angle from the positive x-axis to a given line
(in two dimensions only).

[list_begin arguments]
[arg_def list line] Coordinates of the line
[list_end]




























[para]

[call [cmd ::math::geometry::calculateDistanceToLine] [arg P] [arg line]]

Calculate the distance of point P to the (infinite) line and return the
result








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
Calculate the angle from the positive x-axis to a given line
(in two dimensions only).

[list_begin arguments]
[arg_def list line] Coordinates of the line
[list_end]

[call [cmd ::math::geometry::angleBetween] [arg vector1] [arg vector2]]

Calculate the angle between two vectors (in degrees)

[list_begin arguments]
[arg_def list vector1] First vector
[arg_def list vector2] Second vector
[list_end]

[call [cmd ::math::geometry::inproduct] [arg vector1] [arg vector2]]

Calculate the inner product of two vectors

[list_begin arguments]
[arg_def list vector1] First vector
[arg_def list vector2] Second vector
[list_end]

[call [cmd ::math::geometry::areaParallellogram] [arg vector1] [arg vector2]]

Calculate the area of the parallellogram with the two vectors as its sides

[list_begin arguments]
[arg_def list vector1] First vector
[arg_def list vector2] Second vector
[list_end]

[para]

[call [cmd ::math::geometry::calculateDistanceToLine] [arg P] [arg line]]

Calculate the distance of point P to the (infinite) line and return the
result

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

[call [cmd ::math::geometry::translate] [arg vector] [arg polyline]]

Translate a polyline over a given vector

[list_begin arguments]
[arg_def list vector]   Translation vector
[arg_def list polyline] The polyline to be rotated
[list_end]

[para]

[call [cmd ::math::geometry::rotate] [arg angle] [arg polyline]]

Rotate a polyline over a given angle (degrees) around the origin

[list_begin arguments]
[arg_def list angle]    Angle over which to rotate the polyline (degrees)
[arg_def list polyline] The polyline to be translated
[list_end]

[para]

[call [cmd ::math::geometry::reflect] [arg angle] [arg polyline]]

Reflect a polyline in a line through the origin at a given angle (degrees) to the x-axis







|










|







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

[call [cmd ::math::geometry::translate] [arg vector] [arg polyline]]

Translate a polyline over a given vector

[list_begin arguments]
[arg_def list vector]   Translation vector
[arg_def list polyline] The polyline to be translated
[list_end]

[para]

[call [cmd ::math::geometry::rotate] [arg angle] [arg polyline]]

Rotate a polyline over a given angle (degrees) around the origin

[list_begin arguments]
[arg_def list angle]    Angle over which to rotate the polyline (degrees)
[arg_def list polyline] The polyline to be rotated
[list_end]

[para]

[call [cmd ::math::geometry::reflect] [arg angle] [arg polyline]]

Reflect a polyline in a line through the origin at a given angle (degrees) to the x-axis
607
608
609
610
611
612
613
614
615
[list_begin enumerated]
[enum] [uri http:/wiki.tcl.tk/12070 {Polygon Intersection}]
[enum] [uri http://en.wikipedia.org/wiki/Line-line_intersection]
[enum] [uri http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/]
[list_end]

[vset CATEGORY {math :: geometry}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

634
635
636
637
638
639
640
641
642
[list_begin enumerated]
[enum] [uri http:/wiki.tcl.tk/12070 {Polygon Intersection}]
[enum] [uri http://en.wikipedia.org/wiki/Line-line_intersection]
[enum] [uri http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/]
[list_end]

[vset CATEGORY {math :: geometry}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/misc.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# math.tcl --
#
#	Collection of math functions.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: misc.tcl,v 1.6 2005/10/10 14:02:47 arjenmarkus Exp $

package require Tcl 8.2		;# uses [lindex $l end-$integer]
namespace eval ::math {
}

# ::math::cov --








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# math.tcl --
#
#	Collection of math functions.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: misc.tcl,v 1.6 2005/10/10 14:02:47 arjenmarkus Exp $

package require Tcl 8.2		;# uses [lindex $l end-$integer]
namespace eval ::math {
}

# ::math::cov --
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
        set sum [ expr { $sum+$val } ]
     }
     set mean [ expr { $sum/$N } ]
     set sigma_sq 0
     foreach val [ concat $val1 $val2 $args ] {
        set sigma_sq [ expr { $sigma_sq+pow(($val-$mean),2) } ]
     }
     set sigma_sq [ expr { $sigma_sq/($N-1) } ] 
     set sigma [ expr { sqrt($sigma_sq) } ]
     if { $mean != 0.0 } { 
        set cov [ expr { ($sigma/$mean)*100 } ]
     } else {
        return -code error -errorinfo "Cov undefined for data with zero mean" -errorcode {ARITH DOMAIN}
     }
     set cov
}








|

|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
        set sum [ expr { $sum+$val } ]
     }
     set mean [ expr { $sum/$N } ]
     set sigma_sq 0
     foreach val [ concat $val1 $val2 $args ] {
        set sigma_sq [ expr { $sigma_sq+pow(($val-$mean),2) } ]
     }
     set sigma_sq [ expr { $sigma_sq/($N-1) } ]
     set sigma [ expr { sqrt($sigma_sq) } ]
     if { $mean != 0.0 } {
        set cov [ expr { ($sigma/$mean)*100 } ]
     } else {
        return -code error -errorinfo "Cov undefined for data with zero mean" -errorcode {ARITH DOMAIN}
     }
     set cov
}

70
71
72
73
74
75
76
77
78
79
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
	return $prev1
    }
}

# ::math::integrate --
#
#	calculate the area under a curve defined by a set of (x,y) data pairs.
#	the x data must increase monotonically throughout the data set for the 
#	calculation to be meaningful, therefore the monotonic condition is
#	tested, and an error is thrown if the x value is found to be
#	decreasing.
#
# Arguments:
#	xy_pairs	list of x y pairs (eg, 0 0 10 10 20 20 ...); at least 5
#			data pairs are required, and if the number of data
#			pairs is even, a padding value of (x0, 0) will be
#			added.
# 
# Results:
#	result		A two-element list consisting of the area and error
#			bound (calculation is "Simpson's rule")

proc ::math::integrate { xy_pairs } {
     
     set length [ llength $xy_pairs ]
     
     if { $length < 10 } {
        return -code error "at least 5 x,y pairs must be given"
     }   
     
     ;## are we dealing with x,y pairs?
     if { [ expr {$length % 2} ] } {
        return -code error "unmatched xy pair in input"
     }
     
     ;## are there an even number of pairs?  Augment.
     if { ! [ expr {$length % 4} ] } {
        set xy_pairs [ concat [ lindex $xy_pairs 0 ] 0 $xy_pairs ]
     }
     set x0   [ lindex $xy_pairs 0     ]
     set x1   [ lindex $xy_pairs 2     ]
     set xn   [ lindex $xy_pairs end-1 ]
     set xnminus1 [ lindex $xy_pairs end-3 ]
    
     if { $x1 < $x0 } {
        return -code error "monotonicity broken by x1"
     }

     if { $xn < $xnminus1 } {
        return -code error "monotonicity broken by xn"
     }   
     
     ;## handle the assymetrical elements 0, n, and n-1.
     set sum [ expr {[ lindex $xy_pairs 1 ] + [ lindex $xy_pairs end ]} ]
     set sum [ expr {$sum + (4*[ lindex $xy_pairs end-2 ])} ]

     set data [ lrange $xy_pairs 2 end-4 ]
     
     set xmax $x1
     set i 1
     foreach {x1 y1 x2 y2} $data {
        incr i
        if { $x1 < $xmax } {
           return -code error "monotonicity broken by x$i"
        }
        set xmax $x1
        incr i
        if { $x2 < $xmax } {
           return -code error "monotonicity broken by x$i"
        }
        set xmax $x2
        set sum [ expr {$sum + (4*$y1) + (2*$y2)} ]
     }   
     
     if { $xmax > $xnminus1 } {
        return -code error "monotonicity broken by xn-1"
     }   
    
     set h [ expr { ( $xn - $x0 ) / $i } ]
     set area [ expr { ( $h / 3.0 ) * $sum } ]
     set err_bound  [ expr { ( ( $xn - $x0 ) / 180.0 ) * pow($h,4) * $xn } ]  
     return [ list $area $err_bound ]
}

# ::math::max --
#
#	Return the maximum of two or more values
#







|









|





|

|


|
|




|








|






|
|





|














|
|


|
|


|







70
71
72
73
74
75
76
77
78
79
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
	return $prev1
    }
}

# ::math::integrate --
#
#	calculate the area under a curve defined by a set of (x,y) data pairs.
#	the x data must increase monotonically throughout the data set for the
#	calculation to be meaningful, therefore the monotonic condition is
#	tested, and an error is thrown if the x value is found to be
#	decreasing.
#
# Arguments:
#	xy_pairs	list of x y pairs (eg, 0 0 10 10 20 20 ...); at least 5
#			data pairs are required, and if the number of data
#			pairs is even, a padding value of (x0, 0) will be
#			added.
#
# Results:
#	result		A two-element list consisting of the area and error
#			bound (calculation is "Simpson's rule")

proc ::math::integrate { xy_pairs } {

     set length [ llength $xy_pairs ]

     if { $length < 10 } {
        return -code error "at least 5 x,y pairs must be given"
     }

     ;## are we dealing with x,y pairs?
     if { [ expr {$length % 2} ] } {
        return -code error "unmatched xy pair in input"
     }

     ;## are there an even number of pairs?  Augment.
     if { ! [ expr {$length % 4} ] } {
        set xy_pairs [ concat [ lindex $xy_pairs 0 ] 0 $xy_pairs ]
     }
     set x0   [ lindex $xy_pairs 0     ]
     set x1   [ lindex $xy_pairs 2     ]
     set xn   [ lindex $xy_pairs end-1 ]
     set xnminus1 [ lindex $xy_pairs end-3 ]

     if { $x1 < $x0 } {
        return -code error "monotonicity broken by x1"
     }

     if { $xn < $xnminus1 } {
        return -code error "monotonicity broken by xn"
     }

     ;## handle the assymetrical elements 0, n, and n-1.
     set sum [ expr {[ lindex $xy_pairs 1 ] + [ lindex $xy_pairs end ]} ]
     set sum [ expr {$sum + (4*[ lindex $xy_pairs end-2 ])} ]

     set data [ lrange $xy_pairs 2 end-4 ]

     set xmax $x1
     set i 1
     foreach {x1 y1 x2 y2} $data {
        incr i
        if { $x1 < $xmax } {
           return -code error "monotonicity broken by x$i"
        }
        set xmax $x1
        incr i
        if { $x2 < $xmax } {
           return -code error "monotonicity broken by x$i"
        }
        set xmax $x2
        set sum [ expr {$sum + (4*$y1) + (2*$y2)} ]
     }

     if { $xmax > $xnminus1 } {
        return -code error "monotonicity broken by xn-1"
     }

     set h [ expr { ( $xn - $x0 ) / $i } ]
     set area [ expr { ( $h / 3.0 ) * $sum } ]
     set err_bound  [ expr { ( ( $xn - $x0 ) / 180.0 ) * pow($h,4) * $xn } ]
     return [ list $area $err_bound ]
}

# ::math::max --
#
#	Return the maximum of two or more values
#
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
        set sum [ expr { $sum+$val } ]
     }
     set mean [ expr { $sum/$N } ]
     set sigma_sq 0
     foreach val [ concat $val1 $val2 $args ] {
        set sigma_sq [ expr { $sigma_sq+pow(($val-$mean),2) } ]
     }
     set sigma_sq [ expr { $sigma_sq/($N-1) } ] 
     set sigma [ expr { sqrt($sigma_sq) } ]
     set sigma
}     

# ::math::stats --
#
#	Return the mean, standard deviation, and coefficient of variation as
#	percent, as a list.
#
# Arguments:
#	val1	first value
#	val2	first value
#	args	all other values
#
# Results:
#	{mean stddev coefvar}

proc ::math::stats {val1 val2 args} {
     set sum [ expr { $val1+$val2 } ]
     set N [ expr { [ llength $args ] + 2 } ]
     foreach val $args {
        set sum [ expr { $sum+$val } ]
     }
     set mean [ expr { $sum/$N } ]
     set sigma_sq 0
     foreach val [ concat $val1 $val2 $args ] {
        set sigma_sq [ expr { $sigma_sq+pow(($val-$mean),2) } ]
     }
     set sigma_sq [ expr { $sigma_sq/($N-1) } ] 
     set sigma [ expr { sqrt($sigma_sq) } ]
     set cov [ expr { ($sigma/$mean)*100 } ]
     return [ list $mean $sigma $cov ]
}

# ::math::sum --
#







|


|




















|




|







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
        set sum [ expr { $sum+$val } ]
     }
     set mean [ expr { $sum/$N } ]
     set sigma_sq 0
     foreach val [ concat $val1 $val2 $args ] {
        set sigma_sq [ expr { $sigma_sq+pow(($val-$mean),2) } ]
     }
     set sigma_sq [ expr { $sigma_sq/($N-1) } ]
     set sigma [ expr { sqrt($sigma_sq) } ]
     set sigma
}

# ::math::stats --
#
#	Return the mean, standard deviation, and coefficient of variation as
#	percent, as a list.
#
# Arguments:
#	val1	first value
#	val2	first value
#	args	all other values
#
# Results:
#	{mean stddev coefvar}

proc ::math::stats {val1 val2 args} {
     set sum [ expr { $val1+$val2 } ]
     set N [ expr { [ llength $args ] + 2 } ]
     foreach val $args {
        set sum [ expr { $sum+$val } ]
     }
     set mean [ expr { $sum/double($N) } ]
     set sigma_sq 0
     foreach val [ concat $val1 $val2 $args ] {
        set sigma_sq [ expr { $sigma_sq+pow(($val-$mean),2) } ]
     }
     set sigma_sq [ expr { $sigma_sq/double($N-1) } ]
     set sigma [ expr { sqrt($sigma_sq) } ]
     set cov [ expr { ($sigma/$mean)*100 } ]
     return [ list $mean $sigma $cov ]
}

# ::math::sum --
#

Changes to modules/math/numtheory.dtx.

1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
% \section*{Closings}
% 
% \begin{tcl}
%<*man>
[list_end]

[vset CATEGORY {math :: numtheory}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]
%</man>
% \end{tcl}
% 
% \begin{tcl}
%<test_common>testsuiteCleanup
% \end{tcl}







|







1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
% \section*{Closings}
% 
% \begin{tcl}
%<*man>
[list_end]

[vset CATEGORY {math :: numtheory}]
[include ../common-text/feedback.inc]
[manpage_end]
%</man>
% \end{tcl}
% 
% \begin{tcl}
%<test_common>testsuiteCleanup
% \end{tcl}

Changes to modules/math/numtheory.man.

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
[list_end]

[call [cmd math::numtheory::numberPrimesGauss] [arg N]]
Estimate the number of primes according the formula by Gauss.

[list_begin arguments]
[arg_def integer N in]
Number in question
[list_end]

[call [cmd math::numtheory::numberPrimesLegendre] [arg N]]
Estimate the number of primes according the formula by Legendre.

[list_begin arguments]
[arg_def integer N in]
Number in question
[list_end]

[call [cmd math::numtheory::numberPrimesLegendreModified] [arg N]]
Estimate the number of primes according the modified formula by Legendre.

[list_begin arguments]
[arg_def integer N in]
Number in question








[list_end]

[list_end]

[vset CATEGORY {math :: numtheory}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|







|







|
>
>
>
>
>
>
>
>





|

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
[list_end]

[call [cmd math::numtheory::numberPrimesGauss] [arg N]]
Estimate the number of primes according the formula by Gauss.

[list_begin arguments]
[arg_def integer N in]
Number in question, should be larger than 0
[list_end]

[call [cmd math::numtheory::numberPrimesLegendre] [arg N]]
Estimate the number of primes according the formula by Legendre.

[list_begin arguments]
[arg_def integer N in]
Number in question, should be larger than 0
[list_end]

[call [cmd math::numtheory::numberPrimesLegendreModified] [arg N]]
Estimate the number of primes according the modified formula by Legendre.

[list_begin arguments]
[arg_def integer N in]
Number in question, should be larger than 0
[list_end]

[call [cmd math::numtheory::differenceNumberPrimesLegendreModified] [arg lower] [arg upper]]
Estimate the number of primes between tow limits according the modified formula by Legendre.

[list_begin arguments]
[arg_def integer lower in] Lower limit for the primes, should be larger than 0
[arg_def integer upper in] Upper limit for the primes, should be larger than 0
[list_end]

[list_end]

[vset CATEGORY {math :: numtheory}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/numtheory.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26






27
28
29
30
31
32
33
## 
## This is the file `numtheory.test',
## generated with the SAK utility
## (sak docstrip/regen).
## 
## The original source files were:
## 
## numtheory.dtx  (with options: `test test_common')
## 
## In other words:
## **************************************
## * This Source is not the True Source *
## **************************************
## the true source is the file from which this one was generated.
##
source [file join\
  [file dirname [file dirname [file join [pwd] [info script]]]]\
  devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2.1

testing {
    useLocal numtheory.tcl math::numtheory
}







test prime_trialdivision-1 "Trial division of 1" -body {
   ::math::numtheory::prime_trialdivision 1
} -returnCodes 2 -result 0
test prime_trialdivision-2 "Trial division of 2" -body {
   ::math::numtheory::prime_trialdivision 2
} -returnCodes 2 -result 1
test prime_trialdivision-3 "Trial division of 6" -body {
|



|

|

|

















>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
##
## This is the file `numtheory.test',
## generated with the SAK utility
## (sak docstrip/regen).
##
## The original source files were:
##
## numtheory.dtx  (with options: `test test_common')
##
## In other words:
## **************************************
## * This Source is not the True Source *
## **************************************
## the true source is the file from which this one was generated.
##
source [file join\
  [file dirname [file dirname [file join [pwd] [info script]]]]\
  devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2.1

testing {
    useLocal numtheory.tcl math::numtheory
}

proc compareRounded {expected actual} {
    return [expr {int($expected-$actual) == 0} ]
}

::tcltest::customMatch rounded compareRounded

test prime_trialdivision-1 "Trial division of 1" -body {
   ::math::numtheory::prime_trialdivision 1
} -returnCodes 2 -result 0
test prime_trialdivision-2 "Trial division of 2" -body {
   ::math::numtheory::prime_trialdivision 2
} -returnCodes 2 -result 1
test prime_trialdivision-3 "Trial division of 6" -body {
203
204
205
206
207
208
209





















210
211
212
213
   ::math::numtheory::isprime 118670087467 -randommr 500
} -result on -cleanup {
   namespace eval ::math::numtheory {
      rename Miller--Rabin ""
      rename _orig_Miller--Rabin Miller--Rabin
   }
}





















testsuiteCleanup
## 
## 
## End of file `numtheory.test'.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
|

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
   ::math::numtheory::isprime 118670087467 -randommr 500
} -result on -cleanup {
   namespace eval ::math::numtheory {
      rename Miller--Rabin ""
      rename _orig_Miller--Rabin Miller--Rabin
   }
}

test numberPrimes-1.0 "Number of primes below 100" -match rounded -body {
   set result [::math::numtheory::numberPrimesLegendre 100]
} -result 28

test numberPrimes-1.1 "Number of primes below 100 (modified)" -match rounded -body {
   set result [::math::numtheory::numberPrimesLegendreModified 100]
} -result 28

test numberPrimes-1.2 "Number of primes below 0 (modified)" -body {
   set result [::math::numtheory::numberPrimesLegendreModified 0]
} -result "The limit must be larger than 1" -returnCodes 1

test numberPrimes-1.3 "Number of primes between 100 and 200" -match rounded -body {
   set result [::math::numtheory::differenceNumberPrimesLegendreModified 100 200]
} -result 19

test numberPrimes-1.4 "Number of primes between 100 and 0 - error expected" -body {
   set result [::math::numtheory::differenceNumberPrimesLegendreModified 100 0]
} -result "The upper limit must be larger than 1" -returnCodes 1

testsuiteCleanup
##
##
## End of file `numtheory.test'.

Changes to modules/math/optimize.man.

317
318
319
320
321
322
323
324
325

[para]
The theory of linear programming is the subject of many a text book and
the Simplex algorithm that is implemented here is the best-known
method to solve this type of problems, but it is not the only one.

[vset CATEGORY {math :: optimize}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

317
318
319
320
321
322
323
324
325

[para]
The theory of linear programming is the subject of many a text book and
the Simplex algorithm that is implemented here is the best-known
method to solve this type of problems, but it is not the only one.

[vset CATEGORY {math :: optimize}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/pca.man.

128
129
130
131
132
133
134
135
136

[section EXAMPLE]
TODO: NIST example



[vset CATEGORY PCA]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

128
129
130
131
132
133
134
135
136

[section EXAMPLE]
TODO: NIST example



[vset CATEGORY PCA]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/pdf_stat.tcl.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28

29
30

31
32

33
34
35
36
37
38
39

# ::math::statistics --
#   Namespace holding the procedures and variables
#
namespace eval ::math::statistics {

    namespace export pdf-normal pdf-uniform pdf-lognormal \
	    pdf-exponential \
	    cdf-normal cdf-uniform cdf-lognormal \
	    cdf-exponential \
	    cdf-students-t \
	    random-normal random-uniform random-lognormal \
	    random-exponential \
	    histogram-uniform \
	    pdf-gamma pdf-poisson pdf-chisquare pdf-students-t pdf-beta \
	    pdf-weibull pdf-gumbel pdf-pareto pdf-cauchy \

	    cdf-gamma cdf-poisson cdf-chisquare cdf-beta cdf-F \
	    cdf-weibull cdf-gumbel cdf-pareto cdf-cauchy \

	    random-gamma random-poisson random-chisquare random-students-t random-beta \
	    random-weibull random-gumbel random-pareto random-cauchy \

	    incompleteGamma incompleteBeta \
	    estimate-pareto empirical-distribution bootstrap


    variable cdf_normal_prob     {}
    variable cdf_normal_x        {}
    variable cdf_toms322_cached  {}
    variable initialised_cdf     0
    variable twopi               [expr {2.0*acos(-1.0)}]
    variable pi                  [expr {acos(-1.0)}]







|

|


|



>


>


>

|
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# ::math::statistics --
#   Namespace holding the procedures and variables
#
namespace eval ::math::statistics {

    namespace export pdf-normal pdf-uniform pdf-lognormal \
	    pdf-exponential pdf-triangular pdf-symmetric-triangular \
	    cdf-normal cdf-uniform cdf-lognormal \
	    cdf-exponential cdf-triangular cdf-symmetric-triangular \
	    cdf-students-t \
	    random-normal random-uniform random-lognormal \
	    random-exponential random-triangular \
	    histogram-uniform \
	    pdf-gamma pdf-poisson pdf-chisquare pdf-students-t pdf-beta \
	    pdf-weibull pdf-gumbel pdf-pareto pdf-cauchy \
	    pdf-laplace pdf-kumaraswamy pdf-negative-binomial \
	    cdf-gamma cdf-poisson cdf-chisquare cdf-beta cdf-F \
	    cdf-weibull cdf-gumbel cdf-pareto cdf-cauchy \
	    cdf-laplace cdf-kumaraswamy cdf-negative-binomial \
	    random-gamma random-poisson random-chisquare random-students-t random-beta \
	    random-weibull random-gumbel random-pareto random-cauchy \
	    random-laplace random-kumaraswamy random-negative-binomial \
	    incompleteGamma incompleteBeta \
	    estimate-pareto empirical-distribution bootstrap estimate-exponential \
	    estimate-laplace estimate-negative-binomial

    variable cdf_normal_prob     {}
    variable cdf_normal_x        {}
    variable cdf_toms322_cached  {}
    variable initialised_cdf     0
    variable twopi               [expr {2.0*acos(-1.0)}]
    variable pi                  [expr {acos(-1.0)}]
119
120
121
122
123
124
125








































































126
127
128
129
130
131
132
    set prob [expr {1.0/($pmax-$pmin)}]

    if { $x < $pmin || $x > $pmax } { return 0.0 }

    return $prob
}










































































# pdf-exponential --
#    Return the probabilities belonging to an exponential
#    distribution
#
# Arguments:
#    mean     Mean of the distribution







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    set prob [expr {1.0/($pmax-$pmin)}]

    if { $x < $pmin || $x > $pmax } { return 0.0 }

    return $prob
}


# pdf-triangular --
#    Return the probabilities belonging to a triangular distribution
#    (parameters as minimum/maximum)
#
# Arguments:
#    pmin      Minimum of the distribution
#    pmax      Maximum of the distribution
#    x         Value for which the probability must be determined
#
# Result:
#    Probability of value x under the given distribution
#
# Note:
#    If pmin > pmax, the main weight will be at the larger
#    values.
#
proc ::math::statistics::pdf-triangular { pmin pmax x } {

    if { $pmin == $pmax } {
	return -code error -errorcode ARG \
		-errorinfo "Zero range" \
		"Zero range"
    }

    if { $pmin < $pmax } {
        if { $x < $pmin || $x > $pmax } { return 0.0 }
    } else {
        if { $x < $pmax || $x > $pmin } { return 0.0 }
    }

    set prob [expr {2.0*(1.0-($x-$pmin)/($pmax-$pmin))}]


    return $prob
}


# pdf-symmetric-triangular --
#    Return the probabilities belonging to a symmetric triangular distribution
#    (parameters as minimum/maximum)
#
# Arguments:
#    pmin      Minimum of the distribution
#    pmax      Maximum of the distribution
#    x         Value for which the probability must be determined
#
# Result:
#    Probability of value x under the given distribution
#
proc ::math::statistics::pdf-symmetric-triangular { pmin pmax x } {

    if { $pmin == $pmax } {
	return -code error -errorcode ARG \
		-errorinfo "Zero range" \
		"Zero range"
    }

    if { $pmin < $pmax } {
        if { $x < $pmin || $x > $pmax } { return 0.0 }
    } else {
        if { $x < $pmax || $x > $pmin } { return 0.0 }
    }

    set diff   [expr {abs($pmax-$pmin)}]
    set centre [expr {($pmax+$pmin)/2.0}]

    set prob [expr {2./$diff * (1.0 - 2.*abs($x-$centre)/$diff)}]

    return $prob
}


# pdf-exponential --
#    Return the probabilities belonging to an exponential
#    distribution
#
# Arguments:
#    mean     Mean of the distribution
145
146
147
148
149
150
151






















































































152
153
154
155
156
157
158
    }

    if { $x < 0.0 } { return 0.0 }
    if { $x > 700.0*$mean } { return 0.0 }

    set prob [expr {exp(-$x/double($mean))/$mean}]























































































    return $prob
}


# cdf-normal --
#    Return the cumulative probability belonging to a normal distribution
#







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    }

    if { $x < 0.0 } { return 0.0 }
    if { $x > 700.0*$mean } { return 0.0 }

    set prob [expr {exp(-$x/double($mean))/$mean}]

    return $prob
}


# pdf-laplace --
#    Return the probabilities belonging to a Laplace
#    distribution
#
# Arguments:
#    mean     Mean of the distribution
#    scale    Scale (the spreading) of the distribution
#    x        Value for which the probability must be determined
#
# Result:
#    Probability of value x under the given distribution
#
proc ::math::statistics::pdf-laplace { mean scale x } {
    variable NEGSTDEV
    variable OUTOFRANGE

    if { $scale <= 0.0 } {
	return -code error -errorcode ARG -errorinfo $OUTOFRANGE \
		"$OUTOFRANGE: scale must be positive"
    }

    set prob [expr {exp(-($x-$mean)/double($scale))/(2.0*$scale)}]

    return $prob
}


# pdf-kumaraswamy --
#    Return the probabilities belonging to a Kumaraswamy
#    distribution (akin to the Beta distribution, but tractable)
#
#    Arguments:
#    a         First parameter of the Kumaraswamy distribution
#    b         Second parameter of the Kumaraswamy distribution
#    x         Value of variate
#
# Result:
#    Probability of value x under the given distribution
#
proc ::math::statistics::pdf-kumaraswamy { a b x } {
    variable OUTOFRANGE

    if { $a <= 0.0 || $b <= 0.0 } {
	return -code error -errorcode ARG -errorinfo $OUTOFRANGE \
		"$OUTOFRANGE: parameters a and b must be positive"
    }

    set prob [expr {$a * $b * $x**($a-1) * (1.0 -$x**$a)**($b-1)}]

    return $prob
}


# pdf-negative-binomial --
#    Return the probability belonging to a negative binomial
#    distribution
#
#    Arguments:
#    r         Allowed number of failures for the distribution
#    p         Probability of success for the negative bionomial distribution
#    k         Value of variate (integer)
#
# Result:
#    Probability of k successes under the given distribution
#
proc ::math::statistics::pdf-negative-binomial { r p k } {
    variable OUTOFRANGE
    variable INVALID

    if { $p < 0.0 || $p >= 1.0 } {
	return -code error -errorcode ARG -errorinfo $OUTOFRANGE \
		"$OUTOFRANGE: parameter p must be non-negative and lower than 1"
    }

    if { int($r) != $r || $r < 1 } {
	return -code error -errorcode ARG -errorinfo $INVALIDE \
		"$INVALID: parameter r must be a positive integer"
    }

    set coeff [::math::choose [expr {$k+$r-1}] $k]
    set prob  [expr {$coeff * (1.0 - $p)**$r * $p ** $k}]

    return $prob
}


# cdf-normal --
#    Return the cumulative probability belonging to a normal distribution
#
267
268
269
270
271
272
273





















































































274
275
276
277
278
279
280

    if { $x < $pmin } { return 0.0 }
    if { $x > $pmax } { return 1.0 }

    return $prob
}























































































# cdf-exponential --
#    Return the cumulative probabilities belonging to an exponential
#    distribution
#
# Arguments:
#    mean     Mean of the distribution







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

    if { $x < $pmin } { return 0.0 }
    if { $x > $pmax } { return 1.0 }

    return $prob
}


# cdf-triangular --
#    Return the cumulative probabilities belonging to a triangular distribution
#    (parameters as minimum/maximum)
#
# Arguments:
#    pmin      Minimum of the distribution
#    pmax      Maximum of the distribution
#    x         Value for which the probability must be determined
#
# Result:
#    Probability of value x under the given distribution
#
# Note:
#    If pmin > pmax, the main weight will be at the larger
#    values.
#
proc ::math::statistics::cdf-triangular { pmin pmax x } {

    if { $pmin == $pmax } {
	return -code error -errorcode ARG \
		-errorinfo "Zero range" \
		"Zero range"
    }


    if { $pmin < $pmax } {
        if { $x < $pmin } { return 0.0 }
        if { $x > $pmax } { return 1.0 }
        set xm   [expr {($x - $pmin) / ($pmax - $pmin)}]
        set prob [expr {2.0*$xm - $xm**2}]
    } else {
        if { $x < $pmax } { return 0.0 }
        if { $x > $pmin } { return 1.0 }
        set xm   [expr {($x - $pmax) / ($pmin - $pmax)}]
        set prob [expr {$xm**2}]
    }

    return $prob
}


# cdf-symmetric-triangular --
#    Return the cumulative probabilities belonging to a symmetric triangular distribution
#    (parameters as minimum/maximum)
#
# Arguments:
#    pmin      Minimum of the distribution
#    pmax      Maximum of the distribution
#    x         Value for which the probability must be determined
#
# Result:
#    Probability of value x under the given distribution
#
proc ::math::statistics::cdf-symmetric-triangular { pmin pmax x } {

    if { $pmin == $pmax } {
	return -code error -errorcode ARG \
		-errorinfo "Zero range" \
		"Zero range"
    }


    set diff   [expr {abs($pmax-$pmin)/2.0}]
    set centre [expr {($pmax+$pmin)/2.0}]

    if { $pmin < $pmax } {
        if { $x < $pmin } { return 0.0 }
        if { $x > $pmax } { return 1.0 }
    } else {
        if { $x < $pmax } { return 0.0 }
        if { $x > $pmin } { return 1.0 }
    }

    if { $x < $centre } {
        set xm   [expr {($x - $centre + $diff) / $diff}]
        set prob [expr {0.5 * $xm**2}]
    } else {
        set xm   [expr {($x - $centre - $diff) / $diff}]
        set prob [expr {1.0 - 0.5 * $xm**2}]
    }

    return $prob
}


# cdf-exponential --
#    Return the cumulative probabilities belonging to an exponential
#    distribution
#
# Arguments:
#    mean     Mean of the distribution
296
297
298
299
300
301
302





























































































303
304
305
306
307
308
309
    if { $x > 30.0*$mean } { return 1.0 }

    set prob [expr {1.0-exp(-$x/double($mean))}]

    return $prob
}































































































# Inverse-cdf-uniform --
#    Return the argument belonging to the cumulative probability
#    for a uniform distribution (parameters as minimum/maximum)
#
# Arguments:
#    pmin      Minimum of the distribution







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    if { $x > 30.0*$mean } { return 1.0 }

    set prob [expr {1.0-exp(-$x/double($mean))}]

    return $prob
}


# cdf-laplace --
#    Return the cumulative probabilities belonging to a Laplace
#    distribution
#
# Arguments:
#    mean     Mean of the distribution
#    scale    Scale (the spreading) of the distribution
#    x        Value for which the probability must be determined
#
# Result:
#    Cumulative probability of value x under the given distribution
#
proc ::math::statistics::cdf-laplace { mean scale x } {
    variable NEGSTDEV
    variable OUTOFRANGE

    if { $scale <= 0.0 } {
	return -code error -errorcode ARG -errorinfo $OUTOFRANGE \
		"$OUTOFRANGE: scale must be positive"
    }

    if { $x < $mean } {
        set prob [expr {0.5 * exp(($x-$mean)/double($scale))}]
    } else {
        set prob [expr {1.0 - 0.5 * exp(($mean-$x)/double($scale))}]
    }

    return $prob
}


# cdf-kumaraswamy --
#    Return the cumulative probabilities belonging to a Kumaraswamy
#    distribution (akin to the Beta distribution, but tractable)
#
#    Arguments:
#    a         First parameter of the Kumaraswamy distribution
#    b         Second parameter of the Kumaraswamy distribution
#    x         Value of variate
#
# Result:
#    Cumulative probability of value x under the given distribution
#
proc ::math::statistics::cdf-kumaraswamy { a b x } {
    variable OUTOFRANGE

    if { $a <= 0.0 || $b <= 0.0 } {
	return -code error -errorcode ARG -errorinfo $OUTOFRANGE \
		"$OUTOFRANGE: parameters a and b must be positive"
    }

    set prob [expr {1.0 - (1.0-$x**$a) ** $b}]

    return $prob
}


# cdf-negative-binomial --
#    Return the cumulative probability for a negative binomial distribution
#
#    Arguments:
#    r         Allowed number of failures for the distribution
#    p         Probability of success for the negative bionomial distribution
#    k         Value of variate (integer)
#
# Result:
#    Cumulative probability for up to k successes under the given distribution
#
proc ::math::statistics::cdf-negative-binomial { r p k } {
    variable OUTOFRANGE
    variable INVALID

    if { $p < 0.0 || $p >= 1.0 } {
	return -code error -errorcode ARG -errorinfo $OUTOFRANGE \
		"$OUTOFRANGE: parameter p must be non-negative and lower than 1"
    }

    if { int($r) != $r || $r < 1 } {
	return -code error -errorcode ARG -errorinfo $INVALIDE \
		"$INVALID: parameter r must be a positive integer"
    }

    set sum 0.0

    for { set i 0 } { $i <= $k } { incr i } {
        set prob [pdf-negative-binomial $r $p $i]
        set sum  [expr {$sum + $prob}]
    }

    return $sum
}


# Inverse-cdf-uniform --
#    Return the argument belonging to the cumulative probability
#    for a uniform distribution (parameters as minimum/maximum)
#
# Arguments:
#    pmin      Minimum of the distribution
479
480
481
482
483
484
485





































































486
487
488
489
490
491
492
		"Wrong order or zero range"
    }

    set result {}
    for { set i 0 }  {$i < $number } { incr i } {
	lappend result [Inverse-cdf-uniform $pmin $pmax [expr {rand()}]]
    }






































































    return $result
}


# random-exponential --
#    Return a list of random numbers satisfying an exponential







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
		"Wrong order or zero range"
    }

    set result {}
    for { set i 0 }  {$i < $number } { incr i } {
	lappend result [Inverse-cdf-uniform $pmin $pmax [expr {rand()}]]
    }

    return $result
}


# random-triangular --
#    Return a list of random numbers satisfying a triangular
#    distribution (parameters as minimum/maximum)
#
# Arguments:
#    pmin      Minimum of the distribution
#    pmax      Maximum of the distribution
#    number    Number of values to generate
#
# Result:
#    List of random numbers
#
proc ::math::statistics::random-triangular { pmin pmax number } {

    if { $pmin == $pmax } {
	return -code error -errorcode ARG \
		-errorinfo "Zero range" \
		"Zero range"
    }

    set diff [expr {$pmax - $pmin}]
    if { $pmin < $pmax } {
        set result {}
        for { set i 0 }  {$i < $number } { incr i } {
	    set r [expr {1.0 - sqrt(1.0 - rand())}]
	    lappend result [expr {$pmin + $r * $diff}]
        }
    } else {
        set result {}
        for { set i 0 }  {$i < $number } { incr i } {
	    lappend result [expr {$pmax - sqrt(rand()) * $diff}]
        }
    }

    return $result
}


# random-symmetric-triangular --
#    Return a list of random numbers satisfying a symmetric triangular
#    distribution (parameters as minimum/maximum)
#
# Arguments:
#    pmin      Minimum of the distribution
#    pmax      Maximum of the distribution
#    number    Number of values to generate
#
# Result:
#    List of random numbers
#
proc ::math::statistics::random-symmetric-triangular { pmin pmax number } {

    if { $pmin == $pmax } {
	return -code error -errorcode ARG \
		-errorinfo "Zero range" \
		"Zero range"
    }

    set diff2 [expr {0.5 * ($pmax - $pmin)}]

    set result {}
    for { set i 0 }  {$i < $number } { incr i } {
	lappend result [expr {$pmin + $diff2 * (rand() + rand())}]
    }

    return $result
}


# random-exponential --
#    Return a list of random numbers satisfying an exponential
1895
1896
1897
1898
1899
1900
1901


















































































































1902
1903
1904
1905
1906
1907
1908
    set retval {}
    for {set i 0} {$i < $number} {incr i} {
        lappend retval [expr {$location + $scale * tan( $pi * (rand() - 0.5))}]
    }
    return $retval
}




















































































































# estimate-pareto --
#    Estimate the parameters of a Pareto distribution
#
# Arguments:
#    values    Values that are supposed to be distributed according to Pareto
#







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
    set retval {}
    for {set i 0} {$i < $number} {incr i} {
        lappend retval [expr {$location + $scale * tan( $pi * (rand() - 0.5))}]
    }
    return $retval
}


# random-laplace --
#    Generate a list of Laplace distributed deviates
#
# Arguments:
#    mean     Mean of the distribution
#    scale    Scale (the spreading) of the distribution
#    number   Number of values to return
#
# Result:
#    List of random numbers
#
proc ::math::statistics::random-laplace { mean scale number } {
    variable NEGSTDEV
    variable OUTOFRANGE

    if { $scale <= 0.0 } {
	return -code error -errorcode ARG -errorinfo $OUTOFRANGE \
		"$OUTOFRANGE: scale must be positive"
    }

    set retval {}
    for {set i 0} {$i < $number} {incr i} {
        set p [expr {rand()}]
        if { $p < 0.5 } {
            set x [expr {$mean + $scale * log(1.0 - 2.0*abs($p-0.5))}]
        } else {
            set x [expr {$mean - $scale * log(1.0 - 2.0*abs($p-0.5))}]
        }
        lappend retval $x
    }

    return $retval
}


# random-kumaraswamy --
#    Generate a list of Kumaraswamy distributed deviates
#
#    Arguments:
#    a         First parameter of the Kumaraswamy distribution
#    b         Second parameter of the Kumaraswamy distribution
#    number    Number of values to return
#
# Result:
#    List of random numbers
#
proc ::math::statistics::random-kumaraswamy { a b number } {
    variable OUTOFRANGE

    if { $a <= 0.0 || $b <= 0.0 } {
	return -code error -errorcode ARG -errorinfo $OUTOFRANGE \
		"$OUTOFRANGE: parameters a and b must be positive"
    }

    set ra [expr {1.0 / $a}]
    set rb [expr {1.0 / $b}]

    set retval {}
    for {set i 0} {$i < $number} {incr i} {
        set p [expr {rand()}]
        set x [expr {( 1.0 - (1.0-$p) ** $rb ) ** $ra}]

        lappend retval $x
    }

    return $retval
}


# random-negative-binomial --
#    Generate a list of deviates according to the negative binomial distribution
#
#    Arguments:
#    r         Allowed number of failures for the distribution
#    p         Probability of success for the negative bionomial distribution
#    number    Number of values to return
#
# Result:
#    List of random numbers
#
proc ::math::statistics::random-negative-binomial { r p number } {
    variable OUTOFRANGE
    variable INVALID

    if { $p < 0.0 || $p >= 1.0 } {
	return -code error -errorcode ARG -errorinfo $OUTOFRANGE \
		"$OUTOFRANGE: parameter p must be non-negative and lower than 1"
    }

    if { int($r) != $r || $r < 1} {
	return -code error -errorcode ARG -errorinfo $INVALIDE \
		"$INVALID: parameter r must be a positive integer"
    }

    set retval {}
    for {set i 0} {$i < $number} {incr i} {
        set success 0
        set failure 0

        while { $failure < $r } {
            if { rand() <= $p } {
                incr success
            } else {
                incr failure
            }
        }

        lappend retval $success
    }

    return $retval
}


# estimate-pareto --
#    Estimate the parameters of a Pareto distribution
#
# Arguments:
#    values    Values that are supposed to be distributed according to Pareto
#
1946
1947
1948
1949
1950
1951
1952





























































































1953
1954
1955
1956
1957
1958
1959
        set sum [expr {$sum + log($v) - log($scale)}]
    }
    set shape [expr {$n / $sum}]

    return [list $scale $shape [expr {$shape/sqrt($n)}]]
}































































































# empirical-distribution --
#    Determine the empirical distribution
#
# Arguments:
#    values    Values that are to be examined
#







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
        set sum [expr {$sum + log($v) - log($scale)}]
    }
    set shape [expr {$n / $sum}]

    return [list $scale $shape [expr {$shape/sqrt($n)}]]
}


# estimate-exponential --
#    Estimate the parameter of an exponential distribution
#
# Arguments:
#    values    Values that are supposed to be exponentially distributed
#
# Result:
#    Estimate of the one parameter of the exponential distribution
#    as well as the asymptotic standard deviation
#    (See https://www.statlect.com/fundamentals-of-statistics/exponential-distribution-maximum-likelihood)
#
proc ::math::statistics::estimate-exponential { values } {

    set sum   0.0
    set count 0

    foreach v $values {
        if { $v != "" } {
            set  sum [expr {$sum + $v}]
            incr count
        }
    }

    set parameter [expr {$sum/double($count)}]
    set stdev     [expr {$parameter / sqrt($count)}]

    return [list $parameter $stdev]
}


# estimate-laplace --
#    Estimate the parameter of a Laplace distribution
#
# Arguments:
#    values    Values that are supposed to be Laplace distributed
#
# Result:
#    Estimates of respectively the mean and the scale of the Laplace distribution
#    (See https://en.wikipedia.org/wiki/Laplace_distribution)
#
# Note:
#    According to Wikipedia the estimators are maximum-likelihood estimators
#
proc ::math::statistics::estimate-laplace { values } {

    set mean [median $values]

    set sum   0.0
    set count 0

    foreach v $values {
        if { $v != "" } {
            set  sum [expr {$sum + abs($v-$mean)}]
            incr count
        }
    }

    set scale [expr {$sum/double($count)}]

    return [list $mean $scale]
}


# estimate-negative-binomial --
#    Estimate the parameter p of a negative binomial distribution,
#    given the allowed number of failures
#
# Arguments:
#    r         Allowed number of failures
#    values    Values that are supposed to be distributed according to a negative binomial distribution
#
# Result:
#    Estimate of the probability of success for the distribution
#
# Note:
#    According to Wikipedia the estimators are maximum-likelihood estimators
#
proc ::math::statistics::estimate-negative-binomial { r values } {

    set sum   0.0
    set count 0

    foreach v $values {
        if { $v != "" } {
            set  sum [expr {$sum + $v}]
            incr count
        }
    }

    return [expr {$sum/double($count * $r + $sum)}]
}


# empirical-distribution --
#    Determine the empirical distribution
#
# Arguments:
#    values    Values that are to be examined
#
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
    foreach z    {4.417 3.891 3.291 2.576 2.241 1.960 1.645 1.150 0.674
    0.319 0.126 0.063 0.0125} \
	    pexp {1.e-5 1.e-4 1.e-3 1.e-2 0.025 0.050 0.100 0.250 0.500
    0.750 0.900 0.950 0.990 } {
	set prob [::math::statistics::Cdf-toms322 1 5000 [expr {$z*$z}]]
	puts "$z - $pexp - [expr {1.0-$prob}]"
    }

    puts "Normal distribution (inverted; one-tailed)"
    foreach p {0.001 0.01 0.1 0.25 0.5 0.75 0.9 0.99 0.999} {
	puts "$p - [::math::statistics::Inverse-cdf-normal 0.0 1.0 $p]"
    }
    puts "Normal random variables"
    set rndvars [::math::statistics::random-normal 1.0 2.0 20]
    puts $rndvars







<







2654
2655
2656
2657
2658
2659
2660

2661
2662
2663
2664
2665
2666
2667
    foreach z    {4.417 3.891 3.291 2.576 2.241 1.960 1.645 1.150 0.674
    0.319 0.126 0.063 0.0125} \
	    pexp {1.e-5 1.e-4 1.e-3 1.e-2 0.025 0.050 0.100 0.250 0.500
    0.750 0.900 0.950 0.990 } {
	set prob [::math::statistics::Cdf-toms322 1 5000 [expr {$z*$z}]]
	puts "$z - $pexp - [expr {1.0-$prob}]"
    }

    puts "Normal distribution (inverted; one-tailed)"
    foreach p {0.001 0.01 0.1 0.25 0.5 0.75 0.9 0.99 0.999} {
	puts "$p - [::math::statistics::Inverse-cdf-normal 0.0 1.0 $p]"
    }
    puts "Normal random variables"
    set rndvars [::math::statistics::random-normal 1.0 2.0 20]
    puts $rndvars

Changes to modules/math/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32


33
34
35
36
if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded math                    1.2.5 [list source [file join $dir math.tcl]]
package ifneeded math::fuzzy             0.2.1 [list source [file join $dir fuzzy.tcl]]
package ifneeded math::complexnumbers    1.0.2 [list source [file join $dir qcomplex.tcl]]
package ifneeded math::special           0.3.0 [list source [file join $dir special.tcl]]
package ifneeded math::constants         1.0.2 [list source [file join $dir constants.tcl]]
package ifneeded math::polynomials       1.0.1 [list source [file join $dir polynomials.tcl]]
package ifneeded math::rationalfunctions 1.0.1 [list source [file join $dir rational_funcs.tcl]]
package ifneeded math::fourier           1.0.2 [list source [file join $dir fourier.tcl]]

if {![package vsatisfies [package provide Tcl] 8.3]} {return}
package ifneeded math::roman             1.0   [list source [file join $dir romannumerals.tcl]]

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded math::optimize          1.0.1 [list source [file join $dir optimize.tcl]]
package ifneeded math::interpolate       1.1.1 [list source [file join $dir interpolate.tcl]]
package ifneeded math::bignum            3.1.1 [list source [file join $dir bignum.tcl]]
package ifneeded math::bigfloat          1.2.2 [list source [file join $dir bigfloat.tcl]]
package ifneeded math::machineparameters 0.1   [list source [file join $dir machineparameters.tcl]]

if {![package vsatisfies [package provide Tcl] 8.5]} {return}
package ifneeded math::calculus          0.8.1 [list source [file join $dir calculus.tcl]]
# statistics depends on linearalgebra (for multi-variate linear regression).
# statistics depends on optimize (for logistic regression).
package ifneeded math::statistics        1.3.0 [list source [file join $dir statistics.tcl]]
package ifneeded math::linearalgebra     1.1.6 [list source [file join $dir linalg.tcl]]
package ifneeded math::calculus::symdiff 1.0.1 [list source [file join $dir symdiff.tcl]]
package ifneeded math::bigfloat          2.0.2 [list source [file join $dir bigfloat2.tcl]]
package ifneeded math::numtheory         1.1.1 [list source [file join $dir numtheory.tcl]]
package ifneeded math::decimal           1.0.3 [list source [file join $dir decimal.tcl]]
package ifneeded math::geometry          1.3.0 [list source [file join $dir geometry.tcl]]
package ifneeded math::trig              1.0   [list source [file join $dir trig.tcl]]



if {![package vsatisfies [package require Tcl] 8.6]} {return}
package ifneeded math::exact             1.0   [list source [file join $dir exact.tcl]]
package ifneeded math::PCA               1.0   [list source [file join $dir pca.tcl]]




<










|








|





|

>
>


|

1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded math                    1.2.5 [list source [file join $dir math.tcl]]
package ifneeded math::fuzzy             0.2.1 [list source [file join $dir fuzzy.tcl]]
package ifneeded math::complexnumbers    1.0.2 [list source [file join $dir qcomplex.tcl]]

package ifneeded math::constants         1.0.2 [list source [file join $dir constants.tcl]]
package ifneeded math::polynomials       1.0.1 [list source [file join $dir polynomials.tcl]]
package ifneeded math::rationalfunctions 1.0.1 [list source [file join $dir rational_funcs.tcl]]
package ifneeded math::fourier           1.0.2 [list source [file join $dir fourier.tcl]]

if {![package vsatisfies [package provide Tcl] 8.3]} {return}
package ifneeded math::roman             1.0   [list source [file join $dir romannumerals.tcl]]

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded math::optimize          1.0.1 [list source [file join $dir optimize.tcl]]
package ifneeded math::interpolate       1.1.2 [list source [file join $dir interpolate.tcl]]
package ifneeded math::bignum            3.1.1 [list source [file join $dir bignum.tcl]]
package ifneeded math::bigfloat          1.2.2 [list source [file join $dir bigfloat.tcl]]
package ifneeded math::machineparameters 0.1   [list source [file join $dir machineparameters.tcl]]

if {![package vsatisfies [package provide Tcl] 8.5]} {return}
package ifneeded math::calculus          0.8.1 [list source [file join $dir calculus.tcl]]
# statistics depends on linearalgebra (for multi-variate linear regression).
# statistics depends on optimize (for logistic regression).
package ifneeded math::statistics        1.5.0 [list source [file join $dir statistics.tcl]]
package ifneeded math::linearalgebra     1.1.6 [list source [file join $dir linalg.tcl]]
package ifneeded math::calculus::symdiff 1.0.1 [list source [file join $dir symdiff.tcl]]
package ifneeded math::bigfloat          2.0.2 [list source [file join $dir bigfloat2.tcl]]
package ifneeded math::numtheory         1.1.1 [list source [file join $dir numtheory.tcl]]
package ifneeded math::decimal           1.0.3 [list source [file join $dir decimal.tcl]]
package ifneeded math::geometry          1.3.1 [list source [file join $dir geometry.tcl]]
package ifneeded math::trig              1.0   [list source [file join $dir trig.tcl]]
package ifneeded math::quasirandom       1.0   [list source [file join $dir quasirandom.tcl]]
package ifneeded math::special           0.4.0 [list source [file join $dir special.tcl]]

if {![package vsatisfies [package require Tcl] 8.6]} {return}
package ifneeded math::exact             1.0.1 [list source [file join $dir exact.tcl]]
package ifneeded math::PCA               1.0   [list source [file join $dir pca.tcl]]

Changes to modules/math/polynomials.man.

211
212
213
214
215
216
217
218
219

To recognise that a polynomial definition is indeed a correct
definition, it consists of a list of two elements: the keyword
"POLYNOMIAL" and the list of coefficients in descending order. The
latter makes it easier to implement Horner's rule.

[vset CATEGORY {math :: polynomials}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

211
212
213
214
215
216
217
218
219

To recognise that a polynomial definition is indeed a correct
definition, it consists of a list of two elements: the keyword
"POLYNOMIAL" and the list of coefficients in descending order. The
latter makes it easier to implement Horner's rule.

[vset CATEGORY {math :: polynomials}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/primes.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
## 
## This is the file `primes.tcl',
## generated with the SAK utility
## (sak docstrip/regen).
## 
## The original source files were:
## 
## numtheory.dtx  (with options: `pkg_primes pkg_common')
## 
## In other words:
## **************************************
## * This Source is not the True Source *
## **************************************
## the true source is the file from which this one was generated.
##
# Copyright (c) 2010 by Lars Hellstrom.  All rights reserved.
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# primes.tcl --
#     Provide additional procedures for the number theory package
#
namespace eval ::math::numtheory {
    variable primes {2 3 5 7 11 13 17}
    variable nextPrimeCandidate 19
    variable nextPrimeIncrement  1 ;# Examine numbers 6n+1 and 6n+5

    namespace export firstNprimes primesLowerThan primeFactors uniquePrimeFactors factors \
                     totient moebius legendre jacobi gcd lcm \
                     numberPrimesGauss numberPrimesLegendre numberPrimesLegendreModified

}

# ComputeNextPrime --
#     Determine the next prime
#
# Arguments:
#     None
|



|

|

|



















|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
##
## This is the file `primes.tcl',
## generated with the SAK utility
## (sak docstrip/regen).
##
## The original source files were:
##
## numtheory.dtx  (with options: `pkg_primes pkg_common')
##
## In other words:
## **************************************
## * This Source is not the True Source *
## **************************************
## the true source is the file from which this one was generated.
##
# Copyright (c) 2010 by Lars Hellstrom.  All rights reserved.
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# primes.tcl --
#     Provide additional procedures for the number theory package
#
namespace eval ::math::numtheory {
    variable primes {2 3 5 7 11 13 17}
    variable nextPrimeCandidate 19
    variable nextPrimeIncrement  1 ;# Examine numbers 6n+1 and 6n+5

    namespace export firstNprimes primesLowerThan primeFactors uniquePrimeFactors factors \
                     totient moebius legendre jacobi gcd lcm \
                     numberPrimesGauss numberPrimesLegendre numberPrimesLegendreModified \
                     differenceNumberPrimesLegendreModified
}

# ComputeNextPrime --
#     Determine the next prime
#
# Arguments:
#     None
461
462
463
464
465
466
467



























468
469
470
#
proc ::math::numtheory::numberPrimesLegendreModified {limit} {
    if { $limit <= 1 } {
        return -code error "The limit must be larger than 1"
    }
    expr {$limit / (log($limit) - 1.08366)}
}



























## 
## 
## End of file `primes.tcl'.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|

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
#
proc ::math::numtheory::numberPrimesLegendreModified {limit} {
    if { $limit <= 1 } {
        return -code error "The limit must be larger than 1"
    }
    expr {$limit / (log($limit) - 1.08366)}
}

# differenceNumberPrimesLegendreModified --
#     Return the approximate difference number of primes
#     between a lower and higher limit as given values
#     for approximate number of primes based on the
#     modified formula by Legendre
#
# Arguments:
#     limit1     The lower limit for the interval, largest prime to be included in the l.limit
#     limit2     The upper limit for the interval, largest prime to be included in the u.mlimit
#
# Returns:
#     Approximate difference number of primes
#
proc ::math::numtheory::differenceNumberPrimesLegendreModified {limit1 limit2} {
    if { $limit1 <= 1 } {
        return -code error "The lower limit must be larger than 1"
    }
    if { $limit2 <= 1 } {
        return -code error "The upper limit must be larger than 1"
    }

     set aa [::math::numtheory::numberPrimesLegendreModified [expr ($limit1)]]
     set bb [::math::numtheory::numberPrimesLegendreModified [expr ($limit2)]]
     expr {abs($bb-$aa)}
}

##
##
## End of file `primes.tcl'.

Changes to modules/math/qcomplex.man.

294
295
296
297
298
299
300
301
302
The complex power to be used

[list_end]

[list_end]

[vset CATEGORY {math :: complexnumbers}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

294
295
296
297
298
299
300
301
302
The complex power to be used

[list_end]

[list_end]

[vset CATEGORY {math :: complexnumbers}]
[include ../common-text/feedback.inc]
[manpage_end]

Added modules/math/quasirandom.man.













































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
[vset VERSION 1]
[manpage_begin math::quasirandom n [vset VERSION]]
[keywords {quasi-random}]
[keywords mathematics]
[moddesc {Tcl Math Library}]
[titledesc {Quasi-random points for integration and Monte Carlo type methods}]
[category  Mathematics]
[require Tcl 8.5]
[require TclOO]
[require math::quasirandom [vset VERSION]]
[description]
[para]

In many applications pseudo-random numbers and pseudo-random points in a (limited)
sample space play an important role. For instance in any type of Monte Carlo simulation.
Pseudo-random numbers, however, may be too random and as a consequence a large
number of data points is required to reduce the error or fluctuation in the results
to the desired value.
[para]

Quasi-random numbers can be used as an alternative: instead of "completely" arbitrary
points, points are generated that are diverse enough to cover the entire sample space
in a more or less uniform way. As a consequence convergence to the limit can be
much faster, when such quasi-random numbers are well-chosen.
[para]

The package defines a [term class] "qrpoint" that creates a command to generate
quasi-random points in 1, 2 or more dimensions. The command can either generate
separate points, so that they can be used in a user-defined algorithm or use these
points to calculate integrals of functions defined over 1, 2 or more dimensions.
It also holds several other common algorithms. (NOTE: these are not implemented yet)
[para]
One particular characteristic of the generators is that there are no tuning parameters
involved, which makes the use particularly simple.


[section "COMMANDS"]
A quasi-random point generator is created using the [term qrpoint] class:

[list_begin definitions]

[call [cmd "::math::quasirandom::qrpoint create"] [arg NAME] [arg DIM] [opt ARGS]]
This command takes the following arguments:

[list_begin arguments]
[arg_def string NAME] The name of the command to be created (alternatively: the [term new] subcommand
will generate a unique name)
[arg_def integer/string DIM] The number of dimensions or one of: "circle", "disk", "sphere" or "ball"
[arg_def strings ARGS] Zero or more key-value pairs. The supported options are:

[list_begin itemized]
[item] [term {-start index}]: The index for the next point to be generated (default: 1)
[item] [term {-evaluations number}]: The number of evaluations to be used by default (default: 100)
[list_end]

[list_end]

[list_end]

The points that are returned lie in the hyperblock [lb]0,1[lb]^n (n the number of dimensions)
or on the unit circle, within the unit disk, on the unit sphere or within the unit ball.
[para]

Each generator supports the following subcommands:
[list_begin definitions]

[call [cmd "gen next"]]
Return the coordinates of the next quasi-random point
[nl]

[call [cmd "gen set-start"] [arg index]]
Reset the index for the next quasi-random point. This is useful to control which list of points is returned.
Returns the new or the current value, if no value is given.
[nl]

[call [cmd "gen set-evaluations"] [arg number]]
Reset the default number of evaluations in compound algorithms. Note that the actual number is the
smallest 4-fold larger or equal to the given number. (The 4-fold plays a role in the detailed integration
routine.)
[nl]

[call [cmd "gen integral"] [arg func] [arg minmax] [arg args]]
Calculate the integral of the given function over the block (or the circle, sphere etc.)

[list_begin arguments]
[arg_def string func] The name of the function to be integrated

[arg_def list minmax] List of pairs of minimum and maximum coordinates. This can be used to
map the quasi-random coordinates to the desired hyper-block.
[nl]
If the space is a circle, disk etc. then this argument should be a single value, the radius.
The circle, disk, etc. is centred at the origin. If this is not what is required, then a coordinate
transformation should be made within the function.

[arg_def strings args] Zero or more key-value pairs. The following options are supported:
[list_begin itemized]
[item] [term {-evaluations number}]: The number of evaluations to be used. If not specified use the
default of the generator object.
[list_end]

[list_end]

[list_end]

[section TODO]
Implement other algorithms and variants
[para]
Implement more unit tests.
[para]
Comparison to pseudo-random numbers for integration.


[section References]

Various algorithms exist for generating quasi-random numbers. The generators created in this package are based on:
[uri http://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/]

[manpage_end]

Added modules/math/quasirandom.tcl.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# quasirandom.tcl --
#     Generate quasi-random points in n dimensions and provide simple
#     methods to evaluate an integral
#
#     Note: provide a OO-style interface
#
#     TODO: integral-detailed, minimum, maximum
#
#     Based on the blog "The Unreasonable Effectiveness of Quasirandom Sequences" by Martin Roberts,
#     http://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/
#

package require Tcl 8.5
package require TclOO

package provide math::quasirandom 1.0

namespace eval ::math::quasirandom {

# qrpoints --
#     Create the class
#
::oo::class create qrpoints {

    # constructor --
    #     Construct a new instance of the qrpoints class
    #
    # Arguments:
    #     dim             Number of dimensions, or one of: circle, disk, sphere, ball
    #     args            Zero or more key-value pairs:
    #                     -start       - start the generation with the given multiplier (integer)
    #                     -evaluations - default number of evaluations for the integration
    #                     (possibly others as well)
    #
    constructor {dimin args} {
        my variable dim
        my variable coord_factors
        my variable step
        my variable evaluations
        my variable use_radius
        my variable effective_dim

        if { ( ![string is integer -strict $dimin] || $dimin <= 0 ) && $dimin ni {circle disk sphere ball} } {
            return -code error "The dimension argument should be a positive integer value or one of circle, disk, sphere or ball"
        }

        set use_radius 1
        switch -- $dimin {
            "circle" {
                set dim 1
                set effective_dim 2
                ::oo::objdefine [self] {
                    forward next   my CircleNext
                    forward Volume my CircleVolume
                }
            }
            "disk" {
                set dim 2
                set effective_dim 2
                ::oo::objdefine [self] {
                    forward next   my DiskNext
                    forward Volume my DiskVolume
                }
            }
            "sphere" {
                set dim 2
                set effective_dim 3
                ::oo::objdefine [self] {
                    forward next   my SphereNext
                    forward Volume my SphereVolume
                }
            }
            "ball" {
                set dim 3
                set effective_dim 3
                ::oo::objdefine [self] {
                    forward next   my BallNext
                    forward Volume my BallVolume
                }
            }
            default {
                set dim $dimin
                set use_radius 0
                ::oo::objdefine [self] {
                    forward next   my PlainNext
                    forward Volume my PlainVolume
                }
            }
        }

        set step        1
        set evaluations 100

        set coord_factors [::math::quasirandom::CoordFactors $dim]

        foreach {key value} $args {
            switch -- $key {
            "-start" {

                 my set-step $value
            }
            "-evaluations" {
                 if { ![string is -strict integer $value] || $value <= 0 } {
                     return -code error "The value for the option $key should be a positive integer value"
                 }

                 my set-evaluations $value
            }
            default {
                return -code error "Unknown option: $key -- value: $value"
            }
            }
        }
    }

    # PlainNext --
    #     Generate the next point - for a hyperblock
    #
    method PlainNext {} {
        my variable step
        my variable coord_factors

        set coords {}
        foreach f $coord_factors {
            lappend coords [expr {fmod( $f * $step, 1.0 )}]
        }

        incr step

        return $coords
    }

    # PlainVolume --
    #     Calculate the volume of a hyperblock
    #
    # Arguments:
    #     minmax              List of minimum and maximum per dimension
    #
    # Returns:
    #     The volume
    #
    method PlainVolume {minmax} {
        set volume 1.0
        foreach range $minmax {
            lassign $range xmin xmax
            set volume [expr {$volume * ($xmax-$xmin)}]
        }
        return $volume
    }

    # CircleNext --
    #     Generate the next point on a unit circle
    #
    method CircleNext {} {

        set f      [lindex [my PlainNext] 0]
        set rad    [expr {2.0 * acos(-1.0) * $f}]

        set coords [list [expr {cos($rad)}] [expr {sin($rad)}]]

        return $coords
    }

    # CircleVolume --
    #     Calculate the "volume" of the unit circle
    #
    # Arguments:
    #     radius        Radius of the circle
    #
    method CircleVolume {radius} {
         return [expr {$radius * 2.0*cos(-1.0)}]
    }

    # DiskNext --
    #     Generate the next point on a unit disk
    #
    method DiskNext {} {

        while {1} {
            set coords [my PlainNext]

            lassign $coords x y

            if { hypot($x-0.5,$y-0.5) <= 0.25 } {
                set coords [list [expr {2.0*$x-1.0}] [expr {2.0*$y-1.0}]]
                break
            }
        }
        return $coords
    }

    # DiskVolume --
    #     Calculate the "volume" of the unit disk
    #
    # Arguments:
    #     radius        Radius of the disk
    #
    method DiskVolume {radius} {
         return [expr {$radius**2 * cos(-1.0)}]
    }

    # BallNext --
    #     Generate the next point on a unit ball
    #
    method BallNext {} {

        while {1} {
            set coords [my PlainNext]

            lassign $coords x y z

            set r [expr {($x-0.5)**2 + ($y-0.5)**2 + ($z-0.5)**2}]
            if { $r <= 0.25 } {
                set coords [list [expr {2.0*$x-1.0}] [expr {2.0*$y-1.0}] [expr {2.0*$z-1.0}]]
                break
            }
        }

        return $coords
    }

    # BallVolume --
    #     Calculate the volume of the unit ball
    #
    # Arguments:
    #     radius        Radius of the ball
    #
    method BallVolume {radius} {
         return [expr {4.0/3.0 * $radius**3 * cos(-1.0)}]
    }

    # SphereNext --
    #     Generate the next point on a unit sphere
    #
    method SphereNext {} {

        set coords [my PlainNext]

        lassign $coords u v

        set phi    [expr {2.0 * acos(-1.0) * $v}]
        set lambda [expr {acos(2.0 * $u - 1.0) + 0.5 * acos(-1.0)}]

        set x      [expr {cos($lambda) * cos($phi)}]
        set y      [expr {cos($lambda) * sin($phi)}]
        set z      [expr {sin($lambda)}]

        return [list $x $y $z]
    }

    # SphereVolume --
    #     Calculate the "volume" of the unit sphere
    #
    # Arguments:
    #     radius        Radius of the sphere
    #
    method SphereVolume {radius} {
         return [expr {4.0 * $radius**2 * cos(-1.0)}]
    }

    # set-step --
    #     Set the first step to be used
    #
    method set-step {{value ""}} {
        my variable step

        if { $value eq "" } {
            return $step
        }

        if { ![string is integer -strict $value] } {
            return -code error "The value for the option $key should be an integer value"
        }

        set step [expr {int($value)}]
    }

    # set-evaluations --
    #     Set the number of evaluations for integration
    #
    method set-evaluations {{value ""}} {
        my variable evaluations

        if { $value eq "" } {
            return $evaluations
        }

        if { ![string is integer -strict $value] || $value <= 0 } {
            return -code error "The value for the option $key should be a positive integer value"
        }

        set evaluations [expr {4*int(($value+3)/4)}]  ;# Make sure it is a 4-fold
    }

    # integral --
    #     Evaluate the integral of a function over a given (rectangular) domain
    #
    # Arguments:
    #     func              Function to be integrated
    #     minmax            List of minimum and maximum bounds for each coordinate
    #     args              Key-value pair: number of evaluations
    #
    # Returns:
    #     Estimate of the integral based on "evaluations" evaluations
    #     Note: no error estimate
    #
    method integral {func minmax args} {
        my variable dim
        my variable step
        my variable coord_factors
        my variable evaluations
        my variable use_radius
        my variable effective_dim

        set evals $evaluations

        set func [uplevel 1 [list namespace which -command $func]]

        foreach {key value} $args {
            switch -- $key {
            "-evaluations" {
                 if { ![string is integer -strict $value] || $value <= 0 } {
                     return -code error "The value for the option $key should be a positive integer value"
                 }

                 set evals $value ;# Local only!
            }
            default {
                return -code error "Unknown option: $key -- value: $value"
            }
            }
        }

        if { ! $use_radius } {
            if { [llength $minmax] != $dim } {
                return -code error "The number of ranges (minmax) should be equal to the dimension ($dim)"
            } else {
                set volume [my Volume $minmax]
            }
        } else {
            if { ! [string is double $minmax] } {
                return -code error "For a circle, disk, sphere or ball only the radius should be given"
            } else {
                set radius $minmax
                set minmax [lrepeat $effective_dim [list 0.0 $radius]]
                set volume [my Volume $radius]
            }
        }

        set sum 0.0

        for {set i 0} {$i < $evals} {incr i} {
            set coords {}
            foreach c [my next] range $minmax {
                lassign $range xmin xmax
                lappend coords [expr {$xmin + ($xmax-$xmin) * $c}]
            }
            set sum [expr {$sum + [$func $coords]}]
        }

        return [expr {$sum * $volume / $evals}]
    }

    # integral-detailed --
    #     Evaluate the integral of a function over a given (rectangular) domain
    #     and provide detailed information
    #
    # Arguments:
    #     func              Function to be integrated
    #     minmax            List of minimum and maximum bounds for each coordinate
    #     args              Key-value pair: number of evaluations
    #
    # Returns:
    #     Dictionary of:
    #     -estimate value     - estimate of the integral
    #     -evaluations number - total number of evaluations
    #     -error value        - estimate of the error
    #     -rawvalues list     - list of raw values obtained for the integral
    #
    method integral-detailed {func minmax args} {
        my variable evaluations

        set evals $evaluations

        set func [uplevel 1 [list namespace which -command $func]]

        foreach {key value} $args {
            switch -- $key {
            "-evaluations" {
                 if { ![string is integer -strict $value] || $value <= 0 } {
                     return -code error "The value for the option $key should be a positive integer value"
                 }

                 set evals $value ;# Local only!
            }
            default {
                return -code error "Unknown option: $key -- value: $value"
            }
            }
        }

        lappend args -evaluations [expr {($evals+3)/4}]

        for {set i 0} {$i < 4} {incr i} {
            lappend rawvalues [my integral $func $minmax {*}$args]
        }

        set sum   0.0
        set sqsum 0.0

        foreach value $rawvalues {
            set sum   [expr {$sum + $value}]
            set sqsum [expr {$sqsum + $value**2}]
        }

        set stdev [expr {sqrt(($sqsum - $sum**2/4.0)/3.0)}]
        set sum   [expr {$sum / 4.0}]
                                            # Standard error of mean
        return [dict create -estimate $sum -error [expr {$stdev/2.0}] -rawvalues $rawvalues -evaluations [expr {4*(($evals+3)/4)}]]
    }

} ;# End of class

} ;# End of namespace eval

# CoordFactors --
#     Determine the factors for the coordinates
#
# Arguments:
#     dim         Number of dimensions
#
proc ::math::quasirandom::CoordFactors {dim} {
    set n [expr {$dim + 1}]

    set f 1.0
    for {set i 0} {$i < 10} {incr i} {
        set f [expr {$f - ($f**$n-$f-1.0) / ($n*$f**($n-1)-1.0)}]
    }

    set factors {}
    set af      1.0

    for {set i 0} {$i < $dim} {incr i} {
        set af [expr {$af/$f}]
        lappend factors $af
    }

    return $factors
}

# End of code for package

# --------------------------------------------
# test --
#

if {0} {

::math::quasirandom::qrpoints create square 2

puts [square next]
puts [square next]
puts [square next]


proc f {coords} {
    lassign $coords x y

    expr {$x**2+$y**2}
}

proc g {coords} {
    lassign $coords x y

    expr {(1.0-cos($x))**2 * (1.0-cos($y))**2}
}

# Print four estimates - should not deviate too much from 10.0
puts [square integral f {{0 1} {0 3}}]
puts [square integral f {{0 1} {0 3}}]
puts [square integral f {{0 1} {0 3}}]
puts [square integral f {{0 1} {0 3}}]

# Print a sequence of estimates - should converge to (3pi/2)**2
foreach n {20 40 100 300 1000} {
    square set-evaluations $n

    puts "$n: [square integral g [list [list 0.0 [expr {acos(-1)}]] [list 0.0 [expr {acos(-1)}]]]]"
}


::math::quasirandom::qrpoints create block 3
puts [block next]

puts "Circle ..."
::math::quasirandom::qrpoints create circle circle
puts [circle next]
puts [circle next]
puts [circle next]

# Test values for CoordFactors
# dim = 1: 1.6180339887498948482045...
# dim = 2: 1.3247179572447460259609...
# dim = 3: 1.2207440846057594753616...

set f [::math::quasirandom::CoordFactors 1]
puts 1.6180339887498948482045...
puts [expr {1.0/$f}]

set f [lindex [::math::quasirandom::CoordFactors 2] 0]
puts 1.3247179572447460259609...
puts [expr {1.0/$f}]

set f [lindex [::math::quasirandom::CoordFactors 3] 0]
puts 1.2207440846057594753616...
puts [expr {1.0/$f}]
}

Added modules/math/quasirandom.test.





































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# -*- tcl -*-
# quasirandom.test --
#     Tests for the quasi-random numbers package
#

source [file join \
	    [file dirname [file dirname [file join [pwd] [info script]]]] \
	    devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2.1

testing {
    useLocal  quasirandom.tcl math::quasirandom
}

#
# Functions for integration tests
#
proc const {coords} {
    return 1.0
}

proc fx {coords} {
    set x [lindex $coords 0]
    return $x
}

proc fy {coords} {
    set y [lindex $coords 1]
    return $y
}

proc fz {coords} {
    set z [lindex $coords 2]
    return $z
}

proc fxyz4 {coords} {
    lassign $coords x y z
    return [expr {($x*$y*$z)**4}]
}

#
# Auxiliary proc
#
proc equalCoords {coords1 coords2} {
    set equal 1
    foreach c1 $coords1 c2 $coords2 {
        if { $c1 != $c2 } {
            set equal 0
            break
        }
    }
    return $equal
}

#
# Create and register (in that order!) custom matching procedures
#
proc matchTolerant { expected actual } {
    set match 1
    foreach a $actual e $expected {
	if { $e != 0.0 } {
	    if { abs($e-$a)>1.0e-7*abs($e) &&
		 abs($e-$a)>1.0e-7*abs($a)     } {
		set match 0
		break
	    }
	} else {
	    if { abs($a) > 1.0e-7 } {
		set match 0
	    }
	}
    }
    return $match
}
proc matchOnePercent { expected actual } {
    set match 1
    foreach a $actual e $expected {
	if { $e != 0.0 } {
	    if { abs($e-$a)>1.0e-2*abs($e) &&
		 abs($e-$a)>1.0e-2*abs($a)     } {
		set match 0
		break
	    }
	} else {
	    if { abs($a) > 1.0e-2 } {
		set match 0
	    }
	}
    }
    return $match
}

::tcltest::customMatch tolerant matchTolerant
::tcltest::customMatch error1percent matchOnePercent
::tcltest::customMatch equal equalCoords


#
# Testing CoordFactors: the basis of the algorithm
# Note: exact matching
#
test "Quasirandom-0.1" "Check basic factor for 1 dimension" -body {
    set f [::math::quasirandom::CoordFactors 1]
    return [expr {1.0/$f}]
} -result 1.618033988749895

test "Quasirandom-0.2" "Check basic factor for 2 dimensions" -body {
    set f [lindex [::math::quasirandom::CoordFactors 2] 0]
    return [expr {1.0/$f}]
} -result 1.324717957244746

test "Quasirandom-0.3" "Check basic factor for 3 dimensions" -body {
    set f [lindex [::math::quasirandom::CoordFactors 3] 0]
    return [expr {1.0/$f}]
} -result 1.2207440846057596

test "Quasirandom-0.4" "Check number of factors for 10 dimensions" -body {
    return [llength [::math::quasirandom::CoordFactors 10]]
} -result 10

#
# Basic interface to the qrpoints class
#
test "Quasirandom-1.0" "Simple QR generator for two dimensions" -match tolerant -body {
    ::math::quasirandom::qrpoints create simple 2

    return [simple next]
} -result {0.7548776662466927 0.5698402909980532} -cleanup {simple destroy}

test "Quasirandom-1.1" "Simple QR generator - negative dimension" -body {
    ::math::quasirandom::qrpoints create simple -1
} -returnCodes {error} -result {The dimension argument should be a positive integer value or one of circle, disk, sphere or ball}

test "Quasirandom-1.2" "Simple QR generator - set start" -body {
    ::math::quasirandom::qrpoints create simple  2
    ::math::quasirandom::qrpoints create simple2 2 -start 2

    simple next
    set coords  [simple next]

    set coords2 [simple2 next]  ;# Should be equal to the second point for the [simple] generator

    equalCoords $coords $coords2
} -result 1 -cleanup {simple destroy; simple2 destroy}

#
# Test simple methods
#
test "Quasirandom-2.1" "set-step sets and returns the value" -match equal -body {
    ::math::quasirandom::qrpoints create simple 2

    simple set-step 100
} -result 100 -cleanup {simple destroy}

test "Quasirandom-2.2" "set-evaluations sets and returns the value" -match equal -body {
    ::math::quasirandom::qrpoints create simple 2

    simple set-evaluations 100
} -result 100 -cleanup {simple destroy}

test "Quasirandom-2.3" "set-step returns the value" -match equal -body {
    ::math::quasirandom::qrpoints create simple 2

    simple set-step 100
    simple set-step
} -result 100 -cleanup {simple destroy}

test "Quasirandom-2.4" "set-evaluations returns the value" -match equal -body {
    ::math::quasirandom::qrpoints create simple 2

    simple set-evaluations 100
    simple set-evaluations
} -result 100 -cleanup {simple destroy}

#
# Test of bounds on points
#
test "Quasirandom-3.1" "Points should fall within block" -body {
    ::math::quasirandom::qrpoints create simple 10

    set correct_bound 1

    for {set i 0} {$i < 100} {incr i} {
        set coords [simple next]

        foreach c $coords {
            if { $c < 0.0 || $c > 1.0 } {
                set correct_bound 0
                break
            }
        }
    }

    return $correct_bound
} -result 1 -cleanup {simple destroy}

test "Quasirandom-3.2" "Points should fall on a circle" -match tolerant -body {
    ::math::quasirandom::qrpoints create simple circle

    set correct_bound 1
    set radii {}

    for {set i 0} {$i < 100} {incr i} {
        set coords [simple next]

        lassign $coords x y
        lappend radii [expr {hypot($x,$y)}]
    }

    return $radii
} -result [lrepeat 100 1.0] -cleanup {simple destroy}

test "Quasirandom-3.3" "Points should fall within a disk" -match equal -body {
    ::math::quasirandom::qrpoints create simple disk

    set correct_bounds {}
    for {set i 0} {$i < 100} {incr i} {
        set coords [simple next]

        lassign $coords x y
        lappend correct_bounds [expr {hypot($x,$y) <= 1.0}]
    }

    return $correct_bounds
} -result [lrepeat 100 1] -cleanup {simple destroy}

test "Quasirandom-3.4" "Points should fall on a sphere" -match tolerant -body {
    ::math::quasirandom::qrpoints create simple sphere

    set correct_bound 1
    set radii {}

    for {set i 0} {$i < 100} {incr i} {
        set coords [simple next]

        lassign $coords x y z
        lappend radii [expr {sqrt($x**2 + $y**2 + $z**2)}]
    }

    return $radii
} -result [lrepeat 100 1.0] -cleanup {simple destroy}

test "Quasirandom-3.5" "Points should fall within a ball" -match equal -body {
    ::math::quasirandom::qrpoints create simple ball

    set correct_bounds {}
    for {set i 0} {$i < 100} {incr i} {
        set coords [simple next]

        lassign $coords x y
        lappend correct_bounds [expr {sqrt($x**2 + $y**2 + $z**2) <= 1.0}]
    }

    return $correct_bounds
} -result [lrepeat 100 1] -cleanup {simple destroy}




#
# Test of integral methods
#
# Integrating a constant function means the result is the volume
#
test "Quasirandom-4.1" "Integrate constant function - volume = 1" -match tolerant -body {
    ::math::quasirandom::qrpoints create simple 3

    set result [simple integral const {{0.0 1.0} {0.0 1.0} {0.0 1.0}}]

} -result 1.0 -cleanup {simple destroy}

test "Quasirandom-4.2" "Integrate constant function - volume = 8" -match tolerant -body {
    ::math::quasirandom::qrpoints create simple 3

    set result [simple integral const {{0.0 2.0} {0.0 2.0} {0.0 2.0}}]

} -result 8.0 -cleanup {simple destroy}

test "Quasirandom-4.3" "Integrate constant function - circle" -match tolerant -body {
    ::math::quasirandom::qrpoints create simple circle

    set result [simple integral const 2.0]

} -result [expr {2.0 * 2.0 * cos(-1.0)}] -cleanup {simple destroy}

test "Quasirandom-4.3" "Integrate constant function - disk" -match tolerant -body {
    ::math::quasirandom::qrpoints create simple disk

    set result [simple integral const 2.0]

} -result [expr {2.0**2 * cos(-1.0)}] -cleanup {simple destroy}

test "Quasirandom-4.4" "Integrate constant function - sphere" -match tolerant -body {
    ::math::quasirandom::qrpoints create simple sphere

    set result [simple integral const 2.0]

} -result [expr {4.0 * 2.0**2 * cos(-1.0)}] -cleanup {simple destroy}

test "Quasirandom-4.5" "Integrate constant function - ball" -match tolerant -body {
    ::math::quasirandom::qrpoints create simple ball

    set result [simple integral const 2.0]

} -result [expr {4.0/3.0 * 2.0**3 * cos(-1.0)}] -cleanup {simple destroy}

# We do not use too many evaluations ... error less than 1%
test "Quasirandom-4.6" "Integrate linear function (x, y, z)" -match error1percent -body {
    ::math::quasirandom::qrpoints create simple 3

    set result [list [simple integral fx {{0.0 1.0} {0.0 1.0} {0.0 1.0}}] \
		    [simple integral fy {{0.0 1.0} {0.0 1.0} {0.0 1.0}}] \
		    [simple integral fz {{0.0 1.0} {0.0 1.0} {0.0 1.0}}] ]

} -result {0.5 0.5 0.5} -cleanup {simple destroy}

#
# The function varies "sharply", so we need more evaluations
#
test "Quasirandom-4.7" "Integrate (xyz)**4" -match error1percent -body {
    ::math::quasirandom::qrpoints create simple 3

    # Exact answer is 1/125
    set result [simple integral fxyz4 {{0.0 1.0} {0.0 1.0} {0.0 1.0}} -evaluations 1000]

} -result 0.0080 -cleanup {simple destroy}


#
# Detailed integration: provides error estimates but also an indication that
# the values can differ quite a bit
#
test "Quasirandom-5.1" "Integrate constant function with details - volume = 1" -match tolerant -body {
    ::math::quasirandom::qrpoints create simple 3

    set result [simple integral-detailed const {{0.0 1.0} {0.0 1.0} {0.0 1.0}}]

    set rawvalues [dict get $result -rawvalues]

} -result {1.0 1.0 1.0 1.0} -cleanup {simple destroy}


test "Quasirandom-5.2" "Integrate linear function with details - volume = 1" -match tolerant -body {
    ::math::quasirandom::qrpoints create simple 3

    set result [simple integral-detailed fx {{0.0 1.0} {0.0 1.0} {0.0 1.0}}]

    set rawvalues [dict get $result -rawvalues]

} -result {0.48924267415013695 0.48855550905424594 0.5278683439583554 0.48718117886246404} -cleanup {simple destroy}


test "Quasirandom-5.3" "Integrate (xyz)**4 with details - volume = 1" -match tolerant -body {
    ::math::quasirandom::qrpoints create simple 3

    set result [simple integral-detailed fxyz4 {{0.0 1.0} {0.0 1.0} {0.0 1.0}}]

    set rawvalues [dict get $result -rawvalues]

} -result {0.0022115062627913935 0.009840104253511376 0.014937934937801888 0.007838969739655276} -cleanup {simple destroy}


#
# Test integration procedures in a different namespace
#
test "Quasirandom-6.1" "Integrate ::func::func" -match tolerant -body {
    namespace eval ::func {

        proc func {xy} {
            lassign $xy x y
            expr {$x**2+$y**2}
        }

        ::math::quasirandom::qrpoints create simple 2

        set ::result [simple integral func {{0.0 1.0} {0.0 1.0}}]
    }

    return $result

} -result {0.67353777} -cleanup {::func::simple destroy}


test "Quasirandom-6.2" "Integrate (details) ::func::func" -match tolerant -body {
    namespace eval ::func {

        proc func {xy} {
            lassign $xy x y
            expr {$x**2+$y**2}
        }

        ::math::quasirandom::qrpoints create simple 2

        set ::result [simple integral-detailed func {{0.0 1.0} {0.0 1.0}}]
    }

    return [dict get $result -estimate]

} -result {0.67353777} -cleanup {::func::simple destroy}


# TODO:
# - func in different namespace
# - implement detailed integration and test the details
# - implement minimization

#
# Hm, the less than 1% error in the above test is a coincidence. The error is more
# likely to be 10%.
#
if {0} {
    ::math::quasirandom::qrpoints create simple 3
    # Exact answer is 1/125
    set result [simple integral fxyz4 {{0.0 1.0} {0.0 1.0} {0.0 1.0}} -evaluations 100]
    puts "fxyz4: $result"
    simple set-step 0
    set result [simple integral fxyz4 {{0.0 1.0} {0.0 1.0} {0.0 1.0}} -evaluations 1000]
    puts "fxyz4: $result"
    set result [simple integral fxyz4 {{0.0 1.0} {0.0 1.0} {0.0 1.0}} -evaluations 1000]
    puts "fxyz4: $result"
    set result [simple integral fxyz4 {{0.0 1.0} {0.0 1.0} {0.0 1.0}} -evaluations 1000]
    puts "fxyz4: $result"

    package require math::statistics
    set samples {}
    for {set trial 0} {$trial < 10} {incr trial} {
	set sum 0.0

	for {set p 0} {$p < 100} {incr p} {
	    set x   [expr {rand()}]
	    set y   [expr {rand()}]
	    set z   [expr {rand()}]
	    set sum [expr {$sum + [fxyz4 [list $x $y $z]]}]
	}

	puts "Trial $trial: [expr {$sum/100.0}]"

	lappend samples [expr {$sum/100.0}]
    }

    puts "MonteCarlo (100):"
    puts [::math::statistics::mean $samples]
    puts [::math::statistics::stdev $samples]

    set samples {}
    for {set trial 0} {$trial < 10} {incr trial} {
	set sum 0.0

	for {set p 0} {$p < 1000} {incr p} {
	    set x   [expr {rand()}]
	    set y   [expr {rand()}]
	    set z   [expr {rand()}]
	    set sum [expr {$sum + [fxyz4 [list $x $y $z]]}]
	}

	puts "Trial $trial: [expr {$sum/1000.0}]"

	lappend samples [expr {$sum/1000.0}]
    }

    puts "MonteCarlo (1000):"
    puts [::math::statistics::mean $samples]
    puts [::math::statistics::stdev $samples]

    set samples {}
    for {set trial 0} {$trial < 10} {incr trial} {
	set result [simple integral fxyz4 {{0.0 1.0} {0.0 1.0} {0.0 1.0}} -evaluations 100]

	lappend samples $result
    }

    puts "Quasi-random (100):"
    puts [::math::statistics::mean $samples]
    puts [::math::statistics::stdev $samples]

    set samples {}
    for {set trial 0} {$trial < 10} {incr trial} {
	set result [simple integral fxyz4 {{0.0 1.0} {0.0 1.0} {0.0 1.0}} -evaluations 1000]

	lappend samples $result
    }

    puts "Quasi-random (1000):"
    puts [::math::statistics::mean $samples]
    puts [::math::statistics::stdev $samples]


    puts [simple integral-detailed fx {{0.0 1.0} {0.0 1.0} {0.0 1.0}}]
}


# -------------------------------------------------------------------------

# End of test cases
testsuiteCleanup

Changes to modules/math/rational_funcs.man.

178
179
180
181
182
183
184
185
186
[section "REMARKS ON THE IMPLEMENTATION"]

The implementation of the rational functions relies on the
math::polynomials package. For further remarks see the documentation on
that package.

[vset CATEGORY {math :: rationalfunctions}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

178
179
180
181
182
183
184
185
186
[section "REMARKS ON THE IMPLEMENTATION"]

The implementation of the rational functions relies on the
math::polynomials package. For further remarks see the documentation on
that package.

[vset CATEGORY {math :: rationalfunctions}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/roman.man.

43
44
45
46
47
48
49
50
51
  [list_end]

Of these commands both [emph toroman] and [emph tointeger] are exported
for easier use. The other two are not, as they could interfer or be
confused with existing Tcl commands.

[vset CATEGORY {math :: roman}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

43
44
45
46
47
48
49
50
51
  [list_end]

Of these commands both [emph toroman] and [emph tointeger] are exported
for easier use. The other two are not, as they could interfer or be
confused with existing Tcl commands.

[vset CATEGORY {math :: roman}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/romberg.man.

332
333
334
335
336
337
338
339
340
foreach { value error } [romberg_sine f -1.0 1.0] break
puts [format "integral is %.6g +/- %.6g" $value $error]

integral is 3.97746 +/- 2.3557e-010
}]

[vset CATEGORY {math :: calculus}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

332
333
334
335
336
337
338
339
340
foreach { value error } [romberg_sine f -1.0 1.0] break
puts [format "integral is %.6g +/- %.6g" $value $error]

integral is 3.97746 +/- 2.3557e-010
}]

[vset CATEGORY {math :: calculus}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/special.man.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin math::special n 0.3]
[keywords {Bessel functions}]
[keywords {error function}]
[keywords math]
[keywords {special functions}]
[copyright {2004 Arjen Markus <[email protected]>}]
[moddesc   {Tcl Math Library}]
[titledesc {Special mathematical functions}]
[category  Mathematics]
[require Tcl [opt 8.3]]
[require math::special [opt 0.3]]

[description]
[para]
This package implements several so-called special functions, like
the Gamma function, the Bessel functions and such.

[para]

|








|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin math::special n 0.4]
[keywords {Bessel functions}]
[keywords {error function}]
[keywords math]
[keywords {special functions}]
[copyright {2004 Arjen Markus <[email protected]>}]
[moddesc   {Tcl Math Library}]
[titledesc {Special mathematical functions}]
[category  Mathematics]
[require Tcl [opt 8.5]]
[require math::special [opt 0.4]]

[description]
[para]
This package implements several so-called special functions, like
the Gamma function, the Bessel functions and such.

[para]
95
96
97
98
99
100
101





102
103
104
105
106
107
108
             |             |             |             |
Fresnel      | C           |  all of R   |     --      |   < 2.0e-3
integrals    | S           |  all of R   |     --      |   < 2.0e-3
             |             |             |             |
general      | Beta        | (see Gamma) |     --      |   < 1.0e-9
             | Gamma       |  x != 0,-1, |     --      |   < 1.0e-9
             |             |  -2, ...    |             |





             | sinc        |  all of R   |     --      |   exact
             |             |             |             |
orthogonal   | Legendre    |  all of R   | n = 0,1,... |   exact
polynomials  | Chebyshev   |  all of R   | n = 0,1,... |   exact
             | Laguerre    |  all of R   | n = 0,1,... |   exact
             |             |             | alpha el. R |
             | Hermite     |  all of R   | n = 0,1,... |   exact







>
>
>
>
>







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
             |             |             |             |
Fresnel      | C           |  all of R   |     --      |   < 2.0e-3
integrals    | S           |  all of R   |     --      |   < 2.0e-3
             |             |             |             |
general      | Beta        | (see Gamma) |     --      |   < 1.0e-9
             | Gamma       |  x != 0,-1, |     --      |   < 1.0e-9
             |             |  -2, ...    |             |
             | incBeta     |             |  a, b > 0   |   < 1.0e-9
             | regIncBeta  |             |  a, b > 0   |   < 1.0e-9
             | digamma     |  x != 0,-1  |             |   < 1.0e-9
             |             |  -2, ...    |             |
             |             |             |             |
             | sinc        |  all of R   |     --      |   exact
             |             |             |             |
orthogonal   | Legendre    |  all of R   | n = 0,1,... |   exact
polynomials  | Chebyshev   |  all of R   | n = 0,1,... |   exact
             | Laguerre    |  all of R   | n = 0,1,... |   exact
             |             |             | alpha el. R |
             | Hermite     |  all of R   | n = 0,1,... |   exact
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
[item]
Bessel functions of the second kind (Y_n, K_n)
[item]
Bessel functions of arbitrary order (and hence the Airy functions)
[item]
Chebyshev polynomials of the second kind (U_n)
[item]
The digamma function (psi)
[item]
The incomplete gamma and beta functions
[list_end]

[section "PROCEDURES"]

The package defines the following public procedures:

[list_begin definitions]

[call [cmd ::math::special::Beta] [arg x] [arg y]]

Compute the Beta function for arguments "x" and "y"

[list_begin arguments]
[arg_def float x] First argument for the Beta function

[arg_def float y] Second argument for the Beta function
[list_end]

[para]

























[call [cmd ::math::special::Gamma] [arg x]]

Compute the Gamma function for argument "x"

[list_begin arguments]
[arg_def float x] Argument for the Gamma function
[list_end]











[para]

[call [cmd ::math::special::erf] [arg x]]

Compute the error function for argument "x"

[list_begin arguments]







<
<
|



















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









>
>
>
>
>
>
>
>
>
>







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
[item]
Bessel functions of the second kind (Y_n, K_n)
[item]
Bessel functions of arbitrary order (and hence the Airy functions)
[item]
Chebyshev polynomials of the second kind (U_n)
[item]


The incomplete gamma function
[list_end]

[section "PROCEDURES"]

The package defines the following public procedures:

[list_begin definitions]

[call [cmd ::math::special::Beta] [arg x] [arg y]]

Compute the Beta function for arguments "x" and "y"

[list_begin arguments]
[arg_def float x] First argument for the Beta function

[arg_def float y] Second argument for the Beta function
[list_end]

[para]

[call [cmd ::math::special::incBeta] [arg a] [arg b] [arg x]]

Compute the incomplete Beta function for argument "x" with parameters "a" and "b"

[list_begin arguments]
[arg_def float a] First parameter for the incomplete Beta function, a > 0
[arg_def float b] Second parameter for the incomplete Beta function, b > 0
[arg_def float x] Argument for the incomplete Beta function
[list_end]

[para]

[call [cmd ::math::special::regIncBeta] [arg a] [arg b] [arg x]]

Compute the regularized incomplete Beta function for argument "x" with parameters "a" and "b"

[list_begin arguments]
[arg_def float a] First parameter for the incomplete Beta function, a > 0
[arg_def float b] Second parameter for the incomplete Beta function, b > 0
[arg_def float x] Argument for the regularized incomplete Beta function
[list_end]

[para]

[call [cmd ::math::special::Gamma] [arg x]]

Compute the Gamma function for argument "x"

[list_begin arguments]
[arg_def float x] Argument for the Gamma function
[list_end]

[para]

[call [cmd ::math::special::digamma] [arg x]]

Compute the digamma function (psi) for argument "x"

[list_begin arguments]
[arg_def float x] Argument for the digamma function
[list_end]

[para]

[call [cmd ::math::special::erf] [arg x]]

Compute the error function for argument "x"

[list_begin arguments]
464
465
466
467
468
469
470
471
472
[para]
Much information about these functions can be found in:
[para]
Abramowitz and Stegun: [emph "Handbook of Mathematical Functions"]
(Dover, ISBN 486-61272-4)

[vset CATEGORY {math :: special}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

501
502
503
504
505
506
507
508
509
[para]
Much information about these functions can be found in:
[para]
Abramowitz and Stegun: [emph "Handbook of Mathematical Functions"]
(Dover, ISBN 486-61272-4)

[vset CATEGORY {math :: special}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/special.tcl.

18
19
20
21
22
23
24

25
26
27
28
29
30
31
#
namespace eval ::math::special {
    #
    # Define a number of common mathematical constants
    #
    ::math::constants::constants pi
    variable halfpi [expr {$pi/2.0}]


    #
    # Functions defined in other math submodules
    #
    if { [info commands Beta] == {} } {
       namespace import ::math::Beta
       namespace import ::math::ln_Gamma







>







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#
namespace eval ::math::special {
    #
    # Define a number of common mathematical constants
    #
    ::math::constants::constants pi
    variable halfpi [expr {$pi/2.0}]
    variable tiny 1.0e-30

    #
    # Functions defined in other math submodules
    #
    if { [info commands Beta] == {} } {
       namespace import ::math::Beta
       namespace import ::math::ln_Gamma
286
287
288
289
290
291
292


































































































































293
294
295
296
297
298
299
300
301
    # Rational approximation for upper region.

    set q  [expr {sqrt(-2*log(1-$p))}]
    set x  [expr {-((((($c1*$q+$c2)*$q+$c3)*$q+$c4)*$q+$c5)*$q+$c6) /
    (((($d1*$q+$d2)*$q+$d3)*$q+$d4)*$q+1)}]
    return $x
}



































































































































# Bessel functions and elliptic integrals --
#
source [file join [file dirname [info script]] "bessel.tcl"]
source [file join [file dirname [info script]] "classic_polyns.tcl"]
source [file join [file dirname [info script]] "elliptic.tcl"]
source [file join [file dirname [info script]] "exponential.tcl"]

package provide math::special 0.3.0







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|
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
    # Rational approximation for upper region.

    set q  [expr {sqrt(-2*log(1-$p))}]
    set x  [expr {-((((($c1*$q+$c2)*$q+$c3)*$q+$c4)*$q+$c5)*$q+$c6) /
    (((($d1*$q+$d2)*$q+$d3)*$q+$d4)*$q+1)}]
    return $x
}


# incBeta --
#     Incomplete Beta funtion (not regularized)
#
# Arguments:
#     a, b        Parameters a and b (both > 0)
#     x           Value of the x argument (between 0 and 1)
#
# Notes:
#     Implementation taken from http://codeplea.com/incomplete-beta-function-in-c
#     Accuracy: at least 1.0e-8
#     Test values: https://keisan.casio.com/exec/system/1180573396
#
proc ::math::special::incBeta {a b x} {
    variable tiny

    if { $x < 0.0 || $x > 1.0 } {
        return -code error "Incomplete Beta function: x out of bounds (must be between 0 and 1)"
    }
    if { $a <= 0.0 || $b <= 0.0 } {
        return -code error "Incomplete Beta function: parameter a or b out of bounds (both must be > 0)"
    }

    #
    # Make sure the continued fraction converges fast
    #
    if { $x > ($a+1.0) / ($a+$b+2.0) } {
        set beta1      [Beta $a $b]
        set complement [incBeta $b $a [expr {1.-$x}]]
        return [expr {$beta1 - $complement}]
    }

    set f 1.0
    set c 1.0
    set d 0.0

    for { set i 0 } { $i <= 200 } { incr i } {

        set m [expr {$i/2}]

        #
        # Coefficients of the continued fraction
        #
        if { $i == 0 } {
            set numerator 1.0
        } elseif { $i % 2 == 0 } {
            set numerator [expr {$m * ($b-$m) * $x / ( ($a+2.0*$m-1.0) * ($a+2.0*$m) )}]
        } else {
            set numerator [expr {-($a+$m) * ($a+$b+$m) * $x / ( ($a+2.0*$m) * ($a+2.0*$m+1.0) )}]
        }

        #
        # Iteration (Lentz's algorithm)
        #
        set d [expr {1.0 + $numerator * $d}]
        if { abs($d) < $tiny } {
            set d $tiny
        }

        set d [expr {1.0 / $d}]
        set c [expr {1.0 + $numerator / $c}]

        if { abs($c) < $tiny } {
            set c $tiny
        }

        set cd [expr {$c * $d}]

        set f  [expr {$cd * $f}]

        #
        # Stopping criterium
        #
        if { abs(1.0 - $cd) < 1.0e-8 } {
            set factor [expr {$x ** $a * (1.0-$x) ** $b / $a}]
            return [expr {$factor * ($f - 1.0)}]
        }
    }

    return -code error "Incomplete Beta function: convergence not reached"
}

# regIncBeta --
#     Regularized incomplete Beta funtion
#
# Arguments:
#     a, b        Parameters a and b (both > -1)
#     x           Value of the x argument (between 0 and 1)
#
proc ::math::special::regIncBeta {a b x} {

    set incbeta [incBeta $a $b $x]
    set factor  [Beta $a $b]

    return [expr {$incbeta / $factor}]
}


# digamma --
#     Evaluate the digamma function - approximate via a power series
#
# Arguments
#     x                   Argument of the function
#
# Result:
#     Value of digamma function at x
#
# Notes;
#     Test values: https://keisan.casio.com/exec/system/1180573446
#     Formula taken from: https://math.stackexchange.com/questions/1441753/approximating-the-digamma-function
#
proc ::math::special::digamma {x} {
    if { $x >= 10.0 } {
        set x [expr {$x - 1.0}]
        return [expr {log($x) + 1.0 / (2.0 * $x) - 1.0 / (12.0 * $x**2) + 1.0 / (120.0 * $x**4) - 1.0 / (252.0 * $x**6)
                              + 1.0 / (240.0 * $x**8) - 5.0 / (660.0 * $x**10) + 691.0 / (32760.0 * $x**12) - 1.0 / (12.0 * $x**14)}]
    } else {
        set n [expr {int(11.0 - $x)}]
        set correction 0.0
        for {set i 0} {$i < $n} {incr i} {
            set correction [expr {$correction + 1.0 / ($x + $i)}]
        }

        set newx [expr {$x + $n}]

        return [expr {[digamma $newx] - $correction}]
    }
}


# Bessel functions and elliptic integrals --
#
source [file join [file dirname [info script]] "bessel.tcl"]
source [file join [file dirname [info script]] "classic_polyns.tcl"]
source [file join [file dirname [info script]] "elliptic.tcl"]
source [file join [file dirname [info script]] "exponential.tcl"]

package provide math::special 0.4.0

Changes to modules/math/special.test.

57
58
59
60
61
62
63















64
65

66
67
68
69
70
71
72
            set match 0
            break
        }
    }
    return $match
}
















customMatch numbers         matchNumbers
customMatch numbers-fresnel matchFresnel


test "Erf-1.0" "Values of the error function" \
    -match numbers -body {
    set result {}
    foreach x {0.0 0.1 0.2 0.5 1.0 2.0 -0.1 -0.2 -0.5 -1.0 -2.0} {
        lappend result [::math::special::erf $x]
    }







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
            set match 0
            break
        }
    }
    return $match
}

#
# Expect an accuracy of eight decimals (incomplete Beta and digamma)
#
proc matchAccurate {expected actual} {
    set match 1
    foreach a $actual e $expected {
        if {abs($a-$e) > 1.0e-8} {
            set match 0
            break
        }
    }
    return $match
}


customMatch numbers          matchNumbers
customMatch numbers-fresnel  matchFresnel
customMatch numbers-accurate matchAccurate

test "Erf-1.0" "Values of the error function" \
    -match numbers -body {
    set result {}
    foreach x {0.0 0.1 0.2 0.5 1.0 2.0 -0.1 -0.2 -0.5 -1.0 -2.0} {
        lappend result [::math::special::erf $x]
    }
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
   set result {}
   foreach x {0.0 0.1 0.2 0.5 1.0 1.5 2.0 3.0 4.0 5.0} {
      lappend result [::math::special::fresnel_C $x]
   }
   set result
} -result {0.0  0.09999 0.19992 0.49234 0.77989 0.44526
           0.48825 0.60572 0.49842 0.56363}


test "Fresnel-1.1" "Values of the Fresnel S intergral" \
   -match numbers-fresnel -body {
   set result {}
   foreach x {0.0 0.1 0.2 0.5 1.0 1.5 2.0 3.0 4.0 5.0} {
      lappend result [::math::special::fresnel_S $x]
   }
   set result
} -result {0.0  0.00052 0.00419 0.06473 0.43826 0.69750
           0.34342 0.49631 0.42052 0.49919}


test "invnorm-1.0" "Values of the inverse normal distribution" \
   -match numbers -body {
   set result {}
   foreach p {0.001 0.01 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 0.99 0.999} {
       lappend result [::math::special::invnorm $p]
   }
   set result
} -result {-3.090232304709404 -2.326347874388028 -1.2815515641401563 -0.8416212327266185 -0.5244005132792953 -0.2533471028599986
           0.0 0.2533471028599986 0.5244005132792952 0.8416212327266186 1.2815515641401563 2.326347874388028 3.090232304709404}


test "sinc-1.0" "Values of the sinc function" \
   -match numbers -body {
   set result [::math::special::sinc 0.0]
} -result 1.0




























































# End of test cases
testsuiteCleanup







>










>











>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


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
   set result {}
   foreach x {0.0 0.1 0.2 0.5 1.0 1.5 2.0 3.0 4.0 5.0} {
      lappend result [::math::special::fresnel_C $x]
   }
   set result
} -result {0.0  0.09999 0.19992 0.49234 0.77989 0.44526
           0.48825 0.60572 0.49842 0.56363}


test "Fresnel-1.1" "Values of the Fresnel S intergral" \
   -match numbers-fresnel -body {
   set result {}
   foreach x {0.0 0.1 0.2 0.5 1.0 1.5 2.0 3.0 4.0 5.0} {
      lappend result [::math::special::fresnel_S $x]
   }
   set result
} -result {0.0  0.00052 0.00419 0.06473 0.43826 0.69750
           0.34342 0.49631 0.42052 0.49919}


test "invnorm-1.0" "Values of the inverse normal distribution" \
   -match numbers -body {
   set result {}
   foreach p {0.001 0.01 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 0.99 0.999} {
       lappend result [::math::special::invnorm $p]
   }
   set result
} -result {-3.090232304709404 -2.326347874388028 -1.2815515641401563 -0.8416212327266185 -0.5244005132792953 -0.2533471028599986
           0.0 0.2533471028599986 0.5244005132792952 0.8416212327266186 1.2815515641401563 2.326347874388028 3.090232304709404}


test "sinc-1.0" "Values of the sinc function" \
   -match numbers -body {
   set result [::math::special::sinc 0.0]
} -result 1.0


test "digamma-1.0" "Values of the digamma function"  \
   -match numbers-accurate -body {
   set result {}
   foreach x {-2.5 -1.5 -0.5 0.1 0.25 0.5 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 15.0 20 30.0} {
      lappend result [::math::special::digamma $x]
   }
   set result
} -result {1.103156640645243187226 0.7031566406452431872257 0.03648997397857652055902 -10.42375494041107679517 -4.22745353337626540809 -1.963510026021423479441
           -0.5772156649015328606065 0.4227843351 0.9227843351 1.256117668 1.506117668431800472727 1.706117668431800472727 1.872784335098467139394
           2.015641477955609996536 2.140641477955609996536 2.251752589066721107647 2.351752589066721107647 2.67434666166079370172 2.970523992242149050877
           3.384438132685524876562}


test "incBeta-1.0" "Values of the incomplete Beta function (a,b = 0.5,3)"  \
   -match numbers-accurate -body {
   set result {}
   set a 0.5
   set b 3.0
   foreach x {0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0} {
      lappend result [::math::special::incBeta $a $b $x]
   }
   set result
} -result {0 0.591556741 0.782325650 0.896074104 0.968078601 1.01351972 1.04105792 1.05642273 1.06377207 1.06632003 1.06666667}

test "incBeta-1.1" "Values of the incomplete Beta function (a,b = 2.0,1.3)"  \
   -match numbers-accurate -body {
   set result {}
   set a 2.0
   set b 1.3
   foreach x {0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0} {
      lappend result [::math::special::incBeta $a $b $x]
   }
   set result
} -result {0 0.00489724885 0.0191537005 0.0420524051 0.0727690680 0.110331697 0.153553061 0.200905566 0.250250898 0.298074371 0.334448161}

test "incBeta-2.0" "Values of the regularized incomplete Beta function (a,b = 0.5,3)"  \
   -match numbers-accurate -body {
   set result {}
   set a 0.5
   set b 3.0
   foreach x {0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0} {
      lappend result [::math::special::regIncBeta $a $b $x]
   }
   set result
} -result {0 0.554584445 0.733430297 0.840069473 0.907573688 0.950174737 0.975991803 0.990396306 0.997286318 0.999675025 1}

test "incBeta-2.1" "Values of the regularized incomplete Beta function (a,b = 2.0,1.3)"  \
   -match numbers-accurate -body {
   set result {}
   set a 2.0
   set b 1.3
   foreach x {0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0} {
      lappend result [::math::special::regIncBeta $a $b $x]
   }
   set result
} -result {0 0.0146427741 0.0572695646 0.125736691 0.217579513 0.329891773 0.459123651 0.600707642 0.748250184 0.891242370 1}


# End of test cases
testsuiteCleanup

Changes to modules/math/statistics.man.

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
value would occur assuming the medians of the populations are
equal.

[list_begin arguments]
[arg_def list args] - Two or more lists of data
[list_end]
[para]
























[call [cmd ::math::statistics::group-rank] [arg args]]
Rank the groups of data with respect to the complete set.
Returns a list consisting of the group ID, the value and the rank
(possibly a rational number, in case of ties) for each data item.

[list_begin arguments]
[arg_def list args] - Two or more lists of data
[list_end]
[para]

[call [cmd ::math::statistics::test-Wilcoxon] [arg sample_a] [arg sample_b]]
Compute the Wilcoxon test statistic to determine if two samples have the
same median or not. (The statistic can be regarded as standard normal, if the
sample sizes are both larger than 10. Returns the value of this statistic.

[list_begin arguments]
[arg_def list sample_a] - List of data comprising the first sample
[arg_def list sample_b] - List of data comprising the second sample
[list_end]
[para]








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














|







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
value would occur assuming the medians of the populations are
equal.

[list_begin arguments]
[arg_def list args] - Two or more lists of data
[list_end]
[para]

[call [cmd ::math::statistics::test-Levene] [arg groups]]
Compute the Levene statistic to determine if groups of data have the
same variance (are homoscadastic) or not. The data are organised
in groups. This version uses the mean of the data as the measure
to determine the deviations. The statistic is equivalent to an
F statistic with degrees of freedom k-1 and N-k, k being the
number of groups and N the total number of data.

[list_begin arguments]
[arg_def list groups] - List of groups of data
[list_end]
[para]

[call [cmd ::math::statistics::test-Brown-Forsythe] [arg groups]]
Compute the Brown-Forsythe statistic to determine if groups of data have the
same variance (are homoscadastic) or not. Like the Levene test, but this
version uses the median of the data.

[list_begin arguments]
[arg_def list groups] - List of groups of data
[list_end]
[para]

[call [cmd ::math::statistics::group-rank] [arg args]]
Rank the groups of data with respect to the complete set.
Returns a list consisting of the group ID, the value and the rank
(possibly a rational number, in case of ties) for each data item.

[list_begin arguments]
[arg_def list args] - Two or more lists of data
[list_end]
[para]

[call [cmd ::math::statistics::test-Wilcoxon] [arg sample_a] [arg sample_b]]
Compute the Wilcoxon test statistic to determine if two samples have the
same median or not. (The statistic can be regarded as standard normal, if the
sample sizes are both larger than 10.) Returns the value of this statistic.

[list_begin arguments]
[arg_def list sample_a] - List of data comprising the first sample
[arg_def list sample_b] - List of data comprising the second sample
[list_end]
[para]

896
897
898
899
900
901
902
























903
904
905
906
907
908
909

[list_begin arguments]
[arg_def float xmin] - Minimum value of the distribution
[arg_def float xmin] - Maximum value of the distribution
[arg_def float value] - Value for which the probability is required
[list_end]
[para]

























[call [cmd ::math::statistics::pdf-gamma] [arg alpha] [arg beta] [arg value]]
Return the probability of a given value for a Gamma
distribution with given shape and rate parameters

[list_begin arguments]
[arg_def float alpha] - Shape parameter







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

[list_begin arguments]
[arg_def float xmin] - Minimum value of the distribution
[arg_def float xmin] - Maximum value of the distribution
[arg_def float value] - Value for which the probability is required
[list_end]
[para]

[call [cmd ::math::statistics::pdf-triangular] [arg xmin] [arg xmax] [arg value]]
Return the probability of a given value for a triangular
distribution with given extremes. If the argument min is lower than the argument max, then smaller
values have higher probability and vice versa. In the first case the probability
density function is of the form [emph {f(x) = 2(1-x)}] and the other case it is of the form [emph {f(x) = 2x}].

[list_begin arguments]
[arg_def float xmin] - Minimum value of the distribution
[arg_def float xmin] - Maximum value of the distribution
[arg_def float value] - Value for which the probability is required
[list_end]
[para]

[call [cmd ::math::statistics::pdf-symmetric-triangular] [arg xmin] [arg xmax] [arg value]]
Return the probability of a given value for a symmetric triangular
distribution with given extremes.

[list_begin arguments]
[arg_def float xmin] - Minimum value of the distribution
[arg_def float xmin] - Maximum value of the distribution
[arg_def float value] - Value for which the probability is required
[list_end]
[para]

[call [cmd ::math::statistics::pdf-gamma] [arg alpha] [arg beta] [arg value]]
Return the probability of a given value for a Gamma
distribution with given shape and rate parameters

[list_begin arguments]
[arg_def float alpha] - Shape parameter
1004
1005
1006
1007
1008
1009
1010




































1011
1012
1013
1014
1015
1016
1017

[list_begin arguments]
[arg_def float location] - Location parameter
[arg_def float scale] - Shape parameter
[arg_def float value] - Value for which the probability is required
[list_end]
[para]





































[call [cmd ::math::statistics::cdf-normal] [arg mean] [arg stdev] [arg value]]
Return the cumulative probability of a given value for a normal
distribution with given mean and standard deviation, that is the
probability for values up to the given one.

[list_begin arguments]







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

[list_begin arguments]
[arg_def float location] - Location parameter
[arg_def float scale] - Shape parameter
[arg_def float value] - Value for which the probability is required
[list_end]
[para]

[call [cmd ::math::statistics::pdf-laplace] [arg location] [arg scale] [arg value]]
Return the probability of a given value for a Laplace
distribution with given location and shape parameters. The Laplace distribution
consists of two exponential functions, is peaked and has heavier tails than the
normal distribution.

[list_begin arguments]
[arg_def float location] - Location parameter (mean)
[arg_def float scale] - Shape parameter
[arg_def float value] - Value for which the probability is required
[list_end]
[para]

[call [cmd ::math::statistics::pdf-kumaraswamy] [arg a] [arg b] [arg value]]
Return the probability of a given value for a Kumaraswamy
distribution with given parameters a and b. The Kumaraswamy distribution
is related to the Beta distribution, but has a tractable cumulative distribution function.

[list_begin arguments]
[arg_def float a] - Parameter a
[arg_def float b] - Parameter b
[arg_def float value] - Value for which the probability is required
[list_end]
[para]

[call [cmd ::math::statistics::pdf-negative-binomial] [arg r] [arg p] [arg value]]
Return the probability of a given value for a negative binomial
distribution with an allowed number of failures and the probability of success.

[list_begin arguments]
[arg_def int r] - Allowed number of failures (at least 1)
[arg_def float p] - Probability of success
[arg_def int value] - Number of successes for which the probability is to be returned
[list_end]
[para]

[call [cmd ::math::statistics::cdf-normal] [arg mean] [arg stdev] [arg value]]
Return the cumulative probability of a given value for a normal
distribution with given mean and standard deviation, that is the
probability for values up to the given one.

[list_begin arguments]
1043
1044
1045
1046
1047
1048
1049























1050
1051
1052
1053
1054
1055
1056
[list_end]
[para]

[call [cmd ::math::statistics::cdf-uniform] [arg xmin] [arg xmax] [arg value]]
Return the cumulative probability of a given value for a uniform
distribution with given extremes.
























[list_begin arguments]
[arg_def float xmin] - Minimum value of the distribution
[arg_def float xmin] - Maximum value of the distribution
[arg_def float value] - Value for which the probability is required
[list_end]
[para]








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
[list_end]
[para]

[call [cmd ::math::statistics::cdf-uniform] [arg xmin] [arg xmax] [arg value]]
Return the cumulative probability of a given value for a uniform
distribution with given extremes.

[list_begin arguments]
[arg_def float xmin] - Minimum value of the distribution
[arg_def float xmin] - Maximum value of the distribution
[arg_def float value] - Value for which the probability is required
[list_end]
[para]

[call [cmd ::math::statistics::cdf-triangular] [arg xmin] [arg xmax] [arg value]]
Return the cumulative probability of a given value for a triangular
distribution with given extremes. If xmin < xmax, then lower values have
a higher probability and vice versa, see also [emph pdf-triangular]

[list_begin arguments]
[arg_def float xmin] - Minimum value of the distribution
[arg_def float xmin] - Maximum value of the distribution
[arg_def float value] - Value for which the probability is required
[list_end]
[para]

[call [cmd ::math::statistics::cdf-symmetric-triangular] [arg xmin] [arg xmax] [arg value]]
Return the cumulative probability of a given value for a symmetric triangular
distribution with given extremes.

[list_begin arguments]
[arg_def float xmin] - Minimum value of the distribution
[arg_def float xmin] - Maximum value of the distribution
[arg_def float value] - Value for which the probability is required
[list_end]
[para]

1145
1146
1147
1148
1149
1150
1151




































1152
1153
1154
1155
1156
1157
1158

[list_begin arguments]
[arg_def float nf1] - Degrees of freedom for the numerator
[arg_def float nf2] - Degrees of freedom for the denominator
[arg_def float value] - Value for which the probability is required
[list_end]
[para]





































[call [cmd ::math::statistics::empirical-distribution] [arg values]]
Return a list of values and their empirical probability. The values are sorted in increasing order.
(The implementation follows the description at the corresponding Wikipedia page)

[list_begin arguments]
[arg_def list values] - List of data to be examined







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

[list_begin arguments]
[arg_def float nf1] - Degrees of freedom for the numerator
[arg_def float nf2] - Degrees of freedom for the denominator
[arg_def float value] - Value for which the probability is required
[list_end]
[para]

[call [cmd ::math::statistics::cdf-laplace] [arg location] [arg scale] [arg value]]
Return the cumulative probability of a given value for a Laplace
distribution with given location and shape parameters. The Laplace distribution
consists of two exponential functions, is peaked and has heavier tails than the
normal distribution.

[list_begin arguments]
[arg_def float location] - Location parameter (mean)
[arg_def float scale] - Shape parameter
[arg_def float value] - Value for which the probability is required
[list_end]
[para]

[call [cmd ::math::statistics::cdf-kumaraswamy] [arg a] [arg b] [arg value]]
Return the cumulative probability of a given value for a Kumaraswamy
distribution with given parameters a and b. The Kumaraswamy distribution
is related to the Beta distribution, but has a tractable cumulative distribution function.

[list_begin arguments]
[arg_def float a] - Parameter a
[arg_def float b] - Parameter b
[arg_def float value] - Value for which the probability is required
[list_end]
[para]

[call [cmd ::math::statistics::cdf-negative-binomial] [arg r] [arg p] [arg value]]
Return the cumulative probability of a given value for a negative binomial
distribution with an allowed number of failures and the probability of success.

[list_begin arguments]
[arg_def int r] - Allowed number of failures (at least 1)
[arg_def float p] - Probability of success
[arg_def int value] - Greatest number of successes
[list_end]
[para]

[call [cmd ::math::statistics::empirical-distribution] [arg values]]
Return a list of values and their empirical probability. The values are sorted in increasing order.
(The implementation follows the description at the corresponding Wikipedia page)

[list_begin arguments]
[arg_def list values] - List of data to be examined
1188
1189
1190
1191
1192
1193
1194























1195
1196
1197
1198
1199
1200
1201
[list_end]
[para]

[call [cmd ::math::statistics::random-uniform] [arg xmin] [arg xmax] [arg number]]
Return a list of "number" random values satisfying a uniform
distribution with given extremes.
























[list_begin arguments]
[arg_def float xmin] - Minimum value of the distribution
[arg_def float xmax] - Maximum value of the distribution
[arg_def int number] - Number of values to be returned
[list_end]
[para]








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
[list_end]
[para]

[call [cmd ::math::statistics::random-uniform] [arg xmin] [arg xmax] [arg number]]
Return a list of "number" random values satisfying a uniform
distribution with given extremes.

[list_begin arguments]
[arg_def float xmin] - Minimum value of the distribution
[arg_def float xmax] - Maximum value of the distribution
[arg_def int number] - Number of values to be returned
[list_end]
[para]

[call [cmd ::math::statistics::random-triangular] [arg xmin] [arg xmax] [arg number]]
Return a list of "number" random values satisfying a triangular
distribution with given extremes. If xmin < xmax, then lower values have a higher probability
and vice versa (see also [emph pdf-triangular].

[list_begin arguments]
[arg_def float xmin] - Minimum value of the distribution
[arg_def float xmax] - Maximum value of the distribution
[arg_def int number] - Number of values to be returned
[list_end]
[para]

[call [cmd ::math::statistics::random-symmetric-triangular] [arg xmin] [arg xmax] [arg number]]
Return a list of "number" random values satisfying a symmetric triangular
distribution with given extremes.

[list_begin arguments]
[arg_def float xmin] - Minimum value of the distribution
[arg_def float xmax] - Maximum value of the distribution
[arg_def int number] - Number of values to be returned
[list_end]
[para]

1290
1291
1292
1293
1294
1295
1296



































1297
1298
1299
1300
1301
1302
1303

[list_begin arguments]
[arg_def float location] - Location parameter
[arg_def float scale] - Scale parameter
[arg_def int number] - Number of values to be returned
[list_end]
[para]




































[call [cmd ::math::statistics::histogram-uniform] [arg xmin] [arg xmax] [arg limits] [arg number]]
Return the expected histogram for a uniform distribution.

[list_begin arguments]
[arg_def float xmin] - Minimum value of the distribution
[arg_def float xmax] - Maximum value of the distribution







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

[list_begin arguments]
[arg_def float location] - Location parameter
[arg_def float scale] - Scale parameter
[arg_def int number] - Number of values to be returned
[list_end]
[para]

[call [cmd ::math::statistics::random-laplace] [arg location] [arg scale] [arg number]]
Return a list of "number" random values satisfying a Laplace
distribution with given location and shape parameters. The Laplace distribution
consists of two exponential functions, is peaked and has heavier tails than the
normal distribution.

[list_begin arguments]
[arg_def float location] - Location parameter (mean)
[arg_def float scale] - Shape parameter
[arg_def int number] - Number of values to be returned
[list_end]
[para]

[call [cmd ::math::statistics::random-kumaraswamy] [arg a] [arg b] [arg number]]
Return a list of "number" random values satisying a Kumaraswamy
distribution with given parameters a and b. The Kumaraswamy distribution
is related to the Beta distribution, but has a tractable cumulative distribution function.

[list_begin arguments]
[arg_def float a] - Parameter a
[arg_def float b] - Parameter b
[arg_def int number] - Number of values to be returned
[list_end]
[para]

[call [cmd ::math::statistics::random-negative-binomial] [arg r] [arg p] [arg number]]
Return a list of "number" random values satisying a negative binomial distribution.

[list_begin arguments]
[arg_def int r] - Allowed number of failures (at least 1)
[arg_def float p] - Probability of success
[arg_def int number] - Number of values to be returned
[list_end]
[para]

[call [cmd ::math::statistics::histogram-uniform] [arg xmin] [arg xmax] [arg limits] [arg number]]
Return the expected histogram for a uniform distribution.

[list_begin arguments]
[arg_def float xmin] - Minimum value of the distribution
[arg_def float xmax] - Maximum value of the distribution
1337
1338
1339
1340
1341
1342
1343




























1344
1345
1346
1347
1348
1349
1350
Estimate the parameters for the Pareto distribution that comes closest to the given values.
Returns the estimated scale and shape parameters, as well as the standard error for the shape parameter.

[list_begin arguments]
[arg_def list values] - List of values, assumed to be distributed according to a Pareto distribution
[list_end]
[para]





























[list_end]
TO DO: more function descriptions to be added

[section "DATA MANIPULATION"]
The data manipulation procedures act on lists or lists of lists:








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
Estimate the parameters for the Pareto distribution that comes closest to the given values.
Returns the estimated scale and shape parameters, as well as the standard error for the shape parameter.

[list_begin arguments]
[arg_def list values] - List of values, assumed to be distributed according to a Pareto distribution
[list_end]
[para]

[call [cmd ::math::statistics::estimate-exponential] [arg values]]
Estimate the parameter for the exponential distribution that comes closest to the given values.
Returns an estimate of the one parameter and of the standard error.

[list_begin arguments]
[arg_def list values] - List of values, assumed to be distributed according to an exponential distribution
[list_end]
[para]

[call [cmd ::math::statistics::estimate-laplace] [arg values]]
Estimate the parameters for the Laplace distribution that comes closest to the given values.
Returns an estimate of respectively the location and scale parameters, based on maximum likelihood.

[list_begin arguments]
[arg_def list values] - List of values, assumed to be distributed according to an exponential distribution
[list_end]
[para]

[call [cmd ::math::statistics::estimante-negative-binomial] [arg r] [arg values]]
Estimate the probability of success for the negative binomial distribution that comes closest to the given values.
The allowed number of failures must be given.

[list_begin arguments]
[arg_def int r] - Allowed number of failures (at least 1)
[arg_def int number] - List of values, assumed to be distributed according to a negative binomial distribution.
[list_end]
[para]

[list_end]
TO DO: more function descriptions to be added

[section "DATA MANIPULATION"]
The data manipulation procedures act on lists or lists of lists:

1631
1632
1633
1634
1635
1636
1637
1638
1639
Both time series show a significant periodic component
[item]
The histograms are not very useful in identifying the nature of the time
series - they do not show the periodic nature.
[list_end]

[vset CATEGORY {math :: statistics}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

1859
1860
1861
1862
1863
1864
1865
1866
1867
Both time series show a significant periodic component
[item]
The histograms are not very useful in identifying the nature of the time
series - they do not show the periodic nature.
[list_end]

[vset CATEGORY {math :: statistics}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/statistics.tcl.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# version 0.9:   added kernel density estimation
# version 0.9.3: added histogram-alt, corrected test-normal
# version 1.0:   added test-anova-F
# version 1.0.1: correction in pdf-lognormal and cdf-lognormal
# version 1.1:   added test-Tukey-range and test-Dunnett
# version 1.3:   added wasserstein-distance, kl-divergence and logit regression

package require Tcl 8.5 ; # 8.5+ feature in test-anovo-F: **-operator
package provide math::statistics 1.3.0
package require math

if {![llength [info commands ::lrepeat]]} {
    # Forward portability, emulate lrepeat
    proc ::lrepeat {n args} {
	if {$n < 1} {
	    return -code error "must have a count of at least 1"







|
|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# version 0.9:   added kernel density estimation
# version 0.9.3: added histogram-alt, corrected test-normal
# version 1.0:   added test-anova-F
# version 1.0.1: correction in pdf-lognormal and cdf-lognormal
# version 1.1:   added test-Tukey-range and test-Dunnett
# version 1.3:   added wasserstein-distance, kl-divergence and logit regression

package require Tcl 8.5 ; # 8.5+ feature in test-anova-F and others: **-operator
package provide math::statistics 1.5.0
package require math

if {![llength [info commands ::lrepeat]]} {
    # Forward portability, emulate lrepeat
    proc ::lrepeat {n args} {
	if {$n < 1} {
	    return -code error "must have a count of at least 1"
61
62
63
64
65
66
67

68
69
70
71
72
73
74
	    test-Duckworth test-anova-F test-Tukey-range test-Dunnett
    #
    # Error messages
    #
    variable NEGSTDEV   {Zero or negative standard deviation}
    variable TOOFEWDATA {Too few or invalid data}
    variable OUTOFRANGE {Argument out of range}


    #
    # Coefficients involved
    #
    variable factorNormalPdf
    set factorNormalPdf [expr {sqrt(8.0*atan(1.0))}]








>







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
	    test-Duckworth test-anova-F test-Tukey-range test-Dunnett
    #
    # Error messages
    #
    variable NEGSTDEV   {Zero or negative standard deviation}
    variable TOOFEWDATA {Too few or invalid data}
    variable OUTOFRANGE {Argument out of range}
    variable INVALID    {Argument invalid}

    #
    # Coefficients involved
    #
    variable factorNormalPdf
    set factorNormalPdf [expr {sqrt(8.0*atan(1.0))}]

Changes to modules/math/statistics.test.

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
test "uniform-distribution-1.1" "Test cdf-uniform" -match tolerant -body {
    set x [list \
        [::math::statistics::cdf-uniform   0   10  5] \
        [::math::statistics::cdf-uniform   0.0 1.0 0.5] \
        [::math::statistics::cdf-uniform -10.0 1.0 -4.5] \
        [::math::statistics::cdf-uniform  -2.0 2.0  1.0]]
} -result {0.5 0.5 0.5 0.75}












































test "exponential-distribution-1.0" "Test pdf-exponential" -match tolerant -body {
    set x [list \
        [::math::statistics::pdf-exponential 2   1] \
        [::math::statistics::pdf-exponential 1.0 1.0] \
        [::math::statistics::pdf-exponential 2.0 2.0] \
        [::math::statistics::pdf-exponential 2.0 1.0]]
} -result {0.3032653298563167 0.36787944117144233 0.18393972058572117 0.3032653298563167}

test "exponential-distribution-1.1" "Test cdf-exponential" -match tolerant -body {
    set x [list \
        [::math::statistics::cdf-exponential 2   1] \
        [::math::statistics::cdf-exponential 1.0 1.0] \
        [::math::statistics::cdf-exponential 2.0 2.0] \
        [::math::statistics::cdf-exponential 2.0 1.0]]
} -result {0.3934693402873666 0.6321205588285577 0.6321205588285577 0.3934693402873666}





















































test "normal-distribution-1.0" "Test pdf-normal" -match tolerant -body {
    set x [list \
        [::math::statistics::pdf-normal  0   1   1] \
        [::math::statistics::pdf-normal  0.0 1.0 1.0] \
        [::math::statistics::pdf-normal  2.0 2.0 4.0] \
        [::math::statistics::pdf-normal -2.0 2.0 0.0] \







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
test "uniform-distribution-1.1" "Test cdf-uniform" -match tolerant -body {
    set x [list \
        [::math::statistics::cdf-uniform   0   10  5] \
        [::math::statistics::cdf-uniform   0.0 1.0 0.5] \
        [::math::statistics::cdf-uniform -10.0 1.0 -4.5] \
        [::math::statistics::cdf-uniform  -2.0 2.0  1.0]]
} -result {0.5 0.5 0.5 0.75}

test "triangular-distribution-1.0" "Test pdf-triangular" -match tolerant -body {
    set x [list \
        [::math::statistics::pdf-triangular   0   1.0 0.5]  \
        [::math::statistics::pdf-triangular   1.0 0.0 0.5]  \
        [::math::statistics::pdf-triangular   0.0 1.0 0.25] \
        [::math::statistics::pdf-triangular   1.0 0.0 0.25] \
        [::math::statistics::pdf-triangular   0.0 2.0 0.0]  \
        [::math::statistics::pdf-triangular   0.0 2.0 1.0]  \
        [::math::statistics::pdf-triangular   0.0 2.0 2.0]]
} -result {1.0 1.0 1.5 0.5 2.0 1.0 0.0}
test "triangular-distribution-1.1" "Test cdf-triangular" -match tolerant -body {
    set x [list \
        [::math::statistics::cdf-triangular   0   1.0  0.5] \
        [::math::statistics::cdf-triangular   1.0 0.0  0.5] \
        [::math::statistics::cdf-triangular   0.0 1.0  0.25] \
        [::math::statistics::cdf-triangular   1.0 0.0  0.25] \
        [::math::statistics::cdf-triangular   0.0 2.0  0.0] \
        [::math::statistics::cdf-triangular   0.0 2.0  1.0] \
        [::math::statistics::cdf-triangular   0.0 2.0  2.0]]
} -result {0.75 0.25 0.4375 0.0625 0.0 0.75 1.0}

test "triangular-symmetric-distribution-1.0" "Test pdf-symmetric-triangular" -match tolerant -body {
    set x [list \
        [::math::statistics::pdf-symmetric-triangular 0.0 2.0 -0.5]  \
        [::math::statistics::pdf-symmetric-triangular 0.0 2.0  0.0]  \
        [::math::statistics::pdf-symmetric-triangular 0.0 2.0  0.5]  \
        [::math::statistics::pdf-symmetric-triangular 0.0 2.0  1.0]  \
        [::math::statistics::pdf-symmetric-triangular 0.0 2.0  1.5]  \
        [::math::statistics::pdf-symmetric-triangular 0.0 2.0  2.0]  \
        [::math::statistics::pdf-symmetric-triangular 0.0 2.0  2.5]]
} -result {0.0 0.0 0.5 1.0 0.5 0.0 0.0}

test "triangular-symmetric-distribution-1.1" "Test cdf-symmetric-triangular" -match tolerant -body {
    set x [list \
        [::math::statistics::cdf-symmetric-triangular 0.0 2.0 -0.5]  \
        [::math::statistics::cdf-symmetric-triangular 0.0 2.0  0.0]  \
        [::math::statistics::cdf-symmetric-triangular 0.0 2.0  0.5]  \
        [::math::statistics::cdf-symmetric-triangular 0.0 2.0  1.0]  \
        [::math::statistics::cdf-symmetric-triangular 0.0 2.0  1.5]  \
        [::math::statistics::cdf-symmetric-triangular 0.0 2.0  2.0]  \
        [::math::statistics::cdf-symmetric-triangular 0.0 2.0  2.5]]
} -result {0.0 0.0 0.125 0.5 0.875 1.0 1.0}

test "exponential-distribution-1.0" "Test pdf-exponential" -match tolerant -body {
    set x [list \
        [::math::statistics::pdf-exponential 2   1] \
        [::math::statistics::pdf-exponential 1.0 1.0] \
        [::math::statistics::pdf-exponential 2.0 2.0] \
        [::math::statistics::pdf-exponential 2.0 1.0]]
} -result {0.3032653298563167 0.36787944117144233 0.18393972058572117 0.3032653298563167}

test "exponential-distribution-1.1" "Test cdf-exponential" -match tolerant -body {
    set x [list \
        [::math::statistics::cdf-exponential 2   1] \
        [::math::statistics::cdf-exponential 1.0 1.0] \
        [::math::statistics::cdf-exponential 2.0 2.0] \
        [::math::statistics::cdf-exponential 2.0 1.0]]
} -result {0.3934693402873666 0.6321205588285577 0.6321205588285577 0.3934693402873666}

test "laplace-distribution-1.0" "Test pdf-laplace" -match tolerant -body {
    set x [list \
        [::math::statistics::pdf-laplace  1   1   1] \
        [::math::statistics::pdf-laplace  1.0 1.0 2] \
        [::math::statistics::pdf-laplace -1.0 2.0 0] \
        [::math::statistics::pdf-laplace  1.5 2.5 3]]
} -result {0.5 0.18393972058572117 0.15163266492815836 0.1097623272188053}

test "laplace-distribution-1.1" "Test cdf-laplace" -match tolerant -body {
    set x [list \
        [::math::statistics::cdf-laplace  1   1   1] \
        [::math::statistics::cdf-laplace  1.0 1.0 2] \
        [::math::statistics::cdf-laplace -1.0 2.0 0] \
        [::math::statistics::cdf-laplace  1.5 2.5 3]]
} -result {0.5 0.8160602794142788 0.6967346701436833 0.7255941819529867}

test "kumaraswamy-distribution-1.0" "Test pdf-kumaraswamy" -match tolerant -body {
    set x [list \
        [::math::statistics::pdf-kumaraswamy  1   1   0.5] \
        [::math::statistics::pdf-kumaraswamy  0.5 0.5 0.5] \
        [::math::statistics::pdf-kumaraswamy  1.0 2.0 0] \
        [::math::statistics::pdf-kumaraswamy  1.0 2.0 0.5]]
} -result {1.0 0.6532814824381884 2.0 1.0}

test "kumaraswamy-distribution-1.1" "Test cdf-kumaraswamy" -match tolerant -body {
    set x [list \
        [::math::statistics::cdf-kumaraswamy  1   1   0.5] \
        [::math::statistics::cdf-kumaraswamy  0.5 0.5 0.5] \
        [::math::statistics::cdf-kumaraswamy  1.0 2.0 0] \
        [::math::statistics::cdf-kumaraswamy  1.0 2.0 0.5]]
} -result {0.5 0.4588038998538031 0.0 0.75}

# Non-trivial examples from Wikipedia
test "negative-binomial-distribution-1.0" "Test pdf-negative-binomial" -match tolerant -body {
    set x [list \
        [::math::statistics::pdf-negative-binomial 1 0.3 0] \
        [::math::statistics::pdf-negative-binomial 1 0.9 0] \
        [::math::statistics::pdf-negative-binomial 5 0.4 0] \
        [::math::statistics::pdf-negative-binomial 5 0.4 1] \
        [::math::statistics::pdf-negative-binomial 5 0.4 2] \
        [::math::statistics::pdf-negative-binomial 5 0.4 3] \
        [::math::statistics::pdf-negative-binomial 5 0.4 5]]
} -result {0.7 0.1 0.07776 0.15552 0.186624 0.1741824 0.10032906}

test "negative-binomial-distribution-1.1" "Test cdf-negative-binomial" -match tolerant -body {
    set x [list \
        [::math::statistics::cdf-negative-binomial 5 0.4 3] \
        [::math::statistics::cdf-negative-binomial 1 0.9 0] \
        [::math::statistics::cdf-negative-binomial 1 0.9 1] \
        [::math::statistics::cdf-negative-binomial 1 0.9 2]]
} -result {0.59408 0.1 0.19 0.271}

test "normal-distribution-1.0" "Test pdf-normal" -match tolerant -body {
    set x [list \
        [::math::statistics::pdf-normal  0   1   1] \
        [::math::statistics::pdf-normal  0.0 1.0 1.0] \
        [::math::statistics::pdf-normal  2.0 2.0 4.0] \
        [::math::statistics::pdf-normal -2.0 2.0 0.0] \
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
} -result 100

test "random-numbers-1.11" "Test random-cauchy" -body {
    set rnumbers [::math::statistics::random-cauchy 0 1 100]
    set result [llength $rnumbers]
} -result 100



































test "random-numbers-2.1" "Test estimate-pareto" -match tolerant -body {
    expr {srand($::rseed)}
    set rnumbers [::math::statistics::random-pareto 1.0 3.0 100]
    set result   [::math::statistics::estimate-pareto $rnumbers]
} -result {1.000519 3.668162 0.3668162}











































test "kruskal-wallis-1.0" "Test analysis Kruskal-Wallis" -match tolerant -body {
    ::math::statistics::analyse-Kruskal-Wallis {6.4 6.8 7.2 8.3 8.4 9.1 9.4 9.7} {2.5 3.7 4.9 5.4 5.9 8.1 8.2} {1.3 4.1 4.9 5.2 5.5 8.2}
} -result {9.83627087199 0.00731275323967}
test "kruskal-wallis-1.1" "Test test Kruskal-Wallis" -match tolerant -body {
    ::math::statistics::test-Kruskal-Wallis 0.95 {6.4 6.8 7.2 8.3 8.4 9.1 9.4 9.7} {2.5 3.7 4.9 5.4 5.9 8.1 8.2} {1.3 4.1 4.9 5.2 5.5 8.2}
} -result 1

# Data from Statistical methods in Engineering and Quality Assurance by Peter W.M. John
test "wilcoxon-1.0" "Test test Wilcoxon" -match tolerant -body {
    ::math::statistics::test-Wilcoxon {71.1 68.3 74.8 72.1 71.2 70.4 73.6 66.3 72.7 74.1 70.1 68.5} \
                                      {73.3 70.9 74.6 72.1 72.8 74.2 74.7 69.2 75.5 75.8 70.0 72.1}
} -result -1.67431578065







































# Data from the Wikipedia page on Spearman's rank correlation coefficient
test "spearman-rank-1.0" "Test Spearman rank correlation" -match tolerant -body {
    ::math::statistics::spearman-rank {106  86 100 101  99 103  97 113 112 110} \
                                      {  7   0  27  50  28  29  20  12   6  17}
} -result -0.175757575758








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
} -result 100

test "random-numbers-1.11" "Test random-cauchy" -body {
    set rnumbers [::math::statistics::random-cauchy 0 1 100]
    set result [llength $rnumbers]
} -result 100

test "random-numbers-1.12" "Test random-triangular" -body {
    set result 1
    set rnumbers [::math::statistics::random-triangular -10 10 100]
    # Check the scaling
    foreach r $rnumbers {
        if { $r < -10.0 || $r > 10.0 } {
            set result 0
            break
        }
    }

    # Also the alternative triangle
    set rnumbers [::math::statistics::random-triangular 10 -10 100]
    # Check the scaling
    foreach r $rnumbers {
        if { $r < -10.0 || $r > 10.0 } {
            set result 0
            break
        }
    }

    # The symmetric triangle
    set rnumbers [::math::statistics::random-symmetric-triangular 10 -10 100]
    # Check the scaling
    foreach r $rnumbers {
        if { $r < -10.0 || $r > 10.0 } {
            set result 0
            break
        }
    }

    set result
} -result 1

test "random-numbers-2.1" "Test random/estimate-pareto" -match tolerant -body {
    expr {srand($::rseed)}
    set rnumbers [::math::statistics::random-pareto 1.0 3.0 100]
    set result   [::math::statistics::estimate-pareto $rnumbers]
} -result {1.000519 3.668162 0.3668162}

test "random-numbers-2.2" "Test random/estimate-exponential" -match tolerant -body {
    expr {srand($::rseed)}
    set rnumbers [::math::statistics::random-exponential 2.0 1000]
    set result   [::math::statistics::estimate-exponential $rnumbers]
} -result {1.9976327295438587 0.06317069353857727}

test "random-numbers-2.3" "Test random/estimate-laplace" -match tolerant -body {
    expr {srand($::rseed)}
    set rnumbers [::math::statistics::random-laplace 1.0 1.0 1000]
    set result   [::math::statistics::estimate-laplace $rnumbers]
} -result {1.0106101707362272 0.9319576942526239}

# Very simple test - just check that the numbers lie between 0 and 1
test "random-numbers-2.4" "Test random-kumaraswamy" -body {
    expr {srand($::rseed)}
    set result   1

    foreach {a b} {0.5 0.5  1.0 1.0  0.5 1.0  1.0 0.5  2.0 0.1  0.1 2.0} {
        set rnumbers [::math::statistics::random-kumaraswamy $a $b 1000]
        foreach r $rnumbers {
            if { $r < 0.0 || $r > 1.0 } {
                set result 0
                break
            }
        }
    }
    set result
} -result 1

# Simple test, exact matching
test "random-numbers-2.5" "Test random-negative-binomial" -body {
    expr {srand($::rseed)}
    set rnumbers [::math::statistics::random-negative-binomial 1 0.3 10]
} -result {0 0 3 0 0 0 1 0 1 1}

test "random-numbers-2.6" "Test random/estimate-negative-binomial" -match tolerant -body {
    expr {srand($::rseed)}
    set r        3
    set rnumbers [::math::statistics::random-negative-binomial $r 0.5 1000]
    set pvalue   [::math::statistics::estimate-negative-binomial $r $rnumbers]
} -result 0.50190935

test "kruskal-wallis-1.0" "Test analysis Kruskal-Wallis" -match tolerant -body {
    ::math::statistics::analyse-Kruskal-Wallis {6.4 6.8 7.2 8.3 8.4 9.1 9.4 9.7} {2.5 3.7 4.9 5.4 5.9 8.1 8.2} {1.3 4.1 4.9 5.2 5.5 8.2}
} -result {9.83627087199 0.00731275323967}
test "kruskal-wallis-1.1" "Test test Kruskal-Wallis" -match tolerant -body {
    ::math::statistics::test-Kruskal-Wallis 0.95 {6.4 6.8 7.2 8.3 8.4 9.1 9.4 9.7} {2.5 3.7 4.9 5.4 5.9 8.1 8.2} {1.3 4.1 4.9 5.2 5.5 8.2}
} -result 1

# Data from Statistical methods in Engineering and Quality Assurance by Peter W.M. John
test "wilcoxon-1.0" "Test test Wilcoxon" -match tolerant -body {
    ::math::statistics::test-Wilcoxon {71.1 68.3 74.8 72.1 71.2 70.4 73.6 66.3 72.7 74.1 70.1 68.5} \
                                      {73.3 70.9 74.6 72.1 72.8 74.2 74.7 69.2 75.5 75.8 70.0 72.1}
} -result -1.67431578065

# Very simple tests, merely to show that the procedure "works"
# (No numerical example available)
test "levene-brown-forsythe-1.0" "Test test Levene/Brown-Forsythe" -match tolerant -body {
    set values {{1 2 3} {2 3 4} {5 6 7}}
    ::math::statistics::test-Levene $values
} -result 0.0

test "levene-brown-forsythe-1.1" "Test test Levene/Brown-Forsythe" -match tolerant -body {
    set values {{1 2 3} {2 3 4} {5 6 7}}
    ::math::statistics::test-Brown-Forsythe $values
} -result 0.0

test "levene-brown-forsythe-1.2" "Test test Levene/Brown-Forsythe" -match tolerant -body {
    set values {{1 2 2} {2 3 4} {5 6 7.4}}
    ::math::statistics::test-Levene $values
} -result 0.47937131630648294

test "levene-brown-forsythe-1.3" "Test test Levene/Brown-Forsythe" -match tolerant -body {
    set values {{1 2 2} {2 3 4} {5 6 7.4}}
    ::math::statistics::test-Brown-Forsythe $values
} -result 0.4382022471910113

# Data taken from https://www.itl.nist.gov/div898/handbook/eda/section3/eda35a.htm
# Note: the webpage talks of the Levene test, but is actually the Brown-Forsythe
test "levene-brown-forsythe-1.4" "Test test Levene/Brown-Forsythe" -match tolerant -body {
    set values {{ 1.006 0.996 0.998 1.000 0.992 0.993 1.002 0.999 0.994 1.000 }
                { 0.998 1.006 1.000 1.002 0.997 0.998 0.996 1.000 1.006 0.988 }
                { 0.991 0.987 0.997 0.999 0.995 0.994 1.000 0.999 0.996 0.996 }
                { 1.005 1.002 0.994 1.000 0.995 0.994 0.998 0.996 1.002 0.996 }
                { 0.998 0.998 0.982 0.990 1.002 0.984 0.996 0.993 0.980 0.996 }
                { 1.009 1.013 1.009 0.997 0.988 1.002 0.995 0.998 0.981 0.996 }
                { 0.990 1.004 0.996 1.001 0.998 1.000 1.018 1.010 0.996 1.002 }
                { 0.998 1.000 1.006 1.000 1.002 0.996 0.998 0.996 1.002 1.006 }
                { 1.002 0.998 0.996 0.995 0.996 1.004 1.004 0.998 0.999 0.991 }
               { 0.991 0.995 0.984 0.994 0.997 0.997 0.991 0.998 1.004 0.997 } }
    ::math::statistics::test-Brown-Forsythe $values
} -result 1.705910

# Data from the Wikipedia page on Spearman's rank correlation coefficient
test "spearman-rank-1.0" "Test Spearman rank correlation" -match tolerant -body {
    ::math::statistics::spearman-rank {106  86 100 101  99 103  97 113 112 110} \
                                      {  7   0  27  50  28  29  20  12   6  17}
} -result -0.175757575758

Changes to modules/math/symdiff.man.

64
65
66
67
68
69
70
71
72
==> (($c * (($a * $x) + $b)) + ($a * (($c * $x) + $d)))
math::calculus::symdiff::jacobian {x {$a * $x + $b * $y}
                         y {$c * $x + $d * $y}}
==> {{$a} {$b}} {{$c} {$d}}
}]

[vset CATEGORY {math :: calculus}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

64
65
66
67
68
69
70
71
72
==> (($c * (($a * $x) + $b)) + ($a * (($c * $x) + $d)))
math::calculus::symdiff::jacobian {x {$a * $x + $b * $y}
                         y {$c * $x + $d * $y}}
==> {{$a} {$b}} {{$c} {$d}}
}]

[vset CATEGORY {math :: calculus}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/trig.man.

187
188
189
190
191
192
193
194
195
[list_begin arguments]
[arg_def float angle] Angle (in degrees)
[list_end]

[list_end]

[vset CATEGORY {math :: trig}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

187
188
189
190
191
192
193
194
195
[list_begin arguments]
[arg_def float angle] Angle (in degrees)
[list_end]

[list_end]

[vset CATEGORY {math :: trig}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/math/wilcoxon.tcl.

1
2
3


4
5
6
7
8
9
10
# statistics_new.tcl --
#     Implementation of the Wilcoxon test: test if the medians
#     of two samples are the same


#

# test-Wilcoxon
#     Compute the statistic that indicates if the medians of two
#     samples are the same
#
# Arguments:
|


>
>







1
2
3
4
5
6
7
8
9
10
11
12
# wilcoxon.tcl --
#     Implementation of the Wilcoxon test: test if the medians
#     of two samples are the same
#
#     Also: Levene's and Brown-Forsythe's test
#

# test-Wilcoxon
#     Compute the statistic that indicates if the medians of two
#     samples are the same
#
# Arguments:
222
223
224
225
226
227
228












































































































#
# Result:
#     Rank correlation coefficient
#
proc ::math::statistics::spearman-rank {sample_a sample_b} {
    return [lindex [spearman-rank-extended $sample_a $sample_b] 0]
}



















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
#
# Result:
#     Rank correlation coefficient
#
proc ::math::statistics::spearman-rank {sample_a sample_b} {
    return [lindex [spearman-rank-extended $sample_a $sample_b] 0]
}

# test-Levene --
#     Compute the Levene statistic that indicates if the variances of
#     groups of data are the same
#
# Arguments:
#     groups         List of groups of values to be examined
#
# Result:
#     Statistic for the test (an F statistic with k-1, N-k degrees
#     of freedom - k the number of groups and N the total number
#     of values)
#     The test uses the mean of the values in the groups.
#
proc ::math::statistics::test-Levene {groups} {

    return [Test-Levene-Brown-Forsythe 0 $groups]
}

# test-Brown-Forsythe --
#     Compute the Brown-Forsythe statistic that indicates if the variances of
#     groups of data are the same
#
# Arguments:
#     groups         List of groups of values to be examined
#
# Result:
#     Statistic for the test (an F statistic with k-1, N-k degrees
#     of freedom - k the number of groups and N the total number
#     of values)
#     The test uses the median of the values in the groups.
#
proc ::math::statistics::test-Brown-Forsythe {groups} {

    return [Test-Levene-Brown-Forsythe 1 $groups]
}

# Test-Levene-Brown-Forsythe --
#     Compute either the Levene or the Brown-Forsythe statistic that indicates
#     if the variances of groups of data are the same
#
# Arguments:
#     choice         Which of the two versions
#     groups         List of groups of values to be examined
#
# Result:
#     Statistic for the test
#     The test uses either the mean or the median of the values in the groups.
#
proc ::math::statistics::Test-Levene-Brown-Forsythe {choice groups} {

    #
    # Compute the deviations from the mean/median within each group
    #
    set alldevs {}
    set zscores {}
    set zmeans  {}
    foreach group $groups {
        if { $choice } {
            set zm [median $group]
        } else {
            set zm [mean $group]
        }
        set zgroup {}
        foreach element $group {
            lappend zgroup [expr {abs($element-$zm)}]
        }

        set alldevs [concat $alldevs $zgroup]
        lappend zscores $zgroup
        lappend zmeans  [mean $zgroup]
    }

    set zoverall [mean $alldevs]

    set ndata   [llength $alldevs]
    set ngroups [llength $groups]

    #
    # Compute the numerator of the statistic
    #
    set sumsqmeans 0.0

    foreach zm $zmeans group $groups {
        set n          [llength $group]
        set sumsqmeans [expr { $sumsqmeans + $n * ($zm - $zoverall)**2 }]
    }

    #
    # Compute the denominator
    #
    set sumsqpergroup 0.0

    foreach zm $zmeans zs $zscores {
        set sumsq 0.0
        foreach z $zs {
            set sumsq [expr {$sumsq + ($z-$zm)**2}]
        }

        set sumsqpergroup [expr { $sumsqpergroup + $sumsq }]
    }

    #
    # Finally, the statistic
    #

    return [expr { ($ndata-$ngroups) * $sumsqmeans / double( ($ngroups-1) * $sumsqpergroup ) }]
}

Changes to modules/md4/md4.man.

160
161
162
163
164
165
166
167
168
      Krawczyk, H., Bellare, M. and Canetti, R. "HMAC: Keyed-Hashing for
      Message Authentication", RFC 2104, February 1997.
	([uri http://www.rfc-editor.org/rfc/rfc2104.txt])

[list_end]

[vset CATEGORY md4]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

160
161
162
163
164
165
166
167
168
      Krawczyk, H., Bellare, M. and Canetti, R. "HMAC: Keyed-Hashing for
      Message Authentication", RFC 2104, February 1997.
	([uri http://www.rfc-editor.org/rfc/rfc2104.txt])

[list_end]

[vset CATEGORY md4]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/md5/md5.man.

166
167
168
169
170
171
172
173
174
      Krawczyk, H., Bellare, M. and Canetti, R. "HMAC: Keyed-Hashing for
      Message Authentication", RFC 2104, February 1997.
	([uri http://www.rfc-editor.org/rfc/rfc2104.txt])

[list_end]

[vset CATEGORY md5]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

166
167
168
169
170
171
172
173
174
      Krawczyk, H., Bellare, M. and Canetti, R. "HMAC: Keyed-Hashing for
      Message Authentication", RFC 2104, February 1997.
	([uri http://www.rfc-editor.org/rfc/rfc2104.txt])

[list_end]

[vset CATEGORY md5]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/md5crypt/md5crypt.man.

77
78
79
80
81
82
83
84
85

[example {
% md5crypt::md5crypt password [md5crypt::salt]
$1$dFmvyRmO$T.V3OmzqeEf3hqJp2WFcb.
}]

[vset CATEGORY md5crypt]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

77
78
79
80
81
82
83
84
85

[example {
% md5crypt::md5crypt password [md5crypt::salt]
$1$dFmvyRmO$T.V3OmzqeEf3hqJp2WFcb.
}]

[vset CATEGORY md5crypt]
[include ../common-text/feedback.inc]
[manpage_end]

Deleted modules/mime/badmail1.txt.

1
2
3
4
5
6
7
8
9
10
Date: Tue, 10 Jun 2003 10:32:05 +0200
Message-Id: <[email protected]>
From: Magnus Fisch <[email protected]>
Subject:  Meeting tomorrow
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="----------CSFNU9QKPGZL79"
Bcc:

------------CSFNU9QKPGZL79--

<
<
<
<
<
<
<
<
<
<




















Deleted modules/mime/badmail2.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
From: "Kelsey " <[email protected]>
To: "gdylgzCsurvd1lw" <[email protected]>
Date: Fri, 28 Feb 2003 03:12:35 -0500
Subject: no subject   gdylgzCsurvd1lw
MIME-Version: 1.0
Content-Type: multipart/related;
  boundary="----=_NextPart_000_0000_2CBA2CBA.150C56D2"
X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N
X-Spam-Rating: icarus.apache.org 1.6.2 0/1000/N
Lines: 19
Xref: localhost private-mail:14167

------=_NextPart_000_0000_2CBA2CBA.150C56D2
Content-Type: text/html;
Content-Transfer-Encoding: base64

PCEtLTE1MTQ3LS0+PGJvZHk+DQpJdCdzIG1lIEplPCEtLTI5MDY0LS0+bm5pZmVyLDxicj4g
SSBqdXN0IHdhbjwhLS0xOTE0OS0tPnRlZCB0byBzZW5kIHlvdSB0aGF0IHBpYyB5b3UgYXNr
ZTwhLS0xNTAxMC0tPmQgZm9yIHRoZSBvdDwhLS0yNjUxMi0tPmhlcg0KZGF5LiA8YnI+IDxh
IGhyZWY9Imh0dHA6Ly93d3cuaG90aG9zdC5iei9hYmMvamVubmlmZXIvP1JJRD1jaW5nd2Yi
PkNsaTwhLS0yNzE1My0tPmNrDQpIPCEtLTI2NjcwLS0+ZXJlIHRvIGNhdDwhLS03NDg5LS0+
Y2ggbWUgb24gbXkgd2ViPCEtLTI0ODExLS0+Y2FtICYgc2VlIG1vcmUgcGljcyBvZiBtZS48
L2E+IDxicj48YnI+DQo8YSBocmVmPSJodHRwOi8vd3d3LmhvdGhvc3QuYnovYWJjL2plbm5p
ZmVyLz9SSUQ9Y2luZ3dmIj48aW1nIHNyYz0iaHR0cDovLzIwNy40NC4xODMuMjU0L2FiYy9q
ZW5uaWZlci93b29ob28uanBnIiBib3JkZXI9IjAiPjwvYT4NCjxicj48YnI+PGk+LSB4bzwh
LS0yMzQwMi0tPnhvIEplbm5pZmVyPC9pPjwvcD48YnI+PGJyPjxicj48YnI+PGJyPjxicj48
YnI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+PGJy
Pjxicj48YnI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+DQo8L2JvZHk+



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























































Changes to modules/mime/mime.man.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

[comment {-*- tcl -*- doctools manpage}]
[manpage_begin mime n 1.6]
[see_also ftp]
[see_also http]
[see_also pop3]
[see_also smtp]
[keywords email]
[keywords internet]
[keywords mail]
[keywords mime]
[keywords net]
[keywords {rfc 821}]
[keywords {rfc 822}]
[keywords {rfc 2045}]
[keywords {rfc 2046}]
[keywords {rfc 2049}]
[keywords smtp]
[copyright {1999-2000 Marshall T. Rose}]
[moddesc   {Mime}]
[titledesc {Manipulation of MIME body parts}]
[category  {Text processing}]
[require Tcl 8.5]
[require mime [opt 1.6]]
[description]
[para]

The [package mime] library package provides the commands to create and
manipulate MIME body parts.

[list_begin definitions]
>

|




















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[vset VERSION 1.6.2]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin mime n [vset VERSION]]
[see_also ftp]
[see_also http]
[see_also pop3]
[see_also smtp]
[keywords email]
[keywords internet]
[keywords mail]
[keywords mime]
[keywords net]
[keywords {rfc 821}]
[keywords {rfc 822}]
[keywords {rfc 2045}]
[keywords {rfc 2046}]
[keywords {rfc 2049}]
[keywords smtp]
[copyright {1999-2000 Marshall T. Rose}]
[moddesc   {Mime}]
[titledesc {Manipulation of MIME body parts}]
[category  {Text processing}]
[require Tcl 8.5]
[require mime [opt [vset VERSION]]]
[description]
[para]

The [package mime] library package provides the commands to create and
manipulate MIME body parts.

[list_begin definitions]
397
398
399
400
401
402
403
404
405
[para]

See [uri {/tktview?name=447037} {Ticket 447037}] for additional information.

[list_end]

[vset CATEGORY mime]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

398
399
400
401
402
403
404
405
406
[para]

See [uri {/tktview?name=447037} {Ticket 447037}] for additional information.

[list_end]

[vset CATEGORY mime]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/mime/mime.tcl.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Influenced by Borenstein's/Rose's safe-tcl (circa 1993) and Darren New's
# unpublished package of 1999.
#

# new string features and inline scan are used, requiring 8.3.
package require Tcl 8.5

package provide mime 1.6

if {[catch {package require Trf 2.0}]} {

    # Fall-back to tcl-based procedures of base64 and quoted-printable encoders
    # Warning!
    # These are a fragile emulations of the more general calling sequence
    # that appears to work with this code here.







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Influenced by Borenstein's/Rose's safe-tcl (circa 1993) and Darren New's
# unpublished package of 1999.
#

# new string features and inline scan are used, requiring 8.3.
package require Tcl 8.5

package provide mime 1.6.2

if {[catch {package require Trf 2.0}]} {

    # Fall-back to tcl-based procedures of base64 and quoted-printable encoders
    # Warning!
    # These are a fragile emulations of the more general calling sequence
    # that appears to work with this code here.
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
        shiftjis MS_Kanji
        utf-8 UTF8
    }

    namespace export initialize finalize getproperty \
                     getheader setheader \
                     getbody \
                     copymessage \
                     mapencoding \
                     reversemapencoding \
                     parseaddress \
                     parsedatetime \
                     uniqueID
}








|







326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
        shiftjis MS_Kanji
        utf-8 UTF8
    }

    namespace export initialize finalize getproperty \
                     getheader setheader \
                     getbody \
                     buildmessage copymessage \
                     mapencoding \
                     reversemapencoding \
                     parseaddress \
                     parsedatetime \
                     uniqueID
}

375
376
377
378
379
380
381

382

383
384
385
386
387
388
389
    variable mime

    set token [namespace current]::[incr mime(uid)]
    # FRINK: nocheck
    variable $token
    upvar 0 $token state


    if {[catch {{*}[list mime::initializeaux $token {*}$args]} result eopts]} {

        catch {mime::finalize $token -subordinates dynamic}
        return -options $eopts $result
    }
    return $token
}

# ::mime::initializeaux --







>
|
>







375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
    variable mime

    set token [namespace current]::[incr mime(uid)]
    # FRINK: nocheck
    variable $token
    upvar 0 $token state

    if {[catch {
	mime::initializeaux $token {*}$args
    } result eopts]} {
        catch {mime::finalize $token -subordinates dynamic}
        return -options $eopts $result
    }
    return $token
}

# ::mime::initializeaux --
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
        if {$fileP} {
            if {($pos > $last) || ([set x [gets $state(fd) line]] <= 0)} {
                set blankP 1
            } else {
                incr pos [expr {$x + 1}]
            }
        } else {

        if {$state(lines.current) >= $state(lines.count)} {
            set blankP 1
            set line {}
        } else {
            set line [lindex $state(lines) $state(lines.current)]
            incr state(lines.current)
            set x [string length $line]
            if {$x == 0} {set blankP 1}
        }

        }

         if {(!$blankP) && ([string last \r $line] == {$x - 1})} {
             set line [string range $line 0 [expr {$x - 2}]]
             if {$x == 1} {
                 set blankP 1
             }
         }

        if {(!$blankP) && (([
            string first { } $line] == 0) || ([
            string first \t $line] == 0))} {
            append vline \n $line
            continue
        }







<
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|







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
        if {$fileP} {
            if {($pos > $last) || ([set x [gets $state(fd) line]] <= 0)} {
                set blankP 1
            } else {
                incr pos [expr {$x + 1}]
            }
        } else {

	    if {$state(lines.current) >= $state(lines.count)} {
		set blankP 1
		set line {}
	    } else {
		set line [lindex $state(lines) $state(lines.current)]
		incr state(lines.current)
		set x [string length $line]
		if {$x == 0} {set blankP 1}
	    }
        }


	if {(!$blankP) && ([string last \r $line] == ($x - 1))} {
	    set line [string range $line 0 [expr {$x - 2}]]
	    if {$x == 1} {
		set blankP 1
	    }
	}

        if {(!$blankP) && (([
            string first { } $line] == 0) || ([
            string first \t $line] == 0))} {
            append vline \n $line
            continue
        }
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
                    # the boundary delimiter line rather than part of
                    # the preceding part.
                    #
                    # - The above means that the CRLF before $boundary
                    #   is needed per the RFC, and the parts must not
                    #   have a closing CRLF of their own. See Tcllib bug
                    #   1213527, and patch 1254934 for the problems when
                    #   both file/string brnaches added CRLF after the
                    #   body parts.

                    foreach part $state(parts) {
                        append result "\r\n--$boundary\r\n"
                        append result [buildmessage $part]
                    }
                    append result "\r\n--$boundary--\r\n"







|







2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
                    # the boundary delimiter line rather than part of
                    # the preceding part.
                    #
                    # - The above means that the CRLF before $boundary
                    #   is needed per the RFC, and the parts must not
                    #   have a closing CRLF of their own. See Tcllib bug
                    #   1213527, and patch 1254934 for the problems when
                    #   both file/string branches added CRLF after the
                    #   body parts.

                    foreach part $state(parts) {
                        append result "\r\n--$boundary\r\n"
                        append result [buildmessage $part]
                    }
                    append result "\r\n--$boundary--\r\n"
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
}

# ::mime::qp_decode --
#
#    Tcl version of quote-printable decode
#
# Arguments:
#    string        The quoted-prinatble string to decode.
#       encoded_word  Boolean value to determine whether or not encoded words
#                     (RFC 2047) should be handled or not. (optional)
#
# Results:
#    The decoded string is returned.

proc ::mime::qp_decode {string {encoded_word 0}} {







|







2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
}

# ::mime::qp_decode --
#
#    Tcl version of quote-printable decode
#
# Arguments:
#    string        The quoted-printable string to decode.
#       encoded_word  Boolean value to determine whether or not encoded words
#                     (RFC 2047) should be handled or not. (optional)
#
# Results:
#    The decoded string is returned.

proc ::mime::qp_decode {string {encoded_word 0}} {

Changes to modules/mime/mime.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# mime.test - Test suite for TclMIME                     -*- tcl -*-
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2000 by Ajuba Solutions
# All rights reserved.
#
# RCS: @(#) $Id: mime.test,v 1.31 2012/02/23 17:35:17 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]









<
<







1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
# mime.test - Test suite for TclMIME                     -*- tcl -*-
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2000 by Ajuba Solutions
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

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
    list $err3 $err3a
} "foo {MIME-Version: 1.0\r
Content-Type: text/plain\r
\r
foo}"

test mime-3.7 {Test mime with a bad email [SF Bug 631314 ]} {
    set tok [mime::initialize -file \
		 [file join $tcltest::testsDirectory badmail1.txt]]

    set res {}
    set ctok [lindex [mime::getproperty $tok parts] 0]
    lappend res [dictsort [mime::getproperty $tok]]
    lappend res [dictsort [mime::getproperty $ctok]]
    mime::finalize $tok
    string map [list $ctok CHILD] $res
} {{content multipart/mixed encoding {} params {boundary ----------CSFNU9QKPGZL79} parts CHILD size 0} {content application/octet-stream encoding {} params {charset us-ascii} size 0}}

test mime-3.8 {Test mime with another bad email [SF Bug 631314 ]} {
    set tok [mime::initialize -file \
		 [file join $tcltest::testsDirectory badmail2.txt]]
    set res {}
    set ctok [lindex [mime::getproperty $tok parts] 0]
    lappend res [dictsort [mime::getproperty $tok]]
    lappend res [dictsort [mime::getproperty $ctok]]
    mime::finalize $tok
    string map [list $ctok CHILD] $res
} {{content multipart/related encoding {} params {boundary ----=_NextPart_000_0000_2CBA2CBA.150C56D2} parts CHILD size 659} {content application/octet-stream encoding base64 params {} size 659}}







|
<
<









|
<







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
    list $err3 $err3a
} "foo {MIME-Version: 1.0\r
Content-Type: text/plain\r
\r
foo}"

test mime-3.7 {Test mime with a bad email [SF Bug 631314 ]} {
    set tok [mime::initialize -file [asset badmail1.txt]]


    set res {}
    set ctok [lindex [mime::getproperty $tok parts] 0]
    lappend res [dictsort [mime::getproperty $tok]]
    lappend res [dictsort [mime::getproperty $ctok]]
    mime::finalize $tok
    string map [list $ctok CHILD] $res
} {{content multipart/mixed encoding {} params {boundary ----------CSFNU9QKPGZL79} parts CHILD size 0} {content application/octet-stream encoding {} params {charset us-ascii} size 0}}

test mime-3.8 {Test mime with another bad email [SF Bug 631314 ]} {
    set tok [mime::initialize -file [asset badmail2.txt]]

    set res {}
    set ctok [lindex [mime::getproperty $tok parts] 0]
    lappend res [dictsort [mime::getproperty $tok]]
    lappend res [dictsort [mime::getproperty $ctok]]
    mime::finalize $tok
    string map [list $ctok CHILD] $res
} {{content multipart/related encoding {} params {boundary ----=_NextPart_000_0000_2CBA2CBA.150C56D2} parts CHILD size 659} {content application/octet-stream encoding base64 params {} size 659}}
598
599
600
601
602
603
604









605
606
607
608
609
T3JpZ2luYWwtUmVjaXBpZW50OiA8L2ZheD1ibHViYkBndW1taS5ib290PgpBY3Rpb246IGZhaWxl
ZApEaWFnbm9zdGljLUNvZGU6IHNtdHA7IDU1MCAjNS4xLjAgQWRkcmVzcyByZWplY3RlZC4KUmVt
b3RlLU1UQTogNTMuMjQuMjgyLjE1MA==
}]
    set parts [mime::getproperty $token parts]
    mime::getheader [lindex $parts end] Remote-MTA
} 53.24.282.150










# -------------------------------------------------------------------------

testsuiteCleanup
return







>
>
>
>
>
>
>
>
>





593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
T3JpZ2luYWwtUmVjaXBpZW50OiA8L2ZheD1ibHViYkBndW1taS5ib290PgpBY3Rpb246IGZhaWxl
ZApEaWFnbm9zdGljLUNvZGU6IHNtdHA7IDU1MCAjNS4xLjAgQWRkcmVzcyByZWplY3RlZC4KUmVt
b3RlLU1UQTogNTMuMjQuMjgyLjE1MA==
}]
    set parts [mime::getproperty $token parts]
    mime::getheader [lindex $parts end] Remote-MTA
} 53.24.282.150

# -------------------------------------------------------------------------

test mime-12.1 {Fossil ticket 57909d2e1c} -cleanup {
    mime::finalize $token
    unset -nocomplain token
} -body {
    set token [::mime::initialize -file [asset mail-57909d2e1c.txt]]
} -result {::mime::*} -match glob

# -------------------------------------------------------------------------

testsuiteCleanup
return

Changes to modules/mime/pkgIndex.tcl.

1
2
3
4
if {![package vsatisfies [package provide Tcl] 8.3]} {return}
package ifneeded smtp 1.5 [list source [file join $dir smtp.tcl]]
if {![package vsatisfies [package provide Tcl] 8.5]} {return}
package ifneeded mime 1.6 [list source [file join $dir mime.tcl]]



|
1
2
3
4
if {![package vsatisfies [package provide Tcl] 8.3]} {return}
package ifneeded smtp 1.5 [list source [file join $dir smtp.tcl]]
if {![package vsatisfies [package provide Tcl] 8.5]} {return}
package ifneeded mime 1.6.2 [list source [file join $dir mime.tcl]]

Changes to modules/mime/smtp.man.

199
200
201
202
203
204
205
206
207
208
209
210
    J. Myers, "SMTP Service Extension for Authentication",
    RFC 2554, March 1999.
    ([uri http://www.rfc-editor.org/rfc/rfc2554.txt])

[list_end]

[vset CATEGORY smtp]
[include ../doctools2base/include/feedback.inc]

[keywords mail mail email smtp mime tls \
     {rfc 821} {rfc 822} {rfc 2821} {rfc 3207} {rfc 2554} internet net]
[manpage_end]







|




199
200
201
202
203
204
205
206
207
208
209
210
    J. Myers, "SMTP Service Extension for Authentication",
    RFC 2554, March 1999.
    ([uri http://www.rfc-editor.org/rfc/rfc2554.txt])

[list_end]

[vset CATEGORY smtp]
[include ../common-text/feedback.inc]

[keywords mail mail email smtp mime tls \
     {rfc 821} {rfc 822} {rfc 2821} {rfc 3207} {rfc 2554} internet net]
[manpage_end]

Added modules/mime/test-assets/badmail1.txt.





















>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
Date: Tue, 10 Jun 2003 10:32:05 +0200
Message-Id: <[email protected]>
From: Magnus Fisch <[email protected]>
Subject:  Meeting tomorrow
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="----------CSFNU9QKPGZL79"
Bcc:

------------CSFNU9QKPGZL79--

Added modules/mime/test-assets/badmail2.txt.































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
From: "Kelsey " <[email protected]>
To: "gdylgzCsurvd1lw" <[email protected]>
Date: Fri, 28 Feb 2003 03:12:35 -0500
Subject: no subject   gdylgzCsurvd1lw
MIME-Version: 1.0
Content-Type: multipart/related;
  boundary="----=_NextPart_000_0000_2CBA2CBA.150C56D2"
X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N
X-Spam-Rating: icarus.apache.org 1.6.2 0/1000/N
Lines: 19
Xref: localhost private-mail:14167

------=_NextPart_000_0000_2CBA2CBA.150C56D2
Content-Type: text/html;
Content-Transfer-Encoding: base64

PCEtLTE1MTQ3LS0+PGJvZHk+DQpJdCdzIG1lIEplPCEtLTI5MDY0LS0+bm5pZmVyLDxicj4g
SSBqdXN0IHdhbjwhLS0xOTE0OS0tPnRlZCB0byBzZW5kIHlvdSB0aGF0IHBpYyB5b3UgYXNr
ZTwhLS0xNTAxMC0tPmQgZm9yIHRoZSBvdDwhLS0yNjUxMi0tPmhlcg0KZGF5LiA8YnI+IDxh
IGhyZWY9Imh0dHA6Ly93d3cuaG90aG9zdC5iei9hYmMvamVubmlmZXIvP1JJRD1jaW5nd2Yi
PkNsaTwhLS0yNzE1My0tPmNrDQpIPCEtLTI2NjcwLS0+ZXJlIHRvIGNhdDwhLS03NDg5LS0+
Y2ggbWUgb24gbXkgd2ViPCEtLTI0ODExLS0+Y2FtICYgc2VlIG1vcmUgcGljcyBvZiBtZS48
L2E+IDxicj48YnI+DQo8YSBocmVmPSJodHRwOi8vd3d3LmhvdGhvc3QuYnovYWJjL2plbm5p
ZmVyLz9SSUQ9Y2luZ3dmIj48aW1nIHNyYz0iaHR0cDovLzIwNy40NC4xODMuMjU0L2FiYy9q
ZW5uaWZlci93b29ob28uanBnIiBib3JkZXI9IjAiPjwvYT4NCjxicj48YnI+PGk+LSB4bzwh
LS0yMzQwMi0tPnhvIEplbm5pZmVyPC9pPjwvcD48YnI+PGJyPjxicj48YnI+PGJyPjxicj48
YnI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+PGJy
Pjxicj48YnI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+DQo8L2JvZHk+



Added modules/mime/test-assets/mail-57909d2e1c.txt.











































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
MIME-Version: 1.0
Content-ID: <[email protected]>
Content-Type: multipart/mixed;
              boundary="----- =_U9Pw/kikzJT5t8pT5pl5Pw=="

------- =_U9Pw/kikzJT5t8pT5pl5Pw==
MIME-Version: 1.0
Content-ID: <[email protected]>
Content-Disposition: inline; filename="/model.pl"
Content-Description: Simile model
Date-Modified: 2019-04-11 11:01:36 GMT
Authentication-Code: c0c651af192d709b2757cb9ef0d8c19d
Content-Type: application/x-simile
Content-Transfer-Encoding: base64

c291cmNlKHByb2dyYW09J0FNRScsdmVyc2lvbj0gMTAuOSxlZGl0aW9uPWVudGVycHJpc2UsZGF0
KG5vbmUsaW5faGllcmFyY2h5LGRlc3QsMSldXSxbY3VydmU9Wy05LDFdXSkuCg==

------- =_U9Pw/kikzJT5t8pT5pl5Pw==
MIME-Version: 1.0
Content-ID: <[email protected]>
Content-Disposition: attachment; filename="/model.cnv"
Content-Description: Simile canvas description
Date-Modified: 2019-04-11 11:01:36 GMT
Content-Type: application/x-simile
Content-Transfer-Encoding: base64

IyB3cml0dGVuIG9uIFRodSBBcHIgMTEgMTE6MDE6MzYgR01UIDIwMTkKTG9hZE1vZGVsTG9va3Mg
bl90aGlzIHJlYWx3aWR0aCgxMDguMCkgY3VycmVudGx5X2VkaXRhYmxlfSAtdGV4dCBmbG93MwoK


------- =_U9Pw/kikzJT5t8pT5pl5Pw==
MIME-Version: 1.0
Content-ID: <[email protected]>
Content-Disposition: attachment; filename="/model.spj"
Content-Description: Simile package description
Date-Modified: 2019-04-11 11:01:53 GMT
Content-Type: application/x-simile
Content-Transfer-Encoding: base64

Cg==

------- =_U9Pw/kikzJT5t8pT5pl5Pw==
MIME-Version: 1.0
Content-Description: Run Status
Content-ID: <[email protected]>
Content-Type: application/x-simile
Content-Transfer-Encoding: base64

ZXhlY1RpbWUgMTAwLjAgdGltZVVuaXQgdW5pdCBkaXNwbGF5SW50IDEgaW50TWV0aG9kIEV1bGVy
IHBoYXNlTGlzdCAwLjE=

------- =_U9Pw/kikzJT5t8pT5pl5Pw==--

Changes to modules/multiplexer/multiplexer.man.

122
123
124
125
126
127
128
129
130
EOF: The channel connecting us to the client, its ip-address, and its
ip-port.

[list_end]
[list_end]

[vset CATEGORY multiplexer]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

122
123
124
125
126
127
128
129
130
EOF: The channel connecting us to the client, its ip-address, and its
ip-port.

[list_end]
[list_end]

[vset CATEGORY multiplexer]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/namespacex/namespacex.man.

166
167
168
169
170
171
172
173
174
a child namespace of namespace [arg prefix].

Returns the corresponding list of relative names of child namespaces.

[list_end]

[vset CATEGORY namespacex]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

166
167
168
169
170
171
172
173
174
a child namespace of namespace [arg prefix].

Returns the corresponding list of relative names of child namespaces.

[list_end]

[vset CATEGORY namespacex]
[include ../common-text/feedback.inc]
[manpage_end]

Deleted modules/ncgi/formdata.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Content-Type: multipart/form-data; boundary="---------------------------17661509020136"

-----------------------------17661509020136
Content-Disposition: form-data; name="field1"

value
-----------------------------17661509020136
Content-Disposition: form-data; name="field2"

another value
-----------------------------17661509020136
Content-Disposition: form-data; name="the_file_name"; filename="C:\Program Files\Netscape\Communicator\Program\nareadme.htm"
Content-Type: text/html


<center><h1>
                  Netscape Address Book Sync for Palm Pilot
                                         User Guide
</h1></center>



-----------------------------17661509020136--

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















































Changes to modules/ncgi/ncgi.man.

1
2
3
4
5
6
7
8
[vset VERSION 1.4.3]
[manpage_begin ncgi n [vset VERSION]]
[see_also html]
[keywords CGI]
[keywords cookie]
[keywords form]
[keywords html]
[comment {-*- tcl -*- doctools manpage}]
|







1
2
3
4
5
6
7
8
[vset VERSION 1.4.4]
[manpage_begin ncgi n [vset VERSION]]
[see_also html]
[keywords CGI]
[keywords cookie]
[keywords form]
[keywords html]
[comment {-*- tcl -*- doctools manpage}]
305
306
307
308
309
310
311
312
313
puts -nonewline $fh $filedata
close $fh
}]

[para]

[vset CATEGORY ncgi]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

305
306
307
308
309
310
311
312
313
puts -nonewline $fh $filedata
close $fh
}]

[para]

[vset CATEGORY ncgi]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/ncgi/ncgi.tcl.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# of decoding them.

# We use newer string routines
package require Tcl 8.4
package require fileutil ; # Required by importFile.
package require uri

package provide ncgi 1.4.3

namespace eval ::ncgi {

    # "query" holds the raw query (i.e., form) data
    # This is treated as a cache, too, so you can call ncgi::query more than
    # once








|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# of decoding them.

# We use newer string routines
package require Tcl 8.4
package require fileutil ; # Required by importFile.
package require uri

package provide ncgi 1.4.4

namespace eval ::ncgi {

    # "query" holds the raw query (i.e., form) data
    # This is treated as a cache, too, so you can call ncgi::query more than
    # once

267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285

proc ::ncgi::decode {str} {
    # rewrite "+" back to space
    # protect \ from quoting another '\'
    set str [string map [list + { } "\\" "\\\\" \[ \\\[ \] \\\]] $str]

    # prepare to process all %-escapes
    regsub -all -- {%([Ee][A-Fa-f0-9])%([89ABab][A-Fa-f0-9])%([89ABab][A-Fa-f0-9])} \
	$str {[encoding convertfrom utf-8 [DecodeHex \1\2\3]]} str
    regsub -all -- {%([CDcd][A-Fa-f0-9])%([89ABab][A-Fa-f0-9])}                     \
	$str {[encoding convertfrom utf-8 [DecodeHex \1\2]]} str
    regsub -all -- {%([0-7][A-Fa-f0-9])} $str {\\u00\1} str

    # process \u unicode mapped chars
    return [subst -novar $str]
}

# ::ncgi::encode
#







|

|

|







267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285

proc ::ncgi::decode {str} {
    # rewrite "+" back to space
    # protect \ from quoting another '\'
    set str [string map [list + { } "\\" "\\\\" \[ \\\[ \] \\\]] $str]

    # prepare to process all %-escapes
    regsub -all -nocase -- {%([E][A-F0-9])%([89AB][A-F0-9])%([89AB][A-F0-9])} \
	$str {[encoding convertfrom utf-8 [DecodeHex \1\2\3]]} str
    regsub -all -nocase -- {%([CDcd][A-F0-9])%([89AB][A-F0-9])} \
	$str {[encoding convertfrom utf-8 [DecodeHex \1\2]]} str
    regsub -all -nocase -- {%([A-F0-9][A-F0-9])} $str {\\u00\1} str

    # process \u unicode mapped chars
    return [subst -novar $str]
}

# ::ncgi::encode
#

Changes to modules/ncgi/ncgi.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# -*- tcl -*-
# Tests for the cgi module.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1998-2000 by Ajuba Solutions
#
# RCS: @(#) $Id: ncgi.test,v 1.28 2012/05/03 17:56:07 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]









<
<







1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
# -*- tcl -*-
# Tests for the cgi module.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1998-2000 by Ajuba Solutions



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
    ncgi::decode {%E2%80%A0}
} "\u2020" ; # dagger

test ncgi-3.9 {ncgi::decode, bug 3601995} {
    ncgi::decode {%E2%A0%90}
} "\u2810" ; # a braille pattern

test ncgi-3.10 {ncgi::decode, bug 3601995} {
    ncgi::decode {%E2%B1}
} "%E2%B1" ; # missing byte trailing %A0, do not accept/decode, pass through.

test ncgi-4.1 {ncgi::encode} {
    ncgi::encode abcdef0123
} abcdef0123

test ncgi-4.2 {ncgi::encode} {
    ncgi::encode "\[abc\]def\$0123\\x"







|

|







134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
    ncgi::decode {%E2%80%A0}
} "\u2020" ; # dagger

test ncgi-3.9 {ncgi::decode, bug 3601995} {
    ncgi::decode {%E2%A0%90}
} "\u2810" ; # a braille pattern

test ncgi-3.10 {ncgi::decode, bug 3601995, tkt [1f900bdf6b]} {
    ncgi::decode {%E2%B1}
} "\u00e2\u00b1" ;# Changed with branch `ncgi-1f900bdf6b`, tkt [1f900bdf6b]

test ncgi-4.1 {ncgi::encode} {
    ncgi::encode abcdef0123
} abcdef0123

test ncgi-4.2 {ncgi::encode} {
    ncgi::encode "\[abc\]def\$0123\\x"
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600

test ncgi-14.2 {ncgi::multipart} {
    catch {ncgi::multipart "multipart/form-data" {}} err
    set err
} {No boundary given for multipart document}

test ncgi-14.3 {ncgi::multipart} {
    set in [open [file join [file dirname [info script]] formdata.txt]]
    set X [read $in]
    close $in

    foreach line [split $X \n] {
	if {[string length $line] == 0} {
	    break
	}







|







584
585
586
587
588
589
590
591
592
593
594
595
596
597
598

test ncgi-14.2 {ncgi::multipart} {
    catch {ncgi::multipart "multipart/form-data" {}} err
    set err
} {No boundary given for multipart document}

test ncgi-14.3 {ncgi::multipart} {
    set in [open [asset formdata.txt]]
    set X [read $in]
    close $in

    foreach line [split $X \n] {
	if {[string length $line] == 0} {
	    break
	}
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
                                         User Guide
</h1></center>


}}}

test ncgi-14.4 {ncgi::multipart} {
    set in [open [file join [file dirname [info script]] formdata.txt]]
    set X [read $in]
    close $in

    foreach line [split $X \n] {
	if {[string length $line] == 0} {
	    break
	}







|







610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
                                         User Guide
</h1></center>


}}}

test ncgi-14.4 {ncgi::multipart} {
    set in [open [asset formdata.txt]]
    set X [read $in]
    close $in

    foreach line [split $X \n] {
	if {[string length $line] == 0} {
	    break
	}
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
</h1></center>


}}


test ncgi-14.6 {ncgi::multipart setValue} {
    set in [open [file join [file dirname [info script]] formdata.txt]]
    set X [read $in]
    close $in

    foreach line [split $X \n] {
	if {[string length $line] == 0} {
	    break
	}







|







638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
</h1></center>


}}


test ncgi-14.6 {ncgi::multipart setValue} {
    set in [open [asset formdata.txt]]
    set X [read $in]
    close $in

    foreach line [split $X \n] {
	if {[string length $line] == 0} {
	    break
	}

Changes to modules/ncgi/pkgIndex.tcl.

1
2
if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded ncgi 1.4.3 [list source [file join $dir ncgi.tcl]]

|
1
2
if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded ncgi 1.4.4 [list source [file join $dir ncgi.tcl]]

Added modules/ncgi/test-assets/formdata.txt.

















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Content-Type: multipart/form-data; boundary="---------------------------17661509020136"

-----------------------------17661509020136
Content-Disposition: form-data; name="field1"

value
-----------------------------17661509020136
Content-Disposition: form-data; name="field2"

another value
-----------------------------17661509020136
Content-Disposition: form-data; name="the_file_name"; filename="C:\Program Files\Netscape\Communicator\Program\nareadme.htm"
Content-Type: text/html


<center><h1>
                  Netscape Address Book Sync for Palm Pilot
                                         User Guide
</h1></center>



-----------------------------17661509020136--

Changes to modules/nettool/build/build.tcl.

1
2
3
4
5
6












7
8
9
10
11
12
13
set srcdir [file dirname [file normalize [file join [pwd] [info script]]]]
set moddir [file dirname $srcdir]

set version 0.5.2
set tclversion 8.5
set module [file tail $moddir]













dict set map %module% $module
dict set map %version% $version
dict set map %tclversion% $tclversion
dict set map {    } {}
dict set map "\t" {    }







>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
set srcdir [file dirname [file normalize [file join [pwd] [info script]]]]
set moddir [file dirname $srcdir]

set version 0.5.2
set tclversion 8.5
set module [file tail $moddir]

proc ::ladd {varname args} {
  upvar 1 $varname var
  if ![info exists var] {
      set var {}
  }
  foreach item $args {
    if {$item in $var} continue
    lappend var $item
  }
  return $var
}

dict set map %module% $module
dict set map %version% $version
dict set map %tclversion% $tclversion
dict set map {    } {}
dict set map "\t" {    }

Changes to modules/nettool/nettool.man.

135
136
137
138
139
140
141
142
143

Return a fully qualified path to a folder where [arg appname] should store it's data.
The path is not created, only computed, by this command.

[list_end]
[para]
[vset CATEGORY odie]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

135
136
137
138
139
140
141
142
143

Return a fully qualified path to a folder where [arg appname] should store it's data.
The path is not created, only computed, by this command.

[list_end]
[para]
[vset CATEGORY odie]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/nmea/nmea.man.

94
95
96
97
98
99
100
101
102
    puts "unknown data type $name"
}
}]

[list_end]

[vset CATEGORY nmea]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

94
95
96
97
98
99
100
101
102
    puts "unknown data type $name"
}
}]

[list_end]

[vset CATEGORY nmea]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/nns/nns_auto.man.

111
112
113
114
115
116
117
118
119
[para]

Another loss of the connection, be it during or after re-entering the
remembered information simply restarts the timer and subsequent
reconnection attempts.

[vset CATEGORY nameserv]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

111
112
113
114
115
116
117
118
119
[para]

Another loss of the connection, be it during or after re-entering the
remembered information simply restarts the timer and subsequent
reconnection attempts.

[vset CATEGORY nameserv]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/nns/nns_client.man.

330
331
332
333
334
335
336
337
338
its connection to the name service. Based on package [package uevent].

[def 0.1]
Initial implementation of the client.
[list_end]

[vset CATEGORY nameserv]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

330
331
332
333
334
335
336
337
338
its connection to the name service. Based on package [package uevent].

[def 0.1]
Initial implementation of the client.
[list_end]

[vset CATEGORY nameserv]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/nns/nns_common.man.

39
40
41
42
43
44
45
46
47
The result returned by the command is the id of the default TCP/IP
port a nameservice server will listen on, and a name service client
will try to connect to.

[list_end]

[vset CATEGORY nameserv]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

39
40
41
42
43
44
45
46
47
The result returned by the command is the id of the default TCP/IP
port a nameservice server will listen on, and a name service client
will try to connect to.

[list_end]

[vset CATEGORY nameserv]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/nns/nns_intro.man.

120
121
122
123
124
125
126
127
128
[para]

Developers wishing to modify and/or extend or to just understand the
internals of the nameservice facility however are strongly advised to
read it.

[vset CATEGORY nameserv]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

120
121
122
123
124
125
126
127
128
[para]

Developers wishing to modify and/or extend or to just understand the
internals of the nameservice facility however are strongly advised to
read it.

[vset CATEGORY nameserv]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/nns/nns_protocol.man.

174
175
176
177
178
179
180
181
182

The argument coming before the response tells the client whether the
names in the response were added or removed from the service.

[list_end]

[vset CATEGORY nameserv]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

174
175
176
177
178
179
180
181
182

The argument coming before the response tells the client whether the
names in the response were added or removed from the service.

[list_end]

[vset CATEGORY nameserv]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/nns/nns_server.man.

137
138
139
140
141
142
143
144
145
Changed name of -local switch to -localonly.

[def 0.1]
Initial implementation of the server.
[list_end]

[vset CATEGORY nameserv]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

137
138
139
140
141
142
143
144
145
Changed name of -local switch to -localonly.

[def 0.1]
Initial implementation of the server.
[list_end]

[vset CATEGORY nameserv]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/nntp/nntp.man.

330
331
332
333
334
335
336
337
338
    Date: [clock format [clock seconds] -format "%a, %d %
    b %y %H:%M:%S GMT" -gmt true]

    Test message body"
}]

[vset CATEGORY nntp]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

330
331
332
333
334
335
336
337
338
    Date: [clock format [clock seconds] -format "%a, %d %
    b %y %H:%M:%S GMT" -gmt true]

    Test message body"
}]

[vset CATEGORY nntp]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/ntp/ntp_time.man.

123
124
125
126
127
128
129
130
131
time::getsntp -command on_time pool.ntp.org
}]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY ntp]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

123
124
125
126
127
128
129
130
131
time::getsntp -command on_time pool.ntp.org
}]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY ntp]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/oauth/oauth.man.

1
2
3
4
5
6
7
8
9
[comment {-*- tcl -*- doctools manpage}]
[vset PACKAGE_VERSION 1.0.2]
[manpage_begin oauth n [vset PACKAGE_VERSION]]
[keywords {oauth}]
[keywords {RFC 5849}]
[keywords {RFC 2718}]
[keywords twitter]
[copyright {2014 Javi P. <[email protected]>}]
[moddesc   {oauth}]

|







1
2
3
4
5
6
7
8
9
[comment {-*- tcl -*- doctools manpage}]
[vset PACKAGE_VERSION 1.0.3]
[manpage_begin oauth n [vset PACKAGE_VERSION]]
[keywords {oauth}]
[keywords {RFC 5849}]
[keywords {RFC 2718}]
[keywords twitter]
[copyright {2014 Javi P. <[email protected]>}]
[moddesc   {oauth}]
183
184
185
186
187
188
189
190
191
follow_request_sent => false
notifications => false}]

[list_end]
[para]

[vset CATEGORY oauth]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

183
184
185
186
187
188
189
190
191
follow_request_sent => false
notifications => false}]

[list_end]
[para]

[vset CATEGORY oauth]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/oauth/oauth.tcl.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#       1.5 Timestamp (oauth_timestamp) time in unix format of the request
#       1.6 Token (oauth_token) a parameter you can obtain in your account settings
#       1.7 Version (oauth_version) the OAuth version, actually 1.0

#  TODO: create online documentation

package require Tcl 8.5
package provide oauth 1.0.2

package require http
package require tls
package require base64
package require sha1

http::register https 443 ::tls::socket







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#       1.5 Timestamp (oauth_timestamp) time in unix format of the request
#       1.6 Token (oauth_token) a parameter you can obtain in your account settings
#       1.7 Version (oauth_version) the OAuth version, actually 1.0

#  TODO: create online documentation

package require Tcl 8.5
package provide oauth 1.0.3

package require http
package require tls
package require base64
package require sha1

http::register https 443 ::tls::socket
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
    return $tmp
}

# Split -
#	Split the string on the first separator
#       and return both parts as a list.
proc ::oauth::Split {string sep} {
    regexp "\{^(\[^${sep}\]+)${sep}(.*)\$" $string -> key value
    list $key $value
}

# PercentEncode --
#       Encoding process in http://tools.ietf.org/html/rfc3986#section-2.1
#       for Twitter authentication. (http::formatQuery is lowcase)
proc ::oauth::PercentEncode {string} {







|







279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
    return $tmp
}

# Split -
#	Split the string on the first separator
#       and return both parts as a list.
proc ::oauth::Split {string sep} {
    regexp "^(\[^${sep}\]+)${sep}(.*)\$" $string -> key value
    list $key $value
}

# PercentEncode --
#       Encoding process in http://tools.ietf.org/html/rfc3986#section-2.1
#       for Twitter authentication. (http::formatQuery is lowcase)
proc ::oauth::PercentEncode {string} {

Changes to modules/oauth/pkgIndex.tcl.

1
2
if {![package vsatisfies [package provide Tcl] 8.5]} {return}
package ifneeded oauth 1.0.2 [list source [file join $dir oauth.tcl]]

|
1
2
if {![package vsatisfies [package provide Tcl] 8.5]} {return}
package ifneeded oauth 1.0.3 [list source [file join $dir oauth.tcl]]

Changes to modules/oometa/oometa.man.

143
144
145
146
147
148
149
150
151
152
is faster than [cmd {my meta getnull}] [opt [arg field]] [opt [arg ...]] [arg field]], because
it performs a search instead directly instead of producing the recursive merge product
between the class metadata, the local [emph meta] variable, and THEN performing the search.

[list_end]

[vset CATEGORY tcloo]
[include ../doctools2base/include/feedback.inc]
[manpage_end]








|


143
144
145
146
147
148
149
150
151
152
is faster than [cmd {my meta getnull}] [opt [arg field]] [opt [arg ...]] [arg field]], because
it performs a search instead directly instead of producing the recursive merge product
between the class metadata, the local [emph meta] variable, and THEN performing the search.

[list_end]

[vset CATEGORY tcloo]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/ooutil/ooutil.man.

157
158
159
160
161
162
163
164
165

[list_end]

[section AUTHORS]
Donal Fellows, Andreas Kupries

[vset CATEGORY oo::util]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

157
158
159
160
161
162
163
164
165

[list_end]

[section AUTHORS]
Donal Fellows, Andreas Kupries

[vset CATEGORY oo::util]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/otp/otp.man.

87
88
89
90
91
92
93
94
95
        "Secure Hash Standard", National Institute of Standards
        and Technology, U.S. Department Of Commerce, April 1995.
	([uri http://www.itl.nist.gov/fipspubs/fip180-1.htm])

[list_end]

[vset CATEGORY otp]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

87
88
89
90
91
92
93
94
95
        "Secure Hash Standard", National Institute of Standards
        and Technology, U.S. Department Of Commerce, April 1995.
	([uri http://www.itl.nist.gov/fipspubs/fip180-1.htm])

[list_end]

[vset CATEGORY otp]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/page/page_intro.man.

27
28
29
30
31
32
33
34
35

The packages implementing the plugins are not documented as regular
packages, as they cannot be loaded into a general interpreter, like
tclsh, without extensive preparation of the interpreter. Preparation
which is done for them by the plugin manager.

[vset CATEGORY page]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

27
28
29
30
31
32
33
34
35

The packages implementing the plugins are not documented as regular
packages, as they cannot be loaded into a general interpreter, like
tclsh, without extensive preparation of the interpreter. Preparation
which is done for them by the plugin manager.

[vset CATEGORY page]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/page/page_pluginmgr.man.

792
793
794
795
796
797
798
799
800
[section FEATURES]

The plugin manager currently checks the plugins for only one feature,
[const timeable]. A plugin supporting this feature is assumed to be
able to collect timing statistics on request.

[vset CATEGORY page]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

792
793
794
795
796
797
798
799
800
[section FEATURES]

The plugin manager currently checks the plugins for only one feature,
[const timeable]. A plugin supporting this feature is assumed to be
able to collect timing statistics on request.

[vset CATEGORY page]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/page/page_util_flow.man.

88
89
90
91
92
93
94
95
96

This is the variadic arguments form of the method [method visitl], see
above.

[list_end]

[vset CATEGORY page]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

88
89
90
91
92
93
94
95
96

This is the variadic arguments form of the method [method visitl], see
above.

[list_end]

[vset CATEGORY page]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/page/page_util_norm_lemon.man.

43
44
45
46
47
48
49
50
51
[para]

The exact operations performed are left undocumented for the moment.

[list_end]

[vset CATEGORY page]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

43
44
45
46
47
48
49
50
51
[para]

The exact operations performed are left undocumented for the moment.

[list_end]

[vset CATEGORY page]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/page/page_util_norm_peg.man.

97
98
99
100
101
102
103
104
105
The order matters, to shed as much nodes as possible early, and
to avoid unnecessary work later.

[list_end]
[list_end]

[vset CATEGORY page]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

97
98
99
100
101
102
103
104
105
The order matters, to shed as much nodes as possible early, and
to avoid unnecessary work later.

[list_end]
[list_end]

[vset CATEGORY page]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/page/page_util_peg.man.

100
101
102
103
104
105
106
107
108

See the package [package grammar::peg] for the exact syntax of
[arg pe].

[list_end]

[vset CATEGORY page]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

100
101
102
103
104
105
106
107
108

See the package [package grammar::peg] for the exact syntax of
[arg pe].

[list_end]

[vset CATEGORY page]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/page/page_util_quote.man.

54
55
56
57
58
59
60
61
62
converts it into a string which is accepted by the Tcl parser when
used within a Tcl comment. The string is returned as the result of
this command.

[list_end]

[vset CATEGORY page]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

54
55
56
57
58
59
60
61
62
converts it into a string which is accepted by the Tcl parser when
used within a Tcl comment. The string is returned as the result of
this command.

[list_end]

[vset CATEGORY page]
[include ../common-text/feedback.inc]
[manpage_end]

Added modules/pipeline/TODO.md.









>
>
>
>
1
2
3
4
- Documentation
- Test suite

<!-- vim: set sts=4 sw=4 tw=80 et ft=markdown: -->

Added modules/pipeline/pipeline.tcl.













































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# pipeline.tcl --
#
# Streaming data pipeline infrastructure
#
# Copyright (C) 2019 Andy Goth <[email protected]>
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
package require Tcl 8.6
package require argparse
package provide pipeline 0.3

# Create a namespace for pipeline commands.
namespace eval ::pipeline {}

# ::pipeline::new --
# Creates a pipeline containing the specified filter command prefixes and
# returns the command name used to execute the pipeline.
#
# The returned command accepts the following method name arguments:
#
# destroy     Destroy the pipeline and cleans up all associated resources
# flow        Feed input data through the pipeline and returns the output data
# get         Get buffered output data accumulated by prior calls to [put]
# peek        Get buffered output data without clearing the output buffer
# put         Feed input data through the pipeline and buffers the output data
# run         Feed raw chunks through the pipeline and returns raw chunk output
#
# The [flow] and [put] methods accept the following additional arguments:
#
# -meta META  Arbitary metadata to associate with the input data
# -flush      Commands pipeline flush
# data        Input data, may be empty string
#
# Each argument to the [run] method is a raw chunk, which is a three-element
# list that will be used as the arguments to the first filter coroutine.
#
# A pipeline is a linear sequence of zero or more filters.  Each filter operates
# on the output of its predecessor, with the first filter operating on the input
# to the pipeline.  The output of the last filter is the output of the pipeline.
#
# Each filter is a command prefix to invoke on each pipeline input chunk.  If a
# filter command name is in the ::pipeline or :: (global) namespace, it need not
# be fully qualified.  The [pipeline::loop] command is useful to define filters.
#
# Pipelines are implemented in terms of coroutines.  The pipeline as a whole is
# a coroutine, and each filter in the pipeline is a coroutine.  Coroutines are
# automatically created by [pipeline::new], and filter commands need not create
# coroutines for themselves.  The first time the filter command is invoked, it
# must yield after completing initialization, and the yielded value is ignored.
# When the filter command returns, its coroutine is automatically destroyed.
#
# Aside from the first time the filter command is invoked (described above),
# filter coroutines are given the following three arguments:
#
# - Current input data chunk
# - Arbitrary metadata associated with the input chunk
# - 1 if the pipeline is being flushed, 0 if not
#
# If a filter command is passed zero arguments, the filter must clean up any
# resources it allocated, then return.
#
# When a filter coroutine is invoked, it must yield a list containing zero or
# more output chunks.  Each output chunk is a list containing the following:
#
# - Current output data chunk
# - Arbitrary metadata associated with the output chunk
# - 1 if flush is being commanded, 0 if not
# - 1 if the chunk is to be fed back as new pipeline input, 0 if not
#
# Output chunks may omit any number of elements.  The omitted elements will be
# replaced with the corresponding elements from the input chunk.  If restart is
# omitted, it defaults to 0.  A filter that passes its input through unmodified
# may simply yield {{}}, i.e. a list containing only an empty list.  If a filter
# yields {}, i.e. empty list, then all pipeline data is discarded and further
# filters are not invoked.
#
# Pipeline execution continues until all filter coroutines have been invoked on
# all input chunks.  If any filter output chunks contain the restart flag, the
# entire pipeline sequence will be executed again, repeating until none of the
# filters output any chunks containing the restart flag.
proc ::pipeline::new {args} {
    # Coroutine creation helper routine.
    set coroNew {apply {{args} {
        set i [llength [info commands ::pipeline::Coro*]]
        while {[info commands [set coro ::pipeline::Coro$i]] ne {}} {
            incr i
        }
        coroutine $coro {*}$args
        return $coro
    } ::pipeline}}

    # Create a coroutine command for each filter in the pipeline, as well as a
    # coroutine for the pipeline as a whole.  Return its command name.
    {*}$coroNew apply {{coros} {
        # Pipeline execution core.
        set run {apply {{coros args} {
            # Loop until the input queue is completely drained.  Filters may
            # append chunks to the the input queue, so this loop may repeat.
            set inChunks $args
            set outChunks {}
            while {$inChunks ne {}} {
                # Transfer the pipeline inputs to the first filter inputs.
                set pipeChunks $inChunks
                set inChunks {}

                # Progress through the pipeline, one filter at a time.
                foreach coro $coros {
                    # Loop through all chunks currently in the pipeline.
                    foreach inChunk $pipeChunks[set pipeChunks {}] {
                        # Invoke the filter, and process its output chunks.
                        foreach outChunk [$coro {*}$inChunk] {
                            # Fill in omitted output elements with defaults.
                            if {[llength $outChunk] < 3} {
                                lappend outChunk {*}[lrange $inChunk\
                                        [llength $outChunk] 2]
                            }

                            # Let the output chunk be the input to the next
                            # filter or to the first filter on the next pass.
                            if {[llength $outChunk] >= 4
                             && [lindex $outChunk 3]} {
                                lappend inChunks $outChunk
                            } else {
                                lappend pipeChunks $outChunk
                            }
                        }

                        # If this input chunk commands flush, ensure the last
                        # output chunk arising from this input chunk also
                        # commands flush, creating an empty chunk if needed.
                        if {[lindex $inChunk 2]} {
                            if {$pipeChunks ne {}} {
                                lset pipeChunks end 2 1
                            } else {
                                set pipeChunks {{{} {} 1}}
                            }
                        }
                    }
                }

                # Collect the outputs of the last filter in the pipeline.
                lappend outChunks {*}$pipeChunks
            }
            return $outChunks
        }}}

        # Loop until the destroy method is invoked.
        set out {}
        set buffer {}
        while {1} {
            # Yield the last result, then get the next method and its arguments.
            set args [lassign [yieldto return -level 0 $out[set out {}]] method]

            # Perform method name resolution.
            set method [tcl::prefix match -message method\
                    {destroy flow get peek put run} $method]

            # Several methods do not allow arguments.
            if {$method in {destroy get peek} && $args ne {}} {
                return -code error "wrong # args: should be\
                        \"[info coroutine] $method\""
            }

            # Invoke the method.
            switch $method {
            destroy {
                foreach coro $coros {
                    $coro
                }
                break
            } flow {
                argparse -boolean {{-meta= -default {}} -flush data}
                foreach chunk [{*}$run $coros [list $data $meta $flush]] {
                    append buffer [lindex $chunk 0]
                }
                set out $buffer
                set buffer {}
            } get {
                set out $buffer
                set buffer {}
            } peek {
                set out $buffer
            } put {
                argparse -boolean {{-meta= -default {}} -flush data}
                foreach chunk [{*}$run $coros [list $data $meta $flush]] {
                    append buffer [lindex $chunk 0]
                }
            } run {
                set out [{*}$run $coros {*}$args]
            }}
        }
    } ::pipeline} [lmap filter $args {{*}$coroNew {*}$filter}]
}

# ::pipeline::procLoop --
# Creates a named pipeline filter using the [pipeline::loop] command.
proc ::pipeline::procLoop {name args} {
    uplevel 1 [list interp alias {} $name {} ::pipeline::loop {*}$args]
}

# ::pipeline::loop --
# Pipeline main loop skeleton, suitable for implementing pipeline filters.  The
# following arguments are accepted:
#
# -params PL  [argparse] parameter definition list
# -init SCR   Initialization script before beginning loop
# -command    Positional arguments form a command prefix rather than a script
# -observe    Do not modify pipeline data, ignoring return value or out variable
# -result     Script result is used directly as the output chunk list
# -buffer     Wait until delimiter is encountered before invoking command
# -raw        Command operates on raw chunks rather than processed data
# -partial    Run script for partial buffers as well as complete buffers
# -separate   Disable buffered output merging
# -delim PAT  Buffer delimiter regular expression, default \n
# -trim       Strip buffer delimiter from the command argument
# SCRIPT      Main loop body script or command prefix (multiple arguments)
# ARGS ...    Arguments to bind to the parameter list, requires -params
#
# As an alternative to writing a full [proc] or [apply] script, the -params and
# -init switches may be used to set up the context in which the loop runs.  If
# -params is used, [pipeline::loop] accepts additional arguments following the
# script argument.  These arguments are parsed according to the [argparse]
# parameter list which is given as the argument to -params.  The -init switch
# supplies a custom initialization script to evaluate after processing -params
# and before beginning the loop.  -params and -init conflict with -command.
#
# The -params and -init switches are processed before all other arguments.  As a
# result, their side effects (e.g. setting variables) will still occur even if
# there is an error in processing the remaining arguments.
#
# If the loopArgs variable is created by -params or -init, it is used as a list
# of additional arguments to pass to [pipeline::loop], which will be processed
# after -params and -init and before all other arguments.  If a variable named
# loopArgs exists at the moment [pipeline:loop] is called, it will be unset
# before processing arguments.  After processing -params and -init, loopArgs
# will be restored to its initial state.
#
# If -buffer is used, the pipeline data is divided into chunks according to the
# delimiter defined by the -delim regular expression.  The data matched by the
# regular expression is included at the end of each chunk, except for the last
# chunk which may be incomplete.  When flush is commanded, the buffer is emptied
# after being passed to the script or command prefix, even if incomplete.
#
# -buffer causes the script or command to only be executed when the buffer is
# complete or flush is commanded, unless -partial is used, in which case the
# script or command is executed for every chunk.  When the script or command is
# not executed, subsequent filters in the pipeline are not executed either.
#
# It is an error for the -delim regular expression to match empty string.
#
# If -command is not used, the script argument is executed for each chunk that
# flows through the pipeline.  If -buffer is used (and -partial is not), the
# script is instead only executed for complete buffers and when flush is
# commanded.  The script may interact with the following variables:
#
# input       Input chunk from the pipeline executive
# out         Output chunk list to yield to the pipeline executive
# data        Current input chunk data
# meta        Arbitrary metadata associated with the input chunk
# flush       1 if pipeline is being flushed, 0 if not
#
# Additional variables are available when -buffer is used:
#
# prior       Buffered data preceding this chunk, or empty for the first
# buffer      All data since the last delimiter, excluding the current delimiter
# complete    Delimiter string if complete, empty string if buffer is incomplete
#
# The script may also freely access any other caller variables.  This allows the
# script to maintain state between iterations.
#
# If -result is used, the script result is automatically stored into the out
# variable.  The script need only evaluate to the output chunk list.  If the
# script uses [return], the return value will be stored into the out variable.
#
# At the start of each pass through the loop, the out variable defaults to {{}}.
# If -result is not used and the script does not modify this variable, the input
# will pass through to the output unmodified.  If the script does modify out, it
# is used as a list of output chunks.  See [pipeline::new] for details on the
# format and behavior of output chunk lists.
#
# Changing the input variable affects the default values that will be filled
# into omitted fields in the out variable.  As a special case, if -buffer is
# used without -partial, the default value for the first element of the out
# variable is not the first element of the input variable, but rather the
# concatenation of the buffer and complete variables.
#
# If -command is used, the script argument is instead a sequence of one or more
# arguments forming a command prefix to which the input data will be appended.
# The choice of command arguments is determined by -raw, -buffer, and -trim.
#
# If -raw is not used, the command return value is the output data.  If -buffer
# is not used, the command argument is the input chunk data.  If -buffer is
# used, the command argument is all data buffered since the last delimiter.  If
# -trim is used, the delimiter is not included in the argument but will be
# appended to the return value.
#
# If -raw is used, the command return value is a list of zero or more output
# chunks.  The command argument is a three- or six-element list.  The first
# three elements are data, meta, and flush, and (if -buffer is used) the next
# three are prior, buffer, and complete.  See above for details.
#
# If -observe is used, the out variable, script result, or command return value
# is ignored, and the pipeline filter's output is equal to its input.  This also
# prevents -buffer from pausing the pipeline when the buffer is incomplete.
#
# The output chunks of the script or command will be merged if possible, though
# they will remain distinct chunks when they command flush or have varying
# metadata or restart flags.  -separate may be used to disable merging.
proc ::pipeline::loop {args} {
    # If [pipeline::loop] is the top level of the coroutine, recursively invoke
    # itself one time so that the [upvar] and [uplevel] commands store the
    # variables for the caller-supplied scripts in this stack frame, avoiding
    # conflict with [pipeline:loop]'s own variables.
    if {[info level] == 1} {
        unset args
        return [{*}[info level 0]]
    }

    # Parameter definition list.
    set definition {
        -params=
        -init=
        {-command   -forbid {params init}}
        -observe
        {-result    -forbid {command observe}}
        {-buffer    -key bufferMode}
        {-raw       -require command}
        {-partial   -require buffer}
        -separate
        {-delim=    -require buffer -default {\n}}
        {-trim      -require {buffer command} -forbid raw}
        script
        extra*
    }

    # Unset loopArgs and make a local backup.
    upvar 1 loopArgs loopArgs
    if {[array exists loopArgs]} {
        array set loopArgsBackup [array get loopArgs]
    } elseif {[info exists loopArgs]} {
        set loopArgsBackup $loopArgs
    }
    unset -nocomplain loopArgs

    try {
        # Parse arguments.
        argparse -boolean $definition

        # Evaluate -params and -init if supplied.
        if {[info exists params]} {
            uplevel 1 [list argparse $params $extra]
        }
        if {[info exists init]} {
            uplevel 1 $init
        }

        # If the loopArgs variable was created by -params or -init, prepend it
        # to the argument list and parse again.
        if {[info exists loopArgs]} {
            set args [linsert $args 0 {*}$loopArgs]
            argparse -boolean $definition
        }
    } finally {
        # Restore loopArgs to its original state, even if an error occurred.
        unset -nocomplain loopArgs
        if {[array exists loopArgsBackup]} {
            array set loopArgs [array get loopArgsBackup]
        } elseif {[info exists loopArgsBackup]} {
            set loopArgs $loopArgsBackup
        }
    }

    # Perform some additional argument validation.
    if {$bufferMode && [regexp $delim {}]} {
        return -code error "delimiter pattern matches empty string: $delim"
    } elseif {$extra ne {} && !$command && ![info exists params]} {
        return -code error "too many arguments"
    }

    # Bind the script to the inputs and outputs.  If -command is used, convert
    # the command prefix to a script, potentially modified by -buffer, -raw, and
    # -trim.  Otherwise, precede the script with code to expand the input to
    # separate variables.
    if {$command} {
        # Combine command name and arguments.
        lappend script {*}$extra
        append script " "
        if {$raw} {
            append script {$input}
        } elseif {!$bufferMode} {
            append script {[lindex $input 0]}
        } elseif {$trim} {
            append script {[lindex $input 4]}
        } else {
            append script {[lindex $input 4][lindex $input 5]}
        }

        # Store the command return value into the out variable.
        if {!$observe} {
            set script \[$script\]
            if {$trim} {
                append script {[lindex $input 5]}
            }
            if {!$raw} {
                set script "\[list \[list $script\]\]"
            }
            set script "set out $script"
        }
    } else {
        # If -result is used, store the script result into the out variable.
        # Intercept both "ok" (normal result) and "return" codes.
        if {$result} {
            set script [list try $script on ok out {} on return out {}]
        }

        # Load the data into script variables.
        set vars {data meta flush}
        if {$bufferMode} {
            lappend vars prior buffer complete
        }
        set script "lassign \$input $vars\n$script"
    }

    # Unless -separate is used, plan to merge consecutive chunks having the same
    # metadata and restart flag.  Two chunks cannot be merged if the first one
    # commands flush but the second does not.
    if {$separate} {
        set merge {apply {{out} {return $out}}}
    } else {
        set merge {apply {{out} {
            set i 0
            set j 1
            while {$j < [llength $out]} {
                if {[lindex $out $i 1] eq [lindex $out $j 1]
                 && (![lindex $out $i 2] || [lindex $out $j 2])
                 && ([llength [lindex $out $i]] >= 4 && [lindex $out $i 3])
                 == ([llength [lindex $out $j]] >= 4 && [lindex $out $j 3])} {
                    lset out $i 0 [lindex $out $i 0][lindex $out $j 0]
                    lset out $i 2 [lindex $out $j 2]
                    set out [lreplace $out $j $j]
                } else {
                    incr i
                    incr j
                }
            }
            return $out
        }}}
    }

    # Get access to caller input and output variables.
    upvar 1 input input out scriptOut

    if {$bufferMode} {
        # Loop until the pipeline is destroyed.
        set out {}
        set buffer {}
        while {[set input [yieldto return -level 0 $out]] ne {}} {
            # Concatenate the buffer with the new input data, then divide into
            # complete chunks, each chunk ending with the delimiter pattern.
            lassign $input data meta flush
            set in {}
            while {[regexp -indices -- $delim [set str $buffer$data] match]} {
                set len [expr {[lindex $match 1] - [string length $buffer]}]
                lappend in [list [string range $data 0 $len] $meta 0 $buffer\
                        [string range $str 0 [expr {[lindex $match 0] - 1}]]\
                        [string range $str {*}$match]]
                set data [string replace $data 0 $len]
                set buffer {}
            }

            # Buffer leftover data, and put it into an incomplete chunk.  Create
            # an empty chunk if there are no chunks but meta or flush are used.
            if {$data ne {} || ($in eq {} && ($meta ne {} || $flush))} {
                lappend in [list $data $meta 0 $buffer [append buffer $data] {}]
            }

            # On flush, enable flush in the last chunk, and empty the buffer.
            if {$flush} {
                lset in end 2 1
                set buffer {}
            }

            if {$observe} {
                # In observation mode, simply run the script and ignore output.
                set out {{}}
                foreach input $in {
                    if {$partial || [lindex $input 2]
                     || [lindex $input 5] ne {}} {
                        uplevel 1 $script
                    }
                }
            } else {
                # Run the script body for each input chunk and collect output
                # chunks.  When -partial is not used, flush is not commanded,
                # and the buffer is incomplete, do not run the script.
                set out {}
                foreach input $in {
                    if {$partial || [lindex $input 2]
                     || [lindex $input 5] ne {}} {
                        # Run the loop body script.
                        set scriptOut {{}}
                        uplevel 1 $script

                        # Fill in omitted output elements with defaults.
                        foreach output $scriptOut {
                            if {!$partial && ![llength $output]} {
                                set output [list [uplevel 1 {
                                    string cat $buffer $complete
                                }]]
                            }
                            if {[llength $output] < 3} {
                                lappend output {*}[lrange $input\
                                        [llength $output] 2]
                            }
                            lappend out $output
                        }
                    }
                }
                set out [{*}$merge $out]
            }
        }
    } else {
        # For unbuffered mode, far less processing is required.
        set scriptOut {}
        while {[set input [yieldto return -level 0 $scriptOut]] ne {}} {
            set scriptOut {{}}
            uplevel 1 $script
            set scriptOut [{*}$merge $scriptOut]
        }
    }
}

# ::pipeline::fork --
# Filter procedure for use with [pipeline::new].  Defines anonymous pipelines
# within the context of a parent pipeline.  Each input chunk is used as the
# input to the first filter of each nested pipeline.  The output of this filter
# is the output of the final filter of the first nested pipeline, and the
# outputs of the other nested pipelines are discarded.  Each [pipeline::fork]
# argument is a list of pipeline filter command prefixes.
proc ::pipeline::fork {args} {
    if {$args eq {}} {
        discard
    } else {
        set first [pipeline::new {*}[lindex $args 0]]
        set rest [lmap arg [lrange $args 1 end] {pipeline::new {*}$arg}]
        loop {
            set out [$first run $input]
            foreach coro $rest {
                $coro run $input
            }
        }
    }
}

# ::pipeline::filter --
# Filter procedure for use with [pipeline::new].  Passes or discards chunks for
# which a filter criteria script evaluates to true or false, respectively.
#
# The criteria script has access to all the same variables as the script
# argument to [pipeline::loop], including the additional variables provided by
# the -buffer switch.  The criteria script may also access variables set by the
# initial variable dict, the initialization script, or previous iterations of
# the criteria script.
#
# The following arguments are accepted:
#
# -vars VARS  Dict mapping from variable names and initial values
# -setup SCR  Initialization script
# -expr       Script is instead a Tcl math [expr] expression
# -buffer     Wait until delimiter is encountered before evaluating script
# -partial    Evaluate script for partial buffers as well as complete buffers
# -delim PAT  Buffer delimiter regular expression, default \n
# script      Script to evaluate for each chunk
::pipeline::procLoop ::pipeline::filter -params {
    {-vars=   -default {}}
    {-setup=  -default {}}
    {-expr    -boolean}
    {-buffer  -pass loopArgs}
    {-partial -pass loopArgs}
    {-delim?  -pass loopArgs}
    test
} -init {
    if {$expr} {
        set test [list expr $test]
    }
    dict with vars {}
    eval $setup
} {
    if {![eval $test]} {
        set out {}
    }
}

# ::pipeline::echo --
# Filter procedure for use with [pipeline::new].  Echoes input data to a given
# channel (defaulting to stdout) then passes it through unmodified.  If this
# filter is wrapped using [pipeline::buffer], and flush is not commanded, only
# complete buffers are echoed, with the delimiter appended.  Otherwise, chunks
# are echoed as soon as they are received.  The output channel is flushed after
# every write.
::pipeline::procLoop ::pipeline::echo -params {
    {-buffer  -pass loopArgs}
    {-delim=  -pass loopArgs -require buffer}
    {chan?    -default stdout}
} -observe {
    chan puts -nonewline $chan $data
    chan flush $chan
}

# ::pipeline::regsub --
# Filter procedure for use with [pipeline::new].  Applies [regsub] filtering to
# each complete buffer flowing through the pipeline.
#
# The initial arguments alternate between regular expressions and replacements.
# If an odd number of arguments are given, the final replacement is assumed to
# be empty string.  Additionally, any standard [regsub] switches may be used.
#
# Regular expressions and replacements cannot begin with "-".  One possible
# workaround is to instead begin with "\-".  Another is to precede the regular
# expression and replacement arguments with the special "--" switch.
#
# Regular expression matching and substitution are not applied to the delimiter,
# which is newline by default.  The delimiter can be changed using the -delim
# switch.  See the documentation for [pipeline::buffer] for more information.
#
# If the -erase switch is used, at least one regular expression substitution
# succeeded, and the result is an empty buffer, it is removed in full, and no
# delimiter is appended.  This mode allows [pipeline::regsub] to be used to
# delete entire lines of input, rather than make them be blank lines.
::pipeline::procLoop ::pipeline::regsub -params {
    {{}         -normalize -boolean -pass regsubArgs}
    {-start=    -pass regsubArgs}
    -erase
    {-delim=    -pass loopArgs}
    expReps*!
} -buffer -result {
    # Apply regular expression substitutions.
    foreach {exp rep} $expReps {
        ::regsub {*}$regsubArgs $exp $buffer $rep buffer
    }

    # Append the delimiter unless the buffer is being erased.
    if {!$erase || $buffer ne {}} {
        append buffer $complete
    }

    # Yield any output that may have been obtained.
    if {$buffer ne {}} {
        list [list $buffer]
    }
}

# ::pipeline::trimTrailingSpace --
# Filter procedure for use with [pipeline::new].  Trims trailing whitespace from
# each buffer.  The default delimiter is newline but can be changed with -delim.
# See the documentation for [pipeline::buffer] for more information.
::pipeline::procLoop ::pipeline::trimTrailingSpace -params {
    {-delim=    -pass loopArgs}
} -buffer -partial -result {
    # Find the last non-whitespace character in the current chunk.
    set output {}
    if {[regexp -indices {.*[^ \f\n\r\t\v]} $buffer end]} {
        # Find the last non-whitespace character preceding the current chunk.
        # This was the last character that was output before.
        if {[regexp -indices {.*[^ \f\n\r\t\v]} $prior start]} {
            set start [expr {[lindex $start 1] + 1}]
        } else {
            set start 0
        }

        # Output all characters since the previous output for this buffer
        # through the final non-whitespace character in the current chunk.
        append output [string range $buffer $start [lindex $end 1]]
    }

    # If this is a complete buffer, append the delimiter to the output.
    append output $complete

    # Yield any output that may have been obtained.
    if {$output ne {}} {
        list [list $output]
    }
}

# ::pipeline::squeeze --
# Filter procedure for use with [pipeline::new].  Removes empty buffers at the
# beginning and end of output and collapses consecutive empty buffers into one.
# The default delimiter is newline but can be changed with -delim.  See the
# documentation for [pipeline::buffer] for more information.
::pipeline::procLoop ::pipeline::squeeze -params {
    {-delim=    -pass loopArgs}
} -init {
    set empty 1
} -buffer -partial {
    if {$buffer eq {} && $complete ne {}} {
        # Do not output empty buffers.
        set out {}
        set empty 1
    } elseif {$buffer ne {}} {
        # If a non-empty buffer comes after at least one empty buffer which is
        # not at the beginning of input, precede the output chunk with the most
        # recently observed delimiter.  Otherwise, fall back on the default
        # behavior which is to pass the chunk through directly.
        if {$empty && [info exists delim]} {
            set out [list [list $delim] {}]
        }
        set empty 0
        if {$complete ne {}} {
            set delim $complete
        }
    }
}

# ::pipeline::removeFixed --
# Filter procedure for use with [pipeline::new].  Removes buffers that exactly
# match one or more literal pattern strings, which do not include the delimiter.
# The -prefix switch also removes buffers that begin with any pattern string.
#
# Unlike [pipeline::regsub], this procedure does not delay output until the
# delimiter is encountered.  Buffering only happens in event of a prefix match.
#
# If a flush occurs in the middle of a partial buffer, it will be output as-is,
# even though it could potentially be followed by characters that would make it
# match the removal pattern.
#
# The default delimiter is newline but can be changed with -delim.  See the
# documentation for [pipeline::buffer] for more information.
::pipeline::procLoop ::pipeline::removeFixed -params {
    {{}         -boolean}
    -prefix
    {-delim=    -pass loopArgs}
    patterns*
} -buffer -partial {
    foreach pattern $patterns {
        # Determine the match prefix length.
        if {$prefix && (($complete ne {} || $flush)
         || [string length $pattern] < [string length $buffer])} {
            set len [string length $pattern]
        } elseif {$complete eq {} && !$flush} {
            set len [string length $buffer]
        } else {
            set len -1
        }

        # Check for matches against the current and prior buffers.
        if {[string equal -length $len $buffer $pattern]} {
            # Discard or delay the input if the buffer is complete and exactly
            # matches the pattern, or is incomplete and is a prefix of the
            # pattern, or if prefix matching is enabled and the pattern is a
            # prefix of the buffer.
            set out {}
            break
        } elseif {$prior ne {} && [string equal -length [string length $prior]\
                $prior $pattern]} {
            # If the partial buffer was previously discarded, provisionally
            # output it in full because it ultimately ended up not matching.  It
            # may yet be discarded if it matches another pattern.
            set out [list [list $buffer$complete]]
        }
    }
}

# ::pipeline::tee --
# Filter procedure for use with [pipeline::new].  Tees one pipeline off another,
# connecting the output of the current pipeline at the current point to the
# input of the other pipeline, without affecting the data flowing through the
# current pipeline.  If nothing will call [pipeline::get] on the other pipeline,
# it is best that it contain the [pipeline::discard] filter to avoid unbounded
# growth of its output buffer.
::pipeline::procLoop ::pipeline::tee -params pipeline -observe {
    $pipeline put -meta $meta {*}[if {$flush} {list -flush}] $data
}

# ::pipeline::splice --
# Filter procedure for use with [pipeline::new].  Splices one pipeline into
# another, connecting the output of the current pipeline at the current point to
# the input of the other pipeline, and vice versa.
proc ::pipeline::splice {pipeline} {
    loop -command -raw $pipeline run
}

# ::pipeline::discard --
# Filter procedure for use with [pipeline::new].  Discards all input.  The
# pipeline is ended immediately unless flush is commanded, in which case any
# subsequent filters (there probably won't be any) are executed with no input.
# This filter is useful in combination with [pipeline::tee] to terminate a teed
# pipeline on which [pipeline::get] will never be called.
::pipeline::procLoop ::pipeline::discard -result {}

# vim: set sts=4 sw=4 tw=80 et ft=tcl:

Added modules/pipeline/pkgIndex.tcl.



>
1
package ifneeded pipeline 0.3 [list source [file join $dir pipeline.tcl]]

Deleted modules/pki/CA.crt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-----BEGIN CERTIFICATE-----
MIIEBjCCAu6gAwIBAgIJAJsptsQf3TXPMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV
BAYTAlVTMRAwDgYDVQQIEwdGbG9yaWRhMQ4wDAYDVQQHEwVUYW1wYTEPMA0GA1UE
ChMGVGNsbGliMQwwCgYDVQQLEwNSU0ExDzANBgNVBAMTBlRlc3RDQTAeFw0xMDA4
MDkwNzM3MzhaFw0zNTA4MTAwNzM3MzhaMF8xCzAJBgNVBAYTAlVTMRAwDgYDVQQI
EwdGbG9yaWRhMQ4wDAYDVQQHEwVUYW1wYTEPMA0GA1UEChMGVGNsbGliMQwwCgYD
VQQLEwNSU0ExDzANBgNVBAMTBlRlc3RDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAL9llE7rpNUW+YI8rdQgoG40E/FMMu2h9/6pVzCtILqOLFlSMSIQ
4CxKhIzPuiP+BSufNXmeMXSueifuT2mlb5ap6T2tmd5Vi09um5xw3Spu2Juz7Zfj
LDFnsMxuF3U4Qwl/9qEydmhtDnYATC8iRicXsPGvNVeTZgX3iZzzA3uFkD6NVEki
X1X3MgmE8eCGTw4U/k3MIK7wPQtZMSO4Aey9I/ub5ieZrAK0yZLjiubP27gb8ZIJ
wK2EXI2lZZH6g8JML7RwW5Yr0VoczEf79wKAUi15xQKfh+gxVzTnuKgdJ/ZMyzcW
+Pdap1YlHfewQfxeHBt60Rkr2x2UFU4hLIECAwEAAaOBxDCBwTAdBgNVHQ4EFgQU
hSwdCbdrD6EONdeqS8tIst6yVNUwgZEGA1UdIwSBiTCBhoAUhSwdCbdrD6EONdeq
S8tIst6yVNWhY6RhMF8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdGbG9yaWRhMQ4w
DAYDVQQHEwVUYW1wYTEPMA0GA1UEChMGVGNsbGliMQwwCgYDVQQLEwNSU0ExDzAN
BgNVBAMTBlRlc3RDQYIJAJsptsQf3TXPMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN
AQEFBQADggEBAL7Uhodh2ATX4IvsGqryZdLVnG9TkMn9o8ge9EUupYtt9/9/K+My
dqXCHVuKwMYr5V5S5HAQxwTTQ4ByPaLYz+V8dumyBOdSp5l5x5NWJ+2oCn/DpL7U
9ezqL9gzEf5AVLxigSo/V5c4uUpE4K3tbGHDVpF1z7OT6LOpkvWui1FpLQoDc9HK
BmT1J+fQSHfsScV65T6qsQAGPUyRXqh79LIrY0ZWvDun5xy13KmCk37Gc2+fCx2m
QEJFyaCMojsCfJz2XRtBtwn8bpBnFUP187f4snkU5Ga/5TjQGq6YBP2BWR8W3tM0
zGk5KboIltjQSbW9KYVratpF+gp3e6ni9B0=
-----END CERTIFICATE-----
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















































Deleted modules/pki/CA.key.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,8C1A2E69ACFC3E90

GVnzdBMa+GX2u4jOpSYU6P1JBQYbB9FRrfB/0QGdhKHU2OPEZzYZo2LwgpEBVMWT
dVsbBECil4h0UnUsC/+DmJPv/SF++VJK8JvtO2opNCmeYrH5VAwqN2tqIXX2sWng
9Fk7HVjsLfTUvw6nc5TI07qK2okGcT9yMTjEGXKPLkMs5K16gKoMHf5yQPQmOpfR
HrE8odoPib1JKDV9j4FYjfBEja7Y4GLFbNobvaQIvA/pbKE4mGkGczn6vjdkGTbv
wAI0fIWqfOnfE+VlSz9lT4mOVHt6x4WQbfUgJKf29pL9DH+I22K2cgzGwMLzLot3
IhPiO6coFfLOKKNbRv4gtxTjXvnlwm217GDoEPgDKG1qwWzjSwI8DBsLjMhKHDfz
0ScyItR3wkTVaTE0sQYFS5VmKzgH2rQ8ichk4AUzM5+myxg1ALKi9GRtIKKbY+0H
EseYxzbRhTSVo0GPGiu8j6BVK40uynF4ydrjlETQsJhZZTeJPjPGNh6m3eP5zW0Q
Im8UgW6ZZumzINJPrEKrwRF7qEGSLRv3lkMOj08sYFsSqFnBex90cov1pJOUCCAL
mBgLFFb6P9kEAqZOnNcwrohcf8gmW1pATTgT1+y0OTC1rEJ+asvCn6yN2QkhyNqq
vabFqxyWxVi9MsodP4+eY9Hjhl5WwkuVCnBG69HugOFvVKHIpGxfQjSnQNaYfI6a
UKLixw0ZdfWN8sNG4gcisj/O/VHKbEWwp+N452lTzzFE7+QvCtg6rn+LPLEyTZRb
b7QQc6CcqELL4qksm/FNP8pIyGfsUKYVE79FDK+mxDxZpWEMJ6J6dwj1jwzGbMnP
5sgmAeaSinkqUQf/4AoiU1eIj1fiXHcsub7mFzzBP9NKQZ4YrkBeu7zfsP8Ex5Ol
W3WmKIkw2MBG9Q0dP3HQBDw5k35X5ydJvrtaRJLDZZDwA24WcyKffYUHGV4KhsxC
Vjzkth+MkBaPAtB35tRlr1Fr0wC6MNTeZOuPNgGM+t1ejg1NPN722J+ihne05KW/
wzBgz3veeJeUlxRPZl0Sklct029fV+pZGwxlx72hMiyBwDh9pBhmIjWJFzuQ35CG
DNZm1spGcDU9sd1y1txS+QVd3CDP7a5CrUuI7S8FYJEREGzWGn/dF9hxrbeLLXRf
qvcUwCAobFfV14Z1cwoxZ9MWTXBYynxUYO7TYajb/6vIvYOAQ3DGSPelvNRsrilT
GV0CJ1Mx6JEaTzGQQeB2JxO09T0qxKMT6h4BbLhZRledmrI/Pvp/roUmnvdE3kBn
MkRUxzGBD9EBPA02F2paDRxXPZRHvpGomvP32JL7AJ8tln8z4TsHclpls0E7dmk9
KKQSLk1DOUjarJhPHmGyDOn9tVdgzbfyQjdmZ1wxBvYbBuqS82FcoWohF2GnyYAm
X7tdS9AVNDErVXOmqh2hcYFY3NFBLy0altpMaTVqTx1SwkpHh6YGt9ioltzP7kxz
wxHz/w4DPrxaUOFYZX9dffGceFf5/h2DfhqobnwZuCgDo7SDUKJI0f88bR+1d1q6
qr2T9ZuzIPIllMzGVfNwq5WsPy+klq/lK0QRl6RZdLEM0Q5h6WOYeoxpOGjW6E1h
-----END RSA PRIVATE KEY-----
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































Changes to modules/pki/pki.man.

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
[list_begin enumerated]
[enum]	"openssl rsautl -decrypt" == "::pki::decrypt -binary -priv"
[enum]	"openssl rsautl -verify"  == "::pki::decrypt -binary -pub"
[list_end]

[call [cmd ::pki::sign] [arg input] [arg key] [opt [arg algo]]]

Digitally sign message [arg input] using the private [arg key].  If [arg algo]

is ommited "sha1" is assumed.  Possible values for [arg algo] include


"md5", "sha1", "sha256", and "raw".  Specifyin "raw" for [arg algo] will

inhibit the building of an ASN.1 structure to encode which hashing
algorithm was chosen.








The [arg input] should be the plain text, hashing will be performed on it.


The [arg key] should include the private key.

[comment {
	What is the default for algo?
          -- sha1
	What choices for algo has the user ?
          -- md5, sha1, sha256, and "raw" currently
}]

[call [cmd ::pki::verify] [arg signedmessage] [arg plaintext] [arg key] [opt [arg algo]]]

Verify a digital signature using a public [arg key].  Returns true or false.








[comment {
	What is the default for algo?
          -- The default is to look at the data for the OID of the algorithm, but if it was signed "raw" it will need to be specified.  It's actually ignored right now.
	What choices for algo has the user ?
          -- md5, sha1, sha256

    NOTE: Why is the result OK and ?







|
>
|
>
>
|
>
|
|

>
>
>
>
>
>
>
|
>

|












>
>
>
>
>
>
>







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
[list_begin enumerated]
[enum]	"openssl rsautl -decrypt" == "::pki::decrypt -binary -priv"
[enum]	"openssl rsautl -verify"  == "::pki::decrypt -binary -pub"
[list_end]

[call [cmd ::pki::sign] [arg input] [arg key] [opt [arg algo]]]

Digitally sign message [arg input] using the private [arg key].

[para] If [arg algo] is ommited "sha1" is assumed. Possible values for
[arg algo] include "[const md5]", "[const sha1]", "[const sha256]",
and "[const raw]".

[para] Specifying "[const raw]" for [arg algo] will inhibit the
building of an ASN.1 structure to encode which hashing algorithm was
chosen.

[strong Attention]: In this case the corresponding [cmd pkgi::verify]
must be called [const with] algorithm information.

Conversely, specifying a non-"[const raw]" algorithm here means that
the corresponding [cmd pkgi::verify] invokation has to be made
[strong without] algorithm information.

[para] The [arg input] should be the plain text, hashing will be
performed on it.

[para] The [arg key] should include the private key.

[comment {
	What is the default for algo?
          -- sha1
	What choices for algo has the user ?
          -- md5, sha1, sha256, and "raw" currently
}]

[call [cmd ::pki::verify] [arg signedmessage] [arg plaintext] [arg key] [opt [arg algo]]]

Verify a digital signature using a public [arg key].  Returns true or false.

[para][strong Attention]: The algorithm information [arg algo] has to
be specified if and only if the [cmd pki::sign] which generated the
[arg signedmessage] was called with algorithm "[const raw]". This
inhibited the building of the ASN.1 structure encoding the chosen
hashing algorithm. Conversely, if a proper algorithm was specified
during signing then you [strong {must not}] specify an algorithm here.

[comment {
	What is the default for algo?
          -- The default is to look at the data for the OID of the algorithm, but if it was signed "raw" it will need to be specified.  It's actually ignored right now.
	What choices for algo has the user ?
          -- md5, sha1, sha256

    NOTE: Why is the result OK and ?
294
295
296
297
298
299
300
301
302
[enum]
[list_end]

[section AUTHORS]
Roy Keene

[vset CATEGORY rsa]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

313
314
315
316
317
318
319
320
321
[enum]
[list_end]

[section AUTHORS]
Roy Keene

[vset CATEGORY rsa]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/pki/pki.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
# rsa.test - Copyright (c) 2010 Roy Keene, Andreas Kupries
#
# the test-values are taken from:
#    ??
#
# $Id$

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

|



<
<







1
2
3
4


5
6
7
8
9
10
11
# pki.test - Copyright (c) 2010 Roy Keene, Andreas Kupries
#
# the test-values are taken from:
#    ??



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

66
67
68
69
70



71
72
73
74
75
76
77
78
79
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
testing {
    useLocal pki.tcl pki
}

# -------------------------------------------------------------------------

test rsa-parse-aeskey-1.0 {parse_key} -setup {
    set fd [open [file join $::tcltest::testsDirectory test.key.aes] r]
    set privkey [read $fd]
    close $fd ; unset fd

    set password "ARoseIsARoseIsARose"
} -body {
    dictsort [::pki::pkcs::parse_key $privkey $password]
} -cleanup {
    unset privkey password
} -result {d 4821708078078814272825737770757352316921506482526873519719051463644222257651923197825994018656421190278177720014932984365118366602027256382375921341192781177112398174373076887129954817822368157304055327895506098881228521168940083073283595671416028753301552269895847121119899618677892849270785450525228277087545852904246091363590456069440574806479467479724488815982259021323617233373449030738298588184972148901173121148634892058648703349014218791530847767762515588159636682267580355756974401553230588009724381821442787415368995149629493809933380894522643851913309510865914033228986295772184835354265231482340110365953 e 65537 l 2048 n 20606474229739240365059039861892702888430699076971875439310562489263214483191006887246310401088091004060054335612563612411917991000786455919906798626524375611634511845705141177165689526939976649836053082770641226108840795034158866930145876068965913035873741839723777813944236146677082729876717709231945588228947001753667862858297850461440476551869914895980840772354759428144421149613554402682425181850295101375623815063198594704730226304723548382258248785251384891817576645955371924194287071569929361029204431671633821160423187871463713776212876252047207985933876036458343140423787003660018607222053134170461225878347 p 151903506703070744388477144011062627922344490485619606525415439019240332914406492743669447033002173681213181316912563402042948038453846038272948559137687751740338183189809253891948725876860938554446847405802064303332011747457634488959045893106143553864597546566768167692662722957924358908573096347694362541259 q 135655026516400219835182288872064651548166413404981613626584975073279765274581289299963783472100901444904090497633607380440126562041149560121122191822729803838692049608052805597752016733559257401832457990520641184379220785155858496800358974243933025297673311305372951490297748845447521569920828454777048335233 type rsa}


test rsa-parse-deskey-1.0 {parse_key} -setup {
    set fd [open [file join $::tcltest::testsDirectory test.key.des] r]
    set privkey [read $fd]
    close $fd ; unset fd

    set password "ARoseIsARoseIsARose"
} -body {
    dictsort [::pki::pkcs::parse_key $privkey $password]
} -cleanup {
    unset privkey password
} -result {d 4821708078078814272825737770757352316921506482526873519719051463644222257651923197825994018656421190278177720014932984365118366602027256382375921341192781177112398174373076887129954817822368157304055327895506098881228521168940083073283595671416028753301552269895847121119899618677892849270785450525228277087545852904246091363590456069440574806479467479724488815982259021323617233373449030738298588184972148901173121148634892058648703349014218791530847767762515588159636682267580355756974401553230588009724381821442787415368995149629493809933380894522643851913309510865914033228986295772184835354265231482340110365953 e 65537 l 2048 n 20606474229739240365059039861892702888430699076971875439310562489263214483191006887246310401088091004060054335612563612411917991000786455919906798626524375611634511845705141177165689526939976649836053082770641226108840795034158866930145876068965913035873741839723777813944236146677082729876717709231945588228947001753667862858297850461440476551869914895980840772354759428144421149613554402682425181850295101375623815063198594704730226304723548382258248785251384891817576645955371924194287071569929361029204431671633821160423187871463713776212876252047207985933876036458343140423787003660018607222053134170461225878347 p 151903506703070744388477144011062627922344490485619606525415439019240332914406492743669447033002173681213181316912563402042948038453846038272948559137687751740338183189809253891948725876860938554446847405802064303332011747457634488959045893106143553864597546566768167692662722957924358908573096347694362541259 q 135655026516400219835182288872064651548166413404981613626584975073279765274581289299963783472100901444904090497633607380440126562041149560121122191822729803838692049608052805597752016733559257401832457990520641184379220785155858496800358974243933025297673311305372951490297748845447521569920828454777048335233 type rsa}

test rsa-generate-csr-1.0 {csr} -setup {
    set fd [open [file join $::tcltest::testsDirectory test.key.des] r]
    set privkey [read $fd]
    close $fd ; unset fd

    set password "ARoseIsARoseIsARose"

    set privkey [::pki::pkcs::parse_key $privkey $password]
} -body {

    ::pki::pkcs::create_csr $privkey [list C US ST Florida L Tampa O Tcllib OU RSA CN TestCert] 1
} -cleanup {
    unset privkey password
} -result {-----BEGIN CERTIFICATE REQUEST-----
MIICpjCCAY4CAQAwYTELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0Zsb3JpZGExDjAM



BgNVBAcTBVRhbXBhMQ8wDQYDVQQKEwZUY2xsaWIxDDAKBgNVBAsTA1JTQTERMA8G
A1UEAxMIVGVzdENlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCj
PBaKPeHx1oQb0nfMPeglBgyIpsv8CuIH7CAT8SGxoK1zIBQUhnNOZvel1/Kore68
mY0ftiqmVbLO7aZy9X0Vy97hcEnhIekuPCauVg3kWjOspPbxmd3Bf7vfw7RGsvUt
GGc3FZnU/X3GhzlKCq1osQCSZdLwirDm8ny4tbkTEDnGIB+4IJbSvifGQDqQNwtx
cDigwRwAgDDdaKYBiW4bp+ZowJxorqc60w6xcl8DKhpPPaqRFN2kBcAxU/vztan1
5NjNmmOPIkDcvIDEEkxKDoefTWaaF/MEGNtZZgIfIbVMos9+1soBzBb2ZH5NVtuK
3RGA+4DxUk5kiI+eLANLAgMBAAGgADANBgkqhkiG9w0BAQUFAAOCAQEAff0WNTPX
M6rdFGOXBxTsC7NUGcoquuM6QsceadMbBVRtRUUbaUsusXdxDWhdylqHM3xPNx0L
4Ex0FeL9icD/8xvJmCXzBeNt3uvThTvIwHYqnOCSlhx9InUUx2l6U0rAwZ+CIuMi
7lG2+Z5qVD035bAZ7LT/4s4fjKSL4cTZQOdCcoFtoptj9+L8EItwwYDzffJWdG8s
OUtMBn+Zh45k2UtLKu38jBNtVpNFAEJLlr/Arj6Jj3yTmEFrocxkwK6IPbOHQTu3
tyJ5CkDpUqkxYZ0D4wfr8tFEru0jQNl5bSDt9QQvg1Kj6+OC9aaRvxwnmc6REfky
8sCv80Pn5dNCGg==
-----END CERTIFICATE REQUEST-----
}








test rsa-parse-certv1-1.0 {parse_cert} -setup {
    set fd [open [file join $::tcltest::testsDirectory test-v1.crt] r]
    set pubkey [read $fd]
    close $fd ; unset fd
} -body {
    dictsort [::pki::x509::parse_cert $pubkey]
} -cleanup {
    unset pubkey
} -result {cert 30820221020612481595aa03300d06092a864886f70d0101050500305f310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b1303525341310f300d06035504031306546573744341301e170d3130303830393037353230355a170d3230303830393037353230355a3061310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b13035253413111300f06035504031308546573744365727430820122300d06092a864886f70d01010105000382010f003082010a0282010100a33c168a3de1f1d6841bd277cc3de825060c88a6cbfc0ae207ec2013f121b1a0ad7320141486734e66f7a5d7f2a8adeebc998d1fb62aa655b2ceeda672f57d15cbdee17049e121e92e3c26ae560de45a33aca4f6f199ddc17fbbdfc3b446b2f52d1867371599d4fd7dc687394a0aad68b1009265d2f08ab0e6f27cb8b5b9131039c6201fb82096d2be27c6403a90370b717038a0c11c008030dd68a601896e1ba7e668c09c68aea73ad30eb1725f032a1a4f3daa9114dda405c03153fbf3b5a9f5e4d8cd9a638f2240dcbc80c4124c4a0e879f4d669a17f30418db5966021f21b54ca2cf7ed6ca01cc16f6647e4d56db8add1180fb80f1524e64888f9e2c034b0203010001 data_signature_algo sha1WithRSAEncryption e 65537 extensions {} issuer {C=US, ST=Florida, L=Tampa, O=Tcllib, OU=RSA, CN=TestCA} l 2048 n 20606474229739240365059039861892702888430699076971875439310562489263214483191006887246310401088091004060054335612563612411917991000786455919906798626524375611634511845705141177165689526939976649836053082770641226108840795034158866930145876068965913035873741839723777813944236146677082729876717709231945588228947001753667862858297850461440476551869914895980840772354759428144421149613554402682425181850295101375623815063198594704730226304723548382258248785251384891817576645955371924194287071569929361029204431671633821160423187871463713776212876252047207985933876036458343140423787003660018607222053134170461225878347 notAfter 1596959525 notBefore 1281340325 pubkey 3082010a0282010100a33c168a3de1f1d6841bd277cc3de825060c88a6cbfc0ae207ec2013f121b1a0ad7320141486734e66f7a5d7f2a8adeebc998d1fb62aa655b2ceeda672f57d15cbdee17049e121e92e3c26ae560de45a33aca4f6f199ddc17fbbdfc3b446b2f52d1867371599d4fd7dc687394a0aad68b1009265d2f08ab0e6f27cb8b5b9131039c6201fb82096d2be27c6403a90370b717038a0c11c008030dd68a601896e1ba7e668c09c68aea73ad30eb1725f032a1a4f3daa9114dda405c03153fbf3b5a9f5e4d8cd9a638f2240dcbc80c4124c4a0e879f4d669a17f30418db5966021f21b54ca2cf7ed6ca01cc16f6647e4d56db8add1180fb80f1524e64888f9e2c034b0203010001 pubkey_algo rsaEncryption raw 2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d4949444f5443434169454342684a49465a5771417a414e42676b71686b69473977304241515546414442664d517377435159445651514745774a56557a45510a4d4134474131554543424d48526d7876636d6c6b5954454f4d4177474131554542784d465647467463474578447a414e42674e5642416f54426c526a624778700a596a454d4d416f474131554543784d44556c4e424d513877445159445651514445775a555a584e30513045774868634e4d5441774f4441354d4463314d6a41310a5768634e4d6a41774f4441354d4463314d6a4131576a42684d517377435159445651514745774a56557a45514d4134474131554543424d48526d7876636d6c6b0a5954454f4d4177474131554542784d465647467463474578447a414e42674e5642416f54426c526a62477870596a454d4d416f474131554543784d44556c4e420a4d5245774477594456515144457768555a584e305132567964444343415349774451594a4b6f5a496876634e4151454242514144676745504144434341516f430a67674542414b4d38466f6f39346648576842765364387739364355474449696d792f774b34676673494250784962476772584d67464253476330356d393658580a387169743772795a6a522b324b715a5673733774706e4c316652584c3375467753654568365334384a713557446552614d36796b3976475a3363462f75392f440a74456179395330595a7a63566d645439666361484f556f4b72576978414a4a6c3076434b734f6279664c693175524d514f635967483767676c744b2b4a385a410a4f704133433346774f4b4442484143414d4e316f7067474a6268756e356d6a416e476975707a72544472467958774d71476b38397170455533615146774446540a2b2f4f317166586b324d326159343869514e7938674d515354456f4f6835394e5a706f583877515932316c6d41683868745579697a3337577967484d46765a6b0a666b3157323472644559443767504653546d53496a35347341307343417745414154414e42676b71686b6947397730424151554641414f4341514541657376510a705966785a6a364b49625a666b57487768444830564e693569505576614e6256765a725a5a315231675a416b38527963514e38676e3742614b582f3663696b730a67654b6276477779354a765a614b53656436353734515654562b6d47417141784f572b4c6d5552562b54616f57534b4143393344656264734c324e6c504473720a7575784d676237666e35326e69327141736c506f2b597a65636f6b49574465794b7652554344374774334c44644c5150472f6a547836586e65626237757369460a706671515768465564636650696b30593372664a47356256354875684b52394c7877493348787274344c6c535a49706f6c4d586b776b6c71656f4930654970790a6b4e4a57356332706d336376512f415a33624858574e4271483941345a66334f64697a794b4644356c71714d334832455152586a3063557a516f3257716635330a533657364234463242325a4c612f4f2f45673d3d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a serial_number 20100809075203 signature 7acbd0a587f1663e8a21b65f9161f08431f454d8b988f52f68d6d5bd9ad9675475819024f11c9c40df209fb05a297ffa72292c81e29bbc6c32e49bd968a49e77ae7be1055357e98602a031396f8b994455f936a85922800bddc379b76c2f63653c3b2bbaec4c81bedf9f9da78b6a80b253e8f98cde7289085837b22af454083ec6b772c374b40f1bf8d3c7a5e779b6fbbac885a5fa905a115475c7cf8a4d18deb7c91b96d5e47ba1291f4bc702371f1aede0b952648a6894c5e4c2496a7a8234788a7290d256e5cda99b772f43f019ddb1d758d06a1fd03865fdce762cf22850f996aa8cdc7d844115e3d1c533428d96a9fe774ba5ba07817607664b6bf3bf12 signature_algo sha1WithRSAEncryption subject {C=US, ST=Florida, L=Tampa, O=Tcllib, OU=RSA, CN=TestCert} type rsa version 1}

test rsa-parse-certv3-1.0 {parse_cert} -setup {
    set fd [open [file join $::tcltest::testsDirectory test-v3.crt] r]


    set pubkey [read $fd]
    close $fd ; unset fd

} -body {

    dictsort [::pki::x509::parse_cert $pubkey]
} -cleanup {
    unset pubkey
} -result {cert 30820226a003020102020612481595a9c0300d06092a864886f70d0101050500305f310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b1303525341310f300d06035504031306546573744341301e170d3130303830393037353133365a170d3230303830393037353133365a3061310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b13035253413111300f06035504031308546573744365727430820122300d06092a864886f70d01010105000382010f003082010a0282010100a33c168a3de1f1d6841bd277cc3de825060c88a6cbfc0ae207ec2013f121b1a0ad7320141486734e66f7a5d7f2a8adeebc998d1fb62aa655b2ceeda672f57d15cbdee17049e121e92e3c26ae560de45a33aca4f6f199ddc17fbbdfc3b446b2f52d1867371599d4fd7dc687394a0aad68b1009265d2f08ab0e6f27cb8b5b9131039c6201fb82096d2be27c6403a90370b717038a0c11c008030dd68a601896e1ba7e668c09c68aea73ad30eb1725f032a1a4f3daa9114dda405c03153fbf3b5a9f5e4d8cd9a638f2240dcbc80c4124c4a0e879f4d669a17f30418db5966021f21b54ca2cf7ed6ca01cc16f6647e4d56db8add1180fb80f1524e64888f9e2c034b0203010001 data_signature_algo sha1WithRSAEncryption e 65537 extensions {} issuer {C=US, ST=Florida, L=Tampa, O=Tcllib, OU=RSA, CN=TestCA} l 2048 n 20606474229739240365059039861892702888430699076971875439310562489263214483191006887246310401088091004060054335612563612411917991000786455919906798626524375611634511845705141177165689526939976649836053082770641226108840795034158866930145876068965913035873741839723777813944236146677082729876717709231945588228947001753667862858297850461440476551869914895980840772354759428144421149613554402682425181850295101375623815063198594704730226304723548382258248785251384891817576645955371924194287071569929361029204431671633821160423187871463713776212876252047207985933876036458343140423787003660018607222053134170461225878347 notAfter 1596959496 notBefore 1281340296 pubkey 3082010a0282010100a33c168a3de1f1d6841bd277cc3de825060c88a6cbfc0ae207ec2013f121b1a0ad7320141486734e66f7a5d7f2a8adeebc998d1fb62aa655b2ceeda672f57d15cbdee17049e121e92e3c26ae560de45a33aca4f6f199ddc17fbbdfc3b446b2f52d1867371599d4fd7dc687394a0aad68b1009265d2f08ab0e6f27cb8b5b9131039c6201fb82096d2be27c6403a90370b717038a0c11c008030dd68a601896e1ba7e668c09c68aea73ad30eb1725f032a1a4f3daa9114dda405c03153fbf3b5a9f5e4d8cd9a638f2240dcbc80c4124c4a0e879f4d669a17f30418db5966021f21b54ca2cf7ed6ca01cc16f6647e4d56db8add1180fb80f1524e64888f9e2c034b0203010001 pubkey_algo rsaEncryption raw 2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d494944506a4343416961674177494241674947456b67566c616e414d413047435371475349623344514542425155414d463878437a414a42674e56424159540a416c56544d52417744675944565151494577644762473979615752684d51347744415944565151484577565559573177595445504d4130474131554543684d470a56474e7362476c694d517777436759445651514c45774e5355304578447a414e42674e5642414d54426c526c6333524451544165467730784d4441344d446b770a4e7a55784d7a5a61467730794d4441344d446b774e7a55784d7a5a614d474578437a414a42674e5642415954416c56544d5241774467594456515149457764470a62473979615752684d51347744415944565151484577565559573177595445504d4130474131554543684d4756474e7362476c694d517777436759445651514c0a45774e53553045784554415042674e5642414d544346526c633352445a584a304d494942496a414e42676b71686b6947397730424151454641414f43415138410a4d49494243674b43415145416f7a7757696a33683864614547394a337a44336f4a51594d694b624c2f417269422b7767452f4568736143746379415546495a7a0a546d623370646679714b3375764a6d4e48375971706c57797a75326d63765639466376653458424a345348704c6a776d726c594e35466f7a724b5432385a6e640a77582b3733384f3052724c314c52686e4e78575a31503139786f633553677174614c45416b6d58533849717735764a38754c57354578413578694166754343570a3072346e786b41366b44634c635841346f4d4563414941773357696d41596c754736666d614d4363614b366e4f744d4f73584a6641796f61547a32716b5254640a704158414d56503738375770396554597a5a706a6a794a41334c794178424a4d536736486e30316d6d68667a42426a625757594348794731544b4c506674624b0a41637757396d522b54566262697430526750754138564a4f5a4969506e69774453774944415141424d41304743537147534962334451454242515541413449420a41514177454673454441306d70346d516d4f596263345248515645474e3732334374676345484637756e75343345654f35732f31597130462b5364575231344c0a714673366c52586e506a6b457049466c6d573549304470385131795931387152507438487836796d7874793851576d396c54774d427a7259556839344a71562b0a593351484a625672674c706f4b527073564f7073644d3571513465667651774f30734f77493541616a766b795531644338547378417a794a4d51664b2b5751730a41306c5370714d304874726c31785268445a774543384245332b374976394d53572f52764b364661614f466b796a766657664f4c67526652744d51382b6864560a385261534571716b5373676c477a6d7a53627554486f70426b6c65314b6567713248642f316c706939466f58487247786a7747575677354b4f77574f4361304f0a7946344b5757696a4d4f57624d7249714c71357034614f6b0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a serial_number 20100809075136 signature 30105b040c0d26a7899098e61b73844741510637bdb70ad81c10717bba7bb8dc478ee6cff562ad05f92756475e0ba85b3a9515e73e3904a48165996e48d03a7c435c98d7ca913edf07c7aca6c6dcbc4169bd953c0c073ad8521f7826a57e63740725b56b80ba68291a6c54ea6c74ce6a43879fbd0c0ed2c3b023901a8ef932535742f13b31033c893107caf9642c034952a6a3341edae5d714610d9c040bc044dfeec8bfd3125bf46f2ba15a68e164ca3bdf59f38b8117d1b4c43cfa1755f1169212aaa44ac8251b39b349bb931e8a419257b529e82ad8777fd65a62f45a171eb1b18f0196570e4a3b058e09ad0ec85e0a5968a330e59b32b22a2eae69e1a3a4 signature_algo sha1WithRSAEncryption subject {C=US, ST=Florida, L=Tampa, O=Tcllib, OU=RSA, CN=TestCert} type rsa version 3}

test rsa-parse-cacert-1.0 {parse_cert} -setup {
    set fd [open [file join $::tcltest::testsDirectory CA.crt] r]
    set pubkey [read $fd]
    close $fd ; unset fd

} -body {
    dictsort [::pki::x509::parse_cert $pubkey]
} -cleanup {
    unset pubkey
} -result {cert 308202eea0030201020209009b29b6c41fdd35cf300d06092a864886f70d0101050500305f310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b1303525341310f300d06035504031306546573744341301e170d3130303830393037333733385a170d3335303831303037333733385a305f310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b1303525341310f300d0603550403130654657374434130820122300d06092a864886f70d01010105000382010f003082010a0282010100bf65944eeba4d516f9823cadd420a06e3413f14c32eda1f7fea95730ad20ba8e2c5952312210e02c4a848ccfba23fe052b9f35799e3174ae7a27ee4f69a56f96a9e93dad99de558b4f6e9b9c70dd2a6ed89bb3ed97e32c3167b0cc6e17753843097ff6a13276686d0e76004c2f22462717b0f1af3557936605f7899cf3037b85903e8d5449225f55f7320984f1e0864f0e14fe4dcc20aef03d0b593123b801ecbd23fb9be62799ac02b4c992e38ae6cfdbb81bf19209c0ad845c8da56591fa83c24c2fb4705b962bd15a1ccc47fbf70280522d79c5029f87e8315734e7b8a81d27f64ccb3716f8f75aa756251df7b041fc5e1c1b7ad1192bdb1d94154e212c810203010001a381c43081c1301d0603551d0e04160414852c1d09b76b0fa10e35d7aa4bcb48b2deb254d53081910603551d230481893081868014852c1d09b76b0fa10e35d7aa4bcb48b2deb254d5a163a461305f310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b1303525341310f300d060355040313065465737443418209009b29b6c41fdd35cf300c0603551d13040530030101ff data_signature_algo sha1WithRSAEncryption e 65537 extensions {id-ce-subjectKeyIdentifier {false 0414852c1d09b76b0fa10e35d7aa4bcb48b2deb254d5} id-ce-authorityKeyIdentifier {false 3081868014852c1d09b76b0fa10e35d7aa4bcb48b2deb254d5a163a461305f310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b1303525341310f300d060355040313065465737443418209009b29b6c41fdd35cf} id-ce-basicConstraints {false 1 -1}} issuer {C=US, ST=Florida, L=Tampa, O=Tcllib, OU=RSA, CN=TestCA} l 2048 n 24161606882664512184359265185750837725108535101957340182512690512950889280510175836653980019439405807509520118166835198926328713901946216313990307823213762851130122553610411084164096778558222486569750697608231998818342043083553499928765840766586577148563804434733745484416582976688503343857730022194918419820043366167270205314454789050632414594372175021330643138454461788318306110532766986666994575469007919602783172146356611527403971910037954057021421611608595373199910520988014831498419657809400692831589285260267441816651113464389720766612297754777522129247659432535168409289483999817599902067306541004223550663809 notAfter 2070344258 notBefore 1281339458 pubkey 3082010a0282010100bf65944eeba4d516f9823cadd420a06e3413f14c32eda1f7fea95730ad20ba8e2c5952312210e02c4a848ccfba23fe052b9f35799e3174ae7a27ee4f69a56f96a9e93dad99de558b4f6e9b9c70dd2a6ed89bb3ed97e32c3167b0cc6e17753843097ff6a13276686d0e76004c2f22462717b0f1af3557936605f7899cf3037b85903e8d5449225f55f7320984f1e0864f0e14fe4dcc20aef03d0b593123b801ecbd23fb9be62799ac02b4c992e38ae6cfdbb81bf19209c0ad845c8da56591fa83c24c2fb4705b962bd15a1ccc47fbf70280522d79c5029f87e8315734e7b8a81d27f64ccb3716f8f75aa756251df7b041fc5e1c1b7ad1192bdb1d94154e212c810203010001 pubkey_algo rsaEncryption raw 2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d494945426a434341753667417749424167494a414a737074735166335458504d413047435371475349623344514542425155414d463878437a414a42674e560a42415954416c56544d52417744675944565151494577644762473979615752684d51347744415944565151484577565559573177595445504d413047413155450a43684d4756474e7362476c694d517777436759445651514c45774e5355304578447a414e42674e5642414d54426c526c6333524451544165467730784d4441340a4d446b774e7a4d334d7a68614677307a4e5441344d5441774e7a4d334d7a68614d463878437a414a42674e5642415954416c56544d52417744675944565151490a4577644762473979615752684d51347744415944565151484577565559573177595445504d4130474131554543684d4756474e7362476c694d517777436759440a5651514c45774e5355304578447a414e42674e5642414d54426c526c6333524451544343415349774451594a4b6f5a496876634e4151454242514144676745500a4144434341516f4367674542414c396c6c453772704e55572b594938726451676f473430452f464d4d753268392f3670567a4374494c714f4c466c534d5349510a3443784b68497a507569502b425375664e586d654d5853756569667554326d6c62356170365432746d643556693039756d35787733537075324a757a375a666a0a4c44466e734d78754633553451776c2f39714579646d6874446e59415443386952696358735047764e5665545a675833695a7a7a413375466b44364e56456b690a583158334d676d4538654347547734552f6b334d494b37775051745a4d534f3441657939492f75623569655a72414b30795a4c6a6975625032376762385a494a0a774b32455849326c5a5a483667384a4d4c3752775735597230566f637a45663739774b415569313578514b66682b6778567a546e754b67644a2f5a4d797a63570a2b5064617031596c48666577516678654842743630526b7232783255465534684c4945434177454141614f42784443427754416442674e5648513445466751550a68537764436264724436454f4e6465715338744973743679564e5577675a4547413155644977534269544342686f415568537764436264724436454f4e6465710a5338744973743679564e5768593652684d463878437a414a42674e5642415954416c56544d52417744675944565151494577644762473979615752684d5134770a44415944565151484577565559573177595445504d4130474131554543684d4756474e7362476c694d517777436759445651514c45774e5355304578447a414e0a42674e5642414d54426c526c633352445159494a414a737074735166335458504d41774741315564457751464d414d42416638774451594a4b6f5a496876634e0a415145464251414467674542414c3755686f64683241545834497673477172795a644c566e4739546b4d6e396f3867653945557570597474392f392f4b2b4d790a647158434856754b774d59723556355335484151787754545134427950614c597a2b563864756d79424f645370356c3578354e574a2b326f436e2f44704c37550a39657a714c39677a45663541564c786967536f2f5635633475557045344b337462474844567046317a374f54364c4f706b765775693146704c516f446339484b0a426d54314a2b6651534866735363563635543671735141475055795258716837394c497259305a577644756e35787931334b6d436b33374763322b664378326d0a51454a467961434d6f6a7343664a7a325852744274776e386270426e4655503138376634736e6b553547612f35546a5147713659425032425752385733744d300a7a476b354b626f496c746a51536257394b595672617470462b67703365366e693942303d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a serial_number 11180668503388403151 signature bed4868761d804d7e08bec1aaaf265d2d59c6f5390c9fda3c81ef4452ea58b6df7ff7f2be33276a5c21d5b8ac0c62be55e52e47010c704d34380723da2d8cfe57c76e9b204e752a79979c7935627eda80a7fc3a4bed4f5ecea2fd83311fe4054bc62812a3f579738b94a44e0aded6c61c3569175cfb393e8b3a992f5ae8b51692d0a0373d1ca0664f527e7d04877ec49c57ae53eaab100063d4c915ea87bf4b22b634656bc3ba7e71cb5dca982937ec6736f9f0b1da6404245c9a08ca23b027c9cf65d1b41b709fc6e90671543f5f3b7f8b27914e466bfe538d01aae9804fd81591f16ded334cc693929ba0896d8d049b5bd29856b6ada45fa0a777ba9e2f41d signature_algo sha1WithRSAEncryption subject {C=US, ST=Florida, L=Tampa, O=Tcllib, OU=RSA, CN=TestCA} type rsa version 3}


test rsa-generate-cert-1.0 {cert} -setup {
    set fd [open [file join $::tcltest::testsDirectory test.key.des] r]
    set privkey [read $fd]
    close $fd ; unset fd

    set fd [open [file join $::tcltest::testsDirectory CA.crt] r]
    set cacert [read $fd]
    close $fd ; unset fd

    set fd [open [file join $::tcltest::testsDirectory CA.key] r]
    set cakey [read $fd]
    close $fd ; unset fd

    set password "ARoseIsARoseIsARose"

    set privkey [::pki::pkcs::parse_key $privkey $password]

    array set ca_arr [::pki::pkcs::parse_key $cakey $password]
    array set ca_arr [::pki::x509::parse_cert $cacert]
    set ca [array get ca_arr]

    set csr [::pki::pkcs::parse_csr [::pki::pkcs::create_csr $privkey [list C US ST Florida L Tampa O Tcllib OU RSA CN TestCert]]]
} -body {
    ::pki::x509::create_cert $csr $ca 20100809075203 1281340325 1596959525 0 "" 1
} -cleanup {
    unset privkey cakey cacert ca_arr ca password csr
} -result {-----BEGIN CERTIFICATE-----
MIIDOTCCAiECBhJIFZWqAzANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJVUzEQ
MA4GA1UECBMHRmxvcmlkYTEOMAwGA1UEBxMFVGFtcGExDzANBgNVBAoTBlRjbGxp
YjEMMAoGA1UECxMDUlNBMQ8wDQYDVQQDEwZUZXN0Q0EwHhcNMTAwODA5MDc1MjA1
WhcNMjAwODA5MDc1MjA1WjBhMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHRmxvcmlk
YTEOMAwGA1UEBxMFVGFtcGExDzANBgNVBAoTBlRjbGxpYjEMMAoGA1UECxMDUlNB
MREwDwYDVQQDEwhUZXN0Q2VydDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAKM8Foo94fHWhBvSd8w96CUGDIimy/wK4gfsIBPxIbGgrXMgFBSGc05m96XX
8qit7ryZjR+2KqZVss7tpnL1fRXL3uFwSeEh6S48Jq5WDeRaM6yk9vGZ3cF/u9/D
tEay9S0YZzcVmdT9fcaHOUoKrWixAJJl0vCKsObyfLi1uRMQOcYgH7ggltK+J8ZA
OpA3C3FwOKDBHACAMN1opgGJbhun5mjAnGiupzrTDrFyXwMqGk89qpEU3aQFwDFT
+/O1qfXk2M2aY48iQNy8gMQSTEoOh59NZpoX8wQY21lmAh8htUyiz37WygHMFvZk
fk1W24rdEYD7gPFSTmSIj54sA0sCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAesvQ
pYfxZj6KIbZfkWHwhDH0VNi5iPUvaNbVvZrZZ1R1gZAk8RycQN8gn7BaKX/6ciks
geKbvGwy5JvZaKSed6574QVTV+mGAqAxOW+LmURV+TaoWSKAC93DebdsL2NlPDsr
uuxMgb7fn52ni2qAslPo+YzecokIWDeyKvRUCD7Gt3LDdLQPG/jTx6Xnebb7usiF
pfqQWhFUdcfPik0Y3rfJG5bV5HuhKR9LxwI3Hxrt4LlSZIpolMXkwklqeoI0eIpy
kNJW5c2pm3cvQ/AZ3bHXWNBqH9A4Zf3OdizyKFD5lqqM3H2EQRXj0cUzQo2Wqf53
S6W6B4F2B2ZLa/O/Eg==
-----END CERTIFICATE-----
}

test rsa-generate-cacert-1.0 {cert} -setup {
    set fd [open [file join $::tcltest::testsDirectory test.key.des] r]
    set privkey [read $fd]
    close $fd ; unset fd

    set fd [open [file join $::tcltest::testsDirectory CA.crt] r]
    set cacert [read $fd]
    close $fd ; unset fd

    set fd [open [file join $::tcltest::testsDirectory CA.key] r]
    set cakey [read $fd]
    close $fd ; unset fd

    set password "ARoseIsARoseIsARose"

    set privkey [::pki::pkcs::parse_key $privkey $password]

    array set ca_arr [::pki::pkcs::parse_key $cakey $password]
    array set ca_arr [::pki::x509::parse_cert $cacert]
    set ca [array get ca_arr]

    set csr [::pki::pkcs::parse_csr [::pki::pkcs::create_csr $privkey [list C US ST Florida L Tampa O Tcllib OU RSA CN TestCert]]]
} -body {
    ::pki::x509::create_cert $csr $ca 20100809075203 1281340325 1596959525 1 "" 1
} -cleanup {
    unset privkey cakey cacert ca_arr ca password csr
} -result {-----BEGIN CERTIFICATE-----
MIIDUzCCAjugAwIBAgIGEkgVlaoDMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNVBAYT
AlVTMRAwDgYDVQQIEwdGbG9yaWRhMQ4wDAYDVQQHEwVUYW1wYTEPMA0GA1UEChMG
VGNsbGliMQwwCgYDVQQLEwNSU0ExDzANBgNVBAMTBlRlc3RDQTAeFw0xMDA4MDkw
NzUyMDVaFw0yMDA4MDkwNzUyMDVaMGExCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdG
bG9yaWRhMQ4wDAYDVQQHEwVUYW1wYTEPMA0GA1UEChMGVGNsbGliMQwwCgYDVQQL
EwNSU0ExETAPBgNVBAMTCFRlc3RDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAozwWij3h8daEG9J3zD3oJQYMiKbL/AriB+wgE/EhsaCtcyAUFIZz
Tmb3pdfyqK3uvJmNH7YqplWyzu2mcvV9Fcve4XBJ4SHpLjwmrlYN5FozrKT28Znd
wX+738O0RrL1LRhnNxWZ1P19xoc5SgqtaLEAkmXS8Iqw5vJ8uLW5ExA5xiAfuCCW
0r4nxkA6kDcLcXA4oMEcAIAw3WimAYluG6fmaMCcaK6nOtMOsXJfAyoaTz2qkRTd
pAXAMVP787Wp9eTYzZpjjyJA3LyAxBJMSg6Hn01mmhfzBBjbWWYCHyG1TKLPftbK
AcwW9mR+TVbbit0RgPuA8VJOZIiPniwDSwIDAQABoxMwETAPBgNVHRMBAf8EBTAD
AQH/MA0GCSqGSIb3DQEBBQUAA4IBAQA5nJ5k5HpGnBmDTB/cWd6LP7ygQ/jg9SEc
dVhSb6xy7h7O2txsndfH5fTyJilKRAfl/NGs5ZyV9q97OIP1aAhIRQiKUwSHu2+l
kHHVNn8DFGHRKhA5YSreZKR++tjAmowk0XQbEU33MZVPGPFlrL37V84Xf04MmFdD
kFtZO/soAzO8cPVizz3DNk7SNDCsWjmaTVH1yKmzBLJhrU86o4BEqbYbjbwdtelZ
cgeGPntr9c/ngnUlPU90HNp2e65zHUyf/3hWps72tSx5dNKcaE9NX8xxK5WZde8i
mn/PueMPCKdX1v9Nou51yReEa8D9h7D7klWwacrRoYh9Y4++g1by
-----END CERTIFICATE-----
}

test rsa-verify-certv1-1.0 {verify_cert} -setup {
    set fd [open [file join $::tcltest::testsDirectory test-v1.crt] r]
    set pubcert [read $fd]
    close $fd ; unset fd

    set fd [open [file join $::tcltest::testsDirectory CA.crt] r]
    set cacert [read $fd]
    close $fd ; unset fd

    set pubcert [::pki::x509::parse_cert $pubcert]
    set cacert [::pki::x509::parse_cert $cacert]
} -body {
    ::pki::x509::verify_cert $pubcert [list $cacert]
} -cleanup {
    unset pubcert cacert
} -result {true}

test rsa-verify-certv3-1.0 {verify_cert} -setup {
    set fd [open [file join $::tcltest::testsDirectory test-v3.crt] r]
    set pubcert [read $fd]
    close $fd ; unset fd

    set fd [open [file join $::tcltest::testsDirectory CA.crt] r]
    set cacert [read $fd]
    close $fd ; unset fd

    set pubcert [::pki::x509::parse_cert $pubcert]
    set cacert [::pki::x509::parse_cert $cacert]
} -body {
    ::pki::x509::verify_cert $pubcert [list $cacert]
} -cleanup {
    unset pubcert cacert
} -result {true}

test rsa-verify-badcertv1-1.0 {verify_cert} -setup {
    set fd [open [file join $::tcltest::testsDirectory test-v1.crt] r]
    set pubcert [read $fd]
    close $fd ; unset fd

    set fd [open [file join $::tcltest::testsDirectory test-v1.crt] r]
    set cacert [read $fd]
    close $fd ; unset fd

    set pubcert [::pki::x509::parse_cert $pubcert]
    set cacert [::pki::x509::parse_cert $cacert]
} -body {
    ::pki::x509::verify_cert $pubcert [list $cacert]
} -cleanup {
    unset pubcert cacert
} -result {false}

test rsa-verify-badcertv3-1.0 {verify_cert} -setup {
    set fd [open [file join $::tcltest::testsDirectory test-v3.crt] r]
    set pubcert [read $fd]
    close $fd ; unset fd

    set fd [open [file join $::tcltest::testsDirectory test-v3.crt] r]
    set cacert [read $fd]
    close $fd ; unset fd

    set pubcert [::pki::x509::parse_cert $pubcert]
    set cacert [::pki::x509::parse_cert $cacert]
} -body {
    ::pki::x509::verify_cert $pubcert [list $cacert]
} -cleanup {
    unset pubcert cacert
} -result {false}

test rsa-verify-badcertv3-2.0 {verify_cert} -setup {
    set fd [open [file join $::tcltest::testsDirectory test-v3.crt] r]
    set pubcert [read $fd]
    close $fd ; unset fd

    set fd [open [file join $::tcltest::testsDirectory CA.crt] r]
    set cacert [read $fd]
    close $fd ; unset fd

    set pubcert [::pki::x509::parse_cert $pubcert]
    set cacert [::pki::x509::parse_cert $cacert]

    # Remove all extensions from CA cert
    array set cacert_arr $cacert
    set cacert_arr(extensions) ""
    set cacert [array get cacert_arr]
} -body {
    ::pki::x509::verify_cert $pubcert [list $cacert]
} -cleanup {
    unset pubcert cacert
} -result {false}

test rsa-crypt-roundtrip-1.0 {encrypt, decrypt} -setup {
    set data      "This is a test"
    set password  "ARoseIsARoseIsARose"

    set fd [open [file join $::tcltest::testsDirectory test.key.des] r]
    set privkey [read $fd]
    close $fd ; unset fd

    set fd [open [file join $::tcltest::testsDirectory test-v1.crt] r]
    set pubkey [read $fd]
    close $fd ; unset fd

    array set key [::pki::pkcs::parse_key $privkey $password]
    array set key [::pki::x509::parse_cert $pubkey]
    set keylist   [array get key]
    unset password privkey pubkey key
} -body {
    set ciphertext [::pki::encrypt -binary -pub  -- $data       $keylist]
    set plaintext  [::pki::decrypt -binary -priv -- $ciphertext $keylist]
} -cleanup {
    unset -nocomplain data ciphertext plaintext
} -result {This is a test}

test rsa-sign-verify-1.0 {sign, verify} -setup {
    set data      "This is a test"
    set password  "ARoseIsARoseIsARose"

    set fd [open [file join $::tcltest::testsDirectory test.key.des] r]
    set privkey [read $fd]
    close $fd ; unset fd

    set fd [open [file join $::tcltest::testsDirectory test-v1.crt] r]
    set pubkey [read $fd]
    close $fd ; unset fd

    array set key [::pki::pkcs::parse_key $privkey $password]
    array set key [::pki::x509::parse_cert $pubkey]
    set keylist   [array get key]
    unset password privkey pubkey key
} -body {
    set ciphertext [::pki::encrypt -binary -priv -- $data       $keylist]
    set plaintext  [::pki::decrypt -binary -pub  -- $ciphertext $keylist]
} -cleanup {
    unset -nocomplain data ciphertext plaintext
} -result {This is a test}


foreach keylen {256 512 1024 2048} {

    # Just one key for the whole round and its tests. Its possible to
    # generate one for each test, but then we will really spend way to
    # much effort on the setup of each test.
    set key [::pki::rsa::generate $keylen]

    test rsa-crypt-roundtrip-2.0.$keylen "encrypt, decrypt pub/priv for keylen $keylen" -body {
        set plain    "Pub/priv test"







<
|
<
<





<
>


<
|
<
<





|


<
|
<
<

<


>
|


|
|
>
>
>
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
|
>
>
>
>
>
>
>

|
<
|
<




|

|
|
>
>
|
|
>
|
>
|
<
|
<

|
<
|
<
>

|

|
<
>

|
<
|
<
<
<
|
<
<
<
|
<
<








|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|




|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<

<
|
<
<
<
|
<
<









<
|
<
<
<
|
<
<









<
|
<
<
<
|
<
<









<
|
<
<
<
|
<
<









<
|
<
<
<
|
<
<
















<
<
|
<
<
<
|
<















<
<
|
<
<
<
|
<














<







25
26
27
28
29
30
31

32


33
34
35
36
37

38
39
40

41


42
43
44
45
46
47
48
49

50


51

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66











67
68
69
70
71
72
73
74
75
76

77

78
79
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
testing {
    useLocal pki.tcl pki
}

# -------------------------------------------------------------------------

test rsa-parse-aeskey-1.0 {parse_key} -setup {

    set privkey [asset-get test.key.aes]


    set password "ARoseIsARoseIsARose"
} -body {
    dictsort [::pki::pkcs::parse_key $privkey $password]
} -cleanup {
    unset privkey password

} -result [asset-get result/aes-key]

test rsa-parse-deskey-1.0 {parse_key} -setup {

    set privkey [asset-get test.key.des]


    set password "ARoseIsARoseIsARose"
} -body {
    dictsort [::pki::pkcs::parse_key $privkey $password]
} -cleanup {
    unset privkey password
} -result [asset-get result/des-key]

test rsa-generate-csr-1.0 {csr} -setup {

    set privkey [asset-get test.key.des]


    set password "ARoseIsARoseIsARose"

    set privkey [::pki::pkcs::parse_key $privkey $password]
} -body {
    ::pki::pkcs::create_csr $privkey \
        [list C US ST Florida L Tampa O Tcllib OU RSA CN TestCert] 1
} -cleanup {
    unset privkey password
} -result [asset-get result/des-csr]

test rsa-parse-certv1-1.0 {parse_cert} -setup {
    set pubkey [asset-get test-v1.crt]
} -body {
    dictsort [::pki::x509::parse_cert $pubkey]
} -cleanup {
    unset pubkey
} -result [asset-get result/cert1]












test rsa-parse-certv3-1.0 {parse_cert} -setup {
    set pubkey [asset-get test-v3.crt]
} -body {
    dictsort [::pki::x509::parse_cert $pubkey]
} -cleanup {
    unset pubkey
} -result [asset-get result/cert3]

test rsa-parse-cacert-1.0 {parse_cert} -setup {

    set pubkey [asset-get CA.crt]

} -body {
    dictsort [::pki::x509::parse_cert $pubkey]
} -cleanup {
    unset pubkey
} -result [asset-get result/certCA]

test rsa-generate-cert-1.0 {cert} -setup {
    set privkey [asset-get test.key.des]
    set cacert  [asset-get CA.crt]
    set cakey   [asset-get CA.key]
    set password "ARoseIsARoseIsARose"

    set privkey [::pki::pkcs::parse_key $privkey $password]

    array set ca_arr [::pki::pkcs::parse_key $cakey $password]
    array set ca_arr [::pki::x509::parse_cert $cacert]

    set ca [array get ca_arr]


    set csr [::pki::pkcs::parse_csr \

                 [::pki::pkcs::create_csr $privkey \

                      [list C US ST Florida L Tampa O Tcllib OU RSA CN TestCert]]]
} -body {
    ::pki::x509::create_cert $csr $ca 20100809075203 1281340325 1596959525 0 "" 1
} -cleanup {
    unset privkey cakey cacert ca_arr ca password csr

} -result [asset-get result/cert]

test rsa-generate-cacert-1.0 {cert} -setup {

    set privkey [asset-get test.key.des]



    set cacert  [asset-get CA.crt]



    set cakey   [asset-get CA.key]


    set password "ARoseIsARoseIsARose"

    set privkey [::pki::pkcs::parse_key $privkey $password]

    array set ca_arr [::pki::pkcs::parse_key $cakey $password]
    array set ca_arr [::pki::x509::parse_cert $cacert]
    set ca [array get ca_arr]

    set csr [::pki::pkcs::parse_csr \

























                 [::pki::pkcs::create_csr $privkey \





















                      [list C US ST Florida L Tampa O Tcllib OU RSA CN TestCert]]]
} -body {
    ::pki::x509::create_cert $csr $ca 20100809075203 1281340325 1596959525 1 "" 1
} -cleanup {
    unset privkey cakey cacert ca_arr ca password csr
} -result [asset-get result/cert-b]





















test rsa-verify-certv1-1.0 {verify_cert} -setup {

    set pubcert [asset-get test-v1.crt]



    set cacert [asset-get CA.crt]


    set pubcert [::pki::x509::parse_cert $pubcert]
    set cacert [::pki::x509::parse_cert $cacert]
} -body {
    ::pki::x509::verify_cert $pubcert [list $cacert]
} -cleanup {
    unset pubcert cacert
} -result {true}

test rsa-verify-certv3-1.0 {verify_cert} -setup {

    set pubcert [asset-get test-v3.crt]



    set cacert [asset-get CA.crt]


    set pubcert [::pki::x509::parse_cert $pubcert]
    set cacert [::pki::x509::parse_cert $cacert]
} -body {
    ::pki::x509::verify_cert $pubcert [list $cacert]
} -cleanup {
    unset pubcert cacert
} -result {true}

test rsa-verify-badcertv1-1.0 {verify_cert} -setup {

    set pubcert [asset-get test-v1.crt]



    set cacert [asset-get test-v1.crt]


    set pubcert [::pki::x509::parse_cert $pubcert]
    set cacert [::pki::x509::parse_cert $cacert]
} -body {
    ::pki::x509::verify_cert $pubcert [list $cacert]
} -cleanup {
    unset pubcert cacert
} -result {false}

test rsa-verify-badcertv3-1.0 {verify_cert} -setup {

    set pubcert [asset-get test-v3.crt]



    set cacert [asset-get test-v3.crt]


    set pubcert [::pki::x509::parse_cert $pubcert]
    set cacert [::pki::x509::parse_cert $cacert]
} -body {
    ::pki::x509::verify_cert $pubcert [list $cacert]
} -cleanup {
    unset pubcert cacert
} -result {false}

test rsa-verify-badcertv3-2.0 {verify_cert} -setup {

    set pubcert [asset-get test-v3.crt]



    set cacert [asset-get CA.crt]


    set pubcert [::pki::x509::parse_cert $pubcert]
    set cacert [::pki::x509::parse_cert $cacert]

    # Remove all extensions from CA cert
    array set cacert_arr $cacert
    set cacert_arr(extensions) ""
    set cacert [array get cacert_arr]
} -body {
    ::pki::x509::verify_cert $pubcert [list $cacert]
} -cleanup {
    unset pubcert cacert
} -result {false}

test rsa-crypt-roundtrip-1.0 {encrypt, decrypt} -setup {
    set data      "This is a test"
    set password  "ARoseIsARoseIsARose"


    set privkey [asset-get test.key.des]



    set pubkey [asset-get test-v1.crt]


    array set key [::pki::pkcs::parse_key $privkey $password]
    array set key [::pki::x509::parse_cert $pubkey]
    set keylist   [array get key]
    unset password privkey pubkey key
} -body {
    set ciphertext [::pki::encrypt -binary -pub  -- $data       $keylist]
    set plaintext  [::pki::decrypt -binary -priv -- $ciphertext $keylist]
} -cleanup {
    unset -nocomplain data ciphertext plaintext
} -result {This is a test}

test rsa-sign-verify-1.0 {sign, verify} -setup {
    set data      "This is a test"
    set password  "ARoseIsARoseIsARose"


    set privkey [asset-get test.key.des]



    set pubkey [asset-get test-v1.crt]


    array set key [::pki::pkcs::parse_key $privkey $password]
    array set key [::pki::x509::parse_cert $pubkey]
    set keylist   [array get key]
    unset password privkey pubkey key
} -body {
    set ciphertext [::pki::encrypt -binary -priv -- $data       $keylist]
    set plaintext  [::pki::decrypt -binary -pub  -- $ciphertext $keylist]
} -cleanup {
    unset -nocomplain data ciphertext plaintext
} -result {This is a test}


foreach keylen {256 512 1024 2048} {

    # Just one key for the whole round and its tests. Its possible to
    # generate one for each test, but then we will really spend way to
    # much effort on the setup of each test.
    set key [::pki::rsa::generate $keylen]

    test rsa-crypt-roundtrip-2.0.$keylen "encrypt, decrypt pub/priv for keylen $keylen" -body {
        set plain    "Pub/priv test"
392
393
394
395
396
397
398
399
400
401
402
403
    }

    unset key
}

# -------------------------------------------------------------------------
testsuiteCleanup

# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End:







|




261
262
263
264
265
266
267
268
269
270
271
272
    }

    unset key
}

# -------------------------------------------------------------------------
testsuiteCleanup
return
# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End:

Added modules/pki/test-assets/CA.crt.

















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-----BEGIN CERTIFICATE-----
MIIEBjCCAu6gAwIBAgIJAJsptsQf3TXPMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV
BAYTAlVTMRAwDgYDVQQIEwdGbG9yaWRhMQ4wDAYDVQQHEwVUYW1wYTEPMA0GA1UE
ChMGVGNsbGliMQwwCgYDVQQLEwNSU0ExDzANBgNVBAMTBlRlc3RDQTAeFw0xMDA4
MDkwNzM3MzhaFw0zNTA4MTAwNzM3MzhaMF8xCzAJBgNVBAYTAlVTMRAwDgYDVQQI
EwdGbG9yaWRhMQ4wDAYDVQQHEwVUYW1wYTEPMA0GA1UEChMGVGNsbGliMQwwCgYD
VQQLEwNSU0ExDzANBgNVBAMTBlRlc3RDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAL9llE7rpNUW+YI8rdQgoG40E/FMMu2h9/6pVzCtILqOLFlSMSIQ
4CxKhIzPuiP+BSufNXmeMXSueifuT2mlb5ap6T2tmd5Vi09um5xw3Spu2Juz7Zfj
LDFnsMxuF3U4Qwl/9qEydmhtDnYATC8iRicXsPGvNVeTZgX3iZzzA3uFkD6NVEki
X1X3MgmE8eCGTw4U/k3MIK7wPQtZMSO4Aey9I/ub5ieZrAK0yZLjiubP27gb8ZIJ
wK2EXI2lZZH6g8JML7RwW5Yr0VoczEf79wKAUi15xQKfh+gxVzTnuKgdJ/ZMyzcW
+Pdap1YlHfewQfxeHBt60Rkr2x2UFU4hLIECAwEAAaOBxDCBwTAdBgNVHQ4EFgQU
hSwdCbdrD6EONdeqS8tIst6yVNUwgZEGA1UdIwSBiTCBhoAUhSwdCbdrD6EONdeq
S8tIst6yVNWhY6RhMF8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdGbG9yaWRhMQ4w
DAYDVQQHEwVUYW1wYTEPMA0GA1UEChMGVGNsbGliMQwwCgYDVQQLEwNSU0ExDzAN
BgNVBAMTBlRlc3RDQYIJAJsptsQf3TXPMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN
AQEFBQADggEBAL7Uhodh2ATX4IvsGqryZdLVnG9TkMn9o8ge9EUupYtt9/9/K+My
dqXCHVuKwMYr5V5S5HAQxwTTQ4ByPaLYz+V8dumyBOdSp5l5x5NWJ+2oCn/DpL7U
9ezqL9gzEf5AVLxigSo/V5c4uUpE4K3tbGHDVpF1z7OT6LOpkvWui1FpLQoDc9HK
BmT1J+fQSHfsScV65T6qsQAGPUyRXqh79LIrY0ZWvDun5xy13KmCk37Gc2+fCx2m
QEJFyaCMojsCfJz2XRtBtwn8bpBnFUP187f4snkU5Ga/5TjQGq6YBP2BWR8W3tM0
zGk5KboIltjQSbW9KYVratpF+gp3e6ni9B0=
-----END CERTIFICATE-----

Added modules/pki/test-assets/CA.key.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,8C1A2E69ACFC3E90

GVnzdBMa+GX2u4jOpSYU6P1JBQYbB9FRrfB/0QGdhKHU2OPEZzYZo2LwgpEBVMWT
dVsbBECil4h0UnUsC/+DmJPv/SF++VJK8JvtO2opNCmeYrH5VAwqN2tqIXX2sWng
9Fk7HVjsLfTUvw6nc5TI07qK2okGcT9yMTjEGXKPLkMs5K16gKoMHf5yQPQmOpfR
HrE8odoPib1JKDV9j4FYjfBEja7Y4GLFbNobvaQIvA/pbKE4mGkGczn6vjdkGTbv
wAI0fIWqfOnfE+VlSz9lT4mOVHt6x4WQbfUgJKf29pL9DH+I22K2cgzGwMLzLot3
IhPiO6coFfLOKKNbRv4gtxTjXvnlwm217GDoEPgDKG1qwWzjSwI8DBsLjMhKHDfz
0ScyItR3wkTVaTE0sQYFS5VmKzgH2rQ8ichk4AUzM5+myxg1ALKi9GRtIKKbY+0H
EseYxzbRhTSVo0GPGiu8j6BVK40uynF4ydrjlETQsJhZZTeJPjPGNh6m3eP5zW0Q
Im8UgW6ZZumzINJPrEKrwRF7qEGSLRv3lkMOj08sYFsSqFnBex90cov1pJOUCCAL
mBgLFFb6P9kEAqZOnNcwrohcf8gmW1pATTgT1+y0OTC1rEJ+asvCn6yN2QkhyNqq
vabFqxyWxVi9MsodP4+eY9Hjhl5WwkuVCnBG69HugOFvVKHIpGxfQjSnQNaYfI6a
UKLixw0ZdfWN8sNG4gcisj/O/VHKbEWwp+N452lTzzFE7+QvCtg6rn+LPLEyTZRb
b7QQc6CcqELL4qksm/FNP8pIyGfsUKYVE79FDK+mxDxZpWEMJ6J6dwj1jwzGbMnP
5sgmAeaSinkqUQf/4AoiU1eIj1fiXHcsub7mFzzBP9NKQZ4YrkBeu7zfsP8Ex5Ol
W3WmKIkw2MBG9Q0dP3HQBDw5k35X5ydJvrtaRJLDZZDwA24WcyKffYUHGV4KhsxC
Vjzkth+MkBaPAtB35tRlr1Fr0wC6MNTeZOuPNgGM+t1ejg1NPN722J+ihne05KW/
wzBgz3veeJeUlxRPZl0Sklct029fV+pZGwxlx72hMiyBwDh9pBhmIjWJFzuQ35CG
DNZm1spGcDU9sd1y1txS+QVd3CDP7a5CrUuI7S8FYJEREGzWGn/dF9hxrbeLLXRf
qvcUwCAobFfV14Z1cwoxZ9MWTXBYynxUYO7TYajb/6vIvYOAQ3DGSPelvNRsrilT
GV0CJ1Mx6JEaTzGQQeB2JxO09T0qxKMT6h4BbLhZRledmrI/Pvp/roUmnvdE3kBn
MkRUxzGBD9EBPA02F2paDRxXPZRHvpGomvP32JL7AJ8tln8z4TsHclpls0E7dmk9
KKQSLk1DOUjarJhPHmGyDOn9tVdgzbfyQjdmZ1wxBvYbBuqS82FcoWohF2GnyYAm
X7tdS9AVNDErVXOmqh2hcYFY3NFBLy0altpMaTVqTx1SwkpHh6YGt9ioltzP7kxz
wxHz/w4DPrxaUOFYZX9dffGceFf5/h2DfhqobnwZuCgDo7SDUKJI0f88bR+1d1q6
qr2T9ZuzIPIllMzGVfNwq5WsPy+klq/lK0QRl6RZdLEM0Q5h6WOYeoxpOGjW6E1h
-----END RSA PRIVATE KEY-----

Added modules/pki/test-assets/result/aes-key.



>
1
d 4821708078078814272825737770757352316921506482526873519719051463644222257651923197825994018656421190278177720014932984365118366602027256382375921341192781177112398174373076887129954817822368157304055327895506098881228521168940083073283595671416028753301552269895847121119899618677892849270785450525228277087545852904246091363590456069440574806479467479724488815982259021323617233373449030738298588184972148901173121148634892058648703349014218791530847767762515588159636682267580355756974401553230588009724381821442787415368995149629493809933380894522643851913309510865914033228986295772184835354265231482340110365953 e 65537 l 2048 n 20606474229739240365059039861892702888430699076971875439310562489263214483191006887246310401088091004060054335612563612411917991000786455919906798626524375611634511845705141177165689526939976649836053082770641226108840795034158866930145876068965913035873741839723777813944236146677082729876717709231945588228947001753667862858297850461440476551869914895980840772354759428144421149613554402682425181850295101375623815063198594704730226304723548382258248785251384891817576645955371924194287071569929361029204431671633821160423187871463713776212876252047207985933876036458343140423787003660018607222053134170461225878347 p 151903506703070744388477144011062627922344490485619606525415439019240332914406492743669447033002173681213181316912563402042948038453846038272948559137687751740338183189809253891948725876860938554446847405802064303332011747457634488959045893106143553864597546566768167692662722957924358908573096347694362541259 q 135655026516400219835182288872064651548166413404981613626584975073279765274581289299963783472100901444904090497633607380440126562041149560121122191822729803838692049608052805597752016733559257401832457990520641184379220785155858496800358974243933025297673311305372951490297748845447521569920828454777048335233 type rsa

Added modules/pki/test-assets/result/cert.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-----BEGIN CERTIFICATE-----
MIIDOTCCAiECBhJIFZWqAzANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJVUzEQ
MA4GA1UECBMHRmxvcmlkYTEOMAwGA1UEBxMFVGFtcGExDzANBgNVBAoTBlRjbGxp
YjEMMAoGA1UECxMDUlNBMQ8wDQYDVQQDEwZUZXN0Q0EwHhcNMTAwODA5MDc1MjA1
WhcNMjAwODA5MDc1MjA1WjBhMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHRmxvcmlk
YTEOMAwGA1UEBxMFVGFtcGExDzANBgNVBAoTBlRjbGxpYjEMMAoGA1UECxMDUlNB
MREwDwYDVQQDEwhUZXN0Q2VydDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAKM8Foo94fHWhBvSd8w96CUGDIimy/wK4gfsIBPxIbGgrXMgFBSGc05m96XX
8qit7ryZjR+2KqZVss7tpnL1fRXL3uFwSeEh6S48Jq5WDeRaM6yk9vGZ3cF/u9/D
tEay9S0YZzcVmdT9fcaHOUoKrWixAJJl0vCKsObyfLi1uRMQOcYgH7ggltK+J8ZA
OpA3C3FwOKDBHACAMN1opgGJbhun5mjAnGiupzrTDrFyXwMqGk89qpEU3aQFwDFT
+/O1qfXk2M2aY48iQNy8gMQSTEoOh59NZpoX8wQY21lmAh8htUyiz37WygHMFvZk
fk1W24rdEYD7gPFSTmSIj54sA0sCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAesvQ
pYfxZj6KIbZfkWHwhDH0VNi5iPUvaNbVvZrZZ1R1gZAk8RycQN8gn7BaKX/6ciks
geKbvGwy5JvZaKSed6574QVTV+mGAqAxOW+LmURV+TaoWSKAC93DebdsL2NlPDsr
uuxMgb7fn52ni2qAslPo+YzecokIWDeyKvRUCD7Gt3LDdLQPG/jTx6Xnebb7usiF
pfqQWhFUdcfPik0Y3rfJG5bV5HuhKR9LxwI3Hxrt4LlSZIpolMXkwklqeoI0eIpy
kNJW5c2pm3cvQ/AZ3bHXWNBqH9A4Zf3OdizyKFD5lqqM3H2EQRXj0cUzQo2Wqf53
S6W6B4F2B2ZLa/O/Eg==
-----END CERTIFICATE-----

Added modules/pki/test-assets/result/cert-b.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-----BEGIN CERTIFICATE-----
MIIDUzCCAjugAwIBAgIGEkgVlaoDMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNVBAYT
AlVTMRAwDgYDVQQIEwdGbG9yaWRhMQ4wDAYDVQQHEwVUYW1wYTEPMA0GA1UEChMG
VGNsbGliMQwwCgYDVQQLEwNSU0ExDzANBgNVBAMTBlRlc3RDQTAeFw0xMDA4MDkw
NzUyMDVaFw0yMDA4MDkwNzUyMDVaMGExCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdG
bG9yaWRhMQ4wDAYDVQQHEwVUYW1wYTEPMA0GA1UEChMGVGNsbGliMQwwCgYDVQQL
EwNSU0ExETAPBgNVBAMTCFRlc3RDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAozwWij3h8daEG9J3zD3oJQYMiKbL/AriB+wgE/EhsaCtcyAUFIZz
Tmb3pdfyqK3uvJmNH7YqplWyzu2mcvV9Fcve4XBJ4SHpLjwmrlYN5FozrKT28Znd
wX+738O0RrL1LRhnNxWZ1P19xoc5SgqtaLEAkmXS8Iqw5vJ8uLW5ExA5xiAfuCCW
0r4nxkA6kDcLcXA4oMEcAIAw3WimAYluG6fmaMCcaK6nOtMOsXJfAyoaTz2qkRTd
pAXAMVP787Wp9eTYzZpjjyJA3LyAxBJMSg6Hn01mmhfzBBjbWWYCHyG1TKLPftbK
AcwW9mR+TVbbit0RgPuA8VJOZIiPniwDSwIDAQABoxMwETAPBgNVHRMBAf8EBTAD
AQH/MA0GCSqGSIb3DQEBBQUAA4IBAQA5nJ5k5HpGnBmDTB/cWd6LP7ygQ/jg9SEc
dVhSb6xy7h7O2txsndfH5fTyJilKRAfl/NGs5ZyV9q97OIP1aAhIRQiKUwSHu2+l
kHHVNn8DFGHRKhA5YSreZKR++tjAmowk0XQbEU33MZVPGPFlrL37V84Xf04MmFdD
kFtZO/soAzO8cPVizz3DNk7SNDCsWjmaTVH1yKmzBLJhrU86o4BEqbYbjbwdtelZ
cgeGPntr9c/ngnUlPU90HNp2e65zHUyf/3hWps72tSx5dNKcaE9NX8xxK5WZde8i
mn/PueMPCKdX1v9Nou51yReEa8D9h7D7klWwacrRoYh9Y4++g1by
-----END CERTIFICATE-----

Added modules/pki/test-assets/result/cert1.



>
1
cert 30820221020612481595aa03300d06092a864886f70d0101050500305f310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b1303525341310f300d06035504031306546573744341301e170d3130303830393037353230355a170d3230303830393037353230355a3061310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b13035253413111300f06035504031308546573744365727430820122300d06092a864886f70d01010105000382010f003082010a0282010100a33c168a3de1f1d6841bd277cc3de825060c88a6cbfc0ae207ec2013f121b1a0ad7320141486734e66f7a5d7f2a8adeebc998d1fb62aa655b2ceeda672f57d15cbdee17049e121e92e3c26ae560de45a33aca4f6f199ddc17fbbdfc3b446b2f52d1867371599d4fd7dc687394a0aad68b1009265d2f08ab0e6f27cb8b5b9131039c6201fb82096d2be27c6403a90370b717038a0c11c008030dd68a601896e1ba7e668c09c68aea73ad30eb1725f032a1a4f3daa9114dda405c03153fbf3b5a9f5e4d8cd9a638f2240dcbc80c4124c4a0e879f4d669a17f30418db5966021f21b54ca2cf7ed6ca01cc16f6647e4d56db8add1180fb80f1524e64888f9e2c034b0203010001 data_signature_algo sha1WithRSAEncryption e 65537 extensions {} issuer {C=US, ST=Florida, L=Tampa, O=Tcllib, OU=RSA, CN=TestCA} l 2048 n 20606474229739240365059039861892702888430699076971875439310562489263214483191006887246310401088091004060054335612563612411917991000786455919906798626524375611634511845705141177165689526939976649836053082770641226108840795034158866930145876068965913035873741839723777813944236146677082729876717709231945588228947001753667862858297850461440476551869914895980840772354759428144421149613554402682425181850295101375623815063198594704730226304723548382258248785251384891817576645955371924194287071569929361029204431671633821160423187871463713776212876252047207985933876036458343140423787003660018607222053134170461225878347 notAfter 1596959525 notBefore 1281340325 pubkey 3082010a0282010100a33c168a3de1f1d6841bd277cc3de825060c88a6cbfc0ae207ec2013f121b1a0ad7320141486734e66f7a5d7f2a8adeebc998d1fb62aa655b2ceeda672f57d15cbdee17049e121e92e3c26ae560de45a33aca4f6f199ddc17fbbdfc3b446b2f52d1867371599d4fd7dc687394a0aad68b1009265d2f08ab0e6f27cb8b5b9131039c6201fb82096d2be27c6403a90370b717038a0c11c008030dd68a601896e1ba7e668c09c68aea73ad30eb1725f032a1a4f3daa9114dda405c03153fbf3b5a9f5e4d8cd9a638f2240dcbc80c4124c4a0e879f4d669a17f30418db5966021f21b54ca2cf7ed6ca01cc16f6647e4d56db8add1180fb80f1524e64888f9e2c034b0203010001 pubkey_algo rsaEncryption raw 2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d4949444f5443434169454342684a49465a5771417a414e42676b71686b69473977304241515546414442664d517377435159445651514745774a56557a45510a4d4134474131554543424d48526d7876636d6c6b5954454f4d4177474131554542784d465647467463474578447a414e42674e5642416f54426c526a624778700a596a454d4d416f474131554543784d44556c4e424d513877445159445651514445775a555a584e30513045774868634e4d5441774f4441354d4463314d6a41310a5768634e4d6a41774f4441354d4463314d6a4131576a42684d517377435159445651514745774a56557a45514d4134474131554543424d48526d7876636d6c6b0a5954454f4d4177474131554542784d465647467463474578447a414e42674e5642416f54426c526a62477870596a454d4d416f474131554543784d44556c4e420a4d5245774477594456515144457768555a584e305132567964444343415349774451594a4b6f5a496876634e4151454242514144676745504144434341516f430a67674542414b4d38466f6f39346648576842765364387739364355474449696d792f774b34676673494250784962476772584d67464253476330356d393658580a387169743772795a6a522b324b715a5673733774706e4c316652584c3375467753654568365334384a713557446552614d36796b3976475a3363462f75392f440a74456179395330595a7a63566d645439666361484f556f4b72576978414a4a6c3076434b734f6279664c693175524d514f635967483767676c744b2b4a385a410a4f704133433346774f4b4442484143414d4e316f7067474a6268756e356d6a416e476975707a72544472467958774d71476b38397170455533615146774446540a2b2f4f317166586b324d326159343869514e7938674d515354456f4f6835394e5a706f583877515932316c6d41683868745579697a3337577967484d46765a6b0a666b3157323472644559443767504653546d53496a35347341307343417745414154414e42676b71686b6947397730424151554641414f4341514541657376510a705966785a6a364b49625a666b57487768444830564e693569505576614e6256765a725a5a315231675a416b38527963514e38676e3742614b582f3663696b730a67654b6276477779354a765a614b53656436353734515654562b6d47417141784f572b4c6d5552562b54616f57534b4143393344656264734c324e6c504473720a7575784d676237666e35326e69327141736c506f2b597a65636f6b49574465794b7652554344374774334c44644c5150472f6a547836586e65626237757369460a706671515768465564636650696b30593372664a47356256354875684b52394c7877493348787274344c6c535a49706f6c4d586b776b6c71656f4930654970790a6b4e4a57356332706d336376512f415a33624858574e4271483941345a66334f64697a794b4644356c71714d334832455152586a3063557a516f3257716635330a533657364234463242325a4c612f4f2f45673d3d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a serial_number 20100809075203 signature 7acbd0a587f1663e8a21b65f9161f08431f454d8b988f52f68d6d5bd9ad9675475819024f11c9c40df209fb05a297ffa72292c81e29bbc6c32e49bd968a49e77ae7be1055357e98602a031396f8b994455f936a85922800bddc379b76c2f63653c3b2bbaec4c81bedf9f9da78b6a80b253e8f98cde7289085837b22af454083ec6b772c374b40f1bf8d3c7a5e779b6fbbac885a5fa905a115475c7cf8a4d18deb7c91b96d5e47ba1291f4bc702371f1aede0b952648a6894c5e4c2496a7a8234788a7290d256e5cda99b772f43f019ddb1d758d06a1fd03865fdce762cf22850f996aa8cdc7d844115e3d1c533428d96a9fe774ba5ba07817607664b6bf3bf12 signature_algo sha1WithRSAEncryption subject {C=US, ST=Florida, L=Tampa, O=Tcllib, OU=RSA, CN=TestCert} type rsa version 1

Added modules/pki/test-assets/result/cert3.



>
1
cert 30820226a003020102020612481595a9c0300d06092a864886f70d0101050500305f310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b1303525341310f300d06035504031306546573744341301e170d3130303830393037353133365a170d3230303830393037353133365a3061310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b13035253413111300f06035504031308546573744365727430820122300d06092a864886f70d01010105000382010f003082010a0282010100a33c168a3de1f1d6841bd277cc3de825060c88a6cbfc0ae207ec2013f121b1a0ad7320141486734e66f7a5d7f2a8adeebc998d1fb62aa655b2ceeda672f57d15cbdee17049e121e92e3c26ae560de45a33aca4f6f199ddc17fbbdfc3b446b2f52d1867371599d4fd7dc687394a0aad68b1009265d2f08ab0e6f27cb8b5b9131039c6201fb82096d2be27c6403a90370b717038a0c11c008030dd68a601896e1ba7e668c09c68aea73ad30eb1725f032a1a4f3daa9114dda405c03153fbf3b5a9f5e4d8cd9a638f2240dcbc80c4124c4a0e879f4d669a17f30418db5966021f21b54ca2cf7ed6ca01cc16f6647e4d56db8add1180fb80f1524e64888f9e2c034b0203010001 data_signature_algo sha1WithRSAEncryption e 65537 extensions {} issuer {C=US, ST=Florida, L=Tampa, O=Tcllib, OU=RSA, CN=TestCA} l 2048 n 20606474229739240365059039861892702888430699076971875439310562489263214483191006887246310401088091004060054335612563612411917991000786455919906798626524375611634511845705141177165689526939976649836053082770641226108840795034158866930145876068965913035873741839723777813944236146677082729876717709231945588228947001753667862858297850461440476551869914895980840772354759428144421149613554402682425181850295101375623815063198594704730226304723548382258248785251384891817576645955371924194287071569929361029204431671633821160423187871463713776212876252047207985933876036458343140423787003660018607222053134170461225878347 notAfter 1596959496 notBefore 1281340296 pubkey 3082010a0282010100a33c168a3de1f1d6841bd277cc3de825060c88a6cbfc0ae207ec2013f121b1a0ad7320141486734e66f7a5d7f2a8adeebc998d1fb62aa655b2ceeda672f57d15cbdee17049e121e92e3c26ae560de45a33aca4f6f199ddc17fbbdfc3b446b2f52d1867371599d4fd7dc687394a0aad68b1009265d2f08ab0e6f27cb8b5b9131039c6201fb82096d2be27c6403a90370b717038a0c11c008030dd68a601896e1ba7e668c09c68aea73ad30eb1725f032a1a4f3daa9114dda405c03153fbf3b5a9f5e4d8cd9a638f2240dcbc80c4124c4a0e879f4d669a17f30418db5966021f21b54ca2cf7ed6ca01cc16f6647e4d56db8add1180fb80f1524e64888f9e2c034b0203010001 pubkey_algo rsaEncryption raw 2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d494944506a4343416961674177494241674947456b67566c616e414d413047435371475349623344514542425155414d463878437a414a42674e56424159540a416c56544d52417744675944565151494577644762473979615752684d51347744415944565151484577565559573177595445504d4130474131554543684d470a56474e7362476c694d517777436759445651514c45774e5355304578447a414e42674e5642414d54426c526c6333524451544165467730784d4441344d446b770a4e7a55784d7a5a61467730794d4441344d446b774e7a55784d7a5a614d474578437a414a42674e5642415954416c56544d5241774467594456515149457764470a62473979615752684d51347744415944565151484577565559573177595445504d4130474131554543684d4756474e7362476c694d517777436759445651514c0a45774e53553045784554415042674e5642414d544346526c633352445a584a304d494942496a414e42676b71686b6947397730424151454641414f43415138410a4d49494243674b43415145416f7a7757696a33683864614547394a337a44336f4a51594d694b624c2f417269422b7767452f4568736143746379415546495a7a0a546d623370646679714b3375764a6d4e48375971706c57797a75326d63765639466376653458424a345348704c6a776d726c594e35466f7a724b5432385a6e640a77582b3733384f3052724c314c52686e4e78575a31503139786f633553677174614c45416b6d58533849717735764a38754c57354578413578694166754343570a3072346e786b41366b44634c635841346f4d4563414941773357696d41596c754736666d614d4363614b366e4f744d4f73584a6641796f61547a32716b5254640a704158414d56503738375770396554597a5a706a6a794a41334c794178424a4d536736486e30316d6d68667a42426a625757594348794731544b4c506674624b0a41637757396d522b54566262697430526750754138564a4f5a4969506e69774453774944415141424d41304743537147534962334451454242515541413449420a41514177454673454441306d70346d516d4f596263345248515645474e3732334374676345484637756e75343345654f35732f31597130462b5364575231344c0a714673366c52586e506a6b457049466c6d573549304470385131795931387152507438487836796d7874793851576d396c54774d427a7259556839344a71562b0a593351484a625672674c706f4b527073564f7073644d3571513465667651774f30734f77493541616a766b795531644338547378417a794a4d51664b2b5751730a41306c5370714d304874726c31785268445a774543384245332b374976394d53572f52764b364661614f466b796a766657664f4c67526652744d51382b6864560a385261534571716b5373676c477a6d7a53627554486f70426b6c65314b6567713248642f316c706939466f58487247786a7747575677354b4f77574f4361304f0a7946344b5757696a4d4f57624d7249714c71357034614f6b0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a serial_number 20100809075136 signature 30105b040c0d26a7899098e61b73844741510637bdb70ad81c10717bba7bb8dc478ee6cff562ad05f92756475e0ba85b3a9515e73e3904a48165996e48d03a7c435c98d7ca913edf07c7aca6c6dcbc4169bd953c0c073ad8521f7826a57e63740725b56b80ba68291a6c54ea6c74ce6a43879fbd0c0ed2c3b023901a8ef932535742f13b31033c893107caf9642c034952a6a3341edae5d714610d9c040bc044dfeec8bfd3125bf46f2ba15a68e164ca3bdf59f38b8117d1b4c43cfa1755f1169212aaa44ac8251b39b349bb931e8a419257b529e82ad8777fd65a62f45a171eb1b18f0196570e4a3b058e09ad0ec85e0a5968a330e59b32b22a2eae69e1a3a4 signature_algo sha1WithRSAEncryption subject {C=US, ST=Florida, L=Tampa, O=Tcllib, OU=RSA, CN=TestCert} type rsa version 3

Added modules/pki/test-assets/result/certCA.



>
1
cert 308202eea0030201020209009b29b6c41fdd35cf300d06092a864886f70d0101050500305f310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b1303525341310f300d06035504031306546573744341301e170d3130303830393037333733385a170d3335303831303037333733385a305f310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b1303525341310f300d0603550403130654657374434130820122300d06092a864886f70d01010105000382010f003082010a0282010100bf65944eeba4d516f9823cadd420a06e3413f14c32eda1f7fea95730ad20ba8e2c5952312210e02c4a848ccfba23fe052b9f35799e3174ae7a27ee4f69a56f96a9e93dad99de558b4f6e9b9c70dd2a6ed89bb3ed97e32c3167b0cc6e17753843097ff6a13276686d0e76004c2f22462717b0f1af3557936605f7899cf3037b85903e8d5449225f55f7320984f1e0864f0e14fe4dcc20aef03d0b593123b801ecbd23fb9be62799ac02b4c992e38ae6cfdbb81bf19209c0ad845c8da56591fa83c24c2fb4705b962bd15a1ccc47fbf70280522d79c5029f87e8315734e7b8a81d27f64ccb3716f8f75aa756251df7b041fc5e1c1b7ad1192bdb1d94154e212c810203010001a381c43081c1301d0603551d0e04160414852c1d09b76b0fa10e35d7aa4bcb48b2deb254d53081910603551d230481893081868014852c1d09b76b0fa10e35d7aa4bcb48b2deb254d5a163a461305f310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b1303525341310f300d060355040313065465737443418209009b29b6c41fdd35cf300c0603551d13040530030101ff data_signature_algo sha1WithRSAEncryption e 65537 extensions {id-ce-subjectKeyIdentifier {false 0414852c1d09b76b0fa10e35d7aa4bcb48b2deb254d5} id-ce-authorityKeyIdentifier {false 3081868014852c1d09b76b0fa10e35d7aa4bcb48b2deb254d5a163a461305f310b30090603550406130255533110300e06035504081307466c6f72696461310e300c0603550407130554616d7061310f300d060355040a130654636c6c6962310c300a060355040b1303525341310f300d060355040313065465737443418209009b29b6c41fdd35cf} id-ce-basicConstraints {false 1 -1}} issuer {C=US, ST=Florida, L=Tampa, O=Tcllib, OU=RSA, CN=TestCA} l 2048 n 24161606882664512184359265185750837725108535101957340182512690512950889280510175836653980019439405807509520118166835198926328713901946216313990307823213762851130122553610411084164096778558222486569750697608231998818342043083553499928765840766586577148563804434733745484416582976688503343857730022194918419820043366167270205314454789050632414594372175021330643138454461788318306110532766986666994575469007919602783172146356611527403971910037954057021421611608595373199910520988014831498419657809400692831589285260267441816651113464389720766612297754777522129247659432535168409289483999817599902067306541004223550663809 notAfter 2070344258 notBefore 1281339458 pubkey 3082010a0282010100bf65944eeba4d516f9823cadd420a06e3413f14c32eda1f7fea95730ad20ba8e2c5952312210e02c4a848ccfba23fe052b9f35799e3174ae7a27ee4f69a56f96a9e93dad99de558b4f6e9b9c70dd2a6ed89bb3ed97e32c3167b0cc6e17753843097ff6a13276686d0e76004c2f22462717b0f1af3557936605f7899cf3037b85903e8d5449225f55f7320984f1e0864f0e14fe4dcc20aef03d0b593123b801ecbd23fb9be62799ac02b4c992e38ae6cfdbb81bf19209c0ad845c8da56591fa83c24c2fb4705b962bd15a1ccc47fbf70280522d79c5029f87e8315734e7b8a81d27f64ccb3716f8f75aa756251df7b041fc5e1c1b7ad1192bdb1d94154e212c810203010001 pubkey_algo rsaEncryption raw 2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d494945426a434341753667417749424167494a414a737074735166335458504d413047435371475349623344514542425155414d463878437a414a42674e560a42415954416c56544d52417744675944565151494577644762473979615752684d51347744415944565151484577565559573177595445504d413047413155450a43684d4756474e7362476c694d517777436759445651514c45774e5355304578447a414e42674e5642414d54426c526c6333524451544165467730784d4441340a4d446b774e7a4d334d7a68614677307a4e5441344d5441774e7a4d334d7a68614d463878437a414a42674e5642415954416c56544d52417744675944565151490a4577644762473979615752684d51347744415944565151484577565559573177595445504d4130474131554543684d4756474e7362476c694d517777436759440a5651514c45774e5355304578447a414e42674e5642414d54426c526c6333524451544343415349774451594a4b6f5a496876634e4151454242514144676745500a4144434341516f4367674542414c396c6c453772704e55572b594938726451676f473430452f464d4d753268392f3670567a4374494c714f4c466c534d5349510a3443784b68497a507569502b425375664e586d654d5853756569667554326d6c62356170365432746d643556693039756d35787733537075324a757a375a666a0a4c44466e734d78754633553451776c2f39714579646d6874446e59415443386952696358735047764e5665545a675833695a7a7a413375466b44364e56456b690a583158334d676d4538654347547734552f6b334d494b37775051745a4d534f3441657939492f75623569655a72414b30795a4c6a6975625032376762385a494a0a774b32455849326c5a5a483667384a4d4c3752775735597230566f637a45663739774b415569313578514b66682b6778567a546e754b67644a2f5a4d797a63570a2b5064617031596c48666577516678654842743630526b7232783255465534684c4945434177454141614f42784443427754416442674e5648513445466751550a68537764436264724436454f4e6465715338744973743679564e5577675a4547413155644977534269544342686f415568537764436264724436454f4e6465710a5338744973743679564e5768593652684d463878437a414a42674e5642415954416c56544d52417744675944565151494577644762473979615752684d5134770a44415944565151484577565559573177595445504d4130474131554543684d4756474e7362476c694d517777436759445651514c45774e5355304578447a414e0a42674e5642414d54426c526c633352445159494a414a737074735166335458504d41774741315564457751464d414d42416638774451594a4b6f5a496876634e0a415145464251414467674542414c3755686f64683241545834497673477172795a644c566e4739546b4d6e396f3867653945557570597474392f392f4b2b4d790a647158434856754b774d59723556355335484151787754545134427950614c597a2b563864756d79424f645370356c3578354e574a2b326f436e2f44704c37550a39657a714c39677a45663541564c786967536f2f5635633475557045344b337462474844567046317a374f54364c4f706b765775693146704c516f446339484b0a426d54314a2b6651534866735363563635543671735141475055795258716837394c497259305a577644756e35787931334b6d436b33374763322b664378326d0a51454a467961434d6f6a7343664a7a325852744274776e386270426e4655503138376634736e6b553547612f35546a5147713659425032425752385733744d300a7a476b354b626f496c746a51536257394b595672617470462b67703365366e693942303d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a serial_number 11180668503388403151 signature bed4868761d804d7e08bec1aaaf265d2d59c6f5390c9fda3c81ef4452ea58b6df7ff7f2be33276a5c21d5b8ac0c62be55e52e47010c704d34380723da2d8cfe57c76e9b204e752a79979c7935627eda80a7fc3a4bed4f5ecea2fd83311fe4054bc62812a3f579738b94a44e0aded6c61c3569175cfb393e8b3a992f5ae8b51692d0a0373d1ca0664f527e7d04877ec49c57ae53eaab100063d4c915ea87bf4b22b634656bc3ba7e71cb5dca982937ec6736f9f0b1da6404245c9a08ca23b027c9cf65d1b41b709fc6e90671543f5f3b7f8b27914e466bfe538d01aae9804fd81591f16ded334cc693929ba0896d8d049b5bd29856b6ada45fa0a777ba9e2f41d signature_algo sha1WithRSAEncryption subject {C=US, ST=Florida, L=Tampa, O=Tcllib, OU=RSA, CN=TestCA} type rsa version 3

Added modules/pki/test-assets/result/des-csr.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-----BEGIN CERTIFICATE REQUEST-----
MIICpjCCAY4CAQAwYTELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0Zsb3JpZGExDjAM
BgNVBAcTBVRhbXBhMQ8wDQYDVQQKEwZUY2xsaWIxDDAKBgNVBAsTA1JTQTERMA8G
A1UEAxMIVGVzdENlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCj
PBaKPeHx1oQb0nfMPeglBgyIpsv8CuIH7CAT8SGxoK1zIBQUhnNOZvel1/Kore68
mY0ftiqmVbLO7aZy9X0Vy97hcEnhIekuPCauVg3kWjOspPbxmd3Bf7vfw7RGsvUt
GGc3FZnU/X3GhzlKCq1osQCSZdLwirDm8ny4tbkTEDnGIB+4IJbSvifGQDqQNwtx
cDigwRwAgDDdaKYBiW4bp+ZowJxorqc60w6xcl8DKhpPPaqRFN2kBcAxU/vztan1
5NjNmmOPIkDcvIDEEkxKDoefTWaaF/MEGNtZZgIfIbVMos9+1soBzBb2ZH5NVtuK
3RGA+4DxUk5kiI+eLANLAgMBAAGgADANBgkqhkiG9w0BAQUFAAOCAQEAff0WNTPX
M6rdFGOXBxTsC7NUGcoquuM6QsceadMbBVRtRUUbaUsusXdxDWhdylqHM3xPNx0L
4Ex0FeL9icD/8xvJmCXzBeNt3uvThTvIwHYqnOCSlhx9InUUx2l6U0rAwZ+CIuMi
7lG2+Z5qVD035bAZ7LT/4s4fjKSL4cTZQOdCcoFtoptj9+L8EItwwYDzffJWdG8s
OUtMBn+Zh45k2UtLKu38jBNtVpNFAEJLlr/Arj6Jj3yTmEFrocxkwK6IPbOHQTu3
tyJ5CkDpUqkxYZ0D4wfr8tFEru0jQNl5bSDt9QQvg1Kj6+OC9aaRvxwnmc6REfky
8sCv80Pn5dNCGg==
-----END CERTIFICATE REQUEST-----

Added modules/pki/test-assets/result/des-key.



>
1
d 4821708078078814272825737770757352316921506482526873519719051463644222257651923197825994018656421190278177720014932984365118366602027256382375921341192781177112398174373076887129954817822368157304055327895506098881228521168940083073283595671416028753301552269895847121119899618677892849270785450525228277087545852904246091363590456069440574806479467479724488815982259021323617233373449030738298588184972148901173121148634892058648703349014218791530847767762515588159636682267580355756974401553230588009724381821442787415368995149629493809933380894522643851913309510865914033228986295772184835354265231482340110365953 e 65537 l 2048 n 20606474229739240365059039861892702888430699076971875439310562489263214483191006887246310401088091004060054335612563612411917991000786455919906798626524375611634511845705141177165689526939976649836053082770641226108840795034158866930145876068965913035873741839723777813944236146677082729876717709231945588228947001753667862858297850461440476551869914895980840772354759428144421149613554402682425181850295101375623815063198594704730226304723548382258248785251384891817576645955371924194287071569929361029204431671633821160423187871463713776212876252047207985933876036458343140423787003660018607222053134170461225878347 p 151903506703070744388477144011062627922344490485619606525415439019240332914406492743669447033002173681213181316912563402042948038453846038272948559137687751740338183189809253891948725876860938554446847405802064303332011747457634488959045893106143553864597546566768167692662722957924358908573096347694362541259 q 135655026516400219835182288872064651548166413404981613626584975073279765274581289299963783472100901444904090497633607380440126562041149560121122191822729803838692049608052805597752016733559257401832457990520641184379220785155858496800358974243933025297673311305372951490297748845447521569920828454777048335233 type rsa

Added modules/pki/test-assets/test-v1.crt.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-----BEGIN CERTIFICATE-----
MIIDOTCCAiECBhJIFZWqAzANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJVUzEQ
MA4GA1UECBMHRmxvcmlkYTEOMAwGA1UEBxMFVGFtcGExDzANBgNVBAoTBlRjbGxp
YjEMMAoGA1UECxMDUlNBMQ8wDQYDVQQDEwZUZXN0Q0EwHhcNMTAwODA5MDc1MjA1
WhcNMjAwODA5MDc1MjA1WjBhMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHRmxvcmlk
YTEOMAwGA1UEBxMFVGFtcGExDzANBgNVBAoTBlRjbGxpYjEMMAoGA1UECxMDUlNB
MREwDwYDVQQDEwhUZXN0Q2VydDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAKM8Foo94fHWhBvSd8w96CUGDIimy/wK4gfsIBPxIbGgrXMgFBSGc05m96XX
8qit7ryZjR+2KqZVss7tpnL1fRXL3uFwSeEh6S48Jq5WDeRaM6yk9vGZ3cF/u9/D
tEay9S0YZzcVmdT9fcaHOUoKrWixAJJl0vCKsObyfLi1uRMQOcYgH7ggltK+J8ZA
OpA3C3FwOKDBHACAMN1opgGJbhun5mjAnGiupzrTDrFyXwMqGk89qpEU3aQFwDFT
+/O1qfXk2M2aY48iQNy8gMQSTEoOh59NZpoX8wQY21lmAh8htUyiz37WygHMFvZk
fk1W24rdEYD7gPFSTmSIj54sA0sCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAesvQ
pYfxZj6KIbZfkWHwhDH0VNi5iPUvaNbVvZrZZ1R1gZAk8RycQN8gn7BaKX/6ciks
geKbvGwy5JvZaKSed6574QVTV+mGAqAxOW+LmURV+TaoWSKAC93DebdsL2NlPDsr
uuxMgb7fn52ni2qAslPo+YzecokIWDeyKvRUCD7Gt3LDdLQPG/jTx6Xnebb7usiF
pfqQWhFUdcfPik0Y3rfJG5bV5HuhKR9LxwI3Hxrt4LlSZIpolMXkwklqeoI0eIpy
kNJW5c2pm3cvQ/AZ3bHXWNBqH9A4Zf3OdizyKFD5lqqM3H2EQRXj0cUzQo2Wqf53
S6W6B4F2B2ZLa/O/Eg==
-----END CERTIFICATE-----

Added modules/pki/test-assets/test-v3.crt.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-----BEGIN CERTIFICATE-----
MIIDPjCCAiagAwIBAgIGEkgVlanAMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNVBAYT
AlVTMRAwDgYDVQQIEwdGbG9yaWRhMQ4wDAYDVQQHEwVUYW1wYTEPMA0GA1UEChMG
VGNsbGliMQwwCgYDVQQLEwNSU0ExDzANBgNVBAMTBlRlc3RDQTAeFw0xMDA4MDkw
NzUxMzZaFw0yMDA4MDkwNzUxMzZaMGExCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdG
bG9yaWRhMQ4wDAYDVQQHEwVUYW1wYTEPMA0GA1UEChMGVGNsbGliMQwwCgYDVQQL
EwNSU0ExETAPBgNVBAMTCFRlc3RDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAozwWij3h8daEG9J3zD3oJQYMiKbL/AriB+wgE/EhsaCtcyAUFIZz
Tmb3pdfyqK3uvJmNH7YqplWyzu2mcvV9Fcve4XBJ4SHpLjwmrlYN5FozrKT28Znd
wX+738O0RrL1LRhnNxWZ1P19xoc5SgqtaLEAkmXS8Iqw5vJ8uLW5ExA5xiAfuCCW
0r4nxkA6kDcLcXA4oMEcAIAw3WimAYluG6fmaMCcaK6nOtMOsXJfAyoaTz2qkRTd
pAXAMVP787Wp9eTYzZpjjyJA3LyAxBJMSg6Hn01mmhfzBBjbWWYCHyG1TKLPftbK
AcwW9mR+TVbbit0RgPuA8VJOZIiPniwDSwIDAQABMA0GCSqGSIb3DQEBBQUAA4IB
AQAwEFsEDA0mp4mQmOYbc4RHQVEGN723CtgcEHF7unu43EeO5s/1Yq0F+SdWR14L
qFs6lRXnPjkEpIFlmW5I0Dp8Q1yY18qRPt8Hx6ymxty8QWm9lTwMBzrYUh94JqV+
Y3QHJbVrgLpoKRpsVOpsdM5qQ4efvQwO0sOwI5AajvkyU1dC8TsxAzyJMQfK+WQs
A0lSpqM0Htrl1xRhDZwEC8BE3+7Iv9MSW/RvK6FaaOFkyjvfWfOLgRfRtMQ8+hdV
8RaSEqqkSsglGzmzSbuTHopBkle1Kegq2Hd/1lpi9FoXHrGxjwGWVw5KOwWOCa0O
yF4KWWijMOWbMrIqLq5p4aOk
-----END CERTIFICATE-----

Added modules/pki/test-assets/test.csr.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-----BEGIN CERTIFICATE REQUEST-----
MIICpjCCAY4CAQAwYTELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0Zsb3JpZGExDjAM
BgNVBAcTBVRhbXBhMQ8wDQYDVQQKEwZUY2xsaWIxDDAKBgNVBAsTA1JTQTERMA8G
A1UEAxMIVGVzdENlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCj
PBaKPeHx1oQb0nfMPeglBgyIpsv8CuIH7CAT8SGxoK1zIBQUhnNOZvel1/Kore68
mY0ftiqmVbLO7aZy9X0Vy97hcEnhIekuPCauVg3kWjOspPbxmd3Bf7vfw7RGsvUt
GGc3FZnU/X3GhzlKCq1osQCSZdLwirDm8ny4tbkTEDnGIB+4IJbSvifGQDqQNwtx
cDigwRwAgDDdaKYBiW4bp+ZowJxorqc60w6xcl8DKhpPPaqRFN2kBcAxU/vztan1
5NjNmmOPIkDcvIDEEkxKDoefTWaaF/MEGNtZZgIfIbVMos9+1soBzBb2ZH5NVtuK
3RGA+4DxUk5kiI+eLANLAgMBAAGgADANBgkqhkiG9w0BAQUFAAOCAQEAff0WNTPX
M6rdFGOXBxTsC7NUGcoquuM6QsceadMbBVRtRUUbaUsusXdxDWhdylqHM3xPNx0L
4Ex0FeL9icD/8xvJmCXzBeNt3uvThTvIwHYqnOCSlhx9InUUx2l6U0rAwZ+CIuMi
7lG2+Z5qVD035bAZ7LT/4s4fjKSL4cTZQOdCcoFtoptj9+L8EItwwYDzffJWdG8s
OUtMBn+Zh45k2UtLKu38jBNtVpNFAEJLlr/Arj6Jj3yTmEFrocxkwK6IPbOHQTu3
tyJ5CkDpUqkxYZ0D4wfr8tFEru0jQNl5bSDt9QQvg1Kj6+OC9aaRvxwnmc6REfky
8sCv80Pn5dNCGg==
-----END CERTIFICATE REQUEST-----

Added modules/pki/test-assets/test.key.aes.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,A63D2250AEC17BBA948C0711A7477A88

DcIqtKV3RzcfzOk0K4WwRU4dK4373bsoek/trIvHYbs6sQlU0Ydk8ddDYyWlt0vR
MdEhEi4kTbtWhczSa9kgjQo59fZ8br8iHaSkUDPqKZUCy5qAlLsfRnCiA4JnZaDy
BD8ROFNTdb1MTnGPqrY2+9nv/BAPNlqr+95zcAim7vBJxO0idmUKCzVFAEHn+akD
UPX/Rkku7tIprsA5ePsQ9Z7B8qJ3LqhxKauZE+qV3hcX8/E7fndpYxQ5I3/6W3Wj
hkfH4cTwNC9H0jcaoDDlh0O1xMfq2YQxyq20Cfse8NO11Is8UMbXWBZ90uhk6lnk
xsVzOB2A7WbiiNEfbLBYgsUqy9ffGKhJWXoUUzl6Ze9lolD0mJjinKwAMEszwWNg
qSwJQi+omgv0+0yP2gnMkqwsBzPFrEt/Iw0/nMKNNn8RXK2C3itD61tX/T/4p5Gj
VvISFp+KjlgASBMaSNCE/FsfAsz7OxrkvrOJcEAZ1sWjfBUXSq20ESFGk74S5AUj
xjrSeurl7pyLjfEgx2YR6ybF3SSnVst3wQ9BPLnG8439VKONixSukDvk/XJuY4UO
dLuSm7aTcLy43jLosxLKHJ6jfwJEOhKMFGXkyb1h7UZnU3rydvgJF7Hw+HGsnuH6
0cd4gKyMoTclxRn8oULlQafuOYwTO0xOV5cOjtKdnaTfasd4xrYuWGuW93INvyTh
6lYhVgcjo+F7TDm1bqgAH354Cb3FqERx4VmeJm20YfpPilDuM1ygkh5tObM2ffqr
vJ9T66RsjhqpMv8trjj4F8oZK614D1MVKv7/2A02GEx8eoKiv1IsIoLe4Ihe5Ido
oswOXxdtkJj4kd/feKPOFnCajOdWGR88IMUldMIsTetxAlaNrZkTz0OAKZ0pTRgj
BsiXVwT6OX3GF7cL41Q6FXbLZGrLnGGnOjRFpBK+0JeQ8hQFortqiLBXUaNK//gH
pzMwApPRBfX5VxU4bVxai5WoBz63MAdOJaHKTBfNF8ebMsUC6Z+ue3H/rQmTjscz
zxelmeKHGbFCUyW/bmGh3MDkriXUNVgqFQTqDQIbsOVzwHAQ3m6N7zREcep+/uCk
2VlJY2HRuAsf8U+sATGveYkCcq+1nr1ZPcbeLHom9NL8cDXvWRwj84Y3Fv0BPuod
PRBLZWMe8bOICV7cxsyRPfNf9ov+QyLc7LeMdmy9gYZABnRUZRKAOcNGHDIVULeT
L9+QiyzeW6AK5BgkNrTpHC6fWo6jqfDjZJrhJvQbzvykJwiMJvahuRYlejLVx1HA
uFANAhgM9APAjnzpyvbS5EcB+Q+9TrF8d+MufR3ijvMT2evIsUthwprS7CkJLCXl
WeGw/YI58xWwk1l3LZ8bT04Jy1cS+8CVnmZXtCq0yRVsIVbsMlN4WW1b6AxMTGlC
VB8ne9lw3zSqraDu/8he0TQi0JzYs86CwjDkMTIaIrXn+6W7tlcSUpnrQeAfgx+d
w8qklOraCLAcXWhFw2kbc7pzvKvVzRr2R0GtZaGYInEFUP9e7fJT4R9K1cBi9DGm
gmtJUWHnxI9QMHDslST9NGkrulBisoJ0kuVNUmIX0x2zii7w+Kk5a87lUB06pAmV
-----END RSA PRIVATE KEY-----

Added modules/pki/test-assets/test.key.des.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,2AD65AF586C2E7FF

0pAOYQCqE9NPUJSrK4gu5P9H1yydKcLvuhIIsh5S1RtlEqzz1eythmGRTD/S6QnS
c2zmmkaHndGKB3S55BTw0UnGP3XROdl1VtCqlf2mvp7MY3E9xF+ZKgw6L2yUeFW5
ZlKEyglWIB5J4yKgX8yAe6nqdhNEXG6JolCQH45x5uRiMTtxuGgivmvFfTV3TjaO
GXUMcbNeslJ4PZwxmUFR5YD4QSxwHe4Ur3dz2CMW6ea+TGbWNyqoEEEz81BKeAFF
cAxAtnyWpo9NmRc2TmGRstXrfzBW/lgNrkLgqoNHkfXT5p+kkG4mIInIKWpeKsJB
wByDFIB5+Sr3VkZJYOMJQcYkVWc2Y+o1l8/cqk9cuLYMO81OQw3QEwy0WSkXpVfP
CIbIQOyp3Hi02drlcIjv+d6OYWDYwMB1DiPQSYGO16jFORtC0Mrmt5XiUE4kWTap
3K4MVphvkJaSjUCzbLVzChhXWICwwGPG/x8F1Fkre/xevwdFq6qZB2HfZVqjtWrn
E6nVWjWcaavIxJEJPuCfhU+gKsV/nyxMFqBpck8YRxUE1yYdG9sSHaiL/z8vom1r
09VorVpa1v0AI+05XgJPZHPmjbadNn7oA3knqbICv6Jh0URXlW+TtEWGde+YDz9x
HC6TexiZU2tQcZMtcR999yI9UYXekDS6jXLjfpEZuM971IbUefjEGnBhBpoxW4Zw
MDzmWDJxyT3bz4ZURANm1nE3i/9R6sDwv7egu62wY6wo8KmEA126eX4CE1TAeRyF
7DZCsmMWHQJej8N5kmTpREtBKZhCrmRYOE6vTELZWfsLN00yTpUFzzrM5gfgYDt5
Ry8t9OQrr7T3TZDu20DMrNRL/3/t3Ap133zgM6c/jD955PyfFA3ph/m4wBiVP1cf
LZDh/Qa+z4xvgSML8NHGhLXJgmvdPGcbKGYRj+LNVanSr3yrVJynIcr/3ckiMgEl
lS5hr3VJVNbX/DgNsqkVoQPudl5p/aiMx/qPY3brxsxyLCk6oF0Z7L4ksdSGIaMt
cMH0eNTuqthWK2D2JWrhPWeY0EcSOx4NtNEqUsCQFZhg+mO1xUKJdnc9x1eaHoZe
XR9lRCjBVXD6iBNy2bscJONoz5MhuHjBqYjSF5jQL/Xfe9qgmLrqdiqqIw4R04c3
g09JlDWRS78a68FXhc5Yo6AmqJD4UNMKH3npFUk2Vk+SD6HwUmpM+hFDM+L2tFi+
7QNyKmWwTfFgyLQOG45Kqhl0i6Ia857UedZX7ezrJ2AoiCUn8oT2NmfJif8/jtL4
wVLdkav7L2H64Xd9ZcWtDIWuLT9L1Fuy9LFFByscRSy1jvSj0ILrNB2Og1YWfWEE
t/OzTlm9jpzkiKQxFGCizzt1ZnnQfrB3BN28vPThw9Dh0DRCexYXWpwY2KhHTQFo
ghSBFh0mAZfCpHdiHM27XGvPUAo6WNP8LaA8tvvWArcU3wqaEjpbsaPw2kY0qMY6
Kds/t/Hi3fC75IN7XWfwxr1c6hxeiBgrR48i+nVPXqlWFoT5svsqquwhxukxifoF
fBuX6STP+RwCa5sDqfICPeLTj1jg0zBjUVB7f0w6FiOLfxQIxnNJ+g==
-----END RSA PRIVATE KEY-----

Deleted modules/pki/test-v1.crt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-----BEGIN CERTIFICATE-----
MIIDOTCCAiECBhJIFZWqAzANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJVUzEQ
MA4GA1UECBMHRmxvcmlkYTEOMAwGA1UEBxMFVGFtcGExDzANBgNVBAoTBlRjbGxp
YjEMMAoGA1UECxMDUlNBMQ8wDQYDVQQDEwZUZXN0Q0EwHhcNMTAwODA5MDc1MjA1
WhcNMjAwODA5MDc1MjA1WjBhMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHRmxvcmlk
YTEOMAwGA1UEBxMFVGFtcGExDzANBgNVBAoTBlRjbGxpYjEMMAoGA1UECxMDUlNB
MREwDwYDVQQDEwhUZXN0Q2VydDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAKM8Foo94fHWhBvSd8w96CUGDIimy/wK4gfsIBPxIbGgrXMgFBSGc05m96XX
8qit7ryZjR+2KqZVss7tpnL1fRXL3uFwSeEh6S48Jq5WDeRaM6yk9vGZ3cF/u9/D
tEay9S0YZzcVmdT9fcaHOUoKrWixAJJl0vCKsObyfLi1uRMQOcYgH7ggltK+J8ZA
OpA3C3FwOKDBHACAMN1opgGJbhun5mjAnGiupzrTDrFyXwMqGk89qpEU3aQFwDFT
+/O1qfXk2M2aY48iQNy8gMQSTEoOh59NZpoX8wQY21lmAh8htUyiz37WygHMFvZk
fk1W24rdEYD7gPFSTmSIj54sA0sCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAesvQ
pYfxZj6KIbZfkWHwhDH0VNi5iPUvaNbVvZrZZ1R1gZAk8RycQN8gn7BaKX/6ciks
geKbvGwy5JvZaKSed6574QVTV+mGAqAxOW+LmURV+TaoWSKAC93DebdsL2NlPDsr
uuxMgb7fn52ni2qAslPo+YzecokIWDeyKvRUCD7Gt3LDdLQPG/jTx6Xnebb7usiF
pfqQWhFUdcfPik0Y3rfJG5bV5HuhKR9LxwI3Hxrt4LlSZIpolMXkwklqeoI0eIpy
kNJW5c2pm3cvQ/AZ3bHXWNBqH9A4Zf3OdizyKFD5lqqM3H2EQRXj0cUzQo2Wqf53
S6W6B4F2B2ZLa/O/Eg==
-----END CERTIFICATE-----
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































Deleted modules/pki/test-v3.crt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-----BEGIN CERTIFICATE-----
MIIDPjCCAiagAwIBAgIGEkgVlanAMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNVBAYT
AlVTMRAwDgYDVQQIEwdGbG9yaWRhMQ4wDAYDVQQHEwVUYW1wYTEPMA0GA1UEChMG
VGNsbGliMQwwCgYDVQQLEwNSU0ExDzANBgNVBAMTBlRlc3RDQTAeFw0xMDA4MDkw
NzUxMzZaFw0yMDA4MDkwNzUxMzZaMGExCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdG
bG9yaWRhMQ4wDAYDVQQHEwVUYW1wYTEPMA0GA1UEChMGVGNsbGliMQwwCgYDVQQL
EwNSU0ExETAPBgNVBAMTCFRlc3RDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAozwWij3h8daEG9J3zD3oJQYMiKbL/AriB+wgE/EhsaCtcyAUFIZz
Tmb3pdfyqK3uvJmNH7YqplWyzu2mcvV9Fcve4XBJ4SHpLjwmrlYN5FozrKT28Znd
wX+738O0RrL1LRhnNxWZ1P19xoc5SgqtaLEAkmXS8Iqw5vJ8uLW5ExA5xiAfuCCW
0r4nxkA6kDcLcXA4oMEcAIAw3WimAYluG6fmaMCcaK6nOtMOsXJfAyoaTz2qkRTd
pAXAMVP787Wp9eTYzZpjjyJA3LyAxBJMSg6Hn01mmhfzBBjbWWYCHyG1TKLPftbK
AcwW9mR+TVbbit0RgPuA8VJOZIiPniwDSwIDAQABMA0GCSqGSIb3DQEBBQUAA4IB
AQAwEFsEDA0mp4mQmOYbc4RHQVEGN723CtgcEHF7unu43EeO5s/1Yq0F+SdWR14L
qFs6lRXnPjkEpIFlmW5I0Dp8Q1yY18qRPt8Hx6ymxty8QWm9lTwMBzrYUh94JqV+
Y3QHJbVrgLpoKRpsVOpsdM5qQ4efvQwO0sOwI5AajvkyU1dC8TsxAzyJMQfK+WQs
A0lSpqM0Htrl1xRhDZwEC8BE3+7Iv9MSW/RvK6FaaOFkyjvfWfOLgRfRtMQ8+hdV
8RaSEqqkSsglGzmzSbuTHopBkle1Kegq2Hd/1lpi9FoXHrGxjwGWVw5KOwWOCa0O
yF4KWWijMOWbMrIqLq5p4aOk
-----END CERTIFICATE-----
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































Deleted modules/pki/test.csr.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-----BEGIN CERTIFICATE REQUEST-----
MIICpjCCAY4CAQAwYTELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0Zsb3JpZGExDjAM
BgNVBAcTBVRhbXBhMQ8wDQYDVQQKEwZUY2xsaWIxDDAKBgNVBAsTA1JTQTERMA8G
A1UEAxMIVGVzdENlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCj
PBaKPeHx1oQb0nfMPeglBgyIpsv8CuIH7CAT8SGxoK1zIBQUhnNOZvel1/Kore68
mY0ftiqmVbLO7aZy9X0Vy97hcEnhIekuPCauVg3kWjOspPbxmd3Bf7vfw7RGsvUt
GGc3FZnU/X3GhzlKCq1osQCSZdLwirDm8ny4tbkTEDnGIB+4IJbSvifGQDqQNwtx
cDigwRwAgDDdaKYBiW4bp+ZowJxorqc60w6xcl8DKhpPPaqRFN2kBcAxU/vztan1
5NjNmmOPIkDcvIDEEkxKDoefTWaaF/MEGNtZZgIfIbVMos9+1soBzBb2ZH5NVtuK
3RGA+4DxUk5kiI+eLANLAgMBAAGgADANBgkqhkiG9w0BAQUFAAOCAQEAff0WNTPX
M6rdFGOXBxTsC7NUGcoquuM6QsceadMbBVRtRUUbaUsusXdxDWhdylqHM3xPNx0L
4Ex0FeL9icD/8xvJmCXzBeNt3uvThTvIwHYqnOCSlhx9InUUx2l6U0rAwZ+CIuMi
7lG2+Z5qVD035bAZ7LT/4s4fjKSL4cTZQOdCcoFtoptj9+L8EItwwYDzffJWdG8s
OUtMBn+Zh45k2UtLKu38jBNtVpNFAEJLlr/Arj6Jj3yTmEFrocxkwK6IPbOHQTu3
tyJ5CkDpUqkxYZ0D4wfr8tFEru0jQNl5bSDt9QQvg1Kj6+OC9aaRvxwnmc6REfky
8sCv80Pn5dNCGg==
-----END CERTIFICATE REQUEST-----
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































Deleted modules/pki/test.key.aes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,A63D2250AEC17BBA948C0711A7477A88

DcIqtKV3RzcfzOk0K4WwRU4dK4373bsoek/trIvHYbs6sQlU0Ydk8ddDYyWlt0vR
MdEhEi4kTbtWhczSa9kgjQo59fZ8br8iHaSkUDPqKZUCy5qAlLsfRnCiA4JnZaDy
BD8ROFNTdb1MTnGPqrY2+9nv/BAPNlqr+95zcAim7vBJxO0idmUKCzVFAEHn+akD
UPX/Rkku7tIprsA5ePsQ9Z7B8qJ3LqhxKauZE+qV3hcX8/E7fndpYxQ5I3/6W3Wj
hkfH4cTwNC9H0jcaoDDlh0O1xMfq2YQxyq20Cfse8NO11Is8UMbXWBZ90uhk6lnk
xsVzOB2A7WbiiNEfbLBYgsUqy9ffGKhJWXoUUzl6Ze9lolD0mJjinKwAMEszwWNg
qSwJQi+omgv0+0yP2gnMkqwsBzPFrEt/Iw0/nMKNNn8RXK2C3itD61tX/T/4p5Gj
VvISFp+KjlgASBMaSNCE/FsfAsz7OxrkvrOJcEAZ1sWjfBUXSq20ESFGk74S5AUj
xjrSeurl7pyLjfEgx2YR6ybF3SSnVst3wQ9BPLnG8439VKONixSukDvk/XJuY4UO
dLuSm7aTcLy43jLosxLKHJ6jfwJEOhKMFGXkyb1h7UZnU3rydvgJF7Hw+HGsnuH6
0cd4gKyMoTclxRn8oULlQafuOYwTO0xOV5cOjtKdnaTfasd4xrYuWGuW93INvyTh
6lYhVgcjo+F7TDm1bqgAH354Cb3FqERx4VmeJm20YfpPilDuM1ygkh5tObM2ffqr
vJ9T66RsjhqpMv8trjj4F8oZK614D1MVKv7/2A02GEx8eoKiv1IsIoLe4Ihe5Ido
oswOXxdtkJj4kd/feKPOFnCajOdWGR88IMUldMIsTetxAlaNrZkTz0OAKZ0pTRgj
BsiXVwT6OX3GF7cL41Q6FXbLZGrLnGGnOjRFpBK+0JeQ8hQFortqiLBXUaNK//gH
pzMwApPRBfX5VxU4bVxai5WoBz63MAdOJaHKTBfNF8ebMsUC6Z+ue3H/rQmTjscz
zxelmeKHGbFCUyW/bmGh3MDkriXUNVgqFQTqDQIbsOVzwHAQ3m6N7zREcep+/uCk
2VlJY2HRuAsf8U+sATGveYkCcq+1nr1ZPcbeLHom9NL8cDXvWRwj84Y3Fv0BPuod
PRBLZWMe8bOICV7cxsyRPfNf9ov+QyLc7LeMdmy9gYZABnRUZRKAOcNGHDIVULeT
L9+QiyzeW6AK5BgkNrTpHC6fWo6jqfDjZJrhJvQbzvykJwiMJvahuRYlejLVx1HA
uFANAhgM9APAjnzpyvbS5EcB+Q+9TrF8d+MufR3ijvMT2evIsUthwprS7CkJLCXl
WeGw/YI58xWwk1l3LZ8bT04Jy1cS+8CVnmZXtCq0yRVsIVbsMlN4WW1b6AxMTGlC
VB8ne9lw3zSqraDu/8he0TQi0JzYs86CwjDkMTIaIrXn+6W7tlcSUpnrQeAfgx+d
w8qklOraCLAcXWhFw2kbc7pzvKvVzRr2R0GtZaGYInEFUP9e7fJT4R9K1cBi9DGm
gmtJUWHnxI9QMHDslST9NGkrulBisoJ0kuVNUmIX0x2zii7w+Kk5a87lUB06pAmV
-----END RSA PRIVATE KEY-----
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































Deleted modules/pki/test.key.des.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,2AD65AF586C2E7FF

0pAOYQCqE9NPUJSrK4gu5P9H1yydKcLvuhIIsh5S1RtlEqzz1eythmGRTD/S6QnS
c2zmmkaHndGKB3S55BTw0UnGP3XROdl1VtCqlf2mvp7MY3E9xF+ZKgw6L2yUeFW5
ZlKEyglWIB5J4yKgX8yAe6nqdhNEXG6JolCQH45x5uRiMTtxuGgivmvFfTV3TjaO
GXUMcbNeslJ4PZwxmUFR5YD4QSxwHe4Ur3dz2CMW6ea+TGbWNyqoEEEz81BKeAFF
cAxAtnyWpo9NmRc2TmGRstXrfzBW/lgNrkLgqoNHkfXT5p+kkG4mIInIKWpeKsJB
wByDFIB5+Sr3VkZJYOMJQcYkVWc2Y+o1l8/cqk9cuLYMO81OQw3QEwy0WSkXpVfP
CIbIQOyp3Hi02drlcIjv+d6OYWDYwMB1DiPQSYGO16jFORtC0Mrmt5XiUE4kWTap
3K4MVphvkJaSjUCzbLVzChhXWICwwGPG/x8F1Fkre/xevwdFq6qZB2HfZVqjtWrn
E6nVWjWcaavIxJEJPuCfhU+gKsV/nyxMFqBpck8YRxUE1yYdG9sSHaiL/z8vom1r
09VorVpa1v0AI+05XgJPZHPmjbadNn7oA3knqbICv6Jh0URXlW+TtEWGde+YDz9x
HC6TexiZU2tQcZMtcR999yI9UYXekDS6jXLjfpEZuM971IbUefjEGnBhBpoxW4Zw
MDzmWDJxyT3bz4ZURANm1nE3i/9R6sDwv7egu62wY6wo8KmEA126eX4CE1TAeRyF
7DZCsmMWHQJej8N5kmTpREtBKZhCrmRYOE6vTELZWfsLN00yTpUFzzrM5gfgYDt5
Ry8t9OQrr7T3TZDu20DMrNRL/3/t3Ap133zgM6c/jD955PyfFA3ph/m4wBiVP1cf
LZDh/Qa+z4xvgSML8NHGhLXJgmvdPGcbKGYRj+LNVanSr3yrVJynIcr/3ckiMgEl
lS5hr3VJVNbX/DgNsqkVoQPudl5p/aiMx/qPY3brxsxyLCk6oF0Z7L4ksdSGIaMt
cMH0eNTuqthWK2D2JWrhPWeY0EcSOx4NtNEqUsCQFZhg+mO1xUKJdnc9x1eaHoZe
XR9lRCjBVXD6iBNy2bscJONoz5MhuHjBqYjSF5jQL/Xfe9qgmLrqdiqqIw4R04c3
g09JlDWRS78a68FXhc5Yo6AmqJD4UNMKH3npFUk2Vk+SD6HwUmpM+hFDM+L2tFi+
7QNyKmWwTfFgyLQOG45Kqhl0i6Ia857UedZX7ezrJ2AoiCUn8oT2NmfJif8/jtL4
wVLdkav7L2H64Xd9ZcWtDIWuLT9L1Fuy9LFFByscRSy1jvSj0ILrNB2Og1YWfWEE
t/OzTlm9jpzkiKQxFGCizzt1ZnnQfrB3BN28vPThw9Dh0DRCexYXWpwY2KhHTQFo
ghSBFh0mAZfCpHdiHM27XGvPUAo6WNP8LaA8tvvWArcU3wqaEjpbsaPw2kY0qMY6
Kds/t/Hi3fC75IN7XWfwxr1c6hxeiBgrR48i+nVPXqlWFoT5svsqquwhxukxifoF
fBuX6STP+RwCa5sDqfICPeLTj1jg0zBjUVB7f0w6FiOLfxQIxnNJ+g==
-----END RSA PRIVATE KEY-----
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































Changes to modules/pluginmgr/pluginmgr.man.

419
420
421
422
423
424
425
426
427
Its purpose is give a user of the plugin management the ability to
define commands, packages, etc. a chosen plugin may need while being
loaded.

[list_end]

[vset CATEGORY pluginmgr]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

419
420
421
422
423
424
425
426
427
Its purpose is give a user of the plugin management the ability to
define commands, packages, etc. a chosen plugin may need while being
loaded.

[list_end]

[vset CATEGORY pluginmgr]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/png/png.man.

147
148
149
150
151
152
153
154
155

Takes a list of scanlines in the Tk_GetColor format and writes the represented image
to [arg file].

[list_end]

[vset CATEGORY png]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

147
148
149
150
151
152
153
154
155

Takes a list of scanlines in the Tk_GetColor format and writes the represented image
to [arg file].

[list_end]

[vset CATEGORY png]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/png/png.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
# -*- tcl -*-
# png.test:  tests for png decoding and manipulation.
#
# Copyright (c) 2004 by Andreas Kupries <[email protected]>
#
# RCS: @(#) $Id: png.test,v 1.10 2007/04/30 22:47:14 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]





<
<







1
2
3
4


5
6
7
8
9
10
11
# -*- tcl -*-
# png.test:  tests for png decoding and manipulation.
#
# Copyright (c) 2004 by Andreas Kupries <[email protected]>



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
testing {
    useLocal png.tcl png
}

# -------------------------------------------------------------------------
# Validation

foreach f [TestFilesGlob testimages/*.png] {
    set root [file rootname [file tail $f]]

    # All files have a valid signature, except for two.

    test png-ispng-$root {is png} {
	::png::isPNG $f
    } [expr {







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
testing {
    useLocal png.tcl png
}

# -------------------------------------------------------------------------
# Validation

foreach f [TestFilesGlob test-assets/*.png] {
    set root [file rootname [file tail $f]]

    # All files have a valid signature, except for two.

    test png-ispng-$root {is png} {
	::png::isPNG $f
    } [expr {
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    test png-validate-$root {full validation} {
	::png::validate $f
    } OK ;# {}
}

# Validation II, the bad files ...

foreach f [TestFilesGlob testimages/x*.png] {
    set root [file rootname [file tail $f]]

    test png-validate-$root {full validation} {
	::png::validate $f
    } [expr {[string match x00n0g01 $root] ? "NODATA" : "SIG"}] ;# {}
}








|







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
    test png-validate-$root {full validation} {
	::png::validate $f
    } OK ;# {}
}

# Validation II, the bad files ...

foreach f [TestFilesGlob test-assets/x*.png] {
    set root [file rootname [file tail $f]]

    test png-validate-$root {full validation} {
	::png::validate $f
    } [expr {[string match x00n0g01 $root] ? "NODATA" : "SIG"}] ;# {}
}

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
    tp1n3p08 {color 3 compression 0 depth 8 filter 0 height 32 interlace 0 width 32}
    z00n2c08 {color 2 compression 0 depth 8 filter 0 height 32 interlace 0 width 32}
    z03n2c08 {color 2 compression 0 depth 8 filter 0 height 32 interlace 0 width 32}
    z06n2c08 {color 2 compression 0 depth 8 filter 0 height 32 interlace 0 width 32}
    z09n2c08 {color 2 compression 0 depth 8 filter 0 height 32 interlace 0 width 32}
}

foreach f [TestFilesGlob testimages/*.png] {
    set root [file rootname [file tail $f]]

    # Files beginning with x are invalid, and thus not usable in these
    # tests.

    if {[string match x* $root]} continue








|







211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
    tp1n3p08 {color 3 compression 0 depth 8 filter 0 height 32 interlace 0 width 32}
    z00n2c08 {color 2 compression 0 depth 8 filter 0 height 32 interlace 0 width 32}
    z03n2c08 {color 2 compression 0 depth 8 filter 0 height 32 interlace 0 width 32}
    z06n2c08 {color 2 compression 0 depth 8 filter 0 height 32 interlace 0 width 32}
    z09n2c08 {color 2 compression 0 depth 8 filter 0 height 32 interlace 0 width 32}
}

foreach f [TestFilesGlob test-assets/*.png] {
    set root [file rootname [file tail $f]]

    # Files beginning with x are invalid, and thus not usable in these
    # tests.

    if {[string match x* $root]} continue

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249

array set exptime {
    cm0n0g04 946730096
    cm7n0g04 0
    cm9n0g04 946684799
}

foreach f [TestFilesGlob testimages/cm*.png] {
    set root [file rootname [file tail $f]]

    #puts [clock format $exptime($root) -gmt 1]

    test png-gettimestamp-$root {retrieve timestamp} {
	::png::getTimestamp $f
    } $exptime($root) ; # {}







|







233
234
235
236
237
238
239
240
241
242
243
244
245
246
247

array set exptime {
    cm0n0g04 946730096
    cm7n0g04 0
    cm9n0g04 946684799
}

foreach f [TestFilesGlob test-assets/cm*.png] {
    set root [file rootname [file tail $f]]

    #puts [clock format $exptime($root) -gmt 1]

    test png-gettimestamp-$root {retrieve timestamp} {
	::png::getTimestamp $f
    } $exptime($root) ; # {}
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
to the spec are present.}} {Software {Created on a NeXTstation color using "pnmtopng".}} {Disclaimer Freeware.}}   
    ctzn0g04 {{Title PngSuite} {Author {Willem A.J. van Schaik
([email protected])}}}
}

# - Retrieval

foreach f [TestFilesGlob testimages/*.png] {
    set root [file rootname [file tail $f]]

    # All files have a valid signature, except for two. These we ignore.
    if {[string equal $root xcrn0g04]} continue
    if {[string equal $root xlfn0g04]} continue
    # All files are fully valid, except for all beginning with an
    # 'x'. We ignore them as well.







|







259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
to the spec are present.}} {Software {Created on a NeXTstation color using "pnmtopng".}} {Disclaimer Freeware.}}   
    ctzn0g04 {{Title PngSuite} {Author {Willem A.J. van Schaik
([email protected])}}}
}

# - Retrieval

foreach f [TestFilesGlob test-assets/*.png] {
    set root [file rootname [file tail $f]]

    # All files have a valid signature, except for two. These we ignore.
    if {[string equal $root xcrn0g04]} continue
    if {[string equal $root xlfn0g04]} continue
    # All files are fully valid, except for all beginning with an
    # 'x'. We ignore them as well.
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
# - Removal

# Note: For a bad removeComments tests fail only on platforms where
# the system encoding is not ASCII like, or the EOL is not a plain
# LF. Windows for example, or asian systems.

foreach root [array names comex] {
    set f [localPath testimages/${root}.png]

    test png-removecomment-$root {remove comments} {
	set copy [makeFile {} pngrc.$root]
	file copy -force $f $copy

	::png::removeComments $copy
	set res [list [::png::validate $copy] [::png::getComments $copy]]
	removeFile pngrc.$root
	set res
    } {OK {}}
}

# -------------------------------------------------------------------------
# PhysicalDimensions

test png-physical-dimensions-missing {Test for empty list if no physical dimensions present} {
    ::png::getPixelDimension [file join\
	    [file dirname [file join [pwd] [info script]]]\
	    testimages/physicaldimensions/basi0g01.png]
} {}

test png-physical-dimensions-present {Test to extract physical dimensions} {
    ::png::getPixelDimension [file join\
	    [file dirname [file join [pwd] [info script]]]\
	    testimages/physicaldimensions/basi0g01_300dpi.png]
} {ppux 11811 ppuy 11811 unit meter}

# -------------------------------------------------------------------------
testsuiteCleanup







|
















|
<
<



|
<
<




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
# - Removal

# Note: For a bad removeComments tests fail only on platforms where
# the system encoding is not ASCII like, or the EOL is not a plain
# LF. Windows for example, or asian systems.

foreach root [array names comex] {
    set f [asset ${root}.png]

    test png-removecomment-$root {remove comments} {
	set copy [makeFile {} pngrc.$root]
	file copy -force $f $copy

	::png::removeComments $copy
	set res [list [::png::validate $copy] [::png::getComments $copy]]
	removeFile pngrc.$root
	set res
    } {OK {}}
}

# -------------------------------------------------------------------------
# PhysicalDimensions

test png-physical-dimensions-missing {Test for empty list if no physical dimensions present} {
    ::png::getPixelDimension [asset physicaldimensions/basi0g01.png]


} {}

test png-physical-dimensions-present {Test to extract physical dimensions} {
    ::png::getPixelDimension [asset physicaldimensions/basi0g01_300dpi.png]


} {ppux 11811 ppuy 11811 unit meter}

# -------------------------------------------------------------------------
testsuiteCleanup

Added modules/png/test-assets/basi0g01.png.

cannot compute difference between binary files

Added modules/png/test-assets/basi0g02.png.

cannot compute difference between binary files

Added modules/png/test-assets/basi0g04.png.

cannot compute difference between binary files

Added modules/png/test-assets/basi0g08.png.

cannot compute difference between binary files

Added modules/png/test-assets/basi0g16.png.

cannot compute difference between binary files

Added modules/png/test-assets/basi2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/basi2c16.png.

cannot compute difference between binary files

Added modules/png/test-assets/basi3p01.png.

cannot compute difference between binary files

Added modules/png/test-assets/basi3p02.png.

cannot compute difference between binary files

Added modules/png/test-assets/basi3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/basi3p08.png.

cannot compute difference between binary files

Added modules/png/test-assets/basi4a08.png.

cannot compute difference between binary files

Added modules/png/test-assets/basi4a16.png.

cannot compute difference between binary files

Added modules/png/test-assets/basi6a08.png.

cannot compute difference between binary files

Added modules/png/test-assets/basi6a16.png.

cannot compute difference between binary files

Added modules/png/test-assets/basn0g01.png.

cannot compute difference between binary files

Added modules/png/test-assets/basn0g02.png.

cannot compute difference between binary files

Added modules/png/test-assets/basn0g04.png.

cannot compute difference between binary files

Added modules/png/test-assets/basn0g08.png.

cannot compute difference between binary files

Added modules/png/test-assets/basn0g16.png.

cannot compute difference between binary files

Added modules/png/test-assets/basn2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/basn2c16.png.

cannot compute difference between binary files

Added modules/png/test-assets/basn3p01.png.

cannot compute difference between binary files

Added modules/png/test-assets/basn3p02.png.

cannot compute difference between binary files

Added modules/png/test-assets/basn3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/basn3p08.png.

cannot compute difference between binary files

Added modules/png/test-assets/basn4a08.png.

cannot compute difference between binary files

Added modules/png/test-assets/basn4a16.png.

cannot compute difference between binary files

Added modules/png/test-assets/basn6a08.png.

cannot compute difference between binary files

Added modules/png/test-assets/basn6a16.png.

cannot compute difference between binary files

Added modules/png/test-assets/bgai4a08.png.

cannot compute difference between binary files

Added modules/png/test-assets/bgai4a16.png.

cannot compute difference between binary files

Added modules/png/test-assets/bgan6a08.png.

cannot compute difference between binary files

Added modules/png/test-assets/bgan6a16.png.

cannot compute difference between binary files

Added modules/png/test-assets/bgbn4a08.png.

cannot compute difference between binary files

Added modules/png/test-assets/bggn4a16.png.

cannot compute difference between binary files

Added modules/png/test-assets/bgwn6a08.png.

cannot compute difference between binary files

Added modules/png/test-assets/bgyn6a16.png.

cannot compute difference between binary files

Added modules/png/test-assets/ccwn2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/ccwn3p08.png.

cannot compute difference between binary files

Added modules/png/test-assets/cdfn2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/cdhn2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/cdsn2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/cdun2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/ch1n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/ch2n3p08.png.

cannot compute difference between binary files

Added modules/png/test-assets/cm0n0g04.png.

cannot compute difference between binary files

Added modules/png/test-assets/cm7n0g04.png.

cannot compute difference between binary files

Added modules/png/test-assets/cm9n0g04.png.

cannot compute difference between binary files

Added modules/png/test-assets/cs3n2c16.png.

cannot compute difference between binary files

Added modules/png/test-assets/cs3n3p08.png.

cannot compute difference between binary files

Added modules/png/test-assets/cs5n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/cs5n3p08.png.

cannot compute difference between binary files

Added modules/png/test-assets/cs8n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/cs8n3p08.png.

cannot compute difference between binary files

Added modules/png/test-assets/ct0n0g04.png.

cannot compute difference between binary files

Added modules/png/test-assets/ct1n0g04.png.

cannot compute difference between binary files

Added modules/png/test-assets/ctzn0g04.png.

cannot compute difference between binary files

Added modules/png/test-assets/f00n0g08.png.

cannot compute difference between binary files

Added modules/png/test-assets/f00n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/f01n0g08.png.

cannot compute difference between binary files

Added modules/png/test-assets/f01n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/f02n0g08.png.

cannot compute difference between binary files

Added modules/png/test-assets/f02n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/f03n0g08.png.

cannot compute difference between binary files

Added modules/png/test-assets/f03n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/f04n0g08.png.

cannot compute difference between binary files

Added modules/png/test-assets/f04n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/g03n0g16.png.

cannot compute difference between binary files

Added modules/png/test-assets/g03n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/g03n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/g04n0g16.png.

cannot compute difference between binary files

Added modules/png/test-assets/g04n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/g04n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/g05n0g16.png.

cannot compute difference between binary files

Added modules/png/test-assets/g05n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/g05n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/g07n0g16.png.

cannot compute difference between binary files

Added modules/png/test-assets/g07n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/g07n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/g10n0g16.png.

cannot compute difference between binary files

Added modules/png/test-assets/g10n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/g10n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/g25n0g16.png.

cannot compute difference between binary files

Added modules/png/test-assets/g25n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/g25n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/oi1n0g16.png.

cannot compute difference between binary files

Added modules/png/test-assets/oi1n2c16.png.

cannot compute difference between binary files

Added modules/png/test-assets/oi2n0g16.png.

cannot compute difference between binary files

Added modules/png/test-assets/oi2n2c16.png.

cannot compute difference between binary files

Added modules/png/test-assets/oi4n0g16.png.

cannot compute difference between binary files

Added modules/png/test-assets/oi4n2c16.png.

cannot compute difference between binary files

Added modules/png/test-assets/oi9n0g16.png.

cannot compute difference between binary files

Added modules/png/test-assets/oi9n2c16.png.

cannot compute difference between binary files

Added modules/png/test-assets/physicaldimensions/basi0g01.png.

cannot compute difference between binary files

Added modules/png/test-assets/physicaldimensions/basi0g01_300dpi.png.

cannot compute difference between binary files

Added modules/png/test-assets/pngsuite.doc.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
        PNGSUITE
----------------

        testset for PNG-(de)coders
        created by Willem van Schaik
------------------------------------

This is a collection of graphics images created to test the png applications
like viewers, converters and editors. All (as far as that is possible)
formats supported by the PNG standard are represented.


1.      INTRODUCTION
--------------------

1.1     PNG capabilities
------------------------

Supported color-types are:

        -   grayscale
        -   grayscale + alpha-channel
        -   color palettes
        -   rgb
        -   rgb + alpha-channel

Allowed bitdepths are depending on the color-type, but are in the range
of 1-bit (grayscale, which is b&w) upto 16-bits.

Special features are:

        -   interlacing (Adam-7)
        -   gamma-support
        -   transparency (a poor-man's alpha solution)


1.2     File naming
-------------------

Where possible, the testfiles are 32x32 bits icons. This results in a still
reasonable size of the suite even with a large number of tests. The name
of each test-file reflects thetype in the following way:

        g04i2c08.png
        || |||+---- bit-depth
        || ||+----- color-type (descriptive)
        || |+------ color-type (numerical)
        || +------- interlaced or non-interlaced
        |+--------- parameter of test (in this case gamma-value)
        +---------- test feature (in this case gamma)


1.3     PNG formats
-------------------

color-type:
        0g          -   grayscale
        2c          -   rgb color
        3p          -   paletted
        4a          -   grayscale + alpha channel
        6a          -   rgb color + alpha channel

bit-depth:
        01          -   with color-type 0, 3
        02          -   with color-type 0, 3
        04          -   with color-type 0, 3
        08          -   with color-type 0, 2, 3, 4, 6
        16          -   with color-type 0, 2, 4, 6

interlacing:
        n           -   non-interlaced
        i           -   interlaced


2.      THE TESTS
-----------------

2.1     Sizes
-------------

These tests are there to check if your software handles pictures well, with
picture sizes that are not a multiple of 8. This is particularly important
with Adam-7 type interlacing. In the same way these tests check if pictures
size 1x1 and similar are ok.

        s01         -   1x1 pixel picture
        s02         -   2x2 pixel picture
        s03         -   3x3 pixel picture
        s04         -   4x4 pixel picture
        s05         -   5x5 pixel picture
        s06         -   6x6 pixel picture
        s07         -   7x7 pixel picture
        s08         -   8x8 pixel picture
        s09         -   9x9 pixel picture
        s32         -   32x32 pixel picture
        s33         -   33x33 pixel picture
        s34         -   34x34 pixel picture
        s35         -   35x35 pixel picture
        s36         -   36x36 pixel picture
        s37         -   37x37 pixel picture
        s38         -   38x38 pixel picture
        s39         -   39x39 pixel picture
        s40         -   40x40 pixel picture


2.2     Background
------------------

When the PNG file contains a background chunck, this should be used for
pictures with alpha-channel or pictures with a transparency chunck. For
pictures without this background-chunk, but with alpha, this testset
assumes a black background.

For the images in this test, the left-side should be 100% the background
color, where moving to the right the color should gradually become the
image pattern.

        bga         -   alpha + no background
        bgw         -   alpha + white background
        bgg         -   alpha + gray background
        bgb         -   alpha + black background
        bgy         -   alpha + yellow background


2.3     Transparency
--------------------

Transparency should be used together with a background chunk. To test the
combination of the two the latter 4 tests are there. How to handle pictures
with transparancy, but without a background, opinions can differ. Here we
use black, but especially in the case of paletted images, the normal color
would maybe even be better.

        tp0         -   not transparent for reference
        tp1         -   transparent, but no background chunk
        tbw         -   transparent + white background
        tbg         -   transparent + gray background
        tbb         -   transparent + black background
        tby         -   transparent + yellow background


2.4     Gamma
-------------

To test if your viewer handles gamma-correction, 6 testfiles are available.
They contain corrected color-ramps and a corresponding gamma-chunk with the
file-gamma value. These are created in such a way that when the viewer does
the gamma correction right, all 6 should be displayed identical.

If they are different, probably the gamma correction is omitted. In that
case, have a look at the two right coloumns in the 6 pictures. The image
where those two look the same (when looked from far) reflects the gamma of
your system. However, because of the limited size of the image, you should
do more elaborate tests to determine your display gamma.

        g03         -   file-gamma = 0.35, for display with gamma = 2.8
        g04         -   file-gamma = 0.45, for display with gamma = 2.2 (PC)
        g05         -   file-gamma = 0.55, for display with gamma = 1.8 (Mac)
        g07         -   file-gamma = 0.70, for display with gamma = 1.4
        g10         -   file-gamma = 1.00, for display with gamma = 1.0 (NeXT)
        g25         -   file-gamma = 2.50, for display with gamma = 0.4


2.5     Filtering
-----------------

PNG uses file-filtering, for optimal compression. Normally the type is of
filtering is adjusted to the contents of the picture, but here each file
has the same picture, with a different filtering.

        f0          -   no filtering
        f1          -   sub filtering
        f2          -   up filtering
        f3          -   average filtering
        f4          -   paeth filtering


2.6     Additional palettes
---------------------------

Besides the normal use of paletted images, palette chunks can in combination
with true-color (and other) images also be used to select color lookup-tables
when the video system is of limited capabilities. The suggested palette chunk
is specially created for this purpose.

        pp          -   normal palette chunk
        ps          -   suggested palette chunk


2.7     Ancillary chunks (under construction)
------------------------

To test the correct decoding of ancillary chunks, these test-files contain
one or more examples of these chunkcs. Depending on the type of chunk, a
number of typical values are selected to test. Unluckily, the testset can
not contain all combinations, because that would be an endless set.

The significant bits are used in files with the next higher bit-depth. They
indicate howmany bits are valid.

        cs3         -   3 significant bits
        cs5         -   5 significant bits
        cs8         -   8 significant bits (reference)
        cs3         -   13 significant bits

For the physical pixel dimensions, the result of each decoding should be
a sqare picture. The first (cdf) image is an example of flat (horizontal)
pixels, where the pHYS chunk (x is 1 per unit, y = 4 per unit) must take
care of the correction. The second is just the other way round. The last
example uses the unit specifier, for 1000 pixels per meter. This should
result in a picture of 3.2 cm square.

        cdf         -   physical pixel dimensions, 8x32 flat pixels
        cdh         -   physical pixel dimensions, 32x8 high pixels
        cds         -   physical pixel dimensions, 8x8 square pixels
        cdu         -   physical pixel dimensions, with unit-specifier

        ccw         -   primary chromaticities and white point

        ch1         -   histogram 15 colors
        ch2         -   histogram 256 colors

        cm7         -   modification time, 01-jan-1970
        cm9         -   modification time, 31-dec-1999
        cm0         -   modification time, 01-jan-2000

In the textual chunk, a number of the standard, and some non-standard
text items are included.

        ct0         -   no textual data
        ct1         -   with textual data
        ctz         -   with compressed textual data


2.8     Chunk ordering (still under construction)
----------------------

These testfiles will test the obligatory ordering relations between various
chunk types (not yet) as well as the number of data chunks used for the image.

        oi1         -   mother image with 1 idat-chunk
        oi2         -   image with 2 idat-chunks
        oi4         -   image with 4 unequal sized idat-chunks
        oi9         -   all idat-chunks of length one


2.9     Compression level
-------------------------

Here you will find a set of images compressed by zlib, ranging from level 0 
for no compression at maximum speed upto level 9 for maximum compression.

        z00         -   zlib compression level 0 - none
        z03         -   zlib compression level 3
        z06         -   zlib compression level 6 - default
        z09         -   zlib compression level 9 - maximum


2.10     Corrupted files (under construction)
-----------------------

All these files are illegal. When decoding they should generate appropriate
error-messages.

        x00         -   empty IDAT chunk
        xcr         -   added cr bytes
        xlf         -   added lf bytes
        xc0         -   color type 0
        xc9         -   color type 9
        xd0         -   bit-depth 0
        xd3         -   bit-depth 3
        xd9         -   bit-depth 99
        xcs         -   incorrect IDAT checksum


3.      TEST FILES
------------------

For each of the tests listed above, one or more test-files are created. A
selection is made (for each test) for the color-type and bitdepth to be used
for the tests. Further for a number of tests, both a non-interlaced as well
as an interlaced version is available.


3.1     Basic format test files (non-interlaced)
------------------------------------------------

        basn0g01    -   black & white
        basn0g02    -   2 bit (4 level) grayscale
        basn0g04    -   4 bit (16 level) grayscale
        basn0g08    -   8 bit (256 level) grayscale
        basn0g16    -   16 bit (64k level) grayscale
        basn2c08    -   3x8 bits rgb color
        basn2c16    -   3x16 bits rgb color
        basn3p01    -   1 bit (2 color) paletted
        basn3p02    -   2 bit (4 color) paletted
        basn3p04    -   4 bit (16 color) paletted
        basn3p08    -   8 bit (256 color) paletted
        basn4a08    -   8 bit grayscale + 8 bit alpha-channel
        basn4a16    -   16 bit grayscale + 16 bit alpha-channel
        basn6a08    -   3x8 bits rgb color + 8 bit alpha-channel
        basn6a16    -   3x16 bits rgb color + 16 bit alpha-channel


3.2     Basic format test files (Adam-7 interlaced)
---------------------------------------------------

        basi0g01    -   black & white
        basi0g02    -   2 bit (4 level) grayscale
        basi0g04    -   4 bit (16 level) grayscale
        basi0g08    -   8 bit (256 level) grayscale
        basi0g16    -   16 bit (64k level) grayscale
        basi2c08    -   3x8 bits rgb color
        basi2c16    -   3x16 bits rgb color
        basi3p01    -   1 bit (2 color) paletted
        basi3p02    -   2 bit (4 color) paletted
        basi3p04    -   4 bit (16 color) paletted
        basi3p08    -   8 bit (256 color) paletted
        basi4a08    -   8 bit grayscale + 8 bit alpha-channel
        basi4a16    -   16 bit grayscale + 16 bit alpha-channel
        basi6a08    -   3x8 bits rgb color + 8 bit alpha-channel
        basi6a16    -   3x16 bits rgb color + 16 bit alpha-channel


3.3     Sizes test files
-----------------------

        s01n3p01    -   1x1 paletted file, no interlacing
        s02n3p01    -   2x2 paletted file, no interlacing
        s03n3p01    -   3x3 paletted file, no interlacing
        s04n3p01    -   4x4 paletted file, no interlacing
        s05n3p02    -   5x5 paletted file, no interlacing
        s06n3p02    -   6x6 paletted file, no interlacing
        s07n3p02    -   7x7 paletted file, no interlacing
        s08n3p02    -   8x8 paletted file, no interlacing
        s09n3p02    -   9x9 paletted file, no interlacing
        s32n3p04    -   32x32 paletted file, no interlacing
        s33n3p04    -   33x33 paletted file, no interlacing
        s34n3p04    -   34x34 paletted file, no interlacing
        s35n3p04    -   35x35 paletted file, no interlacing
        s36n3p04    -   36x36 paletted file, no interlacing
        s37n3p04    -   37x37 paletted file, no interlacing
        s38n3p04    -   38x38 paletted file, no interlacing
        s39n3p04    -   39x39 paletted file, no interlacing
        s40n3p04    -   40x40 paletted file, no interlacing

        s01i3p01    -   1x1 paletted file, interlaced
        s02i3p01    -   2x2 paletted file, interlaced
        s03i3p01    -   3x3 paletted file, interlaced
        s04i3p01    -   4x4 paletted file, interlaced
        s05i3p02    -   5x5 paletted file, interlaced
        s06i3p02    -   6x6 paletted file, interlaced
        s07i3p02    -   7x7 paletted file, interlaced
        s08i3p02    -   8x8 paletted file, interlaced
        s09i3p02    -   9x9 paletted file, interlaced
        s32i3p04    -   32x32 paletted file, interlaced
        s33i3p04    -   33x33 paletted file, interlaced
        s34i3p04    -   34x34 paletted file, interlaced
        s35i3p04    -   35x35 paletted file, interlaced
        s36i3p04    -   36x36 paletted file, interlaced
        s37i3p04    -   37x37 paletted file, interlaced
        s38i3p04    -   38x38 paletted file, interlaced
        s39i3p04    -   39x39 paletted file, interlaced
        s40i3p04    -   40x40 paletted file, interlaced


3.4     Background test files (with alpha)
------------------------------------------

        bgai4a08    -   8 bit grayscale, alpha, no background chunk, interlaced
        bgai4a16    -   16 bit grayscale, alpha, no background chunk, interlaced
        bgan6a08    -   3x8 bits rgb color, alpha, no background chunk
        bgan6a16    -   3x16 bits rgb color, alpha, no background chunk

        bgbn4a08    -   8 bit grayscale, alpha, black background chunk
        bggn4a16    -   16 bit grayscale, alpha, gray background chunk
        bgwn6a08    -   3x8 bits rgb color, alpha, white background chunk
        bgyn6a16    -   3x16 bits rgb color, alpha, yellow background chunk


3.5     Transparency (and background) test files
------------------------------------------------

        tp0n1g08    -   not transparent for reference (logo on gray)
        tbbn1g04    -   transparent, black background chunk
        tbwn1g16    -   transparent, white background chunk
        tp0n2c08    -   not transparent for reference (logo on gray)
        tbrn2c08    -   transparent, red background chunk
        tbgn2c16    -   transparent, green background chunk
        tbbn2c16    -   transparent, blue background chunk
        tp0n3p08    -   not transparent for reference (logo on gray)
        tp1n3p08    -   transparent, but no background chunk
        tbbn3p08    -   transparent, black background chunk
        tbgn3p08    -   transparent, light-gray background chunk
        tbwn3p08    -   transparent, white background chunk
        tbyn3p08    -   transparent, yellow background chunk


3.6     Gamma test files
------------------------

        g03n0g16    -   grayscale, file-gamma = 0.35
        g04n0g16    -   grayscale, file-gamma = 0.45
        g05n0g16    -   grayscale, file-gamma = 0.55
        g07n0g16    -   grayscale, file-gamma = 0.70
        g10n0g16    -   grayscale, file-gamma = 1.00
        g25n0g16    -   grayscale, file-gamma = 2.50
        g03n2c08    -   color, file-gamma = 0.35
        g04n2c08    -   color, file-gamma = 0.45
        g05n2c08    -   color, file-gamma = 0.55
        g07n2c08    -   color, file-gamma = 0.70
        g10n2c08    -   color, file-gamma = 1.00
        g25n2c08    -   color, file-gamma = 2.50
        g03n3p04    -   paletted, file-gamma = 0.35
        g04n3p04    -   paletted, file-gamma = 0.45
        g05n3p04    -   paletted, file-gamma = 0.55
        g07n3p04    -   paletted, file-gamma = 0.70
        g10n3p04    -   paletted, file-gamma = 1.00
        g25n3p04    -   paletted, file-gamma = 2.50


3.7     Filtering test files
----------------------------

        f00n0g08    -   grayscale, no interlacing, filter-type 0
        f01n0g08    -   grayscale, no interlacing, filter-type 1
        f02n0g08    -   grayscale, no interlacing, filter-type 2
        f03n0g08    -   grayscale, no interlacing, filter-type 3
        f04n0g08    -   grayscale, no interlacing, filter-type 4
        f00n2c08    -   color, no interlacing, filter-type 0
        f01n2c08    -   color, no interlacing, filter-type 1
        f02n2c08    -   color, no interlacing, filter-type 2
        f03n2c08    -   color, no interlacing, filter-type 3
        f04n2c08    -   color, no interlacing, filter-type 4


3.8     Additional palette chunk test files
-------------------------------------------

        pp0n2c16    -   six-cube palette-chunk in true-color image
        pp0n6a08    -   six-cube palette-chunk in true-color+alpha image
        ps1n0g08    -   six-cube suggested palette (1 byte) in grayscale image
        ps1n2c16    -   six-cube suggested palette (1 byte) in true-color image
        ps2n0g08    -   six-cube suggested palette (2 bytes) in grayscale image
        ps2n2c16    -   six-cube suggested palette (2 bytes) in true-color image


3.9     Ancillary chunks test files
-----------------------------------

        cs5n2c08    -   color, 5 significant bits
        cs8n2c08    -   color, 8 significant bits (reference)
        cs3n2c16    -   color, 13 significant bits
        cs3n3p08    -   paletted, 3 significant bits
        cs5n3p08    -   paletted, 5 significant bits
        cs8n3p08    -   paletted, 8 significant bits (reference)

        cdfn2c08    -   physical pixel dimensions, 8x32 flat pixels
        cdhn2c08    -   physical pixel dimensions, 32x8 high pixels
        cdsn2c08    -   physical pixel dimensions, 8x8 square pixels
        cdun2c08    -   physical pixel dimensions, 1000 pixels per 1 meter

        ccwn2c08    -   chroma chunk w:0.3127,0.3290 r:0.64,0.33 g:0.30,0.60 b:0.15,0.06
        ccwn3p08    -   chroma chunk w:0.3127,0.3290 r:0.64,0.33 g:0.30,0.60 b:0.15,0.06

        ch1n3p04    -   histogram 15 colors
        ch2n3p08    -   histogram 256 colors

        cm7n0g04    -   modification time, 01-jan-1970 00:00:00
        cm9n0g04    -   modification time, 31-dec-1999 23:59:59
        cm0n0g04    -   modification time, 01-jan-2000 12:34:56

        ct0n0g04    -   no textual data
        ct1n0g04    -   with textual data
        ctzn0g04    -   with compressed textual data



3.10    Chunk ordering
----------------------

        oi1n0g16    -   grayscale mother image with 1 idat-chunk
        oi2n0g16    -   grayscale image with 2 idat-chunks
        oi4n0g16    -   grayscale image with 4 unequal sized idat-chunks
        oi9n0g16    -   grayscale image with all idat-chunks length one
        oi1n2c16    -   color mother image with 1 idat-chunk
        oi2n2c16    -   color image with 2 idat-chunks
        oi4n2c16    -   color image with 4 unequal sized idat-chunks
        oi9n2c16    -   color image with all idat-chunks length one



3.11    Compression level
-------------------------

        z00n2c08    -   color, no interlacing, compression level 0 (none)
        z03n2c08    -   color, no interlacing, compression level 3
        z06n2c08    -   color, no interlacing, compression level 6 (default)
        z09n2c08    -   color, no interlacing, compression level 9 (maximum)



3.12     Currupted files
-----------------------

        x00n0g01    -   empty 0x0 grayscale file
        xcrn0g04    -   added cr bytes
        xlfn0g04    -   added lf bytes
        xc0n0c08    -   color type 0
        xc9n0c08    -   color type 9
        xd0n2c00    -   bit-depth 0
        xd3n2c03    -   bit-depth 3
        xd9n2c99    -   bit-depth 99
        xcsn2c08    -   incorrect IDAT checksum


--------
    (c) Willem van Schaik
        [email protected]
        Singapore, October 1996

Added modules/png/test-assets/pngsuite_logo.png.

cannot compute difference between binary files

Added modules/png/test-assets/pp0n2c16.png.

cannot compute difference between binary files

Added modules/png/test-assets/pp0n6a08.png.

cannot compute difference between binary files

Added modules/png/test-assets/ps1n0g08.png.

cannot compute difference between binary files

Added modules/png/test-assets/ps1n2c16.png.

cannot compute difference between binary files

Added modules/png/test-assets/ps2n0g08.png.

cannot compute difference between binary files

Added modules/png/test-assets/ps2n2c16.png.

cannot compute difference between binary files

Added modules/png/test-assets/s01i3p01.png.

cannot compute difference between binary files

Added modules/png/test-assets/s01n3p01.png.

cannot compute difference between binary files

Added modules/png/test-assets/s02i3p01.png.

cannot compute difference between binary files

Added modules/png/test-assets/s02n3p01.png.

cannot compute difference between binary files

Added modules/png/test-assets/s03i3p01.png.

cannot compute difference between binary files

Added modules/png/test-assets/s03n3p01.png.

cannot compute difference between binary files

Added modules/png/test-assets/s04i3p01.png.

cannot compute difference between binary files

Added modules/png/test-assets/s04n3p01.png.

cannot compute difference between binary files

Added modules/png/test-assets/s05i3p02.png.

cannot compute difference between binary files

Added modules/png/test-assets/s05n3p02.png.

cannot compute difference between binary files

Added modules/png/test-assets/s06i3p02.png.

cannot compute difference between binary files

Added modules/png/test-assets/s06n3p02.png.

cannot compute difference between binary files

Added modules/png/test-assets/s07i3p02.png.

cannot compute difference between binary files

Added modules/png/test-assets/s07n3p02.png.

cannot compute difference between binary files

Added modules/png/test-assets/s08i3p02.png.

cannot compute difference between binary files

Added modules/png/test-assets/s08n3p02.png.

cannot compute difference between binary files

Added modules/png/test-assets/s09i3p02.png.

cannot compute difference between binary files

Added modules/png/test-assets/s09n3p02.png.

cannot compute difference between binary files

Added modules/png/test-assets/s32i3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s32n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s33i3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s33n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s34i3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s34n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s35i3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s35n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s36i3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s36n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s37i3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s37n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s38i3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s38n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s39i3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s39n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s40i3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/s40n3p04.png.

cannot compute difference between binary files

Added modules/png/test-assets/tbbn1g04.png.

cannot compute difference between binary files

Added modules/png/test-assets/tbbn2c16.png.

cannot compute difference between binary files

Added modules/png/test-assets/tbbn3p08.png.

cannot compute difference between binary files

Added modules/png/test-assets/tbgn2c16.png.

cannot compute difference between binary files

Added modules/png/test-assets/tbgn3p08.png.

cannot compute difference between binary files

Added modules/png/test-assets/tbrn2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/tbwn1g16.png.

cannot compute difference between binary files

Added modules/png/test-assets/tbwn3p08.png.

cannot compute difference between binary files

Added modules/png/test-assets/tbyn3p08.png.

cannot compute difference between binary files

Added modules/png/test-assets/tp0n1g08.png.

cannot compute difference between binary files

Added modules/png/test-assets/tp0n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/tp0n3p08.png.

cannot compute difference between binary files

Added modules/png/test-assets/tp1n3p08.png.

cannot compute difference between binary files

Added modules/png/test-assets/x00n0g01.png.

cannot compute difference between binary files

Added modules/png/test-assets/xcrn0g04.png.

cannot compute difference between binary files

Added modules/png/test-assets/xlfn0g04.png.



























>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
�PNG





IHDR  ���)�IDATx�]��
�0P*@��#�

#T��10lPF`ؠF=���IQ�*��u�`%qk�
H�񚈩�m�����ߟ	э=,�f�OK

���t��(������F;�P����{xp�]9�/p�*$(�*�y�Ճ�������@�C� 	c�q��N�U#�)11�.��r��f�0���gh(��t���E���kIEND�B`�

Added modules/png/test-assets/z00n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/z03n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/z06n2c08.png.

cannot compute difference between binary files

Added modules/png/test-assets/z09n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basi0g01.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basi0g02.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basi0g04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basi0g08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basi0g16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basi2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basi2c16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basi3p01.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basi3p02.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basi3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basi3p08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basi4a08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basi4a16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basi6a08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basi6a16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basn0g01.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basn0g02.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basn0g04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basn0g08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basn0g16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basn2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basn2c16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basn3p01.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basn3p02.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basn3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basn3p08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basn4a08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basn4a16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basn6a08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/basn6a16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/bgai4a08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/bgai4a16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/bgan6a08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/bgan6a16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/bgbn4a08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/bggn4a16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/bgwn6a08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/bgyn6a16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/ccwn2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/ccwn3p08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/cdfn2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/cdhn2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/cdsn2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/cdun2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/ch1n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/ch2n3p08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/cm0n0g04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/cm7n0g04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/cm9n0g04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/cs3n2c16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/cs3n3p08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/cs5n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/cs5n3p08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/cs8n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/cs8n3p08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/ct0n0g04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/ct1n0g04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/ctzn0g04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/f00n0g08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/f00n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/f01n0g08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/f01n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/f02n0g08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/f02n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/f03n0g08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/f03n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/f04n0g08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/f04n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g03n0g16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g03n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g03n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g04n0g16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g04n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g04n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g05n0g16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g05n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g05n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g07n0g16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g07n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g07n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g10n0g16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g10n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g10n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g25n0g16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g25n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/g25n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/oi1n0g16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/oi1n2c16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/oi2n0g16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/oi2n2c16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/oi4n0g16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/oi4n2c16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/oi9n0g16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/oi9n2c16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/physicaldimensions/basi0g01.png.

cannot compute difference between binary files

Deleted modules/png/testimages/physicaldimensions/basi0g01_300dpi.png.

cannot compute difference between binary files

Deleted modules/png/testimages/pngsuite.doc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
        PNGSUITE
----------------

        testset for PNG-(de)coders
        created by Willem van Schaik
------------------------------------

This is a collection of graphics images created to test the png applications
like viewers, converters and editors. All (as far as that is possible)
formats supported by the PNG standard are represented.


1.      INTRODUCTION
--------------------

1.1     PNG capabilities
------------------------

Supported color-types are:

        -   grayscale
        -   grayscale + alpha-channel
        -   color palettes
        -   rgb
        -   rgb + alpha-channel

Allowed bitdepths are depending on the color-type, but are in the range
of 1-bit (grayscale, which is b&w) upto 16-bits.

Special features are:

        -   interlacing (Adam-7)
        -   gamma-support
        -   transparency (a poor-man's alpha solution)


1.2     File naming
-------------------

Where possible, the testfiles are 32x32 bits icons. This results in a still
reasonable size of the suite even with a large number of tests. The name
of each test-file reflects thetype in the following way:

        g04i2c08.png
        || |||+---- bit-depth
        || ||+----- color-type (descriptive)
        || |+------ color-type (numerical)
        || +------- interlaced or non-interlaced
        |+--------- parameter of test (in this case gamma-value)
        +---------- test feature (in this case gamma)


1.3     PNG formats
-------------------

color-type:
        0g          -   grayscale
        2c          -   rgb color
        3p          -   paletted
        4a          -   grayscale + alpha channel
        6a          -   rgb color + alpha channel

bit-depth:
        01          -   with color-type 0, 3
        02          -   with color-type 0, 3
        04          -   with color-type 0, 3
        08          -   with color-type 0, 2, 3, 4, 6
        16          -   with color-type 0, 2, 4, 6

interlacing:
        n           -   non-interlaced
        i           -   interlaced


2.      THE TESTS
-----------------

2.1     Sizes
-------------

These tests are there to check if your software handles pictures well, with
picture sizes that are not a multiple of 8. This is particularly important
with Adam-7 type interlacing. In the same way these tests check if pictures
size 1x1 and similar are ok.

        s01         -   1x1 pixel picture
        s02         -   2x2 pixel picture
        s03         -   3x3 pixel picture
        s04         -   4x4 pixel picture
        s05         -   5x5 pixel picture
        s06         -   6x6 pixel picture
        s07         -   7x7 pixel picture
        s08         -   8x8 pixel picture
        s09         -   9x9 pixel picture
        s32         -   32x32 pixel picture
        s33         -   33x33 pixel picture
        s34         -   34x34 pixel picture
        s35         -   35x35 pixel picture
        s36         -   36x36 pixel picture
        s37         -   37x37 pixel picture
        s38         -   38x38 pixel picture
        s39         -   39x39 pixel picture
        s40         -   40x40 pixel picture


2.2     Background
------------------

When the PNG file contains a background chunck, this should be used for
pictures with alpha-channel or pictures with a transparency chunck. For
pictures without this background-chunk, but with alpha, this testset
assumes a black background.

For the images in this test, the left-side should be 100% the background
color, where moving to the right the color should gradually become the
image pattern.

        bga         -   alpha + no background
        bgw         -   alpha + white background
        bgg         -   alpha + gray background
        bgb         -   alpha + black background
        bgy         -   alpha + yellow background


2.3     Transparency
--------------------

Transparency should be used together with a background chunk. To test the
combination of the two the latter 4 tests are there. How to handle pictures
with transparancy, but without a background, opinions can differ. Here we
use black, but especially in the case of paletted images, the normal color
would maybe even be better.

        tp0         -   not transparent for reference
        tp1         -   transparent, but no background chunk
        tbw         -   transparent + white background
        tbg         -   transparent + gray background
        tbb         -   transparent + black background
        tby         -   transparent + yellow background


2.4     Gamma
-------------

To test if your viewer handles gamma-correction, 6 testfiles are available.
They contain corrected color-ramps and a corresponding gamma-chunk with the
file-gamma value. These are created in such a way that when the viewer does
the gamma correction right, all 6 should be displayed identical.

If they are different, probably the gamma correction is omitted. In that
case, have a look at the two right coloumns in the 6 pictures. The image
where those two look the same (when looked from far) reflects the gamma of
your system. However, because of the limited size of the image, you should
do more elaborate tests to determine your display gamma.

        g03         -   file-gamma = 0.35, for display with gamma = 2.8
        g04         -   file-gamma = 0.45, for display with gamma = 2.2 (PC)
        g05         -   file-gamma = 0.55, for display with gamma = 1.8 (Mac)
        g07         -   file-gamma = 0.70, for display with gamma = 1.4
        g10         -   file-gamma = 1.00, for display with gamma = 1.0 (NeXT)
        g25         -   file-gamma = 2.50, for display with gamma = 0.4


2.5     Filtering
-----------------

PNG uses file-filtering, for optimal compression. Normally the type is of
filtering is adjusted to the contents of the picture, but here each file
has the same picture, with a different filtering.

        f0          -   no filtering
        f1          -   sub filtering
        f2          -   up filtering
        f3          -   average filtering
        f4          -   paeth filtering


2.6     Additional palettes
---------------------------

Besides the normal use of paletted images, palette chunks can in combination
with true-color (and other) images also be used to select color lookup-tables
when the video system is of limited capabilities. The suggested palette chunk
is specially created for this purpose.

        pp          -   normal palette chunk
        ps          -   suggested palette chunk


2.7     Ancillary chunks (under construction)
------------------------

To test the correct decoding of ancillary chunks, these test-files contain
one or more examples of these chunkcs. Depending on the type of chunk, a
number of typical values are selected to test. Unluckily, the testset can
not contain all combinations, because that would be an endless set.

The significant bits are used in files with the next higher bit-depth. They
indicate howmany bits are valid.

        cs3         -   3 significant bits
        cs5         -   5 significant bits
        cs8         -   8 significant bits (reference)
        cs3         -   13 significant bits

For the physical pixel dimensions, the result of each decoding should be
a sqare picture. The first (cdf) image is an example of flat (horizontal)
pixels, where the pHYS chunk (x is 1 per unit, y = 4 per unit) must take
care of the correction. The second is just the other way round. The last
example uses the unit specifier, for 1000 pixels per meter. This should
result in a picture of 3.2 cm square.

        cdf         -   physical pixel dimensions, 8x32 flat pixels
        cdh         -   physical pixel dimensions, 32x8 high pixels
        cds         -   physical pixel dimensions, 8x8 square pixels
        cdu         -   physical pixel dimensions, with unit-specifier

        ccw         -   primary chromaticities and white point

        ch1         -   histogram 15 colors
        ch2         -   histogram 256 colors

        cm7         -   modification time, 01-jan-1970
        cm9         -   modification time, 31-dec-1999
        cm0         -   modification time, 01-jan-2000

In the textual chunk, a number of the standard, and some non-standard
text items are included.

        ct0         -   no textual data
        ct1         -   with textual data
        ctz         -   with compressed textual data


2.8     Chunk ordering (still under construction)
----------------------

These testfiles will test the obligatory ordering relations between various
chunk types (not yet) as well as the number of data chunks used for the image.

        oi1         -   mother image with 1 idat-chunk
        oi2         -   image with 2 idat-chunks
        oi4         -   image with 4 unequal sized idat-chunks
        oi9         -   all idat-chunks of length one


2.9     Compression level
-------------------------

Here you will find a set of images compressed by zlib, ranging from level 0 
for no compression at maximum speed upto level 9 for maximum compression.

        z00         -   zlib compression level 0 - none
        z03         -   zlib compression level 3
        z06         -   zlib compression level 6 - default
        z09         -   zlib compression level 9 - maximum


2.10     Corrupted files (under construction)
-----------------------

All these files are illegal. When decoding they should generate appropriate
error-messages.

        x00         -   empty IDAT chunk
        xcr         -   added cr bytes
        xlf         -   added lf bytes
        xc0         -   color type 0
        xc9         -   color type 9
        xd0         -   bit-depth 0
        xd3         -   bit-depth 3
        xd9         -   bit-depth 99
        xcs         -   incorrect IDAT checksum


3.      TEST FILES
------------------

For each of the tests listed above, one or more test-files are created. A
selection is made (for each test) for the color-type and bitdepth to be used
for the tests. Further for a number of tests, both a non-interlaced as well
as an interlaced version is available.


3.1     Basic format test files (non-interlaced)
------------------------------------------------

        basn0g01    -   black & white
        basn0g02    -   2 bit (4 level) grayscale
        basn0g04    -   4 bit (16 level) grayscale
        basn0g08    -   8 bit (256 level) grayscale
        basn0g16    -   16 bit (64k level) grayscale
        basn2c08    -   3x8 bits rgb color
        basn2c16    -   3x16 bits rgb color
        basn3p01    -   1 bit (2 color) paletted
        basn3p02    -   2 bit (4 color) paletted
        basn3p04    -   4 bit (16 color) paletted
        basn3p08    -   8 bit (256 color) paletted
        basn4a08    -   8 bit grayscale + 8 bit alpha-channel
        basn4a16    -   16 bit grayscale + 16 bit alpha-channel
        basn6a08    -   3x8 bits rgb color + 8 bit alpha-channel
        basn6a16    -   3x16 bits rgb color + 16 bit alpha-channel


3.2     Basic format test files (Adam-7 interlaced)
---------------------------------------------------

        basi0g01    -   black & white
        basi0g02    -   2 bit (4 level) grayscale
        basi0g04    -   4 bit (16 level) grayscale
        basi0g08    -   8 bit (256 level) grayscale
        basi0g16    -   16 bit (64k level) grayscale
        basi2c08    -   3x8 bits rgb color
        basi2c16    -   3x16 bits rgb color
        basi3p01    -   1 bit (2 color) paletted
        basi3p02    -   2 bit (4 color) paletted
        basi3p04    -   4 bit (16 color) paletted
        basi3p08    -   8 bit (256 color) paletted
        basi4a08    -   8 bit grayscale + 8 bit alpha-channel
        basi4a16    -   16 bit grayscale + 16 bit alpha-channel
        basi6a08    -   3x8 bits rgb color + 8 bit alpha-channel
        basi6a16    -   3x16 bits rgb color + 16 bit alpha-channel


3.3     Sizes test files
-----------------------

        s01n3p01    -   1x1 paletted file, no interlacing
        s02n3p01    -   2x2 paletted file, no interlacing
        s03n3p01    -   3x3 paletted file, no interlacing
        s04n3p01    -   4x4 paletted file, no interlacing
        s05n3p02    -   5x5 paletted file, no interlacing
        s06n3p02    -   6x6 paletted file, no interlacing
        s07n3p02    -   7x7 paletted file, no interlacing
        s08n3p02    -   8x8 paletted file, no interlacing
        s09n3p02    -   9x9 paletted file, no interlacing
        s32n3p04    -   32x32 paletted file, no interlacing
        s33n3p04    -   33x33 paletted file, no interlacing
        s34n3p04    -   34x34 paletted file, no interlacing
        s35n3p04    -   35x35 paletted file, no interlacing
        s36n3p04    -   36x36 paletted file, no interlacing
        s37n3p04    -   37x37 paletted file, no interlacing
        s38n3p04    -   38x38 paletted file, no interlacing
        s39n3p04    -   39x39 paletted file, no interlacing
        s40n3p04    -   40x40 paletted file, no interlacing

        s01i3p01    -   1x1 paletted file, interlaced
        s02i3p01    -   2x2 paletted file, interlaced
        s03i3p01    -   3x3 paletted file, interlaced
        s04i3p01    -   4x4 paletted file, interlaced
        s05i3p02    -   5x5 paletted file, interlaced
        s06i3p02    -   6x6 paletted file, interlaced
        s07i3p02    -   7x7 paletted file, interlaced
        s08i3p02    -   8x8 paletted file, interlaced
        s09i3p02    -   9x9 paletted file, interlaced
        s32i3p04    -   32x32 paletted file, interlaced
        s33i3p04    -   33x33 paletted file, interlaced
        s34i3p04    -   34x34 paletted file, interlaced
        s35i3p04    -   35x35 paletted file, interlaced
        s36i3p04    -   36x36 paletted file, interlaced
        s37i3p04    -   37x37 paletted file, interlaced
        s38i3p04    -   38x38 paletted file, interlaced
        s39i3p04    -   39x39 paletted file, interlaced
        s40i3p04    -   40x40 paletted file, interlaced


3.4     Background test files (with alpha)
------------------------------------------

        bgai4a08    -   8 bit grayscale, alpha, no background chunk, interlaced
        bgai4a16    -   16 bit grayscale, alpha, no background chunk, interlaced
        bgan6a08    -   3x8 bits rgb color, alpha, no background chunk
        bgan6a16    -   3x16 bits rgb color, alpha, no background chunk

        bgbn4a08    -   8 bit grayscale, alpha, black background chunk
        bggn4a16    -   16 bit grayscale, alpha, gray background chunk
        bgwn6a08    -   3x8 bits rgb color, alpha, white background chunk
        bgyn6a16    -   3x16 bits rgb color, alpha, yellow background chunk


3.5     Transparency (and background) test files
------------------------------------------------

        tp0n1g08    -   not transparent for reference (logo on gray)
        tbbn1g04    -   transparent, black background chunk
        tbwn1g16    -   transparent, white background chunk
        tp0n2c08    -   not transparent for reference (logo on gray)
        tbrn2c08    -   transparent, red background chunk
        tbgn2c16    -   transparent, green background chunk
        tbbn2c16    -   transparent, blue background chunk
        tp0n3p08    -   not transparent for reference (logo on gray)
        tp1n3p08    -   transparent, but no background chunk
        tbbn3p08    -   transparent, black background chunk
        tbgn3p08    -   transparent, light-gray background chunk
        tbwn3p08    -   transparent, white background chunk
        tbyn3p08    -   transparent, yellow background chunk


3.6     Gamma test files
------------------------

        g03n0g16    -   grayscale, file-gamma = 0.35
        g04n0g16    -   grayscale, file-gamma = 0.45
        g05n0g16    -   grayscale, file-gamma = 0.55
        g07n0g16    -   grayscale, file-gamma = 0.70
        g10n0g16    -   grayscale, file-gamma = 1.00
        g25n0g16    -   grayscale, file-gamma = 2.50
        g03n2c08    -   color, file-gamma = 0.35
        g04n2c08    -   color, file-gamma = 0.45
        g05n2c08    -   color, file-gamma = 0.55
        g07n2c08    -   color, file-gamma = 0.70
        g10n2c08    -   color, file-gamma = 1.00
        g25n2c08    -   color, file-gamma = 2.50
        g03n3p04    -   paletted, file-gamma = 0.35
        g04n3p04    -   paletted, file-gamma = 0.45
        g05n3p04    -   paletted, file-gamma = 0.55
        g07n3p04    -   paletted, file-gamma = 0.70
        g10n3p04    -   paletted, file-gamma = 1.00
        g25n3p04    -   paletted, file-gamma = 2.50


3.7     Filtering test files
----------------------------

        f00n0g08    -   grayscale, no interlacing, filter-type 0
        f01n0g08    -   grayscale, no interlacing, filter-type 1
        f02n0g08    -   grayscale, no interlacing, filter-type 2
        f03n0g08    -   grayscale, no interlacing, filter-type 3
        f04n0g08    -   grayscale, no interlacing, filter-type 4
        f00n2c08    -   color, no interlacing, filter-type 0
        f01n2c08    -   color, no interlacing, filter-type 1
        f02n2c08    -   color, no interlacing, filter-type 2
        f03n2c08    -   color, no interlacing, filter-type 3
        f04n2c08    -   color, no interlacing, filter-type 4


3.8     Additional palette chunk test files
-------------------------------------------

        pp0n2c16    -   six-cube palette-chunk in true-color image
        pp0n6a08    -   six-cube palette-chunk in true-color+alpha image
        ps1n0g08    -   six-cube suggested palette (1 byte) in grayscale image
        ps1n2c16    -   six-cube suggested palette (1 byte) in true-color image
        ps2n0g08    -   six-cube suggested palette (2 bytes) in grayscale image
        ps2n2c16    -   six-cube suggested palette (2 bytes) in true-color image


3.9     Ancillary chunks test files
-----------------------------------

        cs5n2c08    -   color, 5 significant bits
        cs8n2c08    -   color, 8 significant bits (reference)
        cs3n2c16    -   color, 13 significant bits
        cs3n3p08    -   paletted, 3 significant bits
        cs5n3p08    -   paletted, 5 significant bits
        cs8n3p08    -   paletted, 8 significant bits (reference)

        cdfn2c08    -   physical pixel dimensions, 8x32 flat pixels
        cdhn2c08    -   physical pixel dimensions, 32x8 high pixels
        cdsn2c08    -   physical pixel dimensions, 8x8 square pixels
        cdun2c08    -   physical pixel dimensions, 1000 pixels per 1 meter

        ccwn2c08    -   chroma chunk w:0.3127,0.3290 r:0.64,0.33 g:0.30,0.60 b:0.15,0.06
        ccwn3p08    -   chroma chunk w:0.3127,0.3290 r:0.64,0.33 g:0.30,0.60 b:0.15,0.06

        ch1n3p04    -   histogram 15 colors
        ch2n3p08    -   histogram 256 colors

        cm7n0g04    -   modification time, 01-jan-1970 00:00:00
        cm9n0g04    -   modification time, 31-dec-1999 23:59:59
        cm0n0g04    -   modification time, 01-jan-2000 12:34:56

        ct0n0g04    -   no textual data
        ct1n0g04    -   with textual data
        ctzn0g04    -   with compressed textual data



3.10    Chunk ordering
----------------------

        oi1n0g16    -   grayscale mother image with 1 idat-chunk
        oi2n0g16    -   grayscale image with 2 idat-chunks
        oi4n0g16    -   grayscale image with 4 unequal sized idat-chunks
        oi9n0g16    -   grayscale image with all idat-chunks length one
        oi1n2c16    -   color mother image with 1 idat-chunk
        oi2n2c16    -   color image with 2 idat-chunks
        oi4n2c16    -   color image with 4 unequal sized idat-chunks
        oi9n2c16    -   color image with all idat-chunks length one



3.11    Compression level
-------------------------

        z00n2c08    -   color, no interlacing, compression level 0 (none)
        z03n2c08    -   color, no interlacing, compression level 3
        z06n2c08    -   color, no interlacing, compression level 6 (default)
        z09n2c08    -   color, no interlacing, compression level 9 (maximum)



3.12     Currupted files
-----------------------

        x00n0g01    -   empty 0x0 grayscale file
        xcrn0g04    -   added cr bytes
        xlfn0g04    -   added lf bytes
        xc0n0c08    -   color type 0
        xc9n0c08    -   color type 9
        xd0n2c00    -   bit-depth 0
        xd3n2c03    -   bit-depth 3
        xd9n2c99    -   bit-depth 99
        xcsn2c08    -   incorrect IDAT checksum


--------
    (c) Willem van Schaik
        [email protected]
        Singapore, October 1996
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Deleted modules/png/testimages/pngsuite_logo.png.

cannot compute difference between binary files

Deleted modules/png/testimages/pp0n2c16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/pp0n6a08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/ps1n0g08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/ps1n2c16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/ps2n0g08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/ps2n2c16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s01i3p01.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s01n3p01.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s02i3p01.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s02n3p01.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s03i3p01.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s03n3p01.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s04i3p01.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s04n3p01.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s05i3p02.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s05n3p02.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s06i3p02.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s06n3p02.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s07i3p02.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s07n3p02.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s08i3p02.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s08n3p02.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s09i3p02.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s09n3p02.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s32i3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s32n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s33i3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s33n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s34i3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s34n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s35i3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s35n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s36i3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s36n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s37i3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s37n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s38i3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s38n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s39i3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s39n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s40i3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/s40n3p04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/tbbn1g04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/tbbn2c16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/tbbn3p08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/tbgn2c16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/tbgn3p08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/tbrn2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/tbwn1g16.png.

cannot compute difference between binary files

Deleted modules/png/testimages/tbwn3p08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/tbyn3p08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/tp0n1g08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/tp0n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/tp0n3p08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/tp1n3p08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/x00n0g01.png.

cannot compute difference between binary files

Deleted modules/png/testimages/xcrn0g04.png.

cannot compute difference between binary files

Deleted modules/png/testimages/xlfn0g04.png.

1
2
3
4
5
6
7
8
9
10
11
12
13
�PNG





IHDR  ���)�IDATx�]��
�0P*@��#�

#T��10lPF`ؠF=���IQ�*��u�`%qk�
H�񚈩�m�����ߟ	э=,�f�OK

���t��(������F;�P����{xp�]9�/p�*$(�*�y�Ճ�������@�C� 	c�q��N�U#�)11�.��r��f�0���gh(��t���E���kIEND�B`�
<
<
<
<
<
<
<
<
<
<
<
<
<


























Deleted modules/png/testimages/z00n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/z03n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/z06n2c08.png.

cannot compute difference between binary files

Deleted modules/png/testimages/z09n2c08.png.

cannot compute difference between binary files

Changes to modules/pop3/pop3.man.

266
267
268
269
270
271
272
273
274
	pop3::open -stls 1 \\
		$thehost $theuser $thepassword

	...
}]

[vset CATEGORY pop3]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

266
267
268
269
270
271
272
273
274
	pop3::open -stls 1 \\
		$thehost $theuser $thepassword

	...
}]

[vset CATEGORY pop3]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/pop3d/pop3d.man.

265
266
267
268
269
270
271
272
273

[list_begin enumerated]
[enum] [uri http://www.rfc-editor.org/rfc/rfc1939.txt {RFC 1939}]
[enum] [uri http://www.rfc-editor.org/rfc/rfc2449.txt {RFC 2449}]
[list_end]

[vset CATEGORY pop3d]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

265
266
267
268
269
270
271
272
273

[list_begin enumerated]
[enum] [uri http://www.rfc-editor.org/rfc/rfc1939.txt {RFC 1939}]
[enum] [uri http://www.rfc-editor.org/rfc/rfc2449.txt {RFC 2449}]
[list_end]

[vset CATEGORY pop3d]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/pop3d/pop3d_dbox.man.

156
157
158
159
160
161
162
163
164
call will fail. If [method stat] was not called
before this call, [method get] will assume
that there are zero messages in the mailbox.

[list_end]

[vset CATEGORY pop3d]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

156
157
158
159
160
161
162
163
164
call will fail. If [method stat] was not called
before this call, [method get] will assume
that there are zero messages in the mailbox.

[list_end]

[vset CATEGORY pop3d]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/pop3d/pop3d_udb.man.

104
105
106
107
108
109
110
111
112
remembered internally so that it can be used in the next call of

[arg dbName] [method save] without an argument.

[list_end]

[vset CATEGORY pop3d]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

104
105
106
107
108
109
110
111
112
remembered internally so that it can be used in the next call of

[arg dbName] [method save] without an argument.

[list_end]

[vset CATEGORY pop3d]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/practcl/build/build.tcl.

1
2

3


4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

35
36
37
38
39


40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
set srcdir [file dirname [file normalize [file join [pwd] [info script]]]]
set moddir [file dirname $srcdir]




set version 0.11.1
set tclversion 8.5
set module [file tail $moddir]


set fout [open [file join $moddir [file tail $module].tcl] w]
fconfigure $fout -translation lf
dict set map %module% $module
dict set map %version% $version
dict set map %tclversion% $tclversion
dict set map {    } {}
dict set map "\t" {    }

puts $fout [string map $map {###
    # Amalgamated package for %module%
    # Do not edit directly, tweak the source in src/ and rerun
    # build.tcl
    ###
    package require Tcl %tclversion%
    package provide %module% %version%
    namespace eval ::%module% {}
}]

# Track what files we have included so far
set loaded {}
# These files must be loaded in a particular order

###
# Load other module code that this module will need
###
foreach {omod files} {
  httpwget wget.tcl

} {
  foreach fname $files {
    set file [file join $moddir .. $omod $fname]
    set fin [open $file r]
    puts $fout "###\n# START: [file join $omod $fname]\n###"


    puts $fout [read $fin]
    close $fin
    puts $fout "###\n# END: [file join $omod $fname]\n###"
  }
}

foreach file {
  setup.tcl

  buildutil.tcl
  fileutil.tcl
  installutil.tcl
  makeutil.tcl
  {class metaclass.tcl}

  {class toolset baseclass.tcl}


>

>
>
|
|

>

|

|
|
|
|
|

|
|
|
|
|
|
|
|











>



<

>
>
|
<




|

>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

43
44
45
46

47
48
49
50
51
52
53
54
55
56
57
58
59
60
set srcdir [file dirname [file normalize [file join [pwd] [info script]]]]
set moddir [file dirname $srcdir]
source [file join $srcdir doctool.tcl]

::practcl::doctool create AutoDoc

set version 0.16.4
set tclversion 8.6
set module [file tail $moddir]
set filename $module

set fout [open [file join $moddir $filename.tcl] w]
fconfigure $fout -translation lf
dict set modmap %module% $module
dict set modmap %version% $version
dict set modmap %tclversion% $tclversion
#dict set modmap {    } {}
#dict set modmap "\t" {    }

puts $fout [string map $modmap {###
# Amalgamated package for %module%
# Do not edit directly, tweak the source in src/ and rerun
# build.tcl
###
package require Tcl %tclversion%
package provide %module% %version%
namespace eval ::%module% {}
}]

# Track what files we have included so far
set loaded {}
# These files must be loaded in a particular order

###
# Load other module code that this module will need
###
foreach {omod files} {
  httpwget wget.tcl
  clay {clay.tcl}
} {
  foreach fname $files {
    set file [file join $moddir .. $omod $fname]

    puts $fout "###\n# START: [file join $omod $fname]\n###"
    set content [::practcl::cat [file join $moddir .. $omod $fname]]
    #AutoDoc scan_text $content
    puts $fout [::practcl::docstrip $content]

    puts $fout "###\n# END: [file join $omod $fname]\n###"
  }
}

foreach {file} {
  setup.tcl
  doctool.tcl
  buildutil.tcl
  fileutil.tcl
  installutil.tcl
  makeutil.tcl
  {class metaclass.tcl}

  {class toolset baseclass.tcl}
74
75
76
77
78
79
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








  {class subproject binary.tcl}
  {class subproject core.tcl}

  {class tool.tcl}

} {
  lappend loaded $file
  set fin [open [file join $srcdir {*}$file] r]
  puts $fout "###\n# START: [file join $file]\n###"


  puts $fout [read $fin]
  close $fin
  puts $fout "###\n# END: [file join $file]\n###"
}


# Provide some cleanup and our final package provide
puts $fout [string map $map {
namespace eval ::%module% {
  namespace export *
}
}]
close $fout

###
# Build our pkgIndex.tcl file
###
set fout [open [file join $moddir pkgIndex.tcl] w]
fconfigure $fout -translation lf
puts $fout [string map $map {###
    if {![package vsatisfies [package provide Tcl] %tclversion%]} {return}
    package ifneeded %module% %version% [list source [file join $dir %module%.tcl]]
}]
close $fout















<

>
>
|
<



<

|











|
|
|


>
>
>
>
>
>
>
>
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
  {class subproject binary.tcl}
  {class subproject core.tcl}

  {class tool.tcl}

} {
  lappend loaded $file

  puts $fout "###\n# START: [file join $file]\n###"
  set content [::practcl::cat [file join $srcdir {*}$file]]
  AutoDoc scan_text $content
  puts $fout [::practcl::docstrip $content]

  puts $fout "###\n# END: [file join $file]\n###"
}


# Provide some cleanup and our final package provide
puts $fout [string map $modmap {
namespace eval ::%module% {
  namespace export *
}
}]
close $fout

###
# Build our pkgIndex.tcl file
###
set fout [open [file join $moddir pkgIndex.tcl] w]
fconfigure $fout -translation lf
puts $fout [string map $modmap {###
if {![package vsatisfies [package provide Tcl] %tclversion%]} {return}
package ifneeded %module% %version% [list source [file join $dir %module%.tcl]]
}]
close $fout

set manout [open [file join $moddir $filename.man] w]
puts $manout [AutoDoc manpage map $modmap \
  header [::practcl::cat [file join $srcdir manual.txt]] \
  footer [::practcl::cat [file join $srcdir footer.txt]] \
]
close $manout

Changes to modules/practcl/build/buildutil.tcl.

1
2
3








4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
###
# Build utility functions
###









###
# A command to do nothing. A handy way of
# negating an instruction without
# having to comment it completely out.
# It's also a handy attachment point for
# an object to be named later
###
if {[info command ::noop] eq {}} {
  proc ::noop args {}
}

proc ::practcl::debug args {
  #puts $args
  ::practcl::cputs ::DEBUG_INFO $args
}

###



>
>
>
>
>
>
>
>








<
|
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20

21
22
23
24
25
26
27
###
# Build utility functions
###

###
# Generate a proc if no command already exists by that name
###
proc Proc {name arglist body} {
  if {[info command $name] ne {}} return
  proc $name $arglist $body
}

###
# A command to do nothing. A handy way of
# negating an instruction without
# having to comment it completely out.
# It's also a handy attachment point for
# an object to be named later
###

Proc ::noop args {}


proc ::practcl::debug args {
  #puts $args
  ::practcl::cputs ::DEBUG_INFO $args
}

###
97
98
99
100
101
102
103















104
105
106
107
108
109
110
  return $result
}

proc ::practcl::os {} {
  return [${::practcl::MAIN} define get TEACUP_OS]
}
















if {[::package vcompare $::tcl_version 8.6] < 0} {
  # Approximate ::zipfile::mkzip with exec calls
  proc ::practcl::mkzip {exename barekit vfspath} {
    set path [file dirname [file normalize $exename]]
    set zipfile [file join $path [file rootname $exename].zip]
    file copy -force $barekit $exename
    set pwd [pwd]







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
  return $result
}

proc ::practcl::os {} {
  return [${::practcl::MAIN} define get TEACUP_OS]
}

###
# Build a zipfile. On tcl8.6 this invokes the native Zip implementation
# on older interpreters this invokes zip via exec
###
proc ::practcl::mkzip {exename barekit vfspath} {
  ::practcl::tcllib_require zipfile::mkzip
  ::zipfile::mkzip::mkzip $exename -runtime $barekit -directory $vfspath
}
###
# Dictionary sort a key/value list. Needed because pre tcl8.6
# does not have [emph {lsort -stride 2}]
###
proc ::practcl::sort_dict list {
  return [::lsort -stride 2 -dictionary $list]
}
if {[::package vcompare $::tcl_version 8.6] < 0} {
  # Approximate ::zipfile::mkzip with exec calls
  proc ::practcl::mkzip {exename barekit vfspath} {
    set path [file dirname [file normalize $exename]]
    set zipfile [file join $path [file rootname $exename].zip]
    file copy -force $barekit $exename
    set pwd [pwd]
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139


























140
141
142
143
144
145
146
  proc ::practcl::sort_dict list {
    set result {}
    foreach key [lsort -dictionary [dict keys $list]] {
      dict set result $key [dict get $list $key]
    }
    return $result
  }
} else {
  proc ::practcl::mkzip {exename barekit vfspath} {
    ::practcl::tcllib_require zipfile::mkzip
    ::zipfile::mkzip::mkzip $exename -runtime $barekit -directory $vfspath
  }
  proc ::practcl::sort_dict list {
    return [::lsort -stride 2 -dictionary $list]
  }
}



























proc ::practcl::local_os {} {
  # If we have already run this command, return
  # a cached copy of the data
  if {[info exists ::practcl::LOCAL_INFO]} {
    return $::practcl::LOCAL_INFO
  }
  set result [array get ::practcl::CONFIG]







<
<
<
<
|
<
<
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
  proc ::practcl::sort_dict list {
    set result {}
    foreach key [lsort -dictionary [dict keys $list]] {
      dict set result $key [dict get $list $key]
    }
    return $result
  }




}




###
# Returns a dictionary describing the local operating system.
# Fields return include:
# [list_begin itemized]
# [item] download - Filesystem path where fossil repositories and source tarballs are downloaded for the current user
# [item] EXEEXT - The extension to give to executables. (i.e. .exe on windows)
# [item] fossil_mirror - A URI for a local network web server who acts as a fossil repository mirror
# [item] local_install - Filesystem path where packages for local consumption by the current user are installed
# [item] prefix - The prefix as given to the Tcl core/TEA for installation to local_install in ./configure
# [item] sandbox - The file location where this project unpacks external projects
# [item] TEACUP_PROFILE - The ActiveState/Teacup canonical name for this platform (i.e. win32-ix86 macosx10.5-i386-x86_84)
# [item] TEACUP_OS - The local operating system (windows, macosx, openbsd, etc). Gives the same answer as tcl.m4, except that macosx is given as macosx instead of Darwin.
# [item] TEA_PLATFORM - The platform returned by uname -s-uname -r (on Unix), or "windows" on Windows
# [item] TEACUP_ARCH - The processor architecture for the local os (i.e. ix86, x86_64)
# [item] TEACUP_ARCH - The processor architecture for the local os (i.e. ix86, x86_64)
# [item] teapot - Filesystem path where teapot package files are downloaded for the current user
# [item] userhome - File path to store localized preferences, cache download files, etc for the current user
# [list_end]
# This command uses a combination of local checks with Exec, any tclConfig.sh file that is
# resident, autoconf data where already computed, and data gleaned from a file named
# practcl.rc in userhome. The location for userhome varies by platform and operating system:
# [list_begin itemized]
# [item] Windows: ::env(LOCALAPPDATA)/Tcl
# [item] Macos: ~/Library/Application Support/Tcl
# [item] Other: ~/tcl
# [list_end]
###
proc ::practcl::local_os {} {
  # If we have already run this command, return
  # a cached copy of the data
  if {[info exists ::practcl::LOCAL_INFO]} {
    return $::practcl::LOCAL_INFO
  }
  set result [array get ::practcl::CONFIG]
275
276
277
278
279
280
281
282

283
284
285
286
287




















288
289
290
291
292
293
294

  set ::practcl::LOCAL_INFO $result
  return $result
}


###
# Detect local platform

###
proc ::practcl::config.tcl {path} {
   return [read_configuration $path]
}





















proc ::practcl::read_configuration {path} {
  dict set result buildpath $path
  set result [local_os]
  set OS [dict get $result TEACUP_OS]
  set windows 0
  dict set result USEMSVC 0
  if {[file exists [file join $path config.tcl]]} {







|
>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

  set ::practcl::LOCAL_INFO $result
  return $result
}


###
# A transparent call to ::practcl::read_configuration to preserve backward compadibility
# with older copies of Practcl
###
proc ::practcl::config.tcl {path} {
   return [read_configuration $path]
}

###
# Detect local platform. This command looks for data gleaned by autoconf or autosetup
# in the path specified, or perform its own logic tests if neither has been run.
# A file named config.site present in the location indicates that this project is
# cross compiling, and the data stored in that file is used for the compiler and linker.
# [para]
# This command looks for information from the following files, in the following order:
# [list_begin itemized]
# [item] config.tcl - A file generated by autoconf/configure in newer editions of TEA, encoded as a Tcl script.
# [item] config.site - A file containing cross compiler information, encoded as a SH script
# [item] ::env(VisualStudioVersion) - On Windows, and environmental value that indicates MS Visual Studio is installed
# [list_end]
# [para]
# This command returns a dictionary containing all of the data cleaned from the sources above.
# In the absence of any guidance this command returns the same output as ::practcl::local_os.
# In this mode, if the environmental variable VisualStudioVersion exists, this command
# will provide a template of fields that are appropriate for compiling on Windows under
# Microsoft Visual Studio. The USEMSVC flag in the dictionary is a boolean flag to indicate
# if this is indeed the case.
###
proc ::practcl::read_configuration {path} {
  dict set result buildpath $path
  set result [local_os]
  set OS [dict get $result TEACUP_OS]
  set windows 0
  dict set result USEMSVC 0
  if {[file exists [file join $path config.tcl]]} {
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
  }
  ::practcl::LOCAL tool tcllib env-load
  uplevel #0 [list ::package require $pkg {*}$args]
}

namespace eval ::practcl::platform {}









proc ::practcl::platform::tcl_core_options {os} {
  ###
  # Download our required packages
  ###
  set tcl_config_opts {}
  # Auto-guess options for the local operating system
  switch $os {
    windows {
      #lappend tcl_config_opts --disable-stubs
    }
    linux {
    }
    macosx {
      lappend tcl_config_opts --enable-corefoundation=yes  --enable-framework=no
    }
  }
  lappend tcl_config_opts --with-tzdata
  return $tcl_config_opts
}

proc ::practcl::platform::tk_core_options {os} {
  ###
  # Download our required packages
  ###







>
>
>
>
>
>
>
>
















|







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
  }
  ::practcl::LOCAL tool tcllib env-load
  uplevel #0 [list ::package require $pkg {*}$args]
}

namespace eval ::practcl::platform {}

###
# Return the string to pass to ./configure to compile the Tcl core for the given OS.
# [list_begin itemized]
# [item] windows: --with-tzdata --with-encoding utf-8
# [item] macosx: --enable-corefoundation=yes  --enable-framework=no --with-tzdata --with-encoding utf-8
# [item] other: --with-tzdata --with-encoding utf-8
# [list_end]
###
proc ::practcl::platform::tcl_core_options {os} {
  ###
  # Download our required packages
  ###
  set tcl_config_opts {}
  # Auto-guess options for the local operating system
  switch $os {
    windows {
      #lappend tcl_config_opts --disable-stubs
    }
    linux {
    }
    macosx {
      lappend tcl_config_opts --enable-corefoundation=yes  --enable-framework=no
    }
  }
  lappend tcl_config_opts --with-tzdata --with-encoding utf-8
  return $tcl_config_opts
}

proc ::practcl::platform::tk_core_options {os} {
  ###
  # Download our required packages
  ###

Changes to modules/practcl/build/class/distro/baseclass.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

###
# Standalone class to manage code distribution
# This class is intended to be mixed into another class
# (Thus the lack of ancestors)
###
oo::class create ::practcl::distribution {

  method scm_info {} {
    return {
      scm  None
      hash {}
      maxdate {}
      tags {}
      isodate {}
    }
  }
  
  method DistroMixIn {} {
    my define set scm none
  }

  method Sandbox {} {
    if {[my define exists sandbox]} {
      return [my define get sandbox]
    }
    if {[my organ project] ni {::noop {}}} {
      set sandbox [my <project> define get sandbox]
      if {$sandbox ne {}} {
        my define set sandbox $sandbox
        return $sandbox
      }
    }
    set sandbox [file normalize [file join $::CWD ..]]






|










|








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

###
# Standalone class to manage code distribution
# This class is intended to be mixed into another class
# (Thus the lack of ancestors)
###
::clay::define ::practcl::distribution {

  method scm_info {} {
    return {
      scm  None
      hash {}
      maxdate {}
      tags {}
      isodate {}
    }
  }

  method DistroMixIn {} {
    my define set scm none
  }

  method Sandbox {} {
    if {[my define exists sandbox]} {
      return [my define get sandbox]
    }
    if {[my clay delegate project] ni {::noop {}}} {
      set sandbox [my <project> define get sandbox]
      if {$sandbox ne {}} {
        my define set sandbox $sandbox
        return $sandbox
      }
    }
    set sandbox [file normalize [file join $::CWD ..]]
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
        ::zipfile::decode::unzipfile [file join $download $pkg.zip] $srcdir
        return
      }
    }
    my ScmUnpack
  }
}

oo::objdefine ::practcl::distribution {

  method Sandbox {object} {
    if {[$object define exists sandbox]} {
      return [$object define get sandbox]
    }
    if {[$object organ project] ni {::noop {}}} {
      set sandbox [$object <project> define get sandbox]
      if {$sandbox ne {}} {
        $object define set sandbox $sandbox
        return $sandbox
      }
    }
    set pkg [$object define get name]







<

<




|







66
67
68
69
70
71
72

73

74
75
76
77
78
79
80
81
82
83
84
85
        ::zipfile::decode::unzipfile [file join $download $pkg.zip] $srcdir
        return
      }
    }
    my ScmUnpack
  }
}

oo::objdefine ::practcl::distribution {

  method Sandbox {object} {
    if {[$object define exists sandbox]} {
      return [$object define get sandbox]
    }
    if {[$object clay delegate project] ni {::noop {}}} {
      set sandbox [$object <project> define get sandbox]
      if {$sandbox ne {}} {
        $object define set sandbox $sandbox
        return $sandbox
      }
    }
    set pkg [$object define get name]
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
      $object define set srcdir $srcdir
    }

    set classprefix ::practcl::distribution.
    if {[file exists $srcdir]} {
      foreach class [::info commands ${classprefix}*] {
        if {[$class claim_path $srcdir]} {
          $object mixin distribution $class

          $object define set scm [string range $class [string length ::practcl::distribution.] end]
          return [$object define get scm]
        }
      }
    }
    foreach class [::info commands ${classprefix}*] {
      if {[$class claim_object $object]} {
        $object mixin distribution $class

        $object define set scm [string range $class [string length ::practcl::distribution.] end]
        return [$object define get scm]
      }
    }
    if {[$object define get scm] eq {} && [$object define exists file_url]} {
      set class ::practcl::distribution.snapshot

      $object define set scm snapshot
      $object mixin distribution $class
      return [$object define get scm]
    }
    error "Cannot determine source distribution method"
  }

  method claim_path path {
    return false
  }

  method claim_object object {




    return false
  }
}







|
>
|
|





|
>
|
|




>
|
|
|




|
|

>

>
>
>
>



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
      $object define set srcdir $srcdir
    }

    set classprefix ::practcl::distribution.
    if {[file exists $srcdir]} {
      foreach class [::info commands ${classprefix}*] {
        if {[$class claim_path $srcdir]} {
          $object clay mixinmap distribution $class
          set name [$class claim_option]
          $object define set scm $name
          return $name
        }
      }
    }
    foreach class [::info commands ${classprefix}*] {
      if {[$class claim_object $object]} {
        $object clay mixinmap distribution $class
        set name [$class claim_option]
        $object define set scm $name
        return $name
      }
    }
    if {[$object define get scm] eq {} && [$object define exists file_url]} {
      set class ::practcl::distribution.snapshot
      set name [$class claim_option]
      $object define set scm $name
      $object clay mixinmap distribution $class
      return $name
    }
    error "Cannot determine source distribution method"
  }

  method claim_option {} {
    return Unknown
  }

  method claim_object object {
    return false
  }

  method claim_path path {
    return false
  }
}

Changes to modules/practcl/build/class/distro/fossil.tcl.

1


2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20



oo::class create ::practcl::distribution.fossil {
  superclass ::practcl::distribution

  method scm_info {} {
    set info [next]
    dict set info scm fossil
    foreach {field value} [::practcl::fossil_status [my define get srcdir]] {
      dict set info $field $value
    }
    return $info
  }
  
  # Clone the source
  method ScmClone  {} {
    set srcdir [my SrcDir]
    if {[file exists [file join $srcdir .fslckout]]} {
      return
    }
    if {[file exists [file join $srcdir _FOSSIL_]]} {
|
>
>
|










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
###
# A file distribution based on fossil
###
::clay::define ::practcl::distribution.fossil {
  superclass ::practcl::distribution

  method scm_info {} {
    set info [next]
    dict set info scm fossil
    foreach {field value} [::practcl::fossil_status [my define get srcdir]] {
      dict set info $field $value
    }
    return $info
  }

  # Clone the source
  method ScmClone  {} {
    set srcdir [my SrcDir]
    if {[file exists [file join $srcdir .fslckout]]} {
      return
    }
    if {[file exists [file join $srcdir _FOSSIL_]]} {
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















    set tag [my ScmTag]
    ::practcl::fossil $srcdir update $tag
  }
}

oo::objdefine ::practcl::distribution.fossil {

  # Check for markers in the source root
  method claim_path path {
    if {[file exists [file join $path .fslckout]]} {
      return true
    }
    if {[file exists [file join $path _FOSSIL_]]} {
      return true
    }
    return false
  }

  # Check for markers in the metadata
  method claim_object obj {
    set path [$obj define get srcdir]
    if {[my claim_path $path]} {
      return true
    }
    if {[$obj define get fossil_url] ne {}} {
      return true
    }
    return false
  }
}






















<
<
<
<
<
<
<
<
<
<
<











|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
    set tag [my ScmTag]
    ::practcl::fossil $srcdir update $tag
  }
}

oo::objdefine ::practcl::distribution.fossil {












  # Check for markers in the metadata
  method claim_object obj {
    set path [$obj define get srcdir]
    if {[my claim_path $path]} {
      return true
    }
    if {[$obj define get fossil_url] ne {}} {
      return true
    }
    return false
  }

  method claim_option {} {
    return fossil
  }

  # Check for markers in the source root
  method claim_path path {
    if {[file exists [file join $path .fslckout]]} {
      return true
    }
    if {[file exists [file join $path _FOSSIL_]]} {
      return true
    }
    return false
  }
}

Changes to modules/practcl/build/class/distro/git.tcl.

1
2

3
4
5
6
7
8
9
10



oo::class create ::practcl::distribution.git {
  superclass ::practcl::distribution

  method ScmTag {} {
    if {[my define exists scm_tag]} {
      return [my define get scm_tag]
    }
    if {[my define exists tag]} {
|
|
>
|







1
2
3
4
5
6
7
8
9
10
11
###
# A file distribution based on git
###
::clay::define ::practcl::distribution.git {
  superclass ::practcl::distribution

  method ScmTag {} {
    if {[my define exists scm_tag]} {
      return [my define get scm_tag]
    }
    if {[my define exists tag]} {
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64











    }
    set CWD [pwd]
    set srcdir [my SrcDir]
    set tag [my ScmTag]
    ::practcl::doexec_in $srcdir git pull
    cd $CWD
  }

}
oo::objdefine ::practcl::distribution.git {
  method claim_path path {
   if {[file exists [file join $path .git]]} {
      return true
    }
    return false
  }
  method claim_object obj {
    set path [$obj define get srcdir]
    if {[my claim_path $path]} {
      return true
    }
    if {[$obj define get git_url] ne {}} {
      return true
    }
    return false
  }
}


















|
|

<
<
<
|
<
<










|
>
>
>
>
>
>
>
>
>
>
>
39
40
41
42
43
44
45
46
47
48



49


50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    }
    set CWD [pwd]
    set srcdir [my SrcDir]
    set tag [my ScmTag]
    ::practcl::doexec_in $srcdir git pull
    cd $CWD
  }
}

oo::objdefine ::practcl::distribution.git {






  method claim_object obj {
    set path [$obj define get srcdir]
    if {[my claim_path $path]} {
      return true
    }
    if {[$obj define get git_url] ne {}} {
      return true
    }
    return false
  }

  method claim_option {} {
    return git
  }

  method claim_path path {
   if {[file exists [file join $path .git]]} {
      return true
    }
    return false
  }
}

Changes to modules/practcl/build/class/distro/snapshot.tcl.

1


2
3
4
5
6
7
8
9



oo::class create ::practcl::distribution.snapshot {
  superclass ::practcl::distribution

  method ScmUnpack {} {
    set srcdir [my SrcDir]
    if {[file exists [file join $srcdir .download]]} {
      return 0
    }
|
>
>
|







1
2
3
4
5
6
7
8
9
10
11
###
# A file distribution from zip, tarball, or other non-scm archive format
###
::clay::define ::practcl::distribution.snapshot {
  superclass ::practcl::distribution

  method ScmUnpack {} {
    set srcdir [my SrcDir]
    if {[file exists [file join $srcdir .download]]} {
      return 0
    }
36
37
38
39
40
41
42

43



44




45
46
47
48
49
50
51
52
53
54
    set fosdb [my ScmClone]
    set tag [my ScmTag]
    file mkdir $srcdir
    ::practcl::fossil $srcdir open $fosdb $tag
    return 1
  }
}





oo::objdefine ::practcl::distribution.snapshot {




  method claim_path path {
    if {[file exists [file join $path .download]]} {
      return true
    }
    return false
  }
  method claim_object object {
    return false
  }
}







>

>
>
>
|
>
>
>
>






<
<
|
<
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60


61

    set fosdb [my ScmClone]
    set tag [my ScmTag]
    file mkdir $srcdir
    ::practcl::fossil $srcdir open $fosdb $tag
    return 1
  }
}
oo::objdefine ::practcl::distribution.snapshot {

  method claim_object object {
    return false
  }

  method claim_option {} {
    return snapshot
  }

  method claim_path path {
    if {[file exists [file join $path .download]]} {
      return true
    }
    return false
  }


}

Changes to modules/practcl/build/class/dynamic.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

###
# Dynamic blocks do not generate their own .c files,
# instead the contribute to the amalgamation
# of the main library file
###
::oo::class create ::practcl::dynamic {

  ###
  # Parser functions
  ###

  method cstructure {name definition {argdat {}}} {
    my variable cstruct
    dict set cstruct $name body $definition
    foreach {f v} $argdat {
      dict set cstruct $name $f $v
    }
    if {![dict exists $cstruct $name public]} {
      dict set cstruct $name public 1
    }
  }
  
  method include header {
    my define add include $header
  }

  method include_dir args {
    my define add include_dir {*}$args
  }






|















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

###
# Dynamic blocks do not generate their own .c files,
# instead the contribute to the amalgamation
# of the main library file
###
::clay::define ::practcl::dynamic {

  ###
  # Parser functions
  ###

  method cstructure {name definition {argdat {}}} {
    my variable cstruct
    dict set cstruct $name body $definition
    foreach {f v} $argdat {
      dict set cstruct $name $f $v
    }
    if {![dict exists $cstruct $name public]} {
      dict set cstruct $name public 1
    }
  }

  method include header {
    my define add include $header
  }

  method include_dir args {
    my define add include_dir {*}$args
  }
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
      dict set tcltype $name $func $fname
    }
  }

  ###
  # Module interactions
  ###


  method project-compile-products {} {
    set filename [my define get output_c]
    set result {}
    if {$filename ne {}} {
      ::practcl::debug [self] [self class] [self method] project-compile-products $filename

      if {[my define exists ofile]} {







<
<







169
170
171
172
173
174
175


176
177
178
179
180
181
182
      dict set tcltype $name $func $fname
    }
  }

  ###
  # Module interactions
  ###


  method project-compile-products {} {
    set filename [my define get output_c]
    set result {}
    if {$filename ne {}} {
      ::practcl::debug [self] [self class] [self method] project-compile-products $filename

      if {[my define exists ofile]} {
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
    }
    foreach item [my link list subordinate] {
      lappend result {*}[$item project-compile-products]
    }
    return $result
  }


  method implement path {
    my go
    my Collate_Source $path
    if {[my define get output_c] eq {}} return
    set filename [file join $path [my define get output_c]]
    ::practcl::debug [self] [my define get filename] WANTS TO GENERATE $filename
    my define set cfile $filename







<







201
202
203
204
205
206
207

208
209
210
211
212
213
214
    }
    foreach item [my link list subordinate] {
      lappend result {*}[$item project-compile-products]
    }
    return $result
  }


  method implement path {
    my go
    my Collate_Source $path
    if {[my define get output_c] eq {}} return
    set filename [file join $path [my define get output_c]]
    ::practcl::debug [self] [my define get filename] WANTS TO GENERATE $filename
    my define set cfile $filename
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
      }
      puts $fout "  return TCL_OK\;"
      puts $fout "\x7D"
    }
    close $fout
  }



  ###
  # Practcl internals
  ###

  method initialize {} {
    set filename [my define get filename]
    if {$filename eq {}} {
      return
    }
    if {[my define get name] eq {}} {
      my define set name [file tail [file rootname $filename]]







<
<



<







222
223
224
225
226
227
228


229
230
231

232
233
234
235
236
237
238
      }
      puts $fout "  return TCL_OK\;"
      puts $fout "\x7D"
    }
    close $fout
  }



  ###
  # Practcl internals
  ###

  method initialize {} {
    set filename [my define get filename]
    if {$filename eq {}} {
      return
    }
    if {[my define get name] eq {}} {
      my define set name [file tail [file rootname $filename]]

Changes to modules/practcl/build/class/metaclass.tcl.




1
2
3
4
5
6
7
8
9



::oo::class create ::practcl::metaclass {
  superclass ::oo::object

  method _MorphPatterns {} {
    return {{@name@} {::practcl::@name@} {::practcl::*@name@} {::practcl::*@name@*}}
  }

  method define {submethod args} {
    my variable define
>
>
>
|
<







1
2
3
4

5
6
7
8
9
10
11
###
# The metaclass for all practcl objects
###
::clay::define ::practcl::metaclass {


  method _MorphPatterns {} {
    return {{@name@} {::practcl::@name@} {::practcl::*@name@} {::practcl::*@name@*}}
  }

  method define {submethod args} {
    my variable define
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
      }
      default {
        array $submethod define {*}$args
      }
    }
  }


  method meta {submethod args} {
    my variable meta
    if {![info exists meta]} {
      set meta {}
    }
    switch $submethod {
      dump {
        return $meta
      }
      add {
        set field [lindex $args 0]
        if {![dict exists $meta $field]} {
          dict set meta $field {}
        }
        foreach arg [lrange $args 1 end] {
          if {$arg ni [dict get $meta $field]} {
            dict lappend meta $field $arg
          }
        }
        return [dict get $meta $field]
      }
      remove {
        set field [lindex $args 0]
        if {![dict exists meta $field]} {
          return
        }
        set rlist [lrange $args 1 end]
        set olist [dict get $meta $field]
        set nlist {}
        foreach arg $olist {
          if {$arg in $rlist} continue
          lappend nlist $arg
        }
        dict set meta $field $nlist
        return $nlist
      }
      exists {
        return [dict exists $meta {*}$args]
      }
      getnull -
      get {
        if {[dict exists $meta {*}$args]} {
          return [dict get $meta {*}$args]
        }
        return {}
      }
      cget {
        set field [lindex $args 0]
        if {[dict exists $meta $field]} {
          return [dict get $meta $field]
        }
        return [lindex $args 1]
      }
      set {
        if {[llength $args]==1} {
          foreach {field value} $args {
            dict set meta [string trimright $field :]: $value
          }
        } else {
          set field [lindex $args end-1]
          set value [lindex $args end]
          dict set meta {*}[lrange $args 0 end-2] [string trimright $field :]: $value
        }
      }
      default {
        error "Valid: add cget dump exists get getnull remove set"
      }
    }
  }
  
  method graft args {
    my variable organs
    if {[llength $args] == 1} {
      error "Need two arguments"
    }
    set object {}
    foreach {stub object} $args {
      dict set organs $stub $object
      oo::objdefine [self] forward <${stub}> $object
      oo::objdefine [self] export <${stub}>
    }
    return $object
  }

  method initialize {} {}


  method link {command args} {
    my variable links







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
|







66
67
68
69
70
71
72







































































73










74
75
76
77
78
79
80
81
      }
      default {
        array $submethod define {*}$args
      }
    }
  }








































































  method graft args {










    return [my clay delegate {*}$args]
  }

  method initialize {} {}


  method link {command args} {
    my variable links
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
      } {
        if {[string match $pattern $class]} {
           set mixinslot $slot
           break
        }
      }
      if {$mixinslot ne {}} {
        my mixin $mixinslot $class
      } elseif {[info command $class] ne {}} {
        if {[info object class [self]] ne $class} {
          ::oo::objdefine [self] class $class
          ::practcl::debug [self] morph $class
           my define set class $class
        }
      } else {
        error "[self] Could not detect class for $classname"
      }
    }
    if {[::info exists define(oodefine)]} {
      ::oo::objdefine [self] $define(oodefine)
      #unset define(oodefine)
    }
  }

  method mixin {slot classname} {
    my variable mixinslot
    set class {}
    set map [list @slot@ $slot @name@ $classname]
    foreach pattern [split [string map $map {
      @name@
      @slot@.@name@
      ::practcl::@name@
      ::practcl::@slot@.@name@
      ::practcl::@slot@*@name@
      ::practcl::*@name@*
    }] \n] {
      set pattern [string trim $pattern]
      set matches [info commands $pattern]
      if {![llength $matches]} continue
      set class [lindex $matches 0]
      break
    }
    ::practcl::debug [self] mixin $slot $class
    dict set mixinslot $slot $class
    set mixins {}
    foreach {s c} $mixinslot {
      if {$c eq {}} continue
      lappend mixins $c
    }
    oo::objdefine [self] mixin {*}$mixins
  }

  method organ {{stub all}} {
    my variable organs
    if {![info exists organs]} {
      return {}
    }
    if { $stub eq "all" } {
      return $organs
    }
    if {[dict exists $organs $stub]} {
      return [dict get $organs $stub]
    }
  }

  method script script {
    eval $script
  }

  method select {} {
    my variable define
    if {[info exists define(class)]} {







|
















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
      } {
        if {[string match $pattern $class]} {
           set mixinslot $slot
           break
        }
      }
      if {$mixinslot ne {}} {
        my clay mixinmap $mixinslot $class
      } elseif {[info command $class] ne {}} {
        if {[info object class [self]] ne $class} {
          ::oo::objdefine [self] class $class
          ::practcl::debug [self] morph $class
           my define set class $class
        }
      } else {
        error "[self] Could not detect class for $classname"
      }
    }
    if {[::info exists define(oodefine)]} {
      ::oo::objdefine [self] $define(oodefine)
      #unset define(oodefine)
    }
  }










































  method script script {
    eval $script
  }

  method select {} {
    my variable define
    if {[info exists define(class)]} {

Changes to modules/practcl/build/class/module.tcl.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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

###
# In the end, all C code must be loaded into a module
# This will either be a dynamically loaded library implementing
# a tcl extension, or a compiled in segment of a custom shell/app
###
::oo::class create ::practcl::module {
  superclass ::practcl::object ::practcl::product.dynamic



  method _MorphPatterns {} {
    return {{@name@} {::practcl::module.@name@} ::practcl::module}
  }
  
  method add args {
    my variable links
    set object [::practcl::object new [self] {*}$args]
    foreach linktype [$object linktype] {
      lappend links($linktype) $object
    }
    return $object
  }
  
  
  method install-headers args {}
  
  ###
  # Target handling
  ###
  method make {command args} {
    my variable make_object
    if {![info exists make_object]} {
      set make_object {}
    }
    switch $command {

      pkginfo {
        ###
        # Build local variables needed for install
        ###
        package require platform
        set result {}
        set dat [my define dump]
        set PKG_DIR [dict get $dat name][dict get $dat version]
        dict set result PKG_DIR $PKG_DIR
        dict with dat {}
        if {![info exists DESTDIR]} {
          set DESTDIR {}
        }
        dict set result profile [::platform::identify]
        dict set result os $::tcl_platform(os)
        dict set result platform $::tcl_platform(platform)
        foreach {field value} $dat {
          switch $field {
            includedir -
            mandir -
            datadir -
            libdir -
            libfile -
            name -
            output_tcl -
            version -
            authors -
            license -
            requires {
              dict set result $field $value
            }
            TEA_PLATFORM {
              dict set result platform $value
            }
            TEACUP_OS {
              dict set result os $value
            }
            TEACUP_PROFILE {
              dict set result profile $value
            }
            TEACUP_ZIPFILE {
              dict set result zipfile $value
            }
          }
        }
        if {![dict exists $result zipfile]} {
          dict set result zipfile "[dict get $result name]-[dict get $result version]-[dict get $result profile].zip"
        }
        return $result
      }


      objects {
        return $make_object
      }
      object {

        set name [lindex $args 0]
        if {[dict exists $make_object $name]} {
          return [dict get $make_object $name]
        }
        return {}
      }


      reset {
        foreach {name obj} $make_object {
          $obj reset
        }
      }


      trigger {
        foreach {name obj} $make_object {
          if {$name in $args} {
            $obj triggers
          }
        }
      }


      depends {
        foreach {name obj} $make_object {
          if {$name in $args} {
            $obj check
          }
        }
      }
      filename {

        set name [lindex $args 0]

        if {[dict exists $make_object $name]} {
          return [[dict get $make_object $name] define get filename]
        }
      }
      task -
      target -
      add {
        set name [lindex $args 0]
        set info [uplevel #0 [list subst [lindex $args 1]]]
        set body [lindex $args 2]
        
        set nspace [namespace current]
        if {[dict exist $make_object $name]} {
          set obj [dict get $$make_object $name]
        } else {
          set obj [::practcl::make_obj new [self] $name $info $body]
          dict set make_object $name $obj
          dict set target_make $name 0
          dict set target_trigger $name 0
        }
        if {[dict exists $info aliases]} {
          foreach item [dict get $info aliases] {
            if {![dict exists $make_object $item]} {
              dict set make_object $item $obj
            }
          }
        }
        return $obj
      }




      todo {
         foreach {name obj} $make_object {
          if {[$obj do]} {
            lappend result $name
          }
        }       

      }
      do {



        global CWD SRCDIR project SANDBOX
        foreach {name obj} $make_object {
          if {[$obj do]} {
            eval [$obj define get action]
          }
        }
      }
    }
  }
  
  method child which {
    switch $which {

      organs {
        return [list project [my define get project] module [self]]
      }
    }
  }

 ###






|

>
>




|








|
<

|
<
<
<
|




<
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
>
|
|
|
|
|
|
>
>
|
|
|
|
|
>
>
|
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
>
|
>
|
|
|
|
|
|
<
<
|
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
|
|
|
|
|
|
>
|
|
>
>
>
|
|
|
|
|
|
|
|
<
<


>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26



27
28
29
30
31

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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

###
# In the end, all C code must be loaded into a module
# This will either be a dynamically loaded library implementing
# a tcl extension, or a compiled in segment of a custom shell/app
###
::clay::define ::practcl::module {
  superclass ::practcl::object ::practcl::product.dynamic

  Dict make_object {}

  method _MorphPatterns {} {
    return {{@name@} {::practcl::module.@name@} ::practcl::module}
  }

  method add args {
    my variable links
    set object [::practcl::object new [self] {*}$args]
    foreach linktype [$object linktype] {
      lappend links($linktype) $object
    }
    return $object
  }


  method install-headers args {}




  Ensemble make::_preamble {} {
    my variable make_object
    if {![info exists make_object]} {
      set make_object {}
    }

  }
  Ensemble make::pkginfo {} {
    ###
    # Build local variables needed for install
    ###
    package require platform
    set result {}
    set dat [my define dump]
    set PKG_DIR [dict get $dat name][dict get $dat version]
    dict set result PKG_DIR $PKG_DIR
    dict with dat {}
    if {![info exists DESTDIR]} {
      set DESTDIR {}
    }
    dict set result profile [::platform::identify]
    dict set result os $::tcl_platform(os)
    dict set result platform $::tcl_platform(platform)
    foreach {field value} $dat {
      switch $field {
        includedir -
        mandir -
        datadir -
        libdir -
        libfile -
        name -
        output_tcl -
        version -
        authors -
        license -
        requires {
          dict set result $field $value
        }
        TEA_PLATFORM {
          dict set result platform $value
        }
        TEACUP_OS {
          dict set result os $value
        }
        TEACUP_PROFILE {
          dict set result profile $value
        }
        TEACUP_ZIPFILE {
          dict set result zipfile $value
        }
      }
    }
    if {![dict exists $result zipfile]} {
      dict set result zipfile "[dict get $result name]-[dict get $result version]-[dict get $result profile].zip"
    }
    return $result
  }

  # Return a dictionary of all handles and associated objects
  Ensemble make::objects {} {
    return $make_object
  }

  # Return the object associated with handle [emph name]
  Ensemble make::object name {
    if {[dict exists $make_object $name]} {
      return [dict get $make_object $name]
    }
    return {}
  }

  # Reset all deputy objects
  Ensemble make::reset {} {
    foreach {name obj} $make_object {
      $obj reset
    }
  }

  # Exercise the triggers method for all handles listed
  Ensemble make::trigger args {
    foreach {name obj} $make_object {
      if {$name in $args} {
        $obj triggers
      }
    }
  }

  # Exercise the check method for all handles listed
  Ensemble make::depends args {
    foreach {name obj} $make_object {
      if {$name in $args} {
        $obj check
      }
    }
  }

  # Return the file name of the build product for the listed
  # handle
  Ensemble make::filename name {
    if {[dict exists $make_object $name]} {
      return [[dict get $make_object $name] define get filename]
    }
  }

  Ensemble make::target {name Info body} {


    set info [uplevel #0 [list subst $Info]]


    set nspace [namespace current]
    if {[dict exist $make_object $name]} {
      set obj [dict get $$make_object $name]
    } else {
      set obj [::practcl::make_obj new [self] $name $info $body]
      dict set make_object $name $obj
      dict set target_make $name 0
      dict set target_trigger $name 0
    }
    if {[dict exists $info aliases]} {
      foreach item [dict get $info aliases] {
        if {![dict exists $make_object $item]} {
          dict set make_object $item $obj
        }
      }
    }
    return $obj
  }
  clay set method_ensemble make target aliases {target add}

  # Return a list of handles for object which return true for the
  # do method
  Ensemble make::todo {} {
    foreach {name obj} $make_object {
      if {[$obj do]} {
        lappend result $name
      }
    }
    return $result
  }

  # For each target exercise the action specified in the [emph action]
  # definition if the [emph do] method returns true
  Ensemble make::do {} {
    global CWD SRCDIR project SANDBOX
    foreach {name obj} $make_object {
      if {[$obj do]} {
        eval [$obj define get action]
      }
    }
  }



  method child which {
    switch $which {
      delegate -
      organs {
        return [list project [my define get project] module [self]]
      }
    }
  }

 ###
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
  ###
  # This methods generates the contents of an amalgamated .h file
  # which describes the public API of this module
  ###
  method generate-h {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}








    set includes [my generate-hfile-public-includes]
    foreach inc $includes {
      if {[string index $inc 0] ni {< \"}} {
        ::practcl::cputs result "#include \"$inc\""
      } else {
        ::practcl::cputs result "#include $inc"
      }
    }

    foreach method {
      generate-hfile-public-define
      generate-hfile-public-macro
      generate-hfile-public-typedef
      generate-hfile-public-structure
    } {
      ::practcl::cputs result "/* BEGIN SECTION $method */"
      ::practcl::cputs result [my $method]
      ::practcl::cputs result "/* END SECTION $method */"
    }







>
>
>
>
>
>
>
>








<

<
<







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
  ###
  # This methods generates the contents of an amalgamated .h file
  # which describes the public API of this module
  ###
  method generate-h {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}
    foreach method {
      generate-hfile-public-define
      generate-hfile-public-macro
    } {
      ::practcl::cputs result "/* BEGIN SECTION $method */"
      ::practcl::cputs result [my $method]
      ::practcl::cputs result "/* END SECTION $method */"
    }
    set includes [my generate-hfile-public-includes]
    foreach inc $includes {
      if {[string index $inc 0] ni {< \"}} {
        ::practcl::cputs result "#include \"$inc\""
      } else {
        ::practcl::cputs result "#include $inc"
      }
    }

    foreach method {


      generate-hfile-public-typedef
      generate-hfile-public-structure
    } {
      ::practcl::cputs result "/* BEGIN SECTION $method */"
      ::practcl::cputs result [my $method]
      ::practcl::cputs result "/* END SECTION $method */"
    }
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
          lappend errs [dict get $errdat -errorinfo]
        } else {
          lappend errs $errdat
        }
      }
    }
    if {[llength $errs]} {
      set logfile [file join $::CWD practcl.log]      
      ::practcl::log $logfile "*** ERRORS ***"
      foreach {item trace} $errs {
        ::practcl::log $logfile "###\n# ERROR\n###\n$item"
       ::practcl::log $logfile "###\n# TRACE\n###\n$trace"
      }
      ::practcl::log $logfile "*** DEBUG INFO ***"
      ::practcl::log $logfile $::DEBUG_INFO







|







352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
          lappend errs [dict get $errdat -errorinfo]
        } else {
          lappend errs $errdat
        }
      }
    }
    if {[llength $errs]} {
      set logfile [file join $::CWD practcl.log]
      ::practcl::log $logfile "*** ERRORS ***"
      foreach {item trace} $errs {
        ::practcl::log $logfile "###\n# ERROR\n###\n$item"
       ::practcl::log $logfile "###\n# TRACE\n###\n$trace"
      }
      ::practcl::log $logfile "*** DEBUG INFO ***"
      ::practcl::log $logfile $::DEBUG_INFO

Changes to modules/practcl/build/class/object.tcl.




1
2
3
4
5
6
7
8
9
10
11
12
13
14



::oo::class create ::practcl::object {
  superclass ::practcl::metaclass

  constructor {parent args} {
    my variable links define
    set organs [$parent child organs]
    my graft {*}$organs
    array set define $organs
    array set define [$parent child define]
    array set links {}
    if {[llength $args]==1 && [file exists [lindex $args 0]]} {
      my define set filename [lindex $args 0]
      ::practcl::product select [self]
    } elseif {[llength $args] == 1} {
>
>
>
|





|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
###
# A generic Practcl object
###
::clay::define ::practcl::object {
  superclass ::practcl::metaclass

  constructor {parent args} {
    my variable links define
    set organs [$parent child organs]
    my clay delegate {*}$organs
    array set define $organs
    array set define [$parent child define]
    array set links {}
    if {[llength $args]==1 && [file exists [lindex $args 0]]} {
      my define set filename [lindex $args 0]
      ::practcl::product select [self]
    } elseif {[llength $args] == 1} {

Changes to modules/practcl/build/class/product.tcl.

1


2
3
4
5
6
7
8
9
10



::oo::class create ::practcl::product {


  method code {section body} {
    my variable code
    ::practcl::cputs code($section) $body
  }

  method Collate_Source CWD {}
|
>
>
|
<







1
2
3
4

5
6
7
8
9
10
11
###
# A deliverable for the build system
###
::clay::define ::practcl::product {


  method code {section body} {
    my variable code
    ::practcl::cputs code($section) $body
  }

  method Collate_Source CWD {}
544
545
546
547
548
549
550
551
552
553
554

555
556
557
558
559
560
561
  }

  method target {method args} {
    switch $method {
      is_unix { return [expr {$::tcl_platform(platform) eq "unix"}] }
    }
  }

}

oo::objdefine ::practcl::product {

  method select {object} {
    set class [$object define get class]
    set mixin [$object define get product]
    if {$class eq {} && $mixin eq {}} {
      set filename [$object define get filename]
      if {$filename ne {} && [file exists $filename]} {
        switch [file extension $filename] {







|
<
<

>







545
546
547
548
549
550
551
552


553
554
555
556
557
558
559
560
561
  }

  method target {method args} {
    switch $method {
      is_unix { return [expr {$::tcl_platform(platform) eq "unix"}] }
    }
  }
}


oo::objdefine ::practcl::product {

  method select {object} {
    set class [$object define get class]
    set mixin [$object define get product]
    if {$class eq {} && $mixin eq {}} {
      set filename [$object define get filename]
      if {$filename ne {} && [file exists $filename]} {
        switch [file extension $filename] {
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
          .a {
            set mixin ::practcl::product.clibrary
          }
        }
      }
    }
    if {$class ne {}} {
      $object morph $class
    }
    if {$mixin ne {}} {
      $object mixin product $mixin
    }
  }
}

###
# Flesh out several trivial varieties of product
###
::oo::class create ::practcl::product.cheader {
  superclass ::practcl::product

  method project-compile-products {} {}
  method generate-loader-module {} {}
}




::oo::class create ::practcl::product.csource {
  superclass ::practcl::product

  method project-compile-products {} {
    set result {}
    set filename [my define get filename]
    if {$filename ne {}} {
      ::practcl::debug [self] [self class] [self method] project-compile-products $filename







|


|





|

|






>
>
>
|







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
          .a {
            set mixin ::practcl::product.clibrary
          }
        }
      }
    }
    if {$class ne {}} {
      $object clay mixinmap core $class
    }
    if {$mixin ne {}} {
      $object clay mixinmap product $mixin
    }
  }
}

###
# A product which generated from a C header file. Which is to say, nothing.
###
::clay::define ::practcl::product.cheader {
  superclass ::practcl::product

  method project-compile-products {} {}
  method generate-loader-module {} {}
}

###
# A product which generated from a C source file. Normally an object (.o) file.
###
::clay::define ::practcl::product.csource {
  superclass ::practcl::product

  method project-compile-products {} {
    set result {}
    set filename [my define get filename]
    if {$filename ne {}} {
      ::practcl::debug [self] [self class] [self method] project-compile-products $filename
625
626
627
628
629
630
631






632
633
634
635
636
637
638
639
640






641
642
643
644
645
646
647
648
    foreach item [my link list subordinate] {
      lappend result {*}[$item project-compile-products]
    }
    return $result
  }
}







::oo::class create ::practcl::product.clibrary {
  superclass ::practcl::product

  method linker-products {configdict} {
    return [my define get filename]
  }

}







::oo::class create ::practcl::product.dynamic {
  superclass ::practcl::dynamic ::practcl::product

  method initialize {} {
    set filename [my define get filename]
    if {$filename eq {}} {
      return
    }







>
>
>
>
>
>
|








>
>
>
>
>
>
|







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
    foreach item [my link list subordinate] {
      lappend result {*}[$item project-compile-products]
    }
    return $result
  }
}

###
# A product which is generated from a compiled C library.
# Usually a .a or a .dylib file, but in complex cases may
# actually just be a conduit for one project to integrate the
# source code of another
###
::clay::define ::practcl::product.clibrary {
  superclass ::practcl::product

  method linker-products {configdict} {
    return [my define get filename]
  }

}

###
# A product which is generated from C code that itself is generated
# by practcl or some other means. This C file may or may not produce
# its own .o file, depending on whether it is eligible to become part
# of an amalgamation
###
::clay::define ::practcl::product.dynamic {
  superclass ::practcl::dynamic ::practcl::product

  method initialize {} {
    set filename [my define get filename]
    if {$filename eq {}} {
      return
    }
662
663
664
665
666
667
668



669
670
671
672
    if {[my define get output_c] ne {}} {
      # Turn into a module if we have an output_c file
      my morph ::practcl::module
    }
  }
}




::oo::class create ::practcl::product.critcl {
  superclass ::practcl::dynamic ::practcl::product
}








>
>
>
|



677
678
679
680
681
682
683
684
685
686
687
688
689
690
    if {[my define get output_c] ne {}} {
      # Turn into a module if we have an output_c file
      my morph ::practcl::module
    }
  }
}

###
# A binary product produced by critcl. Note: The implementation is not
# written yet, this class does nothing.
::clay::define ::practcl::product.critcl {
  superclass ::practcl::dynamic ::practcl::product
}

Changes to modules/practcl/build/class/project/baseclass.tcl.

1


2
3
4
5
6
7
8
9



::oo::class create ::practcl::project {
  superclass ::practcl::module

  method _MorphPatterns {} {
    return {{@name@} {::practcl::@name@} {::practcl::project.@name@} {::practcl::project}}
  }

  constructor args {
|
>
>
|







1
2
3
4
5
6
7
8
9
10
11
###
# A toplevel project that is a collection of other projects
###
::clay::define ::practcl::project {
  superclass ::practcl::module

  method _MorphPatterns {} {
    return {{@name@} {::practcl::@name@} {::practcl::project.@name@} {::practcl::project}}
  }

  constructor args {
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
    my link add tool $obj
    oo::objdefine $obj $oodefine
    $obj define set masterpath $::CWD
    $obj go
    return $obj
  }





  method build-tclcore {} {
    set os [my define get TEACUP_OS]
    set tcl_config_opts [::practcl::platform::tcl_core_options $os]
    set tk_config_opts  [::practcl::platform::tk_core_options $os]

    lappend tcl_config_opts --prefix [my define get prefix] --exec-prefix [my define get prefix]
    set tclobj [my tclcore]
    if {[my define get debug 0]} {
      $tclobj define set debug 1
      lappend tcl_config_opts --enable-symbols=true
    }
    $tclobj define set config_opts $tcl_config_opts
    $tclobj go
    $tclobj compile

    set _TclSrcDir [$tclobj define get localsrcdir]
    my define set tclsrcdir $_TclSrcDir

    set tkobj [my tkcore]
    lappend tk_config_opts --with-tcl=[::practcl::file_relative [$tkobj define get builddir]  [$tclobj define get builddir]]
    if {[my define get debug 0]} {
      $tkobj define set debug 1
      lappend tk_config_opts --enable-symbols=true
    }
    $tkobj define set config_opts $tk_config_opts
    $tkobj compile

  }

  method child which {
    switch $which {

      organs {
	# A library can be a project, it can be a module. Any
	# subordinate modules will indicate their existance
        return [list project [self] module [self]]
      }
    }
  }







>
>
>
>

















|
|
|
|
|
|
|
|
|
>




>







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
    my link add tool $obj
    oo::objdefine $obj $oodefine
    $obj define set masterpath $::CWD
    $obj go
    return $obj
  }

  ###
  # Compile the Tcl core. If the define [emph tk] is true, compile the
  # Tk core as well
  ###
  method build-tclcore {} {
    set os [my define get TEACUP_OS]
    set tcl_config_opts [::practcl::platform::tcl_core_options $os]
    set tk_config_opts  [::practcl::platform::tk_core_options $os]

    lappend tcl_config_opts --prefix [my define get prefix] --exec-prefix [my define get prefix]
    set tclobj [my tclcore]
    if {[my define get debug 0]} {
      $tclobj define set debug 1
      lappend tcl_config_opts --enable-symbols=true
    }
    $tclobj define set config_opts $tcl_config_opts
    $tclobj go
    $tclobj compile

    set _TclSrcDir [$tclobj define get localsrcdir]
    my define set tclsrcdir $_TclSrcDir
    if {[my define get tk 0]} {
      set tkobj [my tkcore]
      lappend tk_config_opts --with-tcl=[::practcl::file_relative [$tkobj define get builddir]  [$tclobj define get builddir]]
      if {[my define get debug 0]} {
        $tkobj define set debug 1
        lappend tk_config_opts --enable-symbols=true
      }
      $tkobj define set config_opts $tk_config_opts
      $tkobj compile
    }
  }

  method child which {
    switch $which {
      delegate -
      organs {
	# A library can be a project, it can be a module. Any
	# subordinate modules will indicate their existance
        return [list project [self] module [self]]
      }
    }
  }
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
      return $obj
    }
    ${obj} {*}$args
  }


  method tclcore {} {
    if {[info commands [set obj [my organ tclcore]]] ne {}} {
      return $obj
    }
    if {[info commands [set obj [my project TCLCORE]]] ne {}} {
      my graft tclcore $obj
      return $obj
    }
    if {[info commands [set obj [my project tcl]]] ne {}} {







|







152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
      return $obj
    }
    ${obj} {*}$args
  }


  method tclcore {} {
    if {[info commands [set obj [my clay delegate tclcore]]] ne {}} {
      return $obj
    }
    if {[info commands [set obj [my project TCLCORE]]] ne {}} {
      my graft tclcore $obj
      return $obj
    }
    if {[info commands [set obj [my project tcl]]] ne {}} {
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
      fossil_url http://core.tcl.tk/tcl
    }]
    my graft tclcore $obj
    return $obj
  }

  method tkcore {} {
    if {[set obj [my organ tkcore]] ne {}} {
      return $obj
    }
    if {[set obj [my project tk]] ne {}} {
      my graft tkcore $obj
      return $obj
    }
    if {[set obj [my tool tk]] ne {}} {







|







177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
      fossil_url http://core.tcl.tk/tcl
    }]
    my graft tclcore $obj
    return $obj
  }

  method tkcore {} {
    if {[set obj [my clay delegate tkcore]] ne {}} {
      return $obj
    }
    if {[set obj [my project tk]] ne {}} {
      my graft tkcore $obj
      return $obj
    }
    if {[set obj [my tool tk]] ne {}} {

Changes to modules/practcl/build/class/project/library.tcl.

1


2
3
4
5
6
7
8
9



::oo::class create ::practcl::library {
  superclass ::practcl::project


  method clean {PATH} {
    set objext [my define get OBJEXT o]
    foreach {ofile info} [my project-compile-products] {
      if {[file exists [file join $PATH objs $ofile].${objext}]} {
|
>
>
|







1
2
3
4
5
6
7
8
9
10
11
###
# A toplevel project that produces a library
###
::clay::define ::practcl::library {
  superclass ::practcl::project


  method clean {PATH} {
    set objext [my define get OBJEXT o]
    foreach {ofile info} [my project-compile-products] {
      if {[file exists [file join $PATH objs $ofile].${objext}]} {
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
    set version [my define get pkg_vers [my define get version]]
    if {$version eq {}} {
      set version 0.1a
    }
    set output_tcl [my define get output_tcl]
    if {$output_tcl ne {}} {
      set script "\[list source \[file join \$dir $output_tcl\]\]"
    } elseif {[string is true -strict [my define get SHARED_BUILD]]} {
      set script "\[list load \[file join \$dir [my define get libfile]\] $name\]"
    } else {
      # Provide a null passthrough
      set script "\[list package provide $name $version\]"
    }
    set result "package ifneeded [list $name] [list $version] $script"
    foreach alias $args {







|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
    set version [my define get pkg_vers [my define get version]]
    if {$version eq {}} {
      set version 0.1a
    }
    set output_tcl [my define get output_tcl]
    if {$output_tcl ne {}} {
      set script "\[list source \[file join \$dir $output_tcl\]\]"
    } elseif {[my define get SHARED_BUILD 0]} {
      set script "\[list load \[file join \$dir [my define get libfile]\] $name\]"
    } else {
      # Provide a null passthrough
      set script "\[list package provide $name $version\]"
    }
    set result "package ifneeded [list $name] [list $version] $script"
    foreach alias $args {

Changes to modules/practcl/build/class/project/tclkit.tcl.

1
2

3
4
5
6
7
8
9
10



::oo::class create ::practcl::tclkit {
  superclass ::practcl::library

  method build-tclkit_main {PROJECT PKG_OBJS} {
    ###
    # Build static package list
    ###
    set statpkglist {}
|
|
>
|







1
2
3
4
5
6
7
8
9
10
11
###
# A toplevel project that produces a self-contained executable
###
::clay::define ::practcl::tclkit {
  superclass ::practcl::library

  method build-tclkit_main {PROJECT PKG_OBJS} {
    ###
    # Build static package list
    ###
    set statpkglist {}
66
67
68
69
70
71
72


73
74
75


76
77
78
79
80
81
82

    set map {}
    foreach var {
      vfsroot mainhook mainfunc vfs_main
    } {
      dict set map %${var}% [set $var]
    }


    set preinitscript {
set ::odie(boot_vfs) %vfsroot%
set ::SRCDIR $::odie(boot_vfs)


if {[file exists [file join %vfsroot% tcl_library init.tcl]]} {
  set ::tcl_library [file join %vfsroot% tcl_library]
  set ::auto_path {}
}
if {[file exists [file join %vfsroot% tk_library tk.tcl]]} {
  set ::tk_library [file join %vfsroot% tk_library]
}







>
>



>
>







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

    set map {}
    foreach var {
      vfsroot mainhook mainfunc vfs_main
    } {
      dict set map %${var}% [set $var]
    }
    set thread_init_script {namespace eval ::starkit {}}
    append thread_init_script \n [list set ::starkit::topdir $vfsroot]
    set preinitscript {
set ::odie(boot_vfs) %vfsroot%
set ::SRCDIR $::odie(boot_vfs)
namespace eval ::starkit {}
set ::starkit::topdir %vfsroot%
if {[file exists [file join %vfsroot% tcl_library init.tcl]]} {
  set ::tcl_library [file join %vfsroot% tcl_library]
  set ::auto_path {}
}
if {[file exists [file join %vfsroot% tk_library tk.tcl]]} {
  set ::tk_library [file join %vfsroot% tk_library]
}
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
      if {![dict exists $info version]} {
        error "$statpkg HAS NO VERSION"
      }
      # We employ a NULL to prevent the package system from thinking the
      # package is actually loaded into the interpreter
      $PROJECT code header "extern Tcl_PackageInitProc $initfunc\;\n"
      set script [list package ifneeded $statpkg [dict get $info version] [list ::load {} $statpkg]]
      append main_init_script \n [list set ::kitpkg(${statpkg}) $script]

      if {[dict get $info autoload]} {
        ::practcl::cputs appinit "  if(${initfunc}(interp)) return TCL_ERROR\;"
        ::practcl::cputs appinit "  Tcl_StaticPackage(interp,\"$statpkg\",$initfunc,NULL)\;"
      } else {
        ::practcl::cputs appinit "\n  Tcl_StaticPackage(NULL,\"$statpkg\",$initfunc,NULL)\;"
        append main_init_script \n $script
      }
    }
    append main_init_script \n {
if {[file exists [file join $::SRCDIR packages.tcl]]} {
  #In a wrapped exe, we don't go out to the environment
  set dir $::SRCDIR
  source [file join $::SRCDIR packages.tcl]
}


# Specify a user-specific startup file to invoke if the application
# is run interactively.  Typically the startup file is "~/.apprc"
# where "app" is the name of the application.  If this line is deleted
# then no user-specific startup file will be run under any conditions.
}


    append main_init_script \n [list set tcl_rcFileName [$PROJECT define get tcl_rcFileName ~/.tclshrc]]


    practcl::cputs appinit "  Tcl_Eval(interp,[::practcl::tcl_to_c  $main_init_script]);"
    practcl::cputs appinit {  return TCL_OK;}
    $PROJECT c_function [string map $map "int %mainfunc%(Tcl_Interp *interp)"] [string map $map $appinit]
  }

  method Collate_Source CWD {
    next $CWD
    set name [my define get name]
    # Assume a static shell
    if {[my define exists SHARED_BUILD]} {
      my define set SHARED_BUILD 0
    }
    if {![my define exists TCL_LOCAL_APPINIT]} {
      my define set TCL_LOCAL_APPINIT Tclkit_AppInit
    }
    if {![my define exists TCL_LOCAL_MAIN_HOOK]} {
      my define set TCL_LOCAL_MAIN_HOOK Tclkit_MainHook
    }
    set PROJECT [self]
    set os [$PROJECT define get TEACUP_OS]
    if {[my define get SHARED_BUILD]} {
      puts [list BUILDING TCLSH FOR OS $os]
    } else {
      puts [list BUILDING KIT FOR OS $os]
    }
    set TCLOBJ [$PROJECT tclcore]
    ::practcl::toolset select $TCLOBJ








|
>









|

|
|
|
>
>





>
>

>
>
|



















|







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
      if {![dict exists $info version]} {
        error "$statpkg HAS NO VERSION"
      }
      # We employ a NULL to prevent the package system from thinking the
      # package is actually loaded into the interpreter
      $PROJECT code header "extern Tcl_PackageInitProc $initfunc\;\n"
      set script [list package ifneeded $statpkg [dict get $info version] [list ::load {} $statpkg]]
      append main_init_script \n [list set ::starkit::static_packages(${statpkg}) $script]

      if {[dict get $info autoload]} {
        ::practcl::cputs appinit "  if(${initfunc}(interp)) return TCL_ERROR\;"
        ::practcl::cputs appinit "  Tcl_StaticPackage(interp,\"$statpkg\",$initfunc,NULL)\;"
      } else {
        ::practcl::cputs appinit "\n  Tcl_StaticPackage(NULL,\"$statpkg\",$initfunc,NULL)\;"
        append main_init_script \n $script
      }
    }
    append main_init_script \n {
if {[file exists [file join $::starkit::topdir pkgIndex.tcl]]} {
  #In a wrapped exe, we don't go out to the environment
  set dir $::starkit::topdir
  source [file join $::starkit::topdir pkgIndex.tcl]
}}
    append thread_init_script $main_init_script
    append main_init_script \n {
# Specify a user-specific startup file to invoke if the application
# is run interactively.  Typically the startup file is "~/.apprc"
# where "app" is the name of the application.  If this line is deleted
# then no user-specific startup file will be run under any conditions.
}
    append thread_init_script \n [list set ::starkit::thread_init $thread_init_script]
    append main_init_script \n [list set ::starkit::thread_init $thread_init_script]
    append main_init_script \n [list set tcl_rcFileName [$PROJECT define get tcl_rcFileName ~/.tclshrc]]


    practcl::cputs appinit "  Tcl_Eval(interp,[::practcl::tcl_to_c  $thread_init_script]);"
    practcl::cputs appinit {  return TCL_OK;}
    $PROJECT c_function [string map $map "int %mainfunc%(Tcl_Interp *interp)"] [string map $map $appinit]
  }

  method Collate_Source CWD {
    next $CWD
    set name [my define get name]
    # Assume a static shell
    if {[my define exists SHARED_BUILD]} {
      my define set SHARED_BUILD 0
    }
    if {![my define exists TCL_LOCAL_APPINIT]} {
      my define set TCL_LOCAL_APPINIT Tclkit_AppInit
    }
    if {![my define exists TCL_LOCAL_MAIN_HOOK]} {
      my define set TCL_LOCAL_MAIN_HOOK Tclkit_MainHook
    }
    set PROJECT [self]
    set os [$PROJECT define get TEACUP_OS]
    if {[my define get SHARED_BUILD 0]} {
      puts [list BUILDING TCLSH FOR OS $os]
    } else {
      puts [list BUILDING KIT FOR OS $os]
    }
    set TCLOBJ [$PROJECT tclcore]
    ::practcl::toolset select $TCLOBJ

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
      if {[string is true [$item define get static]]} {
        lappend PKG_OBJS $item
      }
    }
    # Arrange to build an main.c that utilizes TCL_LOCAL_APPINIT and TCL_LOCAL_MAIN_HOOK
    if {$os eq "windows"} {
      set PLATFORM_SRC_DIR win
      if {[my define get SHARED_BUILD]} {
        my add class csource filename [file join $TCLSRCDIR win tclWinReg.c] initfunc Registry_Init pkg_name registry pkg_vers 1.3.1 autoload 1
        my add class csource filename [file join $TCLSRCDIR win tclWinDde.c] initfunc Dde_Init pkg_name dde pkg_vers 1.4.0 autoload 1
      }
      my add class csource ofile [my define get name]_appinit.o filename [file join $TCLSRCDIR win tclAppInit.c] extra [list -DTCL_LOCAL_MAIN_HOOK=[my define get TCL_LOCAL_MAIN_HOOK Tclkit_MainHook] -DTCL_LOCAL_APPINIT=[my define get TCL_LOCAL_APPINIT Tclkit_AppInit]]
    } else {
      set PLATFORM_SRC_DIR unix
      my add class csource ofile [my define get name]_appinit.o filename [file join $TCLSRCDIR unix tclAppInit.c] extra [list -DTCL_LOCAL_MAIN_HOOK=[my define get TCL_LOCAL_MAIN_HOOK Tclkit_MainHook] -DTCL_LOCAL_APPINIT=[my define get TCL_LOCAL_APPINIT Tclkit_AppInit]]
    }

    if {[my define get SHARED_BUILD]} {
      ###
      # Add local static Zlib implementation
      ###
      set cdir [file join $TCLSRCDIR compat zlib]
      foreach file {
        adler32.c compress.c crc32.c
        deflate.c infback.c inffast.c







|









|







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
      if {[string is true [$item define get static]]} {
        lappend PKG_OBJS $item
      }
    }
    # Arrange to build an main.c that utilizes TCL_LOCAL_APPINIT and TCL_LOCAL_MAIN_HOOK
    if {$os eq "windows"} {
      set PLATFORM_SRC_DIR win
      if {![my define get SHARED_BUILD 0]} {
        my add class csource filename [file join $TCLSRCDIR win tclWinReg.c] initfunc Registry_Init pkg_name registry pkg_vers 1.3.1 autoload 1
        my add class csource filename [file join $TCLSRCDIR win tclWinDde.c] initfunc Dde_Init pkg_name dde pkg_vers 1.4.0 autoload 1
      }
      my add class csource ofile [my define get name]_appinit.o filename [file join $TCLSRCDIR win tclAppInit.c] extra [list -DTCL_LOCAL_MAIN_HOOK=[my define get TCL_LOCAL_MAIN_HOOK Tclkit_MainHook] -DTCL_LOCAL_APPINIT=[my define get TCL_LOCAL_APPINIT Tclkit_AppInit]]
    } else {
      set PLATFORM_SRC_DIR unix
      my add class csource ofile [my define get name]_appinit.o filename [file join $TCLSRCDIR unix tclAppInit.c] extra [list -DTCL_LOCAL_MAIN_HOOK=[my define get TCL_LOCAL_MAIN_HOOK Tclkit_MainHook] -DTCL_LOCAL_APPINIT=[my define get TCL_LOCAL_APPINIT Tclkit_AppInit]]
    }

    if {![my define get SHARED_BUILD 0]} {
      ###
      # Add local static Zlib implementation
      ###
      set cdir [file join $TCLSRCDIR compat zlib]
      foreach file {
        adler32.c compress.c crc32.c
        deflate.c infback.c inffast.c
285
286
287
288
289
290
291


292
293



294
295
296
297
298
299
300
301
    if {[file exists $zipfs]} {
      $TCLOBJ define set tip_430 1
      my define set tip_430 1
    } else {
      # The Tclconfig project maintains a mirror of the version
      # released with the Tcl core
      my define set tip_430 0


      ::practcl::LOCAL tool tclconfig unpack
      set COMPATSRCROOT [::practcl::LOCAL tool tclconfig define get srcdir]



      my add class csource ofile tclZipfs.o filename [file join $COMPATSRCROOT compat tclZipfs.c] extra -I[::practcl::file_relative $CWD [file join $TCLSRCDIR compat zlib contrib minizip]]
    }

    my define add include_dir [file join $TCLSRCDIR generic]
    my define add include_dir [file join $TCLSRCDIR $PLATFORM_SRC_DIR]
    # This file will implement TCL_LOCAL_APPINIT and TCL_LOCAL_MAIN_HOOK
    my build-tclkit_main $PROJECT $PKG_OBJS
  }







>
>
|
|
>
>
>
|







297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
    if {[file exists $zipfs]} {
      $TCLOBJ define set tip_430 1
      my define set tip_430 1
    } else {
      # The Tclconfig project maintains a mirror of the version
      # released with the Tcl core
      my define set tip_430 0
      set tclzipfs_c [my define get tclzipfs_c]
      if {![file exists $tclzipfs_c]} {
        ::practcl::LOCAL tool tclconfig unpack
        set COMPATSRCROOT [::practcl::LOCAL tool tclconfig define get srcdir]
        set tclzipfs_c [file join $COMPATSRCROOT compat tclZipfs.c]
      }
      my add class csource ofile tclZipfs.o filename $tclzipfs_c \
        extra -I[::practcl::file_relative $CWD [file join $TCLSRCDIR compat zlib contrib minizip]]
    }

    my define add include_dir [file join $TCLSRCDIR generic]
    my define add include_dir [file join $TCLSRCDIR $PLATFORM_SRC_DIR]
    # This file will implement TCL_LOCAL_APPINIT and TCL_LOCAL_MAIN_HOOK
    my build-tclkit_main $PROJECT $PKG_OBJS
  }
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
    #if {[my define get installdir] ne {}} {
    #  ::practcl::copyDir [file join [my define get installdir] [string trimleft [my define get prefix] /] lib] [file join $vfspath lib]
    #}
    foreach arg $args {
       ::practcl::copyDir $arg $vfspath
    }

    set fout [open [file join $vfspath packages.tcl] w]
    puts $fout [string map [list %platform% [my define get TEACUP_PROFILE]] {set ::tcl_teapot_profile {%platform%}}]
    puts $fout {

set ::PKGIDXFILE [info script]
set dir [file dirname $::PKGIDXFILE]
if {$::tcl_platform(platform) eq "windows"} {
  set ::g(HOME) [file join [file normalize $::env(LOCALAPPDATA)] tcl]
} else {
  set ::g(HOME) [file normalize ~/tcl]
}
set ::tcl_teapot [file join $::g(HOME) teapot $::tcl_teapot_profile]
lappend ::auto_path $::tcl_teapot
}
    puts $fout [list proc installDir [info args ::practcl::installDir] [info body ::practcl::installDir]]
    set buffer [::practcl::pkgindex_path $vfspath]
    puts $fout $buffer
    puts $fout {
# Advertise statically linked packages
foreach {pkg script} [array get ::kitpkg] {
  eval $script
}
}
    puts $fout {
###
# Cache binary packages distributed as dynamic libraries in a known location
###







|


>



|

|

|







|







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
    #if {[my define get installdir] ne {}} {
    #  ::practcl::copyDir [file join [my define get installdir] [string trimleft [my define get prefix] /] lib] [file join $vfspath lib]
    #}
    foreach arg $args {
       ::practcl::copyDir $arg $vfspath
    }

    set fout [open [file join $vfspath pkgIndex.tcl] w]
    puts $fout [string map [list %platform% [my define get TEACUP_PROFILE]] {set ::tcl_teapot_profile {%platform%}}]
    puts $fout {
namespace eval ::starkit {}
set ::PKGIDXFILE [info script]
set dir [file dirname $::PKGIDXFILE]
if {$::tcl_platform(platform) eq "windows"} {
  set ::starkit::localHome [file join [file normalize $::env(LOCALAPPDATA)] tcl]
} else {
  set ::starkit::localHome [file normalize ~/tcl]
}
set ::tcl_teapot [file join $::starkit::localHome teapot $::tcl_teapot_profile]
lappend ::auto_path $::tcl_teapot
}
    puts $fout [list proc installDir [info args ::practcl::installDir] [info body ::practcl::installDir]]
    set buffer [::practcl::pkgindex_path $vfspath]
    puts $fout $buffer
    puts $fout {
# Advertise statically linked packages
foreach {pkg script} [array get ::starkit::static_packages] {
  eval $script
}
}
    puts $fout {
###
# Cache binary packages distributed as dynamic libraries in a known location
###

Changes to modules/practcl/build/class/subproject/baseclass.tcl.




1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21



oo::class create ::practcl::subproject {
  superclass ::practcl::module

  method _MorphPatterns {} {
    return {{::practcl::subproject.@name@} {::practcl::@name@} {@name@} {::practcl::subproject}}
  }


  method BuildDir {PWD} {
    return [my define get srcdir]
  }

  method child which {
    switch $which {

      organs {
	# A library can be a project, it can be a module. Any
	# subordinate modules will indicate their existance
        return [list project [self] module [self]]
      }
    }
  }
>
>
>
|













>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
###
# A subordinate project
###
::clay::define ::practcl::subproject {
  superclass ::practcl::module

  method _MorphPatterns {} {
    return {{::practcl::subproject.@name@} {::practcl::@name@} {@name@} {::practcl::subproject}}
  }


  method BuildDir {PWD} {
    return [my define get srcdir]
  }

  method child which {
    switch $which {
      delegate -
      organs {
	# A library can be a project, it can be a module. Any
	# subordinate modules will indicate their existance
        return [list project [self] module [self]]
      }
    }
  }
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
###


###
# A project which the kit compiles and integrates
# the source for itself
###
oo::class create ::practcl::subproject.source {
  superclass ::practcl::subproject ::practcl::library

  method env-bootstrap {} {
    set LibraryRoot [file join [my define get srcdir] [my define get module_root modules]]
    if {[file exists $LibraryRoot] && $LibraryRoot ni $::auto_path} {
      set ::auto_path [linsert $::auto_path 0 $LibraryRoot]
    }







|







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
###


###
# A project which the kit compiles and integrates
# the source for itself
###
::clay::define ::practcl::subproject.source {
  superclass ::practcl::subproject ::practcl::library

  method env-bootstrap {} {
    set LibraryRoot [file join [my define get srcdir] [my define get module_root modules]]
    if {[file exists $LibraryRoot] && $LibraryRoot ni $::auto_path} {
      set ::auto_path [linsert $::auto_path 0 $LibraryRoot]
    }
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  method linktype {} {
    return {subordinate package source}
  }

}

# a copy from the teapot
oo::class create ::practcl::subproject.teapot {
  superclass ::practcl::subproject

  method env-bootstrap {} {
    set pkg [my define get pkg_name [my define get name]]
    package require $pkg
  }








|







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
  method linktype {} {
    return {subordinate package source}
  }

}

# a copy from the teapot
::clay::define ::practcl::subproject.teapot {
  superclass ::practcl::subproject

  method env-bootstrap {} {
    set pkg [my define get pkg_name [my define get name]]
    package require $pkg
  }

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
    my unpack
    set prefix [string trimleft [my <project> define get prefix] /]
    ::practcl::tcllib_require zipfile::decode
    ::zipfile::decode::unzipfile [file join $download $pkg.zip] [file join $DEST $prefix lib $pkg]
  }
}

oo::class create ::practcl::subproject.kettle {
  superclass ::practcl::subproject

  method kettle {path args} {
    my variable kettle
    if {![info exists kettle]} {
      ::practcl::LOCAL tool kettle env-load
      set kettle [file join [::practcl::LOCAL tool kettle define get srcdir] kettle]
    }
    set srcdir [my SourceRoot]
    ::practcl::dotclexec $kettle -f [file join $srcdir build.tcl] {*}$args
  }

  method install DEST {
    my kettle reinstall --prefix $DEST
  }
}

oo::class create ::practcl::subproject.critcl {
  superclass ::practcl::subproject

  method install DEST {
    my critcl -pkg [my define get name]
    set srcdir [my SourceRoot]
    ::practcl::copyDir [file join $srcdir [my define get name]] [file join $DEST lib [my define get name]]
  }
}


oo::class create ::practcl::subproject.sak {
  superclass ::practcl::subproject

  method env-bootstrap {} {
    set LibraryRoot [file join [my define get srcdir] [my define get module_root modules]]
    if {[file exists $LibraryRoot] && $LibraryRoot ni $::auto_path} {
      set ::auto_path [linsert $::auto_path 0 $LibraryRoot]
    }







|

















|









<
|







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
    my unpack
    set prefix [string trimleft [my <project> define get prefix] /]
    ::practcl::tcllib_require zipfile::decode
    ::zipfile::decode::unzipfile [file join $download $pkg.zip] [file join $DEST $prefix lib $pkg]
  }
}

::clay::define ::practcl::subproject.kettle {
  superclass ::practcl::subproject

  method kettle {path args} {
    my variable kettle
    if {![info exists kettle]} {
      ::practcl::LOCAL tool kettle env-load
      set kettle [file join [::practcl::LOCAL tool kettle define get srcdir] kettle]
    }
    set srcdir [my SourceRoot]
    ::practcl::dotclexec $kettle -f [file join $srcdir build.tcl] {*}$args
  }

  method install DEST {
    my kettle reinstall --prefix $DEST
  }
}

::clay::define ::practcl::subproject.critcl {
  superclass ::practcl::subproject

  method install DEST {
    my critcl -pkg [my define get name]
    set srcdir [my SourceRoot]
    ::practcl::copyDir [file join $srcdir [my define get name]] [file join $DEST lib [my define get name]]
  }
}


::clay::define ::practcl::subproject.sak {
  superclass ::practcl::subproject

  method env-bootstrap {} {
    set LibraryRoot [file join [my define get srcdir] [my define get module_root modules]]
    if {[file exists $LibraryRoot] && $LibraryRoot ni $::auto_path} {
      set ::auto_path [linsert $::auto_path 0 $LibraryRoot]
    }
260
261
262
263
264
265
266


267
268
269



270
271
272
273
274












































    ::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
  }

  method install-module {DEST args} {


    set pkg [my define get pkg_name [my define get name]]
    set prefix [my <project> define get prefix [file normalize [file join ~ tcl]]]
    set pkgpath [file join $prefix lib $pkg]



    foreach module $args {
      ::practcl::installDir [file join $pkgpath $module] [file join $DEST $module]
    }
  }
}



















































>
>
|
|
|
>
>
>
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
    ::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
  }

  method install-module {DEST args} {
    set srcdir [my define get srcdir]
    if {[llength $args]==1 && [lindex $args 0] in {* all}} {
      set pkg [my define get pkg_name [my define get name]]
      ::practcl::dotclexec [file join $srcdir installer.tcl] \
        -pkg-path [file join $DEST $pkg]  \
        -no-examples -no-html -no-nroff \
        -no-wait -no-gui -no-apps
    } else {
      foreach module $args {
        ::practcl::installModule [file join $srcdir modules $module] [file join $DEST $module]
      }
    }
  }
}


::clay::define ::practcl::subproject.practcl {
  superclass ::practcl::subproject

  method env-bootstrap {} {
    set LibraryRoot [file join [my define get srcdir] [my define get module_root modules]]
    if {[file exists $LibraryRoot] && $LibraryRoot ni $::auto_path} {
      set ::auto_path [linsert $::auto_path 0 $LibraryRoot]
    }
  }

  method env-install {} {
    ###
    # Handle teapot installs
    ###
    set pkg [my define get pkg_name [my define get name]]
    my unpack
    set prefix [my <project> define get prefix [file normalize [file join ~ tcl]]]
    set srcdir [my define get srcdir]
    ::practcl::dotclexec [file join $srcdir make.tcl] install [file join $prefix lib $pkg]
  }

  method install DEST {
    ###
    # Handle teapot installs
    ###
    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]
    puts [list INSTALLING  [my define get name] to [file join $DEST $prefix lib $pkg]]
    ::practcl::dotclexec [file join $srcdir make.tcl] install [file join $DEST $prefix lib $pkg]
  }

  method install-module {DEST args} {
    set pkg [my define get pkg_name [my define get name]]
    set srcdir [my define get srcdir]
    ::practcl::dotclexec [file join $srcdir make.tcl] install-module $DEST {*}$args
  }
}


Changes to modules/practcl/build/class/subproject/binary.tcl.

1
2
3
4
5
6
7
8
9
10
11
12

###
# A binary package
###
oo::class create ::practcl::subproject.binary {
  superclass ::practcl::subproject

  method clean {} {
    set builddir [file normalize [my define get builddir]]
    if {![file exists $builddir]} return
    if {[file exists [file join $builddir make.tcl]]} {
      ::practcl::domake.tcl $builddir clean
<

|

|








1
2
3
4
5
6
7
8
9
10
11

###
# A subordinate binary package
###
::clay::define ::practcl::subproject.binary {
  superclass ::practcl::subproject

  method clean {} {
    set builddir [file normalize [my define get builddir]]
    if {![file exists $builddir]} return
    if {[file exists [file join $builddir make.tcl]]} {
      ::practcl::domake.tcl $builddir clean
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    set prefix [my <project> define get prefix [file normalize [file join ~ tcl]]]
    set srcdir [my define get srcdir]
    lappend options --prefix $prefix --exec-prefix $prefix
    my define set config_opts $options
    my go
    my clean
    my compile
    my make-install {}
  }

  method project-compile-products {} {}

  method ComputeInstall {} {
    if {[my define exists install]} {
      switch [my define get install] {







|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
    set prefix [my <project> define get prefix [file normalize [file join ~ tcl]]]
    set srcdir [my define get srcdir]
    lappend options --prefix $prefix --exec-prefix $prefix
    my define set config_opts $options
    my go
    my clean
    my compile
    my make install {}
  }

  method project-compile-products {} {}

  method ComputeInstall {} {
    if {[my define exists install]} {
      switch [my define get install] {
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
    ###
    set srcdir [my define get srcdir]
    if {[my define get static 1]} {
      puts "BUILDING Static $name $srcdir"
    } else {
      puts "BUILDING Dynamic $name $srcdir"
    }
    my make-compile
    cd $PWD
  }

  method Configure {} {
    cd $::CWD
    my unpack
    ::practcl::toolset select [self]
    set srcdir [file normalize [my define get srcdir]]
    set builddir [file normalize [my define get builddir]]
    file mkdir $builddir
    my make-autodetect
  }

  method install DEST {
    set PWD [pwd]
    set PREFIX  [my <project> define get prefix]
    ###
    # Handle teapot installs







|










|







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
    ###
    set srcdir [my define get srcdir]
    if {[my define get static 1]} {
      puts "BUILDING Static $name $srcdir"
    } else {
      puts "BUILDING Dynamic $name $srcdir"
    }
    my make compile
    cd $PWD
  }

  method Configure {} {
    cd $::CWD
    my unpack
    ::practcl::toolset select [self]
    set srcdir [file normalize [my define get srcdir]]
    set builddir [file normalize [my define get builddir]]
    file mkdir $builddir
    my make autodetect
  }

  method install DEST {
    set PWD [pwd]
    set PREFIX  [my <project> define get prefix]
    ###
    # Handle teapot installs
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
          set dest  [file join $DEST [string trimleft $PREFIX /] lib [file tail $teapath]]
          ::practcl::copyDir $teapath $dest
          return
        }
      }
    }
    my compile
    my make-install $DEST
    cd $PWD
  }
}




oo::class create ::practcl::subproject.tea {
  superclass ::practcl::subproject.binary

}




oo::class create ::practcl::subproject.library {
  superclass ::practcl::subproject.binary ::practcl::library
  method install DEST {
    my compile
  }
}


# An external library

oo::class create ::practcl::subproject.external {
  superclass ::practcl::subproject.binary
  method install DEST {
    my compile
  }
}







|




>
>
>
|




>
>
>
|






>
|
>
|





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
          set dest  [file join $DEST [string trimleft $PREFIX /] lib [file tail $teapath]]
          ::practcl::copyDir $teapath $dest
          return
        }
      }
    }
    my compile
    my make install $DEST
    cd $PWD
  }
}

###
# A subordinate TEA based binary package
###
::clay::define ::practcl::subproject.tea {
  superclass ::practcl::subproject.binary

}

###
# A subordinate C library built by this project
###
::clay::define ::practcl::subproject.library {
  superclass ::practcl::subproject.binary ::practcl::library
  method install DEST {
    my compile
  }
}

###
# A subordinate external C library
###
::clay::define ::practcl::subproject.external {
  superclass ::practcl::subproject.binary
  method install DEST {
    my compile
  }
}

Changes to modules/practcl/build/class/subproject/core.tcl.

1
2
3
4
5
6
7
8
9

oo::class create ::practcl::subproject.core {
  superclass ::practcl::subproject.binary

  method env-bootstrap {} {}

  method env-present {} {
    set PREFIX [my <project> define get prefix]
    set name [my define get name]

|







1
2
3
4
5
6
7
8
9

::clay::define ::practcl::subproject.core {
  superclass ::practcl::subproject.binary

  method env-bootstrap {} {}

  method env-present {} {
    set PREFIX [my <project> define get prefix]
    set name [my define get name]
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

    set prefix [my <project> define get prefix [file normalize [file join ~ tcl]]]
    lappend options --prefix $prefix --exec-prefix $prefix
    my define set config_opts $options
    puts [list [self] OS [dict get $os TEACUP_OS] options $options]
    my go
    my compile
    my make-install {}
  }

  method go {} {
    my define set core_binary 1
    next
  }

  method linktype {} {
    return {subordinate core.library}
  }
}







|











17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

    set prefix [my <project> define get prefix [file normalize [file join ~ tcl]]]
    lappend options --prefix $prefix --exec-prefix $prefix
    my define set config_opts $options
    puts [list [self] OS [dict get $os TEACUP_OS] options $options]
    my go
    my compile
    my make install {}
  }

  method go {} {
    my define set core_binary 1
    next
  }

  method linktype {} {
    return {subordinate core.library}
  }
}

Changes to modules/practcl/build/class/target.tcl.

1



2
3
4
5
6
7
8
9




::oo::class create ::practcl::make_obj {
  superclass ::practcl::metaclass

  constructor {module_object name info {action_body {}}} {
    my variable define triggered domake
    set triggered 0
    set domake 0
    set define(name) $name
|
>
>
>
|







1
2
3
4
5
6
7
8
9
10
11
12
###
# A build deliverable object. Normally an object file, header, or tcl script
# which must be compiled or generated in some way
###
::clay::define ::practcl::make_obj {
  superclass ::practcl::metaclass

  constructor {module_object name info {action_body {}}} {
    my variable define triggered domake
    set triggered 0
    set domake 0
    set define(name) $name
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
        if {$filename ne {} && ![file exists $filename]} {
          set needs_make 1
        }
      }
    }
    return $needs_make
  }
  
  method output {} {
    set result {}
    set filename [my define get filename]
    if {$filename ne {}} {
      lappend result $filename
    }
    foreach filename [my define get files] {
      if {$filename ne {}} {
        lappend result $filename
      }
    }
    return $result
  }

  method reset {} {
    my variable triggered domake needs_make
    set triggerd 0
    set domake 0
    set needs_make 0
  }
  
  method triggers {} {
    my variable triggered domake define
    if {$triggered} {
      return $domake
    }
    set triggered 1
    set make_objects [my <module> make objects]







|




















|







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
        if {$filename ne {} && ![file exists $filename]} {
          set needs_make 1
        }
      }
    }
    return $needs_make
  }

  method output {} {
    set result {}
    set filename [my define get filename]
    if {$filename ne {}} {
      lappend result $filename
    }
    foreach filename [my define get files] {
      if {$filename ne {}} {
        lappend result $filename
      }
    }
    return $result
  }

  method reset {} {
    my variable triggered domake needs_make
    set triggerd 0
    set domake 0
    set needs_make 0
  }

  method triggers {} {
    my variable triggered domake define
    if {$triggered} {
      return $domake
    }
    set triggered 1
    set make_objects [my <module> make objects]

Changes to modules/practcl/build/class/toolset/baseclass.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26


27
28
29
30







31
32
33
34
35
36
37
###
# Ancestor-less class intended to be a mixin
# which defines a family of build related behaviors
# that are modified when targetting either gcc or msvc
###
oo::class create ::practcl::toolset {
  ###
  # find or fake a key/value list describing this project
  ###
  method config.sh {} {
    return [my read_configuration]
  }
  

  method BuildDir {PWD} {
    set name [my define get name]
    set debug [my define get debug 0]
    if {[my <project> define get LOCAL 0]} {
      return [my define get builddir [file join $PWD local $name]]
    }
    if {$debug} {
      return [my define get builddir [file join $PWD debug $name]]
    } else {
      return [my define get builddir [file join $PWD pkg $name]]
    }
  }
  


  method MakeDir {srcdir} {
    return $srcdir
  }
  







  method read_configuration {} {
    my variable conf_result
    if {[info exists conf_result]} {
      return $conf_result
    }
    set result {}
    set name [my define get name]





|






|
>












|
>
>



|
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
###
# Ancestor-less class intended to be a mixin
# which defines a family of build related behaviors
# that are modified when targetting either gcc or msvc
###
::clay::define ::practcl::toolset {
  ###
  # find or fake a key/value list describing this project
  ###
  method config.sh {} {
    return [my read_configuration]
  }

  # Compute the location where the product will be built
  method BuildDir {PWD} {
    set name [my define get name]
    set debug [my define get debug 0]
    if {[my <project> define get LOCAL 0]} {
      return [my define get builddir [file join $PWD local $name]]
    }
    if {$debug} {
      return [my define get builddir [file join $PWD debug $name]]
    } else {
      return [my define get builddir [file join $PWD pkg $name]]
    }
  }

  # Return where the Makefile is located relative to [emph srcdir].
  # For this implementation the MakeDir is always srcdir.
  method MakeDir {srcdir} {
    return $srcdir
  }

  # Read information about the build process for this package.
  # For this implementation, data is sought in the following locations
  # in the following order:
  # config.tcl (generated by practcl.) PKGConfig.sh. The Makefile
  # [para]
  # If the Makefile needs to be consulted, but does not exist, the
  # Configure method is invoked
  method read_configuration {} {
    my variable conf_result
    if {[info exists conf_result]} {
      return $conf_result
    }
    set result {}
    set name [my define get name]
72
73
74
75
76
77
78



79
80
81
82
83
84
85
      }
      set conf_result $result
      return $result
    }
    ###
    # Oh man... we have to guess
    ###



    set filename [file join $builddir Makefile]
    if {![file exists $filename]} {
      error "Could not locate any configuration data in $srcdir"
    }
    foreach {field dat} [::practcl::read_Makefile $filename] {
      dict set result $field $dat
    }







>
>
>







82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
      }
      set conf_result $result
      return $result
    }
    ###
    # Oh man... we have to guess
    ###
    if {![file exists [file join $builddir Makefile]]} {
      my Configure
    }
    set filename [file join $builddir Makefile]
    if {![file exists $filename]} {
      error "Could not locate any configuration data in $srcdir"
    }
    foreach {field dat} [::practcl::read_Makefile $filename] {
      dict set result $field $dat
    }
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
      }
    }
    append defs " -DPACKAGE_NAME=\"${name}\" -DPACKAGE_VERSION=\"${version}\""
    append defs " -DPACKAGE_TARNAME=\"${name}\" -DPACKAGE_STRING=\"${name}\x5c\x20${version}\""
    return $defs
  }


  method critcl args {
    if {![info exists critcl]} {
      ::practcl::LOCAL tool critcl env-load
      set critcl [file join [::practcl::LOCAL tool critcl define get srcdir] main.tcl
    }
    set srcdir [my SourceRoot]
    set PWD [pwd]
    cd $srcdir
    ::practcl::dotclexec $critcl {*}$args
    cd $PWD
  }
  
  method make-autodetect {} {}
}


oo::objdefine ::practcl::toolset {


  method select object {
    ###
    # Select the toolset to use for this project
    ###
    if {[$object define exists toolset]} {
      return [$object define get toolset]
    }
    set class [$object define get toolset]
    if {$class ne {}} {
      $object mixin toolset $class
    } else {
      if {[info exists ::env(VisualStudioVersion)]} {
        $object mixin toolset ::practcl::toolset.msvc
      } else {
        $object mixin toolset ::practcl::toolset.gcc
      }
    }
  }
}







>











|
<
|
<
<

|
<









|


|

|




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
      }
    }
    append defs " -DPACKAGE_NAME=\"${name}\" -DPACKAGE_VERSION=\"${version}\""
    append defs " -DPACKAGE_TARNAME=\"${name}\" -DPACKAGE_STRING=\"${name}\x5c\x20${version}\""
    return $defs
  }

  # Invoke critcl in an external process
  method critcl args {
    if {![info exists critcl]} {
      ::practcl::LOCAL tool critcl env-load
      set critcl [file join [::practcl::LOCAL tool critcl define get srcdir] main.tcl
    }
    set srcdir [my SourceRoot]
    set PWD [pwd]
    cd $srcdir
    ::practcl::dotclexec $critcl {*}$args
    cd $PWD
  }
}




oo::objdefine ::practcl::toolset {
  # Perform the selection for the toolset mixin

  method select object {
    ###
    # Select the toolset to use for this project
    ###
    if {[$object define exists toolset]} {
      return [$object define get toolset]
    }
    set class [$object define get toolset]
    if {$class ne {}} {
      $object clay mixinmap toolset $class
    } else {
      if {[info exists ::env(VisualStudioVersion)]} {
        $object clay mixinmap toolset ::practcl::toolset.msvc
      } else {
        $object clay mixinmap toolset ::practcl::toolset.gcc
      }
    }
  }
}

Changes to modules/practcl/build/class/toolset/gcc.tcl.

1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19

::oo::class create ::practcl::toolset.gcc {
  superclass ::practcl::toolset

  method Autoconf {} {
    ###
    # Re-run autoconf for this project
    # Not a good idea in practice... but in the right hands it can be useful
    ###
    set pwd [pwd]
    set srcdir [file normalize [my define get srcdir]]

    cd $srcdir
    foreach template {configure.ac configure.in} {
      set input [file join $srcdir $template]
      if {[file exists $input]} {
        puts "autoconf -f $input > [file join $srcdir configure]"
        exec autoconf -f $input > [file join $srcdir configure]
      }
    }

|









>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

::clay::define ::practcl::toolset.gcc {
  superclass ::practcl::toolset

  method Autoconf {} {
    ###
    # Re-run autoconf for this project
    # Not a good idea in practice... but in the right hands it can be useful
    ###
    set pwd [pwd]
    set srcdir [file normalize [my define get srcdir]]
    set localsrcdir [my MakeDir $srcdir]
    cd $localsrcdir
    foreach template {configure.ac configure.in} {
      set input [file join $srcdir $template]
      if {[file exists $input]} {
        puts "autoconf -f $input > [file join $srcdir configure]"
        exec autoconf -f $input > [file join $srcdir configure]
      }
    }
51
52
53
54
55
56
57


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75



76
77






78


79
80
81
82
83
84
85
86
87
88
      }
    }
    if {[my <project> define get CONFIG_SITE] != {}} {
      lappend opts --host=[my <project> define get HOST]
    }
    set inside_msys [string is true -strict [my <project> define get MSYS_ENV 0]]
    lappend opts --with-tclsh=[info nameofexecutable]


    if {![my <project> define get LOCAL 0]} {
      set obj [my <project> tclcore]
      if {$obj ne {}} {
        if {$inside_msys} {
          lappend opts --with-tcl=[::practcl::file_relative [file normalize $builddir] [$obj define get builddir]]
        } else {
          lappend opts --with-tcl=[file normalize [$obj define get builddir]]
        }
      }
      if {[my define get tk 0]} {
        set obj [my <project> tkcore]
        if {$obj ne {}} {
          if {$inside_msys} {
            lappend opts --with-tk=[::practcl::file_relative [file normalize $builddir] [$obj define get builddir]]
          } else {
            lappend opts --with-tk=[file normalize [$obj define get builddir]]
          }
        }



      }
    } else {






      lappend opts --with-tcl=[file join $PREFIX lib]


      if {[my define get tk 0]} {
        lappend opts --with-tk=[file join $PREFIX lib]
      }
    }

    lappend opts {*}[my define get config_opts]
    if {![regexp -- "--prefix" $opts]} {
      lappend opts --prefix=$PREFIX --exec-prefix=$PREFIX
    }
    if {[my define get debug 0]} {







>
>
|
|
|
|
|
|
|
|
|
<








>
>
>


>
>
>
>
>
>
|
>
>
|
|








52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
      }
    }
    if {[my <project> define get CONFIG_SITE] != {}} {
      lappend opts --host=[my <project> define get HOST]
    }
    set inside_msys [string is true -strict [my <project> define get MSYS_ENV 0]]
    lappend opts --with-tclsh=[info nameofexecutable]

    if {[my define get tk 0]} {
      if {![my <project> define get LOCAL 0]} {
        set obj [my <project> tclcore]
        if {$obj ne {}} {
          if {$inside_msys} {
            lappend opts --with-tcl=[::practcl::file_relative [file normalize $builddir] [$obj define get builddir]]
          } else {
            lappend opts --with-tcl=[file normalize [$obj define get builddir]]
          }
        }

        set obj [my <project> tkcore]
        if {$obj ne {}} {
          if {$inside_msys} {
            lappend opts --with-tk=[::practcl::file_relative [file normalize $builddir] [$obj define get builddir]]
          } else {
            lappend opts --with-tk=[file normalize [$obj define get builddir]]
          }
        }
      } else {
        lappend opts --with-tcl=[file join $PREFIX lib]
        lappend opts --with-tk=[file join $PREFIX lib]
      }
    } else {
      if {![my <project> define get LOCAL 0]} {
        set obj [my <project> tclcore]
        if {$obj ne {}} {
          if {$inside_msys} {
            lappend opts --with-tcl=[::practcl::file_relative [file normalize $builddir] [$obj define get builddir]]
          } else {
            lappend opts --with-tcl=[file normalize [$obj define get builddir]]
          }
        }
      } else {
        lappend opts --with-tcl=[file join $PREFIX lib]
      }
    }

    lappend opts {*}[my define get config_opts]
    if {![regexp -- "--prefix" $opts]} {
      lappend opts --prefix=$PREFIX --exec-prefix=$PREFIX
    }
    if {[my define get debug 0]} {
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
      windows {
        if {[file exists [file join $srcdir win]]} {
          my define add include_dir [file join $srcdir win]
        }
        if {[file exists [file join $srcdir win Makefile.in]]} {
          set localsrcdir [file join $srcdir win]
        }





      }
      default {
        if {[file exists [file join $srcdir $os]]} {
          my define add include_dir [file join $srcdir $os]
        }
        if {[file exists [file join $srcdir unix]]} {
          my define add include_dir [file join $srcdir unix]
        }
        if {[file exists [file join $srcdir $os Makefile.in]]} {
          set localsrcdir [file join $srcdir $os]
        } elseif {[file exists [file join $srcdir unix Makefile.in]]} {
          set localsrcdir [file join $srcdir unix]
        }
      }
    }
    return $localsrcdir
  }

  method make-autodetect {} {
    set srcdir [my define get srcdir]
    set localsrcdir [my define get localsrcdir]



    if {$srcdir eq $localsrcdir} {
      if {![file exists [file join $srcdir tclconfig install-sh]]} {
        # ensure we have tclconfig with all of the trimmings
        set teapath {}
        if {[file exists [file join $srcdir .. tclconfig install-sh]]} {
          set teapath [file join $srcdir .. tclconfig]
        } else {







>
>
>
>
>


















|

|
>
>
>







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
      windows {
        if {[file exists [file join $srcdir win]]} {
          my define add include_dir [file join $srcdir win]
        }
        if {[file exists [file join $srcdir win Makefile.in]]} {
          set localsrcdir [file join $srcdir win]
        }
      }
      macosx {
        if {[file exists [file join $srcdir unix Makefile.in]]} {
          set localsrcdir [file join $srcdir unix]
        }
      }
      default {
        if {[file exists [file join $srcdir $os]]} {
          my define add include_dir [file join $srcdir $os]
        }
        if {[file exists [file join $srcdir unix]]} {
          my define add include_dir [file join $srcdir unix]
        }
        if {[file exists [file join $srcdir $os Makefile.in]]} {
          set localsrcdir [file join $srcdir $os]
        } elseif {[file exists [file join $srcdir unix Makefile.in]]} {
          set localsrcdir [file join $srcdir unix]
        }
      }
    }
    return $localsrcdir
  }

  Ensemble make::autodetect {} {
    set srcdir [my define get srcdir]
    set localsrcdir [my MakeDir $srcdir]
    if {$localsrcdir eq {}} {
      set localsrcdir $srcdir
    }
    if {$srcdir eq $localsrcdir} {
      if {![file exists [file join $srcdir tclconfig install-sh]]} {
        # ensure we have tclconfig with all of the trimmings
        set teapath {}
        if {[file exists [file join $srcdir .. tclconfig install-sh]]} {
          set teapath [file join $srcdir .. tclconfig]
        } else {
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
    if {[my <project> define get CONFIG_SITE] ne {}} {
      set ::env(CONFIG_SITE) [my <project> define get CONFIG_SITE]
    }
    catch {exec sh [file join $localsrcdir configure] {*}$opts >>& [file join $builddir autoconf.log]}
    cd $::CWD
  }

  method make-clean {} {
    set builddir [file normalize [my define get builddir]]
    catch {::practcl::domake $builddir clean}
  }

  method make-compile {} {
    set name [my define get name]
    set srcdir [my define get srcdir]
    if {[my define get static 1]} {
      puts "BUILDING Static $name $srcdir"
    } else {
      puts "BUILDING Dynamic $name $srcdir"
    }







|




|







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
    if {[my <project> define get CONFIG_SITE] ne {}} {
      set ::env(CONFIG_SITE) [my <project> define get CONFIG_SITE]
    }
    catch {exec sh [file join $localsrcdir configure] {*}$opts >>& [file join $builddir autoconf.log]}
    cd $::CWD
  }

  Ensemble make::clean {} {
    set builddir [file normalize [my define get builddir]]
    catch {::practcl::domake $builddir clean}
  }

  Ensemble make::compile {} {
    set name [my define get name]
    set srcdir [my define get srcdir]
    if {[my define get static 1]} {
      puts "BUILDING Static $name $srcdir"
    } else {
      puts "BUILDING Dynamic $name $srcdir"
    }
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
        ::practcl::domake.tcl $builddir all
      }
    } else {
      ::practcl::domake $builddir all
    }
  }

  method make-install DEST {
    set PWD [pwd]
    set builddir [my define get builddir]
    if {[my <project> define get LOCAL 0] || $DEST eq {}} {
      if {[file exists [file join $builddir make.tcl]]} {
        puts "[self] Local INSTALL (Practcl)"
        ::practcl::domake.tcl $builddir install
      } elseif {[my define get broken_destroot 0] == 0} {







|







226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
        ::practcl::domake.tcl $builddir all
      }
    } else {
      ::practcl::domake $builddir all
    }
  }

  Ensemble make::install DEST {
    set PWD [pwd]
    set builddir [my define get builddir]
    if {[my <project> define get LOCAL 0] || $DEST eq {}} {
      if {[file exists [file join $builddir make.tcl]]} {
        puts "[self] Local INSTALL (Practcl)"
        ::practcl::domake.tcl $builddir install
      } elseif {[my define get broken_destroot 0] == 0} {
440
441
442
443
444
445
446








447

448
449
450
451







452
453
454
455
456
457
458
method build-library {outfile PROJECT} {
  array set proj [$PROJECT define dump]
  set path $proj(builddir)
  cd $path
  set includedir .
  #lappend includedir [::practcl::file_relative $path $proj(TCL_INCLUDES)]
  lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TCL_SRC_DIR) generic]]]








  lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(srcdir) generic]]]

  if {[$PROJECT define get tk 0]} {
    lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) generic]]]
    lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) ttk]]]
    lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) xlib]]]







    lappend includedir [::practcl::file_relative $path [file normalize $proj(TK_BIN_DIR)]]
  }
  foreach include [$PROJECT toolset-include-directory] {
    set cpath [::practcl::file_relative $path [file normalize $include]]
    if {$cpath ni $includedir} {
      lappend includedir $cpath
    }







>
>
>
>
>
>
>
>

>




>
>
>
>
>
>
>







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
method build-library {outfile PROJECT} {
  array set proj [$PROJECT define dump]
  set path $proj(builddir)
  cd $path
  set includedir .
  #lappend includedir [::practcl::file_relative $path $proj(TCL_INCLUDES)]
  lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TCL_SRC_DIR) generic]]]
  if {[$PROJECT define get TEA_PRIVATE_TCL_HEADERS 0]} {
    if {[$PROJECT define get TEA_PLATFORM] eq "windows"} {
      lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TCL_SRC_DIR) win]]]
    } else {
      lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TCL_SRC_DIR) unix]]]
    }
  }

  lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(srcdir) generic]]]

  if {[$PROJECT define get tk 0]} {
    lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) generic]]]
    lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) ttk]]]
    lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) xlib]]]
    if {[$PROJECT define get TEA_PRIVATE_TK_HEADERS 0]} {
      if {[$PROJECT define get TEA_PLATFORM] eq "windows"} {
        lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) win]]]
      } else {
        lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) unix]]]
      }
    }
    lappend includedir [::practcl::file_relative $path [file normalize $proj(TK_BIN_DIR)]]
  }
  foreach include [$PROJECT toolset-include-directory] {
    set cpath [::practcl::file_relative $path [file normalize $include]]
    if {$cpath ni $includedir} {
      lappend includedir $cpath
    }
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
    catch {exec $ranlib $outfile}
  }
}

###
# Produce a static executable
###
method build-tclsh {outfile PROJECT} {

  puts " BUILDING STATIC TCLSH "

















  set TCLOBJ [$PROJECT tclcore]
  ::practcl::toolset select $TCLOBJ
  set PKG_OBJS {}
  foreach item [$PROJECT link list core.library] {
    if {[string is true [$item define get static]]} {
      lappend PKG_OBJS $item
    }
  }
  foreach item [$PROJECT link list package] {
    if {[string is true [$item define get static]]} {
      lappend PKG_OBJS $item
    }
  }
  array set TCL [$TCLOBJ read_configuration]



  set TKOBJ  [$PROJECT tkcore]
  if {[info command $TKOBJ] eq {}} {
    set TKOBJ ::noop
    $PROJECT define set static_tk 0
  } else {
    ::practcl::toolset select $TKOBJ
    array set TK  [$TKOBJ read_configuration]
    set do_tk [$TKOBJ define get static]
    $PROJECT define set static_tk $do_tk
    $PROJECT define set tk $do_tk
    set TKSRCDIR [$TKOBJ define get srcdir]
  }
  set path [file dirname $outfile]
  cd $path
  ###
  # For a static Tcl shell, we need to build all local sources
  # with the same DEFS flags as the tcl core was compiled with.
  # The DEFS produced by a TEA extension aren't intended to operate
  # with the internals of a staticly linked Tcl
  ###







|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














>
>
|
<
|
|
<
<
<
<
<
<
<
<

<







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
    catch {exec $ranlib $outfile}
  }
}

###
# Produce a static executable
###
method build-tclsh {outfile PROJECT {path {auto}}} {
  if {[my define get tk 0] && [my define get static_tk 0]} {
    puts " BUILDING STATIC TCL/TK EXE $PROJECT"
    set TKOBJ  [$PROJECT tkcore]
    if {[info command $TKOBJ] eq {}} {
      set TKOBJ ::noop
      $PROJECT define set static_tk 0
    } else {
      ::practcl::toolset select $TKOBJ
      array set TK  [$TKOBJ read_configuration]
      set do_tk [$TKOBJ define get static]
      $PROJECT define set static_tk $do_tk
      $PROJECT define set tk $do_tk
      set TKSRCDIR [$TKOBJ define get srcdir]
    }
  } else {
    puts " BUILDING STATIC TCL EXE $PROJECT"
    set TKOBJ ::noop
    my define set static_tk 0
  }
  set TCLOBJ [$PROJECT tclcore]
  ::practcl::toolset select $TCLOBJ
  set PKG_OBJS {}
  foreach item [$PROJECT link list core.library] {
    if {[string is true [$item define get static]]} {
      lappend PKG_OBJS $item
    }
  }
  foreach item [$PROJECT link list package] {
    if {[string is true [$item define get static]]} {
      lappend PKG_OBJS $item
    }
  }
  array set TCL [$TCLOBJ read_configuration]
  if {$path in {{} auto}} {
    set path [file dirname [file normalize $outfile]]
  }

  if {$path eq "."} {
    set path [pwd]








  }

  cd $path
  ###
  # For a static Tcl shell, we need to build all local sources
  # with the same DEFS flags as the tcl core was compiled with.
  # The DEFS produced by a TEA extension aren't intended to operate
  # with the internals of a staticly linked Tcl
  ###
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
  append COMPILE " " $defs
  lappend OBJECTS {*}[my build-compile-sources $PROJECT $COMPILE $COMPILE $INCLUDES]

  set TCLSRC [file normalize $TCLSRCDIR]

  if {[${PROJECT} define get TEACUP_OS] eq "windows"} {
    set windres [$PROJECT define get RC windres]
    set RSOBJ [file join $path build tclkit.res.o]
    set RCSRC [${PROJECT} define get kit_resource_file]
    set RCMAN [${PROJECT} define get kit_manifest_file]


    set cmd [list $windres -o $RSOBJ -DSTATIC_BUILD --include [::practcl::file_relative $path [file join $TCLSRC generic]]]
    if {[$PROJECT define get static_tk]} {
      if {$RCSRC eq {} || ![file exists $RCSRC]} {
        set RCSRC [file join $TKSRCDIR win rc wish.rc]
      }
      if {$RCMAN eq {} || ![file exists $RCMAN]} {
        set RCMAN [file join [$TKOBJ define get builddir] wish.exe.manifest]
      }



      set TKSRC [file normalize $TKSRCDIR]
      lappend cmd --include [::practcl::file_relative $path [file join $TKSRC generic]] \
        --include [::practcl::file_relative $path [file join $TKSRC win]] \
        --include [::practcl::file_relative $path [file join $TKSRC win rc]]
    } else {
      if {$RCSRC eq {} || ![file exists $RCSRC]} {
        set RCSRC [file join $TCLSRCDIR tclsh.rc]
      }
      if {$RCMAN eq {} || ![file exists $RCMAN]} {
        set RCMAN [file join [$TCLOBJ define get builddir] tclsh.exe.manifest]
      }



    }
    foreach item [${PROJECT} define get resource_include] {
      lappend cmd --include [::practcl::file_relative $path [file normalize $item]]
    }
    lappend cmd [file tail $RCSRC]
    if {![file exists [file join $path [file tail $RCSRC]]]} {
      file copy -force $RCSRC [file join $path [file tail $RCSRC]]
    }
    if {![file exists [file join $path [file tail $RCMAN]]]} {
      file copy -force $RCMAN [file join $path [file tail $RCMAN]]
    }



    ::practcl::doexec {*}$cmd
    lappend OBJECTS $RSOBJ
  }
  puts "***"
  set cmd "$TCL(cc)"
  if {$debug} {
   append cmd " $TCL(cflags_debug)"







|


>









>
>
>






|




>
>
>











>
>
>







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
  append COMPILE " " $defs
  lappend OBJECTS {*}[my build-compile-sources $PROJECT $COMPILE $COMPILE $INCLUDES]

  set TCLSRC [file normalize $TCLSRCDIR]

  if {[${PROJECT} define get TEACUP_OS] eq "windows"} {
    set windres [$PROJECT define get RC windres]
    set RSOBJ [file join $path objs tclkit.res.o]
    set RCSRC [${PROJECT} define get kit_resource_file]
    set RCMAN [${PROJECT} define get kit_manifest_file]
    set RCICO [${PROJECT} define get kit_icon_file]

    set cmd [list $windres -o $RSOBJ -DSTATIC_BUILD --include [::practcl::file_relative $path [file join $TCLSRC generic]]]
    if {[$PROJECT define get static_tk]} {
      if {$RCSRC eq {} || ![file exists $RCSRC]} {
        set RCSRC [file join $TKSRCDIR win rc wish.rc]
      }
      if {$RCMAN eq {} || ![file exists $RCMAN]} {
        set RCMAN [file join [$TKOBJ define get builddir] wish.exe.manifest]
      }
      if {$RCICO eq {} || ![file exists $RCICO]} {
        set RCICO [file join $TKSRCDIR win rc wish.ico]
      }
      set TKSRC [file normalize $TKSRCDIR]
      lappend cmd --include [::practcl::file_relative $path [file join $TKSRC generic]] \
        --include [::practcl::file_relative $path [file join $TKSRC win]] \
        --include [::practcl::file_relative $path [file join $TKSRC win rc]]
    } else {
      if {$RCSRC eq {} || ![file exists $RCSRC]} {
        set RCSRC [file join $TCLSRCDIR win tclsh.rc]
      }
      if {$RCMAN eq {} || ![file exists $RCMAN]} {
        set RCMAN [file join [$TCLOBJ define get builddir] tclsh.exe.manifest]
      }
      if {$RCICO eq {} || ![file exists $RCICO]} {
        set RCICO [file join $TCLSRCDIR win tclsh.ico]
      }
    }
    foreach item [${PROJECT} define get resource_include] {
      lappend cmd --include [::practcl::file_relative $path [file normalize $item]]
    }
    lappend cmd [file tail $RCSRC]
    if {![file exists [file join $path [file tail $RCSRC]]]} {
      file copy -force $RCSRC [file join $path [file tail $RCSRC]]
    }
    if {![file exists [file join $path [file tail $RCMAN]]]} {
      file copy -force $RCMAN [file join $path [file tail $RCMAN]]
    }
    if {![file exists [file join $path [file tail $RCICO]]]} {
      file copy -force $RCICO [file join $path [file tail $RCICO]]
    }
    ::practcl::doexec {*}$cmd
    lappend OBJECTS $RSOBJ
  }
  puts "***"
  set cmd "$TCL(cc)"
  if {$debug} {
   append cmd " $TCL(cflags_debug)"

Changes to modules/practcl/build/class/toolset/msvc.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
::oo::class create ::practcl::toolset.msvc {
  superclass ::practcl::toolset

  # MSVC always builds in the source directory
  method BuildDir {PWD} {
    set srcdir [my define get srcdir]
    return $srcdir
  }

  
  # Do nothing
  method make-autodetect {} {
  }
  
  method make-clean {} {
    set PWD [pwd]
    set srcdir [my define get srcdir]
    cd $srcdir
    catch {::practcl::doexec nmake -f makefile.vc clean}
    cd $PWD
  }
  
  method make-compile {} {
    set srcdir [my define get srcdir]
    if {[my define get static 1]} {
      puts "BUILDING Static $name $srcdir"
    } else {
      puts "BUILDING Dynamic $name $srcdir"
    }
    cd $srcdir
|








|

|

|
|






|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
::clay::define ::practcl::toolset.msvc {
  superclass ::practcl::toolset

  # MSVC always builds in the source directory
  method BuildDir {PWD} {
    set srcdir [my define get srcdir]
    return $srcdir
  }


  # Do nothing
  Ensemble make::autodetect {} {
  }

  Ensemble make::clean {} {
    set PWD [pwd]
    set srcdir [my define get srcdir]
    cd $srcdir
    catch {::practcl::doexec nmake -f makefile.vc clean}
    cd $PWD
  }

  Ensemble make::compile {} {
    set srcdir [my define get srcdir]
    if {[my define get static 1]} {
      puts "BUILDING Static $name $srcdir"
    } else {
      puts "BUILDING Dynamic $name $srcdir"
    }
    cd $srcdir
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
        cd [file join $srcdir win]
        ::practcl::doexec nmake -f makefile.vc INSTALLDIR=[my <project> define get installdir]  {*}[my NmakeOpts] release
      } else {
        error "No make.tcl or makefile.vc found for project $name"
      }
    }
  }
  
  method make-install DEST {
    set PWD [pwd]
    set srcdir [my define get srcdir]
    cd $srcdir
    if {$DEST eq {}} {
      error "No destination given"
    }
    if {[my <project> define get LOCAL 0] || $DEST eq {}} {







|
|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
        cd [file join $srcdir win]
        ::practcl::doexec nmake -f makefile.vc INSTALLDIR=[my <project> define get installdir]  {*}[my NmakeOpts] release
      } else {
        error "No make.tcl or makefile.vc found for project $name"
      }
    }
  }

  Ensemble make::install DEST {
    set PWD [pwd]
    set srcdir [my define get srcdir]
    cd $srcdir
    if {$DEST eq {}} {
      error "No destination given"
    }
    if {[my <project> define get LOCAL 0] || $DEST eq {}} {
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
      } else {
        puts "[self] VFS INSTALL $DEST"
        ::practcl::doexec nmake -f makefile.vc INSTALLDIR=$DEST {*}[my NmakeOpts] install
      }
    }
    cd $PWD
  }
  
  # Detect what directory contains the Makefile template
  method MakeDir {srcdir} {
    set localsrcdir $srcdir
    if {[file exists [file join $srcdir generic]]} {
      my define add include_dir [file join $srcdir generic]
    }
    if {[file exists [file join $srcdir win]]} {
       my define add include_dir [file join $srcdir win]
    }
    if {[file exists [file join $srcdir makefile.vc]]} {
      set localsrcdir [file join $srcdir win]
    }
    return $localsrcdir
  }
  
  method NmakeOpts {} {
    set opts {}
    set builddir [file normalize [my define get builddir]]

    if {[my <project> define exists tclsrcdir]} {
      ###
      # On Windows we are probably running under MSYS, which doesn't deal with







|














|







70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
      } else {
        puts "[self] VFS INSTALL $DEST"
        ::practcl::doexec nmake -f makefile.vc INSTALLDIR=$DEST {*}[my NmakeOpts] install
      }
    }
    cd $PWD
  }

  # Detect what directory contains the Makefile template
  method MakeDir {srcdir} {
    set localsrcdir $srcdir
    if {[file exists [file join $srcdir generic]]} {
      my define add include_dir [file join $srcdir generic]
    }
    if {[file exists [file join $srcdir win]]} {
       my define add include_dir [file join $srcdir win]
    }
    if {[file exists [file join $srcdir makefile.vc]]} {
      set localsrcdir [file join $srcdir win]
    }
    return $localsrcdir
  }

  method NmakeOpts {} {
    set opts {}
    set builddir [file normalize [my define get builddir]]

    if {[my <project> define exists tclsrcdir]} {
      ###
      # On Windows we are probably running under MSYS, which doesn't deal with

Added modules/practcl/build/doctool.tcl.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
namespace eval ::practcl {}

###
# Concatenate a file
###
proc ::practcl::cat fname {
    if {![file exists $fname]} {
       return
    }
    set fin [open $fname r]
    set data [read $fin]
    close $fin
    return $data
}

###
# Strip the global comments from tcl code. Used to
# prevent the documentation markup comments from clogging
# up files intended for distribution in machine readable format.
###
proc ::practcl::docstrip text {
  set result {}
  foreach line [split $text \n] {
    append thisline $line \n
    if {![info complete $thisline]} continue
    set outline $thisline
    set thisline {}
    if {[string trim $outline] eq {}} {
      continue
    }
    if {[string index [string trim $outline] 0] eq "#"} continue
    set cmd [string trim [lindex $outline 0] :]
    if {$cmd eq "namespace" && [lindex $outline 1] eq "eval"} {
      append result [list {*}[lrange $outline 0 end-1]] " " \{ \n [docstrip [lindex $outline end]]\} \n
      continue
    }
    if {[string match "*::define" $cmd] && [llength $outline]==3} {
      append result [list {*}[lrange $outline 0 end-1]] " " \{ \n [docstrip [lindex $outline end]]\} \n
      continue
    }
    if {$cmd eq "oo::class" && [lindex $outline 1] eq "create"} {
      append result [list {*}[lrange $outline 0 end-1]] " " \{ \n [docstrip [lindex $outline end]]\} \n
      continue
    }
    append result $outline
  }
  return $result
}

###
# Append a line of text to a variable. Optionally apply a string mapping.
# argspec:
#   map {mandatory 0 positional 1}
#   text {mandatory 1 positional 1}
###
proc ::putb {buffername args} {
  upvar 1 $buffername buffer
  switch [llength $args] {
    1 {
      append buffer [lindex $args 0] \n
    }
    2 {
      append buffer [string map {*}$args] \n
    }
    default {
      error "usage: putb buffername ?map? string"
    }
  }
}

###
# Tool for build scripts to dynamically generate manual files from comments
# in source code files
# example:
# set authors {
#   {John Doe} {[email protected]}
#   {Tom RichardHarry} {[email protected]}
# }
# # Create the object
# ::practcl::doctool create AutoDoc
# set fout [open [file join $moddir module.tcl] w]
# foreach file [glob [file join $srcdir *.tcl]] {
#   set content [::practcl::cat [file join $srcdir $file]]
#    # Scan the file
#    AutoDoc scan_text $content
#    # Strip the comments from the distribution
#    puts $fout [::practcl::docstrip $content]
# }
# # Write out the manual page
# set manout [open [file join $moddir module.man] w]
# dict set args header [string map $modmap [::practcl::cat [file join $srcdir manual.txt]]]
# dict set args footer [string map $modmap [::practcl::cat [file join $srcdir footer.txt]]]
# dict set args authors $authors
# puts $manout [AutoDoc manpage {*}$args]
# close $manout
###
::oo::class create ::practcl::doctool {
  constructor {} {
    my reset
  }

  ###
  # Process an argument list into an informational dict.
  # This method also understands non-positional
  # arguments expressed in the notation of Tip 471
  # [uri https://core.tcl-lang.org/tips/doc/trunk/tip/479.md].
  # [para]
  # The output will be a dictionary of all of the fields and whether the fields
  # are [const positional], [const mandatory], and whether they have a
  # [const default] value.
  # [para]
  # example:
  #   my argspec {a b {c 10}}
  #
  #   > a {positional 1 mandatory 1} b {positional 1 mandatory 1} c {positional 1 mandatory 0 default 10}
  ###
  method argspec {argspec} {
    set result [dict create]
    foreach arg $argspec {
      set name [lindex $arg 0]
      dict set result $name positional 1
      dict set result $name mandatory  1
      if {$name in {args dictargs}} {
        switch [llength $arg] {
          1 {
            dict set result $name mandatory 0
          }
          2 {
            dict for {optname optinfo} [lindex $arg 1] {
              set optname [string trim $optname -:]
              dict set result $optname {positional 1 mandatory 0}
              dict for {f v} $optinfo {
                dict set result $optname [string trim $f -:] $v
              }
            }
          }
          default {
            error "Bad argument"
          }
        }
      } else {
        switch [llength $arg] {
          1 {
            dict set result $name mandatory 1
          }
          2 {
            dict set result $name mandatory 0
            dict set result $name default   [lindex $arg 1]
          }
          default {
            error "Bad argument"
          }
        }
      }
    }
    return $result
  }

  ###
  # Convert a block of comments into an informational dictionary.
  # If lines in the comment start with a single word ending in a colon,
  # all subsequent lines are appended to a dictionary field of that name.
  # If no fields are given, all of the text is appended to the [const description]
  # field.
  # example:
  # my comment {Does something cool}
  # > description {Does something cool}
  #
  # my comment {
  # title : Something really cool
  # author : Sean Woods
  # author : John Doe
  # description :
  # This does something really cool!
  # }
  # > description {This does something really cool!}
  #   title {Something really cool}
  #   author {Sean Woods
  #   John Doe}
  ###
  method comment block {
    set count 0
    set field description
    set result [dict create description {}]
    foreach line [split $block \n] {
      set sline [string trim $line]
      set fwidx [string first " " $sline]
      if {$fwidx < 0} {
        set firstword [string range $sline 0 end]
        set restline {}
      } else {
        set firstword [string range $sline 0 [expr {$fwidx-1}]]
        set restline [string range $sline [expr {$fwidx+1}] end]
      }
      if {[string index $firstword end] eq ":"} {
        set field [string tolower [string trim $firstword -:]]
        switch $field {
          dictargs -
          arglist {
            set field argspec
          }
          desc {
            set field description
          }
        }
        if {[string length $restline]} {
          dict append result $field "$restline\n"
        }
      } else {
        dict append result $field "$line\n"
      }
    }
    return $result
  }

  method keyword.Annotation {resultvar commentblock type name body} {
    upvar 1 $resultvar result
    set name [string trim $name :]
    if {[dict exists $result $type $name]} {
      set info [dict get $result $type $name]
    } else {
      set info [my comment $commentblock]
    }
    foreach {f v} $body {
      dict set info $f $v
    }
    dict set result $type $name $info
  }

  ###
  # Process an oo::objdefine call that modifies the class object
  # itself
  ####
  method keyword.Class {resultvar commentblock name body} {
    upvar 1 $resultvar result
    set name [string trim $name :]
    if {[dict exists $result class $name]} {
      set info [dict get $result class $name]
    } else {
      set info [my comment $commentblock]
    }
    set commentblock {}
    foreach line [split $body \n] {
      append thisline $line \n
      if {![info complete $thisline]} continue
      set thisline [string trim $thisline]
      if {[string index $thisline 0] eq "#"} {
        append commentblock [string trimleft $thisline #] \n
        set thisline {}
        continue
      }
      set cmd [string trim [lindex $thisline 0] ":"]
      switch $cmd {
        Option -
        option {
          my keyword.Annotation info $commentblock option [lindex $thisline 1] [lindex $thisline 2]
          set commentblock {}
        }
        variable -
        Variable {
          my keyword.Annotation info $commentblock variable [lindex $thisline 1] [list type scaler default [lindex $thisline 2]]
          set commentblock {}
        }
        Dict -
        Array {
          set iinfo [lindex $thisline 2]
          dict set iinfo type [string tolower $cmd]
          my keyword.Annotation info $commentblock variable [lindex $thisline 1] $iinfo
          set commentblock {}
        }
        Componant -
        Delegate {
          my keyword.Annotation info $commentblock delegate [lindex $thisline 1] [lindex $thisline 2]
          set commentblock {}
        }
        method -
        Ensemble {
          my keyword.Class_Method info $commentblock  {*}[lrange $thisline 1 end-1]
          set commentblock {}
        }
      }
      set thisline {}
    }
    dict set result class $name $info
  }

  ###
  # Process an oo::define, clay::define, etc statement.
  ###
  method keyword.class {resultvar commentblock name body} {
    upvar 1 $resultvar result
    set name [string trim $name :]
    if {[dict exists $result class $name]} {
      set info [dict get $result class $name]
    } else {
      set info [my comment $commentblock]
    }
    set commentblock {}
    foreach line [split $body \n] {
      append thisline $line \n
      if {![info complete $thisline]} continue
      set thisline [string trim $thisline]
      if {[string index $thisline 0] eq "#"} {
        append commentblock [string trimleft $thisline #] \n
        set thisline {}
        continue
      }
      set cmd [string trim [lindex $thisline 0] ":"]
      switch $cmd {
        Option -
        option {
          puts [list keyword.Annotation $cmd $thisline]
          my keyword.Annotation info $commentblock option [lindex $thisline 1] [lindex $thisline 2]
          set commentblock {}
        }
        variable -
        Variable {
          my keyword.Annotation info $commentblock variable [lindex $thisline 1] [list default [lindex $thisline 2]]
          set commentblock {}
        }
        Dict -
        Array {
          set iinfo [lindex $thisline 2]
          dict set iinfo type [string tolower $cmd]
          my keyword.Annotation info $commentblock variable [lindex $thisline 1] $iinfo
          set commentblock {}
        }
        Componant -
        Delegate {
          my keyword.Annotation info $commentblock delegate [lindex $thisline 1] [lindex $thisline 2]
          set commentblock {}
        }
        superclass {
          dict set info ancestors [lrange $thisline 1 end]
          set commentblock {}
        }
        classmethod -
        class_method -
        Class_Method {
          my keyword.Class_Method info $commentblock  {*}[lrange $thisline 1 end-1]
          set commentblock {}
        }
        destructor -
        constructor {
          my keyword.method info $commentblock {*}[lrange $thisline 0 end-1]
          set commentblock {}
        }
        method -
        Ensemble {
          my keyword.method info $commentblock  {*}[lrange $thisline 1 end-1]
          set commentblock {}
        }
      }
      set thisline {}
    }
    dict set result class $name $info
  }

  ###
  # Process a statement for a clay style class method
  ###
  method keyword.Class_Method {resultvar commentblock name args} {
    upvar 1 $resultvar result
    set info [my comment $commentblock]
    if {[dict exists $info show_body] && [dict get $info show_body]} {
      dict set info internals [lindex $args end]
    }
    if {[dict exists $info ensemble]} {
      dict for {method minfo} [dict get $info ensemble] {
        dict set result Class_Method "${name} $method" $minfo
      }
    } else {
      switch [llength $args] {
        1 {
          set argspec [lindex $args 0]
        }
        0 {
          set argspec dictargs
          #set body [lindex $args 0]
        }
        default {error "could not interpret method $name {*}$args"}
      }
      if {![dict exists $info argspec]} {
        dict set info argspec [my argspec $argspec]
      }
      dict set result Class_Method [string trim $name :] $info
    }
  }

  ###
  # Process a statement for a tcloo style object method
  ###
  method keyword.method {resultvar commentblock name args} {
    upvar 1 $resultvar result
    set info [my comment $commentblock]
    if {[dict exists $info show_body] && [dict get $info show_body]} {
      dict set info internals [lindex $args end]
    }
    if {[dict exists $info ensemble]} {
      dict for {method minfo} [dict get $info ensemble] {
        dict set result method "\"${name} $method\"" $minfo
      }
    } else {
      switch [llength $args] {
        1 {
          set argspec [lindex $args 0]
        }
        0 {
          set argspec dictargs
          #set body [lindex $args 0]
        }
        default {error "could not interpret method $name {*}$args"}
      }
      if {![dict exists $info argspec]} {
        dict set info argspec [my argspec $argspec]
      }
      dict set result method "\"[split [string trim $name :] ::]\"" $info
    }
  }

  ###
  # Process a proc statement
  ###
  method keyword.proc {commentblock name argspec} {
    set info [my comment $commentblock]
    if {![dict exists $info argspec]} {
      dict set info argspec [my argspec $argspec]
    }
    return $info
  }

  ###
  # Reset the state of the object and its embedded coroutine
  ###
  method reset {} {
    my variable coro
    set coro [info object namespace [self]]::coro
    oo::objdefine [self] forward coro $coro
    if {[info command $coro] ne {}} {
      rename $coro {}
    }
    coroutine $coro {*}[namespace code {my Main}]
  }

  ###
  # Main body of the embedded coroutine for the object
  ###
  method Main {} {

    my variable info
    set info [dict create]
    yield [info coroutine]
    set thisline {}
    set commentblock {}
    set linec 0
    while 1 {
      set line [yield]
      append thisline $line \n
      if {![info complete $thisline]} continue
      set thisline [string trim $thisline]
      if {[string index $thisline 0] eq "#"} {
        append commentblock [string trimleft $thisline #] \n
        set thisline {}
        continue
      }
      set cmd [string trim [lindex $thisline 0] ":"]
      switch $cmd {
        dictargs::proc {
          set procinfo [my keyword.proc $commentblock [lindex $thisline 1] [list args [list dictargs [lindex $thisline 2]]]]
          if {[dict exists $procinfo show_body] && [dict get $procinfo show_body]} {
            dict set procinfo internals [lindex $thisline end]
          }
          dict set info proc [string trim [lindex $thisline 1] :] $procinfo
          set commentblock {}
        }
        tcllib::PROC -
        PROC -
        Proc -
        proc {
          set procinfo [my keyword.proc $commentblock {*}[lrange $thisline 1 2]]
          if {[dict exists $procinfo show_body] && [dict get $procinfo show_body]} {
            dict set procinfo internals [lindex $thisline end]
          }
          dict set info proc [string trim [lindex $thisline 1] :] $procinfo
          set commentblock {}
        }
        oo::objdefine {
          if {[llength $thisline]==3} {
            lassign $thisline tcmd name body
            my keyword.Class info $commentblock $name $body
          } else {
            puts "Warning: bare oo::define in library"
          }
        }
        oo::define {
          if {[llength $thisline]==3} {
            lassign $thisline tcmd name body
            my keyword.class info $commentblock $name $body
          } else {
            puts "Warning: bare oo::define in library"
          }
        }
        tao::define -
        clay::define -
        tool::define {
          lassign $thisline tcmd name body
          my keyword.class info $commentblock $name $body
          set commentblock {}
        }
        oo::class {
          lassign $thisline tcmd mthd name body
          my keyword.class info $commentblock $name $body
          set commentblock {}
        }
        default {
          if {[lindex [split $cmd ::] end] eq "define"} {
            lassign $thisline tcmd name body
            my keyword.class info $commentblock $name $body
            set commentblock {}
          }
          set commentblock {}
        }
      }
      set thisline {}
    }
  }

  ###
  # Generate the manual page text for a method or proc
  ###
  method section.method {keyword method minfo} {
    set result {}
    set line "\[call $keyword \[cmd $method\]"
    if {[dict exists $minfo argspec]} {
      dict for {argname arginfo} [dict get $minfo argspec] {
        set positional 1
        set mandatory  1
        set repeating 0
        dict with arginfo {}
        if {$mandatory==0} {
          append line " \[opt \""
        } else {
          append line " "
        }
        if {$positional} {
          append line "\[arg $argname"
        } else {
          append line "\[option \"$argname"
          if {[dict exists $arginfo type]} {
            append line " \[emph [dict get $arginfo type]\]"
          } else {
            append line " \[emph value\]"
          }
          append line "\""
        }
        append line "\]"
        if {$mandatory==0} {
          if {[dict exists $arginfo default]} {
            append line " \[const \"[dict get $arginfo default]\"\]"
          }
          append line "\"\]"
        }
        if {$repeating} {
          append line " \[opt \[option \"$argname...\"\]\]"
        }
      }
    }
    append line \]
    putb result $line
    if {[dict exists $minfo description]} {
      putb result [dict get $minfo description]
    }
    if {[dict exists $minfo example]} {
      putb result "\[para\]Example: \[example [list [dict get $minfo example]]\]"
    }
    if {[dict exists $minfo internals]} {
      putb result "\[para\]Internals: \[example [list [dict get $minfo internals]]\]"
    }
    return $result
  }

  method section.annotation {type name iinfo} {
    set result "\[call $type \[cmd $name\]\]"
    if {[dict exists $iinfo description]} {
      putb result [dict get $iinfo description]
    }
    if {[dict exists $iinfo example]} {
      putb result "\[para\]Example: \[example [list [dict get $minfo example]]\]"
    }
    return $result
  }

  ###
  # Generate the manual page text for a class
  ###
  method section.class {class_name class_info} {
    set result {}
    putb result "\[subsection \{Class  $class_name\}\]"
    if {[dict exists $class_info ancestors]} {
      set line "\[emph \"ancestors\"\]:"
      foreach {c} [dict get $class_info ancestors] {
        append line " \[class [string trim $c :]\]"
      }
      putb result $line
      putb result {[para]}
    }
    dict for {f v} $class_info {
      if {$f in {Class_Method method description ancestors example option variable delegate}} continue
      putb result "\[emph \"$f\"\]: $v"
      putb result {[para]}
    }
    if {[dict exists $class_info example]} {
      putb result "\[example \{[list [dict get $class_info example]]\}\]"
      putb result {[para]}
    }
    if {[dict exists $class_info description]} {
      putb result [dict get $class_info description]
      putb result {[para]}
    }
    dict for {f v} $class_info {
      if {$f ni {option variable delegate}} continue
      putb result "\[class \{[string totitle $f]\}\]"
      #putb result "Methods on the class object itself."
      putb result {[list_begin definitions]}
      dict for {item iinfo} [dict get $class_info $f] {
        putb result [my section.annotation $f $item $iinfo]
      }
      putb result {[list_end]}
      putb result {[para]}
    }
    if {[dict exists $class_info Class_Method]} {
      putb result "\[class \{Class Methods\}\]"
      #putb result "Methods on the class object itself."
      putb result {[list_begin definitions]}
      dict for {method minfo} [dict get $class_info Class_Method] {
        putb result [my section.method classmethod $method $minfo]
      }
      putb result {[list_end]}
      putb result {[para]}
    }
    if {[dict exists $class_info method]} {
      putb result "\[class {Methods}\]"
      putb result {[list_begin definitions]}
      dict for {method minfo} [dict get $class_info method] {
        putb result [my section.method method $method $minfo]
      }
      putb result {[list_end]}
      putb result {[para]}
    }
    return $result
  }

  ###
  # Generate the manual page text for the commands section
  ###
  method section.command {procinfo} {
    set result {}
    putb result "\[section \{Commands\}\]"
    putb result {[list_begin definitions]}
    dict for {method minfo} $procinfo {
      putb result [my section.method proc $method $minfo]
    }
    putb result {[list_end]}
    return $result
  }

  ###
  # Generate the manual page. Returns the completed text suitable for saving in .man file.
  # The header argument is a block of doctools text to go in before the machine generated
  # section. footer is a block of doctools text to go in after the machine generated
  # section. authors is a list of individual authors and emails in the form of AUTHOR EMAIL ?AUTHOR EMAIL?...
  #
  # argspec:
  #   header {mandatory 0 positional 0}
  #   footer {mandatory 0 positional 0}
  #   authors {mandatory 0 positional 0 type list}
  ###
  method manpage args {
    my variable info
    set map {%version% 0.0 %module% {Your_Module_Here}}
    set result {}
    set header {}
    set footer {}
    set authors {}
    dict with args {}
    dict set map %keyword% comment
    putb result $map {[%keyword% {-*- tcl -*- doctools manpage}]
[vset PACKAGE_VERSION %version%]
[manpage_begin %module% n [vset PACKAGE_VERSION]]}
    putb result $map $header

    dict for {sec_type sec_info} $info {
      switch $sec_type {
        proc {
          putb result [my section.command $sec_info]
        }
        class {
          putb result "\[section Classes\]"
          dict for {class_name class_info} $sec_info {
            putb result [my section.class $class_name $class_info]
          }
        }
        default {
          putb result "\[section [list $sec_type $sec_name]\]"
          if {[dict exists $sec_info description]} {
            putb result [dict get $sec_info description]
          }
        }
      }
    }
    if {[llength $authors]} {
      putb result {[section AUTHORS]}
      foreach {name email} $authors {
        putb result "$name \[uri mailto:$email\]\[para\]"
      }
    }
    putb result $footer
    putb result {[manpage_end]}
    return $result
  }

  # Scan a block of text
  method scan_text {text} {
    my variable linecount coro
    set linecount 0
    foreach line [split $text \n] {
      incr linecount
      $coro $line
    }
  }

  # Scan a file of text
  method scan_file {filename} {
    my variable linecount coro
    set fin [open $filename r]
    set linecount 0
    while {[gets $fin line]>=0} {
      incr linecount
      $coro $line
    }
    close $fin
  }
}

Changes to modules/practcl/build/fileutil.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13


14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
###
# Bits stolen from fileutil
###
proc ::practcl::cat fname {
    if {![file exists $fname]} {
       return
    }
    set fin [open $fname r]
    set data [read $fin]
    close $fin
    return $data
}



proc ::practcl::grep {pattern {files {}}} {
    set result [list]
    if {[llength $files] == 0} {
	      # read from stdin
    	  set lnum 0
	      while {[gets stdin line] >= 0} {
	          incr lnum
    	      if {[regexp -- $pattern $line]} {
		            lappend result "${lnum}:${line}"
	          }
    	  }
    } else {
	      foreach filename $files {
            set file [open $filename r]
            set lnum 0
            while {[gets $file line] >= 0} {
                incr lnum
                if {[regexp -- $pattern $line]} {
                    lappend result "${filename}:${lnum}:${line}"
                }
            }
            close $file
    	  }
    }
    return $result
}

proc ::practcl::file_lexnormalize {sp} {
    set spx [file split $sp]

    # Resolution of embedded relative modifiers (., and ..).

    if {
	([lsearch -exact $spx . ] < 0) &&
	([lsearch -exact $spx ..] < 0)
    } {
	# Quick path out if there are no relative modifiers
	return $sp
    }

    set absolute [expr {![string equal [file pathtype $sp] relative]}]
    # A volumerelative path counts as absolute for our purposes.

    set sp $spx
    set np {}
    set noskip 1

    while {[llength $sp]} {
	set ele    [lindex $sp 0]
	set sp     [lrange $sp 1 end]
	set islast [expr {[llength $sp] == 0}]

	if {[string equal $ele ".."]} {
	    if {
		($absolute  && ([llength $np] >  1)) ||
		(!$absolute && ([llength $np] >= 1))
	    } {
		# .. : Remove the previous element added to the
		# new path, if there actually is enough to remove.
		set np [lrange $np 0 end-1]
	    }
	} elseif {[string equal $ele "."]} {
	    # Ignore .'s, they stay at the current location
	    continue
	} else {
	    # A regular element.
	    lappend np $ele
	}
    }
    if {[llength $np] > 0} {
	return [eval [linsert $np 0 file join]]
	# 8.5: return [file join {*}$np]
    }
    return {}
}








proc ::practcl::file_relative {base dst} {
    # Ensure that the link to directory 'dst' is properly done relative to
    # the directory 'base'.

    if {![string equal [file pathtype $base] [file pathtype $dst]]} {
	return -code error "Unable to compute relation for paths of different pathtypes: [file pathtype $base] vs. [file pathtype $dst], ($base vs. $dst)"
    }

    set base [file_lexnormalize [file join [pwd] $base]]
    set dst  [file_lexnormalize [file join [pwd] $dst]]

    set save $dst
    set base [file split $base]
    set dst  [file split $dst]

    while {[string equal [lindex $dst 0] [lindex $base 0]]} {
	set dst  [lrange $dst  1 end]
	set base [lrange $base 1 end]
	if {![llength $dst]} {break}
    }

    set dstlen  [llength $dst]
    set baselen [llength $base]

    if {($dstlen == 0) && ($baselen == 0)} {
	# Cases:
	# (a) base == dst

	set dst .
    } else {
	# Cases:
	# (b) base is: base/sub = sub
	#     dst  is: base     = {}

	# (c) base is: base     = {}
	#     dst  is: base/sub = sub

	while {$baselen > 0} {
	    set dst [linsert $dst 0 ..]
	    incr baselen -1
	}
	# 8.5: set dst [file join {*}$dst]
	set dst [eval [linsert $dst 0 file join]]
    }

    return $dst
}










































proc ::practcl::log {fname comment} {
  set fname [file normalize $fname]
  if {[info exists ::practcl::logchan($fname)]} {
    set fout $::practcl::logchan($fname)
    after cancel $::practcl::logevent($fname)
  } else {
    set fout [open $fname a]



<
<
<
|
<
<
<
<
|
|
>
>



|
|
|
|
|
|
|
|

|









|










|
|

|
|










|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


|
|




>
>
>
>
>
>
>





|










|
|
|






|
|

|

|
|
|

|
|

|
|
|
|
|
|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3



4




5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
###
# Bits stolen from fileutil
###









###
# Search for the pattern [emph pattern] amongst $files
###
proc ::practcl::grep {pattern {files {}}} {
    set result [list]
    if {[llength $files] == 0} {
            # read from stdin
            set lnum 0
            while {[gets stdin line] >= 0} {
                incr lnum
                if {[regexp -- $pattern $line]} {
                        lappend result "${lnum}:${line}"
                }
            }
    } else {
            foreach filename $files {
            set file [open $filename r]
            set lnum 0
            while {[gets $file line] >= 0} {
                incr lnum
                if {[regexp -- $pattern $line]} {
                    lappend result "${filename}:${lnum}:${line}"
                }
            }
            close $file
            }
    }
    return $result
}

proc ::practcl::file_lexnormalize {sp} {
    set spx [file split $sp]

    # Resolution of embedded relative modifiers (., and ..).

    if {
      ([lsearch -exact $spx . ] < 0) &&
      ([lsearch -exact $spx ..] < 0)
    } {
      # Quick path out if there are no relative modifiers
      return $sp
    }

    set absolute [expr {![string equal [file pathtype $sp] relative]}]
    # A volumerelative path counts as absolute for our purposes.

    set sp $spx
    set np {}
    set noskip 1

    while {[llength $sp]} {
      set ele    [lindex $sp 0]
      set sp     [lrange $sp 1 end]
      set islast [expr {[llength $sp] == 0}]

      if {[string equal $ele ".."]} {
          if {
            ($absolute  && ([llength $np] >  1)) ||
            (!$absolute && ([llength $np] >= 1))
          } {
            # .. : Remove the previous element added to the
            # new path, if there actually is enough to remove.
            set np [lrange $np 0 end-1]
          }
      } elseif {[string equal $ele "."]} {
          # Ignore .'s, they stay at the current location
          continue
      } else {
          # A regular element.
          lappend np $ele
      }
    }
    if {[llength $np] > 0} {
      return [eval [linsert $np 0 file join]]
      # 8.5: return [file join {*}$np]
    }
    return {}
}

###
# Calculate a relative path between base and dst
#
# example:
#  ::practcl::file_relative ~/build/tcl/unix ~/build/tcl/library
#  > ../library
###
proc ::practcl::file_relative {base dst} {
    # Ensure that the link to directory 'dst' is properly done relative to
    # the directory 'base'.

    if {![string equal [file pathtype $base] [file pathtype $dst]]} {
      return -code error "Unable to compute relation for paths of different pathtypes: [file pathtype $base] vs. [file pathtype $dst], ($base vs. $dst)"
    }

    set base [file_lexnormalize [file join [pwd] $base]]
    set dst  [file_lexnormalize [file join [pwd] $dst]]

    set save $dst
    set base [file split $base]
    set dst  [file split $dst]

    while {[string equal [lindex $dst 0] [lindex $base 0]]} {
      set dst  [lrange $dst  1 end]
      set base [lrange $base 1 end]
      if {![llength $dst]} {break}
    }

    set dstlen  [llength $dst]
    set baselen [llength $base]

    if {($dstlen == 0) && ($baselen == 0)} {
      # Cases:
      # (a) base == dst

      set dst .
    } else {
      # Cases:
      # (b) base is: base/sub = sub
      #     dst  is: base     = {}

      # (c) base is: base     = {}
      #     dst  is: base/sub = sub

      while {$baselen > 0} {
          set dst [linsert $dst 0 ..]
          incr baselen -1
      }
      # 8.5: set dst [file join {*}$dst]
      set dst [eval [linsert $dst 0 file join]]
    }

    return $dst
}

# ::fileutil::findByPattern --
#
#      Specialization of find. Finds files based on their names,
#      which have to match the specified patterns. Options are used
#      to specify which type of patterns (regexp-, glob-style) is
#      used.
#
# Arguments:
#      basedir            Directory to start searching from.
#      args            Options (-glob, -regexp, --) followed by a
#                  list of patterns to search for.
#
# Results:
#      files            a list of interesting files.

proc ::practcl::findByPattern {basedir patterns} {
    set queue $basedir
    set result {}
    while {[llength $queue]} {
      set item [lindex $queue 0]
      set queue [lrange $queue 1 end]
      if {[file isdirectory $item]} {
        foreach path [glob -nocomplain [file join $item *]] {
          lappend queue $path
        }
        continue
      }
      foreach pattern $patterns {
        set fname [file tail $item]
        if {[string match $pattern $fname]} {
          lappend result $item
          break
        }
      }
    }
    return $result
}

###
# Record an event in the practcl log
###
proc ::practcl::log {fname comment} {
  set fname [file normalize $fname]
  if {[info exists ::practcl::logchan($fname)]} {
    set fout $::practcl::logchan($fname)
    after cancel $::practcl::logevent($fname)
  } else {
    set fout [open $fname a]

Added modules/practcl/build/footer.txt.





>
>
1
2
[vset CATEGORY practcl]
[include ../common-text/feedback.inc]

Changes to modules/practcl/build/installutil.tcl.

1
2
3
4










5
6

























7
8
9
10
11
12
13
14

15











16
17
18
19
20
21
22
###
# Installer tools
###
proc ::practcl::_isdirectory name {










  return [file isdirectory $name]
}

























###
# Return true if the pkgindex file contains
# any statement other than "package ifneeded"
# and/or if any package ifneeded loads a DLL
###
proc ::practcl::_pkgindex_directory {path} {
  set buffer {}
  set pkgidxfile [file join $path pkgIndex.tcl]

  if {![file exists $pkgidxfile]} {











    # No pkgIndex file, read the source
    foreach file [glob -nocomplain $path/*.tm] {
      set file [file normalize $file]
      set fname [file rootname [file tail $file]]
      ###
      # We used to be able to ... Assume the package is correct in the filename
      # No hunt for a "package provides"
<
<
<
|
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|
>
|
>
>
>
>
>
>
>
>
>
>
>










1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66



proc ::practcl::_pkgindex_simpleIndex {path} {
set buffer {}
  set pkgidxfile    [file join $path pkgIndex.tcl]
  set modfile       [file join $path [file tail $path].tcl]
  set use_pkgindex  [file exists $pkgidxfile]
  set tclfiles      {}
  set found 0
  set mlist [list pkgIndex.tcl index.tcl [file tail $modfile] version_info.tcl]
  foreach file [glob -nocomplain [file join $path *.tcl]] {
    if {[file tail $file] ni $mlist} {
      #puts [list NONMODFILE $file]
      return {}
    }
  }
  foreach file [glob -nocomplain [file join $path *.tcl]] {
    if { [file tail $file] == "version_info.tcl" } continue
    set fin [open $file r]
    set dat [read $fin]
    close $fin
    if {![regexp "package provide" $dat]} continue
    set fname [file rootname [file tail $file]]
    # Look for a package provide statement
    foreach line [split $dat \n] {
      set line [string trim $line]
      if { [string range $line 0 14] != "package provide" } continue
      set package [lindex $line 2]
      set version [lindex $line 3]
      if {[string index $package 0] in "\$ \[ @"} continue
      if {[string index $version 0] in "\$ \[ @"} continue
      #puts "PKGLINE $line"
      append buffer "package ifneeded $package $version \[list source \[file join %DIR% [file tail $file]\]\]" \n
      break
    }
  }
  return $buffer
}


###
# Return true if the pkgindex file contains
# any statement other than "package ifneeded"
# and/or if any package ifneeded loads a DLL
###
proc ::practcl::_pkgindex_directory {path} {
  set buffer {}
  set pkgidxfile    [file join $path pkgIndex.tcl]
  set modfile       [file join $path [file tail $path].tcl]
  set use_pkgindex  [file exists $pkgidxfile]
  set tclfiles      {}
  if {$use_pkgindex && [file exists $modfile]} {
    set use_pkgindex 0
    set mlist [list pkgIndex.tcl [file tail $modfile]]
    foreach file [glob -nocomplain [file join $path *.tcl]] {
      lappend tclfiles [file tail $file]
      if {[file tail $file] in $mlist} continue
      incr use_pkgindex
    }
  }
  if {!$use_pkgindex} {
    # No pkgIndex file, read the source
    foreach file [glob -nocomplain $path/*.tm] {
      set file [file normalize $file]
      set fname [file rootname [file tail $file]]
      ###
      # We used to be able to ... Assume the package is correct in the filename
      # No hunt for a "package provides"
106
107
108
109
110
111
112
113


114
115
116
117
118
119
120
    append buffer $thisline \n
    set thisline {}
  }
  if {$trace} {puts [list [file dirname $pkgidxfile] $buffer]}
  return $buffer
}




proc ::practcl::_pkgindex_path_subdir {path} {
  set result {}
  if {[file exists [file join $path src build.tcl]]} {
    # Tool style module, don't dive into subdirectories
    return $path
  }
  foreach subpath [glob -nocomplain [file join $path *]] {







|
>
>







150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
    append buffer $thisline \n
    set thisline {}
  }
  if {$trace} {puts [list [file dirname $pkgidxfile] $buffer]}
  return $buffer
}

###
# Helper function for ::practcl::pkgindex_path
###
proc ::practcl::_pkgindex_path_subdir {path} {
  set result {}
  if {[file exists [file join $path src build.tcl]]} {
    # Tool style module, don't dive into subdirectories
    return $path
  }
  foreach subpath [glob -nocomplain [file join $path *]] {
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
        set path_indexed($path) 0
      }
    } else {
      puts [list WARNING: NO PATHS FOUND IN $base]
    }
    set path_indexed($base) 1
    set path_indexed([file join $base boot tcl]) 1













    foreach path $paths {
      if {$path_indexed($path)} continue
      set thisdir [file_relative $base $path]
      set idxbuf [::practcl::_pkgindex_directory $path]
      if {[string length $idxbuf]} {
        incr path_indexed($path)
        append buffer "set dir \[set PKGDIR \[file join \[lindex \$::PATHSTACK end\] $thisdir\]\]" \n
        append buffer [string map {$dir $PKGDIR} [string trimright $idxbuf]] \n
      }
    }
  }
  append buffer {
set dir [lindex $::PATHSTACK end]
set ::PATHSTACK [lrange $::PATHSTACK 0 end-1]
}
  return $buffer
}



proc ::practcl::installDir {d1 d2} {
  puts [format {%*sCreating %s} [expr {4 * [info level]}] {} [file tail $d2]]
  file delete -force -- $d2
  file mkdir $d2

  foreach ftail [glob -directory $d1 -nocomplain -tails *] {
    set f [file join $d1 $ftail]







>
>
>
>
>
>
>
>
>
>
>
>
>


















>
>







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
        set path_indexed($path) 0
      }
    } else {
      puts [list WARNING: NO PATHS FOUND IN $base]
    }
    set path_indexed($base) 1
    set path_indexed([file join $base boot tcl]) 1
    append buffer \n {# SINGLE FILE MODULES BEGIN} \n {set dir [lindex $::PATHSTACK end]} \n
    foreach path $paths {
      if {$path_indexed($path)} continue
      set thisdir [file_relative $base $path]
      set simpleIdx [_pkgindex_simpleIndex $path]
      if {[string length $simpleIdx]==0} continue
      incr path_indexed($path)
      if {[string length $simpleIdx]} {
        incr path_indexed($path)
        append buffer [string map [list %DIR% "\$dir \{$thisdir\}"] [string trimright $simpleIdx]] \n
      }
    }
    append buffer {# SINGLE FILE MODULES END} \n
    foreach path $paths {
      if {$path_indexed($path)} continue
      set thisdir [file_relative $base $path]
      set idxbuf [::practcl::_pkgindex_directory $path]
      if {[string length $idxbuf]} {
        incr path_indexed($path)
        append buffer "set dir \[set PKGDIR \[file join \[lindex \$::PATHSTACK end\] $thisdir\]\]" \n
        append buffer [string map {$dir $PKGDIR} [string trimright $idxbuf]] \n
      }
    }
  }
  append buffer {
set dir [lindex $::PATHSTACK end]
set ::PATHSTACK [lrange $::PATHSTACK 0 end-1]
}
  return $buffer
}

# Delete the contents of [emph d2], and then
# recusively Ccopy the contents of [emph d1] to [emph d2].
proc ::practcl::installDir {d1 d2} {
  puts [format {%*sCreating %s} [expr {4 * [info level]}] {} [file tail $d2]]
  file delete -force -- $d2
  file mkdir $d2

  foreach ftail [glob -directory $d1 -nocomplain -tails *] {
    set f [file join $d1 $ftail]
213
214
215
216
217
218
219

220
221
222
223
224
225
226
  if {$::tcl_platform(platform) eq {unix}} {
    file attributes $d2 -permissions 0755
  } else {
    file attributes $d2 -readonly 1
  }
}


proc ::practcl::copyDir {d1 d2 {toplevel 1}} {
  #if {$toplevel} {
  #  puts [list ::practcl::copyDir $d1 -> $d2]
  #}
  #file delete -force -- $d2
  file mkdir $d2
  if {[file isfile $d1]} {







>







274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
  if {$::tcl_platform(platform) eq {unix}} {
    file attributes $d2 -permissions 0755
  } else {
    file attributes $d2 -readonly 1
  }
}

# Recursively copy the contents of [emph d1] to [emph d2]
proc ::practcl::copyDir {d1 d2 {toplevel 1}} {
  #if {$toplevel} {
  #  puts [list ::practcl::copyDir $d1 -> $d2]
  #}
  #file delete -force -- $d2
  file mkdir $d2
  if {[file isfile $d1]} {
243
244
245
246
247
248
249

































































        } else {
          file attributes [file join $d2 $ftail] -readonly 1
        }
      }
    }
  }
}








































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
        } else {
          file attributes [file join $d2 $ftail] -readonly 1
        }
      }
    }
  }
}

proc ::practcl::buildModule {modpath} {
  set buildscript [file join $modpath build build.tcl]
  if {![file exists $buildscript]} return
  set pkgIndexFile [file join $modpath pkgIndex.tcl]
  if {[file exists $pkgIndexFile]} {
    set latest 0
    foreach file [::practcl::findByPattern [file dirname $buildscript] *.tcl] {
      set mtime [file mtime $file]
      if {$mtime>$latest} {
        set latest $mtime
      }
    }
    set IdxTime [file mtime $pkgIndexFile]
    if {$latest<$IdxTime} return
  }
  ::practcl::dotclexec $buildscript
}

###
# Install a module from MODPATH to the directory specified.
# [emph dpath] is assumed to be the fully qualified path where module is to be placed.
# Any existing files will be deleted at that path.
# If the path is symlink the process will return with no error and no action.
# If the module has contents in the build/ directory that are newer than the
# .tcl files in the module source directory, and a build/build.tcl file exists,
# the build/build.tcl file is run.
# If the source directory includes a file named index.tcl, the directory is assumed
# to be in the tao style of modules, and the entire directory (and all subdirectories)
# are copied verbatim.
# If no index.tcl file is present, all .tcl files are copied from the module source
# directory, and a pkgIndex.tcl file is generated if non yet exists.
# I a folder named htdocs exists in the source directory, that directory is copied
# verbatim to the destination.
###
proc ::practcl::installModule {modpath DEST} {
  if {[file exists [file join $DEST modules]]} {
    set dpath [file join $DEST modules [file tail $modpath]]
  } else {
    set dpath $DEST
  }
  if {[file exists $dpath] && [file type $dpath] eq "link"} return
  if {[file exists [file join $modpath index.tcl]]} {
    # IRM/Tao style modules non-amalgamated
    ::practcl::installDir $modpath $dpath
    return
  }
  buildModule $modpath
  set files [glob -nocomplain [file join $modpath *.tcl]]
  if {[llength $files]} {
    if {[llength $files]>1} {
      if {![file exists [file join $modpath pkgIndex.tcl]]} {
        pkg_mkIndex $modpath
      }
    }
    file delete -force $dpath
    file mkdir $dpath
    foreach file $files {
      file copy $file $dpath
    }
  }
  if {[file exists [file join $modpath htdocs]]} {
    ::practcl::copyDir [file join $modpath htdocs] [file join $dpath htdocs]
  }
}

Changes to modules/practcl/build/makeutil.tcl.

1
2
3

4
5
6
7
8
9
10
11
12





13
14
15
16










17
18
19
20
21
22
23
###
# Backward compatible Make facilities
# These were used early in development and are consdiered deprecated

###

proc ::practcl::trigger {args} {
  ::practcl::LOCAL make trigger {*}$args
  foreach {name obj} [::practcl::LOCAL make objects] {
    set ::make($name) [$obj do]
  }
}






proc ::practcl::depends {args} {
  ::practcl::LOCAL make depends {*}$args
}











proc ::practcl::target {name info {action {}}} {
  set obj [::practcl::LOCAL make task $name $info $action]
  set ::make($name) 0
  set filename [$obj define get filename]
  if {$filename ne {}} {
    set ::target($name) $filename
  }

|
|
>

<







>
>
>
>
>




>
>
>
>
>
>
>
>
>
>







1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
###
# show_body: 1
# description:
# Trigger build targets, and recompute dependencies
###

proc ::practcl::trigger {args} {
  ::practcl::LOCAL make trigger {*}$args
  foreach {name obj} [::practcl::LOCAL make objects] {
    set ::make($name) [$obj do]
  }
}

###
# show_body: 1
# description:
# Calculate if a dependency for any of the arguments needs to
# be fulfilled or rebuilt.
proc ::practcl::depends {args} {
  ::practcl::LOCAL make depends {*}$args
}

###
# show_body: 1
# description:
# Declare a build product. This proc is just a shorthand for
# [emph {::practcl::LOCAL make task $name $info $action}]
# [para]
# Registering a build product with this command will create
# an entry in the global [variable make] array, and populate
# a value in the global [variable target] array.
###
proc ::practcl::target {name info {action {}}} {
  set obj [::practcl::LOCAL make task $name $info $action]
  set ::make($name) 0
  set filename [$obj define get filename]
  if {$filename ne {}} {
    set ::target($name) $filename
  }

Added modules/practcl/build/manual.txt.











































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[keywords practcl]
[copyright {2016-2018 Sean Woods <[email protected]>}]
[moddesc {The The Proper Rational API for C to Tool Command Language Module}]
[titledesc {The Practcl Module}]
[category {TclOO}]
[require TclOO 1.0]
[description]
The Practcl module is a tool for integrating large modules for C API
Tcl code that requires custom Tcl types and TclOO objects.
[para]
The concept with Practcl is that is a single file package that can
assist any tcl based project with distribution, compilation, linking,
VFS preparation, executable assembly, and installation. Practcl also
allows one project to invoke the build system from another project,
allowing complex projects such as a statically linked basekit to be
assembled with relative ease.
[para]
Practcl ships as a single file, and aside from a Tcl 8.6 interpreter,
has no external dependencies.
[para]
Making a practcl project

Changes to modules/practcl/pkgIndex.tcl.

1
2
3
4
###
if {![package vsatisfies [package provide Tcl] 8.5]} {return}
package ifneeded practcl 0.11.1 [list source [file join $dir practcl.tcl]]


|
|

1
2
3
4
###
if {![package vsatisfies [package provide Tcl] 8.6]} {return}
package ifneeded practcl 0.16.4 [list source [file join $dir practcl.tcl]]

Changes to modules/practcl/practcl.man.

1
2
3
4
5
6
7
8
9
10
11
12
13












14
15
16
































































































































































































































17
18
19
20




















































































































21
22
23


















































































































24













































































































































































































































25

26






27


28
29































































30









































31

32
33

34
35

36















































































































37

38

39
40










































































































































































































































41
42



















































































































43

44
45

46


















































































































47

48




















































































































49

50
51

52




















































































































53


54
















































































































55
56


57



58








































59






































































60
61

62
63

[comment {-*- practcl -*-}]
[vset VERSION 0.11]
[manpage_begin practcl n [vset VERSION]]
[keywords practcl]
[copyright {2016-2018 Sean Woods <[email protected]>}]
[moddesc {The The Proper Rational API for C to Tool Command Language Module}]
[titledesc {The Practcl Module}]
[category {TclOO}]
[require TclOO 1.0]
[require practcl [vset VERSION]]
[description]
The Practcl module is a tool for integrating large modules for C API
Tcl code that requires custom Tcl types and TclOO objects.













[section COMMANDS]
[list_begin definitions]

































































































































































































































[call [cmd CPUTS] [arg varname] [arg body] [opt [arg body]...]]
Appends blocks of text to a buffer. This command tries to reduce the number
of line breaks between bodies.





















































































































[call [cmd practcl::_isdirectory] [arg path]]
Returns true if [arg path] is a directory, using the test 
































































































































































































































































































































































[list_end]








[list_begin definitions]


[call [cmd practcl::object] [arg "parent"] [opt [arg "keyvaluelist"]]]
































































A generic Practcl object











































[call [cmd practcl::library] [opt [arg "keyvaluelist"]]]


A Practcl object representing a library container


[call [cmd practcl::exe] [opt [arg "keyvaluelist"]]]

















































































































A Practcl object representing a wrapped executable


[call [cmd practcl::product] [arg "parent"] [opt [arg "keyvaluelist"]]]











































































































































































































































A Practcl object representing a compiled product





















































































































[call [cmd practcl::cheader] [arg "parent"] [opt [arg "keyvaluelist"]]]


A Practcl object representing an externally generated c header




















































































































[call [cmd practcl::csource] [arg "parent"] [opt [arg "keyvaluelist"]]]






















































































































A Practcl object representing an externally generated c source file


[call [cmd practcl::module] [arg "parent"] [opt [arg "keyvaluelist"]]]























































































































A Practcl object representing a dynamically generated C/H/Tcl suite

















































































































[call [cmd practcl::submodule] [arg "parent"] [opt [arg "keyvaluelist"]]]






A Practcl object representing a dynamically generated C/H/Tcl suite, subordinate to a module








































[list_end]







































































[vset CATEGORY practcl]

[include ../doctools2base/include/feedback.inc]
[manpage_end]

|
|
|






<



>
>
>
>
>
>
>
>
>
>
>
>

|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>

>
>
>
>
>
>

>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|

>
|

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
>

>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
|

>
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
[comment {-*- tcl -*- doctools manpage}]
[vset PACKAGE_VERSION 0.16.4]
[manpage_begin practcl n [vset PACKAGE_VERSION]]
[keywords practcl]
[copyright {2016-2018 Sean Woods <[email protected]>}]
[moddesc {The The Proper Rational API for C to Tool Command Language Module}]
[titledesc {The Practcl Module}]
[category {TclOO}]
[require TclOO 1.0]

[description]
The Practcl module is a tool for integrating large modules for C API
Tcl code that requires custom Tcl types and TclOO objects.
[para]
The concept with Practcl is that is a single file package that can
assist any tcl based project with distribution, compilation, linking,
VFS preparation, executable assembly, and installation. Practcl also
allows one project to invoke the build system from another project,
allowing complex projects such as a statically linked basekit to be
assembled with relative ease.
[para]
Practcl ships as a single file, and aside from a Tcl 8.6 interpreter,
has no external dependencies.
[para]
Making a practcl project

[section {Commands}]
[list_begin definitions]
[call proc [cmd practcl::cat] [arg fname]]

 Concatenate a file




[call proc [cmd practcl::docstrip] [arg text]]

 Strip the global comments from tcl code. Used to
 prevent the documentation markup comments from clogging
 up files intended for distribution in machine readable format.




[call proc [cmd putb] [opt "[arg map]"] [arg text]]

 Append a line of text to a variable. Optionally apply a string mapping.


[call proc [cmd Proc] [arg name] [arg arglist] [arg body]]

 Generate a proc if no command already exists by that name




[call proc [cmd noop] [opt "[arg args]"]]

 A command to do nothing. A handy way of
 negating an instruction without
 having to comment it completely out.
 It's also a handy attachment point for
 an object to be named later




[call proc [cmd practcl::debug] [opt "[arg args]"]]


[call proc [cmd practcl::doexec] [opt "[arg args]"]]

 Drop in a static copy of Tcl




[call proc [cmd practcl::doexec_in] [arg path] [opt "[arg args]"]]


[call proc [cmd practcl::dotclexec] [opt "[arg args]"]]


[call proc [cmd practcl::domake] [arg path] [opt "[arg args]"]]


[call proc [cmd practcl::domake.tcl] [arg path] [opt "[arg args]"]]


[call proc [cmd practcl::fossil] [arg path] [opt "[arg args]"]]


[call proc [cmd practcl::fossil_status] [arg dir]]


[call proc [cmd practcl::os]]


[call proc [cmd practcl::mkzip] [arg exename] [arg barekit] [arg vfspath]]

 Build a zipfile. On tcl8.6 this invokes the native Zip implementation
 on older interpreters this invokes zip via exec




[call proc [cmd practcl::sort_dict] [arg list]]

 Dictionary sort a key/value list. Needed because pre tcl8.6
 does not have [emph {lsort -stride 2}]




[call proc [cmd practcl::local_os]]

 Returns a dictionary describing the local operating system.
 Fields return include:
 [list_begin itemized]
 [item] download - Filesystem path where fossil repositories and source tarballs are downloaded for the current user
 [item] EXEEXT - The extension to give to executables. (i.e. .exe on windows)
 [item] fossil_mirror - A URI for a local network web server who acts as a fossil repository mirror
 [item] local_install - Filesystem path where packages for local consumption by the current user are installed
 [item] prefix - The prefix as given to the Tcl core/TEA for installation to local_install in ./configure
 [item] sandbox - The file location where this project unpacks external projects
 [item] TEACUP_PROFILE - The ActiveState/Teacup canonical name for this platform (i.e. win32-ix86 macosx10.5-i386-x86_84)
 [item] TEACUP_OS - The local operating system (windows, macosx, openbsd, etc). Gives the same answer as tcl.m4, except that macosx is given as macosx instead of Darwin.
 [item] TEA_PLATFORM - The platform returned by uname -s-uname -r (on Unix), or "windows" on Windows
 [item] TEACUP_ARCH - The processor architecture for the local os (i.e. ix86, x86_64)
 [item] TEACUP_ARCH - The processor architecture for the local os (i.e. ix86, x86_64)
 [item] teapot - Filesystem path where teapot package files are downloaded for the current user
 [item] userhome - File path to store localized preferences, cache download files, etc for the current user
 [list_end]
 This command uses a combination of local checks with Exec, any tclConfig.sh file that is
 resident, autoconf data where already computed, and data gleaned from a file named
 practcl.rc in userhome. The location for userhome varies by platform and operating system:
 [list_begin itemized]
 [item] Windows: ::env(LOCALAPPDATA)/Tcl
 [item] Macos: ~/Library/Application Support/Tcl
 [item] Other: ~/tcl
 [list_end]




[call proc [cmd practcl::config.tcl] [arg path]]

 A transparent call to ::practcl::read_configuration to preserve backward compadibility
 with older copies of Practcl




[call proc [cmd practcl::read_configuration] [arg path]]

 Detect local platform. This command looks for data gleaned by autoconf or autosetup
 in the path specified, or perform its own logic tests if neither has been run.
 A file named config.site present in the location indicates that this project is
 cross compiling, and the data stored in that file is used for the compiler and linker.
 [para]
 This command looks for information from the following files, in the following order:
 [list_begin itemized]
 [item] config.tcl - A file generated by autoconf/configure in newer editions of TEA, encoded as a Tcl script.
 [item] config.site - A file containing cross compiler information, encoded as a SH script
 [item] ::env(VisualStudioVersion) - On Windows, and environmental value that indicates MS Visual Studio is installed
 [list_end]
 [para]
 This command returns a dictionary containing all of the data cleaned from the sources above.
 In the absence of any guidance this command returns the same output as ::practcl::local_os.
 In this mode, if the environmental variable VisualStudioVersion exists, this command
 will provide a template of fields that are appropriate for compiling on Windows under
 Microsoft Visual Studio. The USEMSVC flag in the dictionary is a boolean flag to indicate
 if this is indeed the case.




[call proc [cmd practcl::tcllib_require] [arg pkg] [opt "[arg args]"]]
 Try to load  a package, and failing that
 retrieve tcllib



[call proc [cmd practcl::platform::tcl_core_options] [arg os]]

 Return the string to pass to ./configure to compile the Tcl core for the given OS.
 [list_begin itemized]
 [item] windows: --with-tzdata --with-encoding utf-8
 [item] macosx: --enable-corefoundation=yes  --enable-framework=no --with-tzdata --with-encoding utf-8
 [item] other: --with-tzdata --with-encoding utf-8
 [list_end]




[call proc [cmd practcl::platform::tk_core_options] [arg os]]


[call proc [cmd practcl::read_rc_file] [arg filename] [opt "[arg localdat] [const ""]"]]

 Read a stylized key/value list stored in a file




[call proc [cmd practcl::read_sh_subst] [arg line] [arg info]]

Converts a XXX.sh file into a series of Tcl variables




[call proc [cmd practcl::read_sh_file] [arg filename] [opt "[arg localdat] [const ""]"]]



[call proc [cmd practcl::read_Config.sh] [arg filename]]

 A simpler form of read_sh_file tailored
 to pulling data from (tcl|tk)Config.sh




[call proc [cmd practcl::read_Makefile] [arg filename]]

 A simpler form of read_sh_file tailored
 to pulling data from a Makefile




[call proc [cmd practcl::cputs] [arg varname] [opt "[arg args]"]]
 Append arguments to a buffer
 The command works like puts in that each call will also insert
 a line feed. Unlike puts, blank links in the interstitial are
 suppressed



[call proc [cmd practcl::tcl_to_c] [arg body]]


[call proc [cmd practcl::_tagblock] [arg text] [opt "[arg style] [const "tcl"]"] [opt "[arg note] [const ""]"]]


[call proc [cmd practcl::de_shell] [arg data]]


[call proc [cmd practcl::grep] [arg pattern] [opt "[arg files] [const ""]"]]

 Search for the pattern [emph pattern] amongst $files




[call proc [cmd practcl::file_lexnormalize] [arg sp]]


[call proc [cmd practcl::file_relative] [arg base] [arg dst]]

 Calculate a relative path between base and dst


[para]Example: [example {  ::practcl::file_relative ~/build/tcl/unix ~/build/tcl/library
  > ../library


}]

[call proc [cmd practcl::findByPattern] [arg basedir] [arg patterns]]


[call proc [cmd practcl::log] [arg fname] [arg comment]]

 Record an event in the practcl log




[call proc [cmd practcl::_pkgindex_simpleIndex] [arg path]]


[call proc [cmd practcl::_pkgindex_directory] [arg path]]

 Return true if the pkgindex file contains
 any statement other than "package ifneeded"
 and/or if any package ifneeded loads a DLL




[call proc [cmd practcl::_pkgindex_path_subdir] [arg path]]

 Helper function for ::practcl::pkgindex_path




[call proc [cmd practcl::pkgindex_path] [opt "[arg args]"]]

 Index all paths given as though they will end up in the same
 virtual file system




[call proc [cmd practcl::installDir] [arg d1] [arg d2]]
 Delete the contents of [emph d2], and then
 recusively Ccopy the contents of [emph d1] to [emph d2].



[call proc [cmd practcl::copyDir] [arg d1] [arg d2] [opt "[arg toplevel] [const "1"]"]]
 Recursively copy the contents of [emph d1] to [emph d2]



[call proc [cmd practcl::buildModule] [arg modpath]]


[call proc [cmd practcl::installModule] [arg modpath] [arg DEST]]

 Install a module from MODPATH to the directory specified.
 [emph dpath] is assumed to be the fully qualified path where module is to be placed.
 Any existing files will be deleted at that path.
 If the path is symlink the process will return with no error and no action.
 If the module has contents in the build/ directory that are newer than the
 .tcl files in the module source directory, and a build/build.tcl file exists,
 the build/build.tcl file is run.
 If the source directory includes a file named index.tcl, the directory is assumed
 to be in the tao style of modules, and the entire directory (and all subdirectories)
 are copied verbatim.
 If no index.tcl file is present, all .tcl files are copied from the module source
 directory, and a pkgIndex.tcl file is generated if non yet exists.
 I a folder named htdocs exists in the source directory, that directory is copied
 verbatim to the destination.




[call proc [cmd practcl::trigger] [opt "[arg args]"]]

 Trigger build targets, and recompute dependencies



[para]Internals: [example {
  ::practcl::LOCAL make trigger {*}$args
  foreach {name obj} [::practcl::LOCAL make objects] {
    set ::make($name) [$obj do]
  }
}]

[call proc [cmd practcl::depends] [opt "[arg args]"]]

 Calculate if a dependency for any of the arguments needs to
 be fulfilled or rebuilt.


[para]Internals: [example {
  ::practcl::LOCAL make depends {*}$args
}]

[call proc [cmd practcl::target] [arg name] [arg info] [opt "[arg action] [const ""]"]]

 Declare a build product. This proc is just a shorthand for
 [emph {::practcl::LOCAL make task $name $info $action}]
 [para]
 Registering a build product with this command will create
 an entry in the global [variable make] array, and populate
 a value in the global [variable target] array.



[para]Internals: [example {
  set obj [::practcl::LOCAL make task $name $info $action]
  set ::make($name) 0
  set filename [$obj define get filename]
  if {$filename ne {}} {
    set ::target($name) $filename
  }
}]

[list_end]

[section Classes]
[subsection {Class  practcl::doctool}]
[example {{ set authors {
   {John Doe} {[email protected]}
   {Tom RichardHarry} {[email protected]}
 }
 # Create the object
 ::practcl::doctool create AutoDoc
 set fout [open [file join $moddir module.tcl] w]
 foreach file [glob [file join $srcdir *.tcl]] {
   set content [::practcl::cat [file join $srcdir $file]]
    # Scan the file
    AutoDoc scan_text $content
    # Strip the comments from the distribution
    puts $fout [::practcl::docstrip $content]
 }
 # Write out the manual page
 set manout [open [file join $moddir module.man] w]
 dict set args header [string map $modmap [::practcl::cat [file join $srcdir manual.txt]]]
 dict set args footer [string map $modmap [::practcl::cat [file join $srcdir footer.txt]]]
 dict set args authors $authors
 puts $manout [AutoDoc manpage {*}$args]
 close $manout


}}]
[para]

 Tool for build scripts to dynamically generate manual files from comments
 in source code files

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "constructor"]]


[call method [cmd "argspec"] [arg argspec]]

 Process an argument list into an informational dict.
 This method also understands non-positional
 arguments expressed in the notation of Tip 471
 [uri https://core.tcl-lang.org/tips/doc/trunk/tip/479.md].
 [para]
 The output will be a dictionary of all of the fields and whether the fields
 are [const positional], [const mandatory], and whether they have a
 [const default] value.
 [para]

[para]Example: [example {   my argspec {a b {c 10}}

   > a {positional 1 mandatory 1} b {positional 1 mandatory 1} c {positional 1 mandatory 0 default 10}


}]

[call method [cmd "comment"] [arg block]]

 Convert a block of comments into an informational dictionary.
 If lines in the comment start with a single word ending in a colon,
 all subsequent lines are appended to a dictionary field of that name.
 If no fields are given, all of the text is appended to the [const description]
 field.

[para]Example: [example { my comment {Does something cool}
 > description {Does something cool}

 my comment {
 title : Something really cool
 author : Sean Woods
 author : John Doe
 description :
 This does something really cool!
 }
 > description {This does something really cool!}
   title {Something really cool}
   author {Sean Woods
   John Doe}


}]

[call method [cmd "keyword.Annotation"] [arg resultvar] [arg commentblock] [arg type] [arg name] [arg body]]


[call method [cmd "keyword.Class"] [arg resultvar] [arg commentblock] [arg name] [arg body]]

 Process an oo::objdefine call that modifies the class object
 itself




[call method [cmd "keyword.class"] [arg resultvar] [arg commentblock] [arg name] [arg body]]

 Process an oo::define, clay::define, etc statement.




[call method [cmd "keyword.Class_Method"] [arg resultvar] [arg commentblock] [arg name] [opt "[arg args]"]]

 Process a statement for a clay style class method




[call method [cmd "keyword.method"] [arg resultvar] [arg commentblock] [arg name] [opt "[arg args]"]]

 Process a statement for a tcloo style object method




[call method [cmd "keyword.proc"] [arg commentblock] [arg name] [arg argspec]]

 Process a proc statement




[call method [cmd "reset"]]

 Reset the state of the object and its embedded coroutine




[call method [cmd "Main"]]

 Main body of the embedded coroutine for the object




[call method [cmd "section.method"] [arg keyword] [arg method] [arg minfo]]

 Generate the manual page text for a method or proc




[call method [cmd "section.annotation"] [arg type] [arg name] [arg iinfo]]


[call method [cmd "section.class"] [arg class_name] [arg class_info]]

 Generate the manual page text for a class




[call method [cmd "section.command"] [arg procinfo]]

 Generate the manual page text for the commands section




[call method [cmd "manpage"] [opt "[option "header [emph value]"]"] [opt "[option "footer [emph value]"]"] [opt "[option "authors [emph list]"]"]]

 Generate the manual page. Returns the completed text suitable for saving in .man file.
 The header argument is a block of doctools text to go in before the machine generated
 section. footer is a block of doctools text to go in after the machine generated
 section. authors is a list of individual authors and emails in the form of AUTHOR EMAIL ?AUTHOR EMAIL?...



[call method [cmd "scan_text"] [arg text]]
 Scan a block of text



[call method [cmd "scan_file"] [arg filename]]
 Scan a file of text



[list_end]
[para]

[subsection {Class  practcl::metaclass}]

 The metaclass for all practcl objects



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "_MorphPatterns"]]


[call method [cmd "define"] [arg submethod] [opt "[arg args]"]]


[call method [cmd "graft"] [opt "[arg args]"]]


[call method [cmd "initialize"]]


[call method [cmd "link"] [arg command] [opt "[arg args]"]]


[call method [cmd "morph"] [arg classname]]


[call method [cmd "script"] [arg script]]


[call method [cmd "select"]]


[call method [cmd "source"] [arg filename]]


[list_end]
[para]

[subsection {Class  practcl::toolset}]

 Ancestor-less class intended to be a mixin
 which defines a family of build related behaviors
 that are modified when targetting either gcc or msvc



[para]
[class {Class Methods}]
[list_begin definitions]
[call classmethod [cmd select] [arg object]]
 Perform the selection for the toolset mixin



[list_end]
[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "config.sh"]]

 find or fake a key/value list describing this project




[call method [cmd "BuildDir"] [arg PWD]]
 Compute the location where the product will be built



[call method [cmd "MakeDir"] [arg srcdir]]
 Return where the Makefile is located relative to [emph srcdir].
 For this implementation the MakeDir is always srcdir.



[call method [cmd "read_configuration"]]
 Read information about the build process for this package.
 For this implementation, data is sought in the following locations
 in the following order:
 config.tcl (generated by practcl.) PKGConfig.sh. The Makefile
 [para]
 If the Makefile needs to be consulted, but does not exist, the
 Configure method is invoked



[call method [cmd "build-cflags"] [arg PROJECT] [arg DEFS] [arg namevar] [arg versionvar] [arg defsvar]]
 method DEFS
 This method populates 4 variables:
 name - The name of the package
 version - The version of the package
 defs - C flags passed to the compiler
 includedir - A list of paths to feed to the compiler for finding headers




[call method [cmd "critcl"] [opt "[arg args]"]]
 Invoke critcl in an external process



[list_end]
[para]

[subsection {Class  practcl::toolset.gcc}]
[emph "ancestors"]: [class practcl::toolset]
[para]

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "Autoconf"]]


[call method [cmd "BuildDir"] [arg PWD]]


[call method [cmd "ConfigureOpts"]]


[call method [cmd "MakeDir"] [arg srcdir]]
 Detect what directory contains the Makefile template



[call method [cmd "make {} autodetect"]]


[call method [cmd "make {} clean"]]


[call method [cmd "make {} compile"]]


[call method [cmd "make {} install"] [arg DEST]]


[call method [cmd "build-compile-sources"] [arg PROJECT] [arg COMPILE] [arg CPPCOMPILE] [arg INCLUDES]]


[call method [cmd "build-Makefile"] [arg path] [arg PROJECT]]


[call method [cmd "build-library"] [arg outfile] [arg PROJECT]]

 Produce a static or dynamic library




[call method [cmd "build-tclsh"] [arg outfile] [arg PROJECT] [opt "[arg path] [const "auto"]"]]

 Produce a static executable




[list_end]
[para]

[subsection {Class  practcl::toolset.msvc}]
[emph "ancestors"]: [class practcl::toolset]
[para]

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "BuildDir"] [arg PWD]]
 MSVC always builds in the source directory



[call method [cmd "make {} autodetect"]]
 Do nothing



[call method [cmd "make {} clean"]]


[call method [cmd "make {} compile"]]


[call method [cmd "make {} install"] [arg DEST]]


[call method [cmd "MakeDir"] [arg srcdir]]
 Detect what directory contains the Makefile template



[call method [cmd "NmakeOpts"]]


[list_end]
[para]

[subsection {Class  practcl::make_obj}]
[emph "ancestors"]: [class practcl::metaclass]
[para]

 A build deliverable object. Normally an object file, header, or tcl script
 which must be compiled or generated in some way



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "constructor"] [arg module_object] [arg name] [arg info] [opt "[arg action_body] [const ""]"]]


[call method [cmd "do"]]


[call method [cmd "check"]]


[call method [cmd "output"]]


[call method [cmd "reset"]]


[call method [cmd "triggers"]]


[list_end]
[para]

[subsection {Class  practcl::object}]
[emph "ancestors"]: [class practcl::metaclass]
[para]

 A generic Practcl object



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "constructor"] [arg parent] [opt "[arg args]"]]


[call method [cmd "child"] [arg method]]


[call method [cmd "go"]]


[list_end]
[para]

[subsection {Class  practcl::dynamic}]

 Dynamic blocks do not generate their own .c files,
 instead the contribute to the amalgamation
 of the main library file



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "cstructure"] [arg name] [arg definition] [opt "[arg argdat] [const ""]"]]

 Parser functions




[call method [cmd "include"] [arg header]]


[call method [cmd "include_dir"] [opt "[arg args]"]]


[call method [cmd "include_directory"] [opt "[arg args]"]]


[call method [cmd "c_header"] [arg body]]


[call method [cmd "c_code"] [arg body]]


[call method [cmd "c_function"] [arg header] [arg body] [opt "[arg info] [const ""]"]]


[call method [cmd "c_tcloomethod"] [arg name] [arg body] [opt "[arg arginfo] [const ""]"]]


[call method [cmd "cmethod"] [arg name] [arg body] [opt "[arg arginfo] [const ""]"]]
 Alias to classic name



[call method [cmd "c_tclproc_nspace"] [arg nspace]]


[call method [cmd "c_tclcmd"] [arg name] [arg body] [opt "[arg arginfo] [const ""]"]]


[call method [cmd "c_tclproc_raw"] [arg name] [arg body] [opt "[arg arginfo] [const ""]"]]
 Alias to classic name



[call method [cmd "tcltype"] [arg name] [arg argdat]]


[call method [cmd "project-compile-products"]]

 Module interactions




[call method [cmd "implement"] [arg path]]


[call method [cmd "initialize"]]

 Practcl internals




[call method [cmd "linktype"]]


[call method [cmd "generate-cfile-constant"]]


[call method [cmd "generate-cfile-header"]]


[call method [cmd "generate-cfile-tclapi"]]

 Generate code that provides implements Tcl API
 calls




[call method [cmd "generate-loader-module"]]

 Generate code that runs when the package/module is
 initialized into the interpreter




[call method [cmd "Collate_Source"] [arg CWD]]


[call method [cmd "select"]]
 Once an object marks itself as some
 flavor of dynamic, stop trying to morph
 it into something else



[list_end]
[para]

[subsection {Class  practcl::product}]

 A deliverable for the build system



[para]
[class {Class Methods}]
[list_begin definitions]
[call classmethod [cmd select] [arg object]]


[list_end]
[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "code"] [arg section] [arg body]]


[call method [cmd "Collate_Source"] [arg CWD]]


[call method [cmd "project-compile-products"]]


[call method [cmd "generate-debug"] [opt "[arg spaces] [const ""]"]]


[call method [cmd "generate-cfile-constant"]]


[call method [cmd "generate-cfile-public-structure"]]

 Populate const static data structures




[call method [cmd "generate-cfile-header"]]


[call method [cmd "generate-cfile-global"]]


[call method [cmd "generate-cfile-private-typedef"]]


[call method [cmd "generate-cfile-private-structure"]]


[call method [cmd "generate-cfile-functions"]]

 Generate code that provides subroutines called by
 Tcl API methods




[call method [cmd "generate-cfile-tclapi"]]

 Generate code that provides implements Tcl API
 calls




[call method [cmd "generate-hfile-public-define"]]


[call method [cmd "generate-hfile-public-macro"]]


[call method [cmd "generate-hfile-public-typedef"]]


[call method [cmd "generate-hfile-public-structure"]]


[call method [cmd "generate-hfile-public-headers"]]


[call method [cmd "generate-hfile-public-function"]]


[call method [cmd "generate-hfile-public-includes"]]


[call method [cmd "generate-hfile-public-verbatim"]]


[call method [cmd "generate-loader-external"]]


[call method [cmd "generate-loader-module"]]


[call method [cmd "generate-stub-function"]]


[call method [cmd "IncludeAdd"] [arg headervar] [opt "[arg args]"]]


[call method [cmd "generate-tcl-loader"]]


[call method [cmd "generate-tcl-pre"]]

 This methods generates any Tcl script file
 which is required to pre-initialize the C library




[call method [cmd "generate-tcl-post"]]


[call method [cmd "linktype"]]


[call method [cmd "Ofile"] [arg filename]]


[call method [cmd "project-static-packages"]]

 Methods called by the master project




[call method [cmd "toolset-include-directory"]]

 Methods called by the toolset




[call method [cmd "target"] [arg method] [opt "[arg args]"]]


[list_end]
[para]

[subsection {Class  practcl::product.cheader}]
[emph "ancestors"]: [class practcl::product]
[para]

 A product which generated from a C header file. Which is to say, nothing.



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "project-compile-products"]]


[call method [cmd "generate-loader-module"]]


[list_end]
[para]

[subsection {Class  practcl::product.csource}]
[emph "ancestors"]: [class practcl::product]
[para]

 A product which generated from a C source file. Normally an object (.o) file.



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "project-compile-products"]]


[list_end]
[para]

[subsection {Class  practcl::product.clibrary}]
[emph "ancestors"]: [class practcl::product]
[para]

 A product which is generated from a compiled C library.
 Usually a .a or a .dylib file, but in complex cases may
 actually just be a conduit for one project to integrate the
 source code of another



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "linker-products"] [arg configdict]]


[list_end]
[para]

[subsection {Class  practcl::product.dynamic}]
[emph "ancestors"]: [class practcl::dynamic] [class practcl::product]
[para]

 A product which is generated from C code that itself is generated
 by practcl or some other means. This C file may or may not produce
 its own .o file, depending on whether it is eligible to become part
 of an amalgamation



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "initialize"]]


[list_end]
[para]

[subsection {Class  practcl::product.critcl}]
[emph "ancestors"]: [class practcl::dynamic] [class practcl::product]
[para]

 A binary product produced by critcl. Note: The implementation is not
 written yet, this class does nothing.


[para]

[subsection {Class  practcl::module}]
[emph "ancestors"]: [class practcl::object] [class practcl::product.dynamic]
[para]

 In the end, all C code must be loaded into a module
 This will either be a dynamically loaded library implementing
 a tcl extension, or a compiled in segment of a custom shell/app



[para]
[class {Variable}]
[list_begin definitions]
[call variable [cmd make_object]]

[list_end]
[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "_MorphPatterns"]]


[call method [cmd "add"] [opt "[arg args]"]]


[call method [cmd "install-headers"] [opt "[arg args]"]]


[call method [cmd "make {} _preamble"]]


[call method [cmd "make {} pkginfo"]]


[call method [cmd "make {} objects"]]
 Return a dictionary of all handles and associated objects



[call method [cmd "make {} object"] [arg name]]
 Return the object associated with handle [emph name]



[call method [cmd "make {} reset"]]
 Reset all deputy objects



[call method [cmd "make {} trigger"] [opt "[arg args]"]]
 Exercise the triggers method for all handles listed



[call method [cmd "make {} depends"] [opt "[arg args]"]]
 Exercise the check method for all handles listed



[call method [cmd "make {} filename"] [arg name]]
 Return the file name of the build product for the listed
 handle



[call method [cmd "make {} target"] [arg name] [arg Info] [arg body]]


[call method [cmd "make {} todo"]]
 Return a list of handles for object which return true for the
 do method



[call method [cmd "make {} do"]]
 For each target exercise the action specified in the [emph action]
 definition if the [emph do] method returns true



[call method [cmd "child"] [arg which]]


[call method [cmd "generate-c"]]

 This methods generates the contents of an amalgamated .c file
 which implements the loader for a batch of tools




[call method [cmd "generate-h"]]

 This methods generates the contents of an amalgamated .h file
 which describes the public API of this module




[call method [cmd "generate-loader"]]


[call method [cmd "initialize"]]


[call method [cmd "implement"] [arg path]]


[call method [cmd "linktype"]]


[list_end]
[para]

[subsection {Class  practcl::project}]
[emph "ancestors"]: [class practcl::module]
[para]

 A toplevel project that is a collection of other projects



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "_MorphPatterns"]]


[call method [cmd "constructor"] [opt "[arg args]"]]


[call method [cmd "add_object"] [arg object]]


[call method [cmd "add_project"] [arg pkg] [arg info] [opt "[arg oodefine] [const ""]"]]


[call method [cmd "add_tool"] [arg pkg] [arg info] [opt "[arg oodefine] [const ""]"]]


[call method [cmd "build-tclcore"]]

 Compile the Tcl core. If the define [emph tk] is true, compile the
 Tk core as well




[call method [cmd "child"] [arg which]]


[call method [cmd "linktype"]]


[call method [cmd "project"] [arg pkg] [opt "[arg args]"]]
 Exercise the methods of a sub-object



[call method [cmd "tclcore"]]


[call method [cmd "tkcore"]]


[call method [cmd "tool"] [arg pkg] [opt "[arg args]"]]


[list_end]
[para]

[subsection {Class  practcl::library}]
[emph "ancestors"]: [class practcl::project]
[para]

 A toplevel project that produces a library



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "clean"] [arg PATH]]


[call method [cmd "project-compile-products"]]


[call method [cmd "go"]]


[call method [cmd "generate-decls"] [arg pkgname] [arg path]]


[call method [cmd "implement"] [arg path]]


[call method [cmd "generate-make"] [arg path]]
 Backward compadible call



[call method [cmd "linktype"]]


[call method [cmd "package-ifneeded"] [opt "[arg args]"]]
 Create a "package ifneeded"
 Args are a list of aliases for which this package will answer to



[call method [cmd "shared_library"] [opt "[arg filename] [const ""]"]]


[call method [cmd "static_library"] [opt "[arg filename] [const ""]"]]


[list_end]
[para]

[subsection {Class  practcl::tclkit}]
[emph "ancestors"]: [class practcl::library]
[para]

 A toplevel project that produces a self-contained executable



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "build-tclkit_main"] [arg PROJECT] [arg PKG_OBJS]]


[call method [cmd "Collate_Source"] [arg CWD]]


[call method [cmd "wrap"] [arg PWD] [arg exename] [arg vfspath] [opt "[arg args]"]]
 Wrap an executable




[list_end]
[para]

[subsection {Class  practcl::distribution}]

 Standalone class to manage code distribution
 This class is intended to be mixed into another class
 (Thus the lack of ancestors)



[para]
[class {Class Methods}]
[list_begin definitions]
[call classmethod [cmd Sandbox] [arg object]]


[call classmethod [cmd select] [arg object]]


[call classmethod [cmd claim_option]]


[call classmethod [cmd claim_object] [arg object]]


[call classmethod [cmd claim_path] [arg path]]


[list_end]
[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "scm_info"]]


[call method [cmd "DistroMixIn"]]


[call method [cmd "Sandbox"]]


[call method [cmd "SrcDir"]]


[call method [cmd "ScmTag"]]


[call method [cmd "ScmClone"]]


[call method [cmd "ScmUnpack"]]


[call method [cmd "ScmUpdate"]]


[call method [cmd "Unpack"]]


[list_end]
[para]

[subsection {Class  practcl::distribution.snapshot}]
[emph "ancestors"]: [class practcl::distribution]
[para]

 A file distribution from zip, tarball, or other non-scm archive format



[para]
[class {Class Methods}]
[list_begin definitions]
[call classmethod [cmd claim_object] [arg object]]


[call classmethod [cmd claim_option]]


[call classmethod [cmd claim_path] [arg path]]


[list_end]
[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "ScmUnpack"]]


[list_end]
[para]

[subsection {Class  practcl::distribution.fossil}]
[emph "ancestors"]: [class practcl::distribution]
[para]

 A file distribution based on fossil



[para]
[class {Class Methods}]
[list_begin definitions]
[call classmethod [cmd claim_object] [arg obj]]
 Check for markers in the metadata



[call classmethod [cmd claim_option]]


[call classmethod [cmd claim_path] [arg path]]
 Check for markers in the source root



[list_end]
[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "scm_info"]]


[call method [cmd "ScmClone"]]
 Clone the source



[call method [cmd "ScmTag"]]


[call method [cmd "ScmUnpack"]]


[call method [cmd "ScmUpdate"]]


[list_end]
[para]

[subsection {Class  practcl::distribution.git}]
[emph "ancestors"]: [class practcl::distribution]
[para]

 A file distribution based on git



[para]
[class {Class Methods}]
[list_begin definitions]
[call classmethod [cmd claim_object] [arg obj]]


[call classmethod [cmd claim_option]]


[call classmethod [cmd claim_path] [arg path]]


[list_end]
[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "ScmTag"]]


[call method [cmd "ScmUnpack"]]


[call method [cmd "ScmUpdate"]]


[list_end]
[para]

[subsection {Class  practcl::subproject}]
[emph "ancestors"]: [class practcl::module]
[para]

 A subordinate project



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "_MorphPatterns"]]


[call method [cmd "BuildDir"] [arg PWD]]


[call method [cmd "child"] [arg which]]


[call method [cmd "compile"]]


[call method [cmd "go"]]


[call method [cmd "install"] [opt "[arg args]"]]
 Install project into the local build system



[call method [cmd "linktype"]]


[call method [cmd "linker-products"] [arg configdict]]


[call method [cmd "linker-external"] [arg configdict]]


[call method [cmd "linker-extra"] [arg configdict]]


[call method [cmd "env-bootstrap"]]

 Methods for packages/tools that can be downloaded
 possibly built and used internally by this Practcl
 process


 Load the facility into the interpreter




[call method [cmd "env-exec"]]

 Return a file path that exec can call




[call method [cmd "env-install"]]

 Install the tool into the local environment




[call method [cmd "env-load"]]

 Do whatever is necessary to get the tool
 into the local environment




[call method [cmd "env-present"]]

 Check if tool is available for load/already loaded




[call method [cmd "sources"]]


[call method [cmd "update"]]


[call method [cmd "unpack"]]


[list_end]
[para]

[subsection {Class  practcl::subproject.source}]
[emph "ancestors"]: [class practcl::subproject] [class practcl::library]
[para]

 A project which the kit compiles and integrates
 the source for itself



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "env-bootstrap"]]


[call method [cmd "env-present"]]


[call method [cmd "linktype"]]


[list_end]
[para]

[subsection {Class  practcl::subproject.teapot}]
[emph "ancestors"]: [class practcl::subproject]
[para]
 a copy from the teapot


[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "env-bootstrap"]]


[call method [cmd "env-install"]]


[call method [cmd "env-present"]]


[call method [cmd "install"] [arg DEST]]


[list_end]
[para]

[subsection {Class  practcl::subproject.kettle}]
[emph "ancestors"]: [class practcl::subproject]
[para]

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "kettle"] [arg path] [opt "[arg args]"]]


[call method [cmd "install"] [arg DEST]]


[list_end]
[para]

[subsection {Class  practcl::subproject.critcl}]
[emph "ancestors"]: [class practcl::subproject]
[para]

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "install"] [arg DEST]]


[list_end]
[para]

[subsection {Class  practcl::subproject.sak}]
[emph "ancestors"]: [class practcl::subproject]
[para]

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "env-bootstrap"]]


[call method [cmd "env-install"]]


[call method [cmd "env-present"]]


[call method [cmd "install"] [arg DEST]]


[call method [cmd "install-module"] [arg DEST] [opt "[arg args]"]]


[list_end]
[para]

[subsection {Class  practcl::subproject.practcl}]
[emph "ancestors"]: [class practcl::subproject]
[para]

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "env-bootstrap"]]


[call method [cmd "env-install"]]


[call method [cmd "install"] [arg DEST]]


[call method [cmd "install-module"] [arg DEST] [opt "[arg args]"]]


[list_end]
[para]

[subsection {Class  practcl::subproject.binary}]
[emph "ancestors"]: [class practcl::subproject]
[para]

 A subordinate binary package



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "clean"]]


[call method [cmd "env-install"]]


[call method [cmd "project-compile-products"]]


[call method [cmd "ComputeInstall"]]


[call method [cmd "go"]]


[call method [cmd "linker-products"] [arg configdict]]


[call method [cmd "project-static-packages"]]


[call method [cmd "BuildDir"] [arg PWD]]


[call method [cmd "compile"]]


[call method [cmd "Configure"]]


[call method [cmd "install"] [arg DEST]]


[list_end]
[para]

[subsection {Class  practcl::subproject.tea}]
[emph "ancestors"]: [class practcl::subproject.binary]
[para]

 A subordinate TEA based binary package



[para]

[subsection {Class  practcl::subproject.library}]
[emph "ancestors"]: [class practcl::subproject.binary] [class practcl::library]
[para]

 A subordinate C library built by this project



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "install"] [arg DEST]]


[list_end]
[para]

[subsection {Class  practcl::subproject.external}]
[emph "ancestors"]: [class practcl::subproject.binary]
[para]

 A subordinate external C library



[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "install"] [arg DEST]]


[list_end]
[para]

[subsection {Class  practcl::subproject.core}]
[emph "ancestors"]: [class practcl::subproject.binary]
[para]

[para]
[class {Methods}]
[list_begin definitions]
[call method [cmd "env-bootstrap"]]


[call method [cmd "env-present"]]


[call method [cmd "env-install"]]


[call method [cmd "go"]]


[call method [cmd "linktype"]]


[list_end]
[para]

[vset CATEGORY practcl]
[include ../common-text/feedback.inc]

[manpage_end]

Changes to modules/practcl/practcl.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70




































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































71
72
73
74
75
76
77
78
79
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
###
# Amalgamated package for practcl
# Do not edit directly, tweak the source in src/ and rerun
# build.tcl
###
package require Tcl 8.5
package provide practcl 0.11.1
namespace eval ::practcl {}

###
# START: httpwget/wget.tcl
###
###
# Tool to download file from the web
# Enhacements to http
###
package provide http::wget 0.1
package require http

::namespace eval ::http {}

###
# topic: 1ed971e03ae89415e2f25d20e59b765c
# description: this proc contributed by Donal Fellows
###
proc ::http::_followRedirects {url args} {
    while 1 {
        set token [geturl $url -validate 1]
        set ncode [ncode $token]
        if { $ncode eq "404" } {
          error "URL Not found"
        }
        switch -glob $ncode {
            30[1237] {### redirect - see below ###}
            default  {cleanup $token ; return $url}
        }
        upvar #0 $token state
        array set meta [set ${token}(meta)]
        cleanup $token
        if {![info exists meta(Location)]} {
           return $url
        }
        set url $meta(Location)
        unset meta
    }
    return $url
}

###
# topic: fced7bc395596569ac225a719c686dcc
###
proc ::http::wget {url destfile {verbose 1}} {
    set tmpchan [open $destfile w]
    fconfigure $tmpchan -translation binary
    if { $verbose } {
        puts [list  GETTING [file tail $destfile] from $url]
    }
    set real_url [_followRedirects $url]
    set token [geturl $real_url -channel $tmpchan -binary yes]
    if {[ncode $token] != "200"} {
      error "DOWNLOAD FAILED"
    }
    cleanup $token
    close $tmpchan
}


###
# END: httpwget/wget.tcl
###




































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































###
# START: setup.tcl
###
###
# Practcl
# An object oriented templating system for stamping out Tcl API calls to C
###

package require TclOO
###
# Seek out Tcllib if it's available
###
set tcllib_path {}
foreach path {.. ../.. ../../..} {
  foreach path [glob -nocomplain [file join [file normalize $path] tcllib* modules]] {
    set tclib_path $path
    lappend ::auto_path $path
    break
  }
  if {$tcllib_path ne {}} break
}
namespace eval ::practcl {}

namespace eval ::practcl::OBJECT {}


###
# END: setup.tcl
###

































































































































































































































































































































































































































































































































































































































###
# START: buildutil.tcl
###
###
# Build utility functions
###

###
# A command to do nothing. A handy way of
# negating an instruction without
# having to comment it completely out.
# It's also a handy attachment point for
# an object to be named later
###
if {[info command ::noop] eq {}} {
  proc ::noop args {}
}

proc ::practcl::debug args {
  #puts $args
  ::practcl::cputs ::DEBUG_INFO $args
}

###
# Drop in a static copy of Tcl
###
proc ::practcl::doexec args {
  puts [list {*}$args]
  exec {*}$args >&@ stdout
}

proc ::practcl::doexec_in {path args} {
  set PWD [pwd]
  cd $path
  puts [list {*}$args]
  exec {*}$args >&@ stdout
  cd $PWD
}

proc ::practcl::dotclexec args {
  puts [list [info nameofexecutable] {*}$args]
  exec [info nameofexecutable] {*}$args >&@ stdout
}

proc ::practcl::domake {path args} {
  set PWD [pwd]
  cd $path
  puts [list *** $path ***]
  puts [list make {*}$args]
  exec make {*}$args >&@ stdout
  cd $PWD
}

proc ::practcl::domake.tcl {path args} {
  set PWD [pwd]
  cd $path
  puts [list *** $path ***]
  puts [list make.tcl {*}$args]
  exec [info nameofexecutable] make.tcl {*}$args >&@ stdout
  cd $PWD
}

proc ::practcl::fossil {path args} {
  set PWD [pwd]
  cd $path
  puts [list {*}$args]
  exec fossil {*}$args >&@ stdout
  cd $PWD
}


proc ::practcl::fossil_status {dir} {
  if {[info exists ::fosdat($dir)]} {
    return $::fosdat($dir)
  }
  set result {
tags experimental
version {}





|
|





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



<
<
<
<
<

<
<
<









|
>
|
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



<
<
<
|
<
<
<
<
<
<
<
|
|

|




<
<
<
<




<







<




<








<








<







<
<







1
2
3
4
5
6
7
8
9
10
11
12






















































13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943





1944



1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573



2574







2575
2576
2577
2578
2579
2580
2581
2582




2583
2584
2585
2586

2587
2588
2589
2590
2591
2592
2593

2594
2595
2596
2597

2598
2599
2600
2601
2602
2603
2604
2605

2606
2607
2608
2609
2610
2611
2612
2613

2614
2615
2616
2617
2618
2619
2620


2621
2622
2623
2624
2625
2626
2627
###
# Amalgamated package for practcl
# Do not edit directly, tweak the source in src/ and rerun
# build.tcl
###
package require Tcl 8.6
package provide practcl 0.16.4
namespace eval ::practcl {}

###
# START: httpwget/wget.tcl
###























































###
# END: httpwget/wget.tcl
###
###
# START: clay/clay.tcl
###
package provide clay 0.8.6
namespace eval ::clay {
}
namespace eval ::clay {
}
set ::clay::trace 0
if {[info commands ::cron::object_destroy] eq {}} {
  # Provide a noop if we aren't running with the cron scheduler
  namespace eval ::cron {}
  proc ::cron::object_destroy args {}
}
proc ::clay::PROC {name arglist body {ninja {}}} {
  if {[info commands $name] ne {}} return
  proc $name $arglist $body
  eval $ninja
}
if {[info commands ::PROC] eq {}} {
  namespace eval ::clay { namespace export PROC }
  namespace eval :: { namespace import ::clay::PROC }
}
proc ::clay::_ancestors {resultvar class} {
  upvar 1 $resultvar result
  if {$class in $result} {
    return
  }
  lappend result $class
  foreach aclass [::info class superclasses $class] {
    _ancestors result $aclass
  }
}
proc ::clay::ancestors {args} {
  set result {}
  set queue  {}
  set metaclasses {}

  foreach class $args {
    set ancestors($class) {}
    _ancestors ancestors($class) $class
  }
  foreach class [lreverse $args] {
    foreach aclass $ancestors($class) {
      if {$aclass in $result} continue
      set skip 0
      foreach bclass $args {
        if {$class eq $bclass} continue
        if {$aclass in $ancestors($bclass)} {
          set skip 1
          break
        }
      }
      if {$skip} continue
      lappend result $aclass
    }
  }
  foreach class [lreverse $args] {
    foreach aclass $ancestors($class) {
      if {$aclass in $result} continue
      lappend result $aclass
    }
  }
  ###
  # Screen out classes that do not participate in clay
  # interactions
  ###
  set output {}
  foreach {item} $result {
    if {[catch {$item clay noop} err]} {
      continue
    }
    lappend output $item
  }
  return $output
}
proc ::clay::args_to_dict args {
  if {[llength $args]==1} {
    return [lindex $args 0]
  }
  return $args
}
proc ::clay::args_to_options args {
  set result {}
  foreach {var val} [args_to_dict {*}$args] {
    lappend result [string trim $var -:] $val
  }
  return $result
}
proc ::clay::dynamic_arguments {ensemble method arglist args} {
  set idx 0
  set len [llength $args]
  if {$len > [llength $arglist]} {
    ###
    # Catch if the user supplies too many arguments
    ###
    set dargs 0
    if {[lindex $arglist end] ni {args dictargs}} {
      return -code error -level 2 "Usage: $ensemble $method [string trim [dynamic_wrongargs_message $arglist]]"
    }
  }
  foreach argdef $arglist {
    if {$argdef eq "args"} {
      ###
      # Perform args processing in the style of tcl
      ###
      uplevel 1 [list set args [lrange $args $idx end]]
      break
    }
    if {$argdef eq "dictargs"} {
      ###
      # Perform args processing in the style of tcl
      ###
      uplevel 1 [list set args [lrange $args $idx end]]
      ###
      # Perform args processing in the style of clay
      ###
      set dictargs [::clay::args_to_options {*}[lrange $args $idx end]]
      uplevel 1 [list set dictargs $dictargs]
      break
    }
    if {$idx > $len} {
      ###
      # Catch if the user supplies too few arguments
      ###
      if {[llength $argdef]==1} {
        return -code error -level 2 "Usage: $ensemble $method [string trim [dynamic_wrongargs_message $arglist]]"
      } else {
        uplevel 1 [list set [lindex $argdef 0] [lindex $argdef 1]]
      }
    } else {
      uplevel 1 [list set [lindex $argdef 0] [lindex $args $idx]]
    }
    incr idx
  }
}
proc ::clay::dynamic_wrongargs_message {arglist} {
  set result ""
  set dargs 0
  foreach argdef $arglist {
    if {$argdef in {args dictargs}} {
      set dargs 1
      break
    }
    if {[llength $argdef]==1} {
      append result " $argdef"
    } else {
      append result " ?[lindex $argdef 0]?"
    }
  }
  if { $dargs } {
    append result " ?option value?..."
  }
  return $result
}
proc ::clay::is_dict { d } {
  # is it a dict, or can it be treated like one?
  if {[catch {::dict size $d} err]} {
    #::set ::errorInfo {}
    return 0
  }
  return 1
}
proc ::clay::is_null value {
  return [expr {$value in {{} NULL}}]
}
proc ::clay::leaf args {
  set marker [string index [lindex $args end] end]
  set result [path {*}${args}]
  if {$marker eq "/"} {
    return $result
  }
  return [list {*}[lrange $result 0 end-1] [string trim [string trim [lindex $result end]] /]]
}
proc ::clay::K {a b} {set a}
if {[info commands ::K] eq {}} {
  namespace eval ::clay { namespace export K }
  namespace eval :: { namespace import ::clay::K }
}
proc ::clay::noop args {}
if {[info commands ::noop] eq {}} {
  namespace eval ::clay { namespace export noop }
  namespace eval :: { namespace import ::clay::noop }
}
proc ::clay::cleanup {} {
  set count 0
  if {![info exists ::clay::idle_destroy]} return
  set objlist $::clay::idle_destroy
  set ::clay::idle_destroy {}
  foreach obj $objlist {
    if {![catch {$obj destroy}]} {
      incr count
    }
  }
  return $count
}
proc ::clay::object_create {objname {class {}}} {
  #if {$::clay::trace>0} {
  #  puts [list $objname CREATE]
  #}
}
proc ::clay::object_rename {object newname} {
  if {$::clay::trace>0} {
    puts [list $object RENAME -> $newname]
  }
}
proc ::clay::object_destroy args {
  if {![info exists ::clay::idle_destroy]} {
    set ::clay::idle_destroy {}
  }
  foreach objname $args {
    if {$::clay::trace>0} {
      puts [list $objname DESTROY]
    }
    ::cron::object_destroy $objname
    if {$objname in $::clay::idle_destroy} continue
    lappend ::clay::idle_destroy $objname
  }
}
proc ::clay::path args {
  set result {}
  foreach item $args {
    set item [string trim $item :./]
    foreach subitem [split $item /] {
      lappend result [string trim ${subitem}]/
    }
  }
  return $result
}
proc ::clay::putb {buffername args} {
  upvar 1 $buffername buffer
  switch [llength $args] {
    1 {
      append buffer [lindex $args 0] \n
    }
    2 {
      append buffer [string map {*}$args] \n
    }
    default {
      error "usage: putb buffername ?map? string"
    }
  }
}
if {[info command ::putb] eq {}} {
  namespace eval ::clay { namespace export putb }
  namespace eval :: { namespace import ::clay::putb }
}
proc ::clay::script_path {} {
  set path [file dirname [file join [pwd] [info script]]]
  return $path
}
proc ::clay::NSNormalize qualname {
  if {![string match ::* $qualname]} {
    set qualname ::clay::classes::$qualname
  }
  regsub -all {::+} $qualname "::"
}
proc ::clay::uuid_generate args {
  return [uuid generate]
}
namespace eval ::clay {
  variable option_class {}
  variable core_classes {::oo::class ::oo::object}
}
package require Tcl 8.6 ;# try in pipeline.tcl. Possibly other things.
if {[info commands irmmd5] eq {}} {
  if {[catch {package require odielibc}]} {
    package require md5 2
  }
}
::namespace eval ::clay {
}
::namespace eval ::clay::classes {
}
::namespace eval ::clay::define {
}
::namespace eval ::clay::tree {
}
::namespace eval ::clay::dict {
}
::namespace eval ::clay::list {
}
::namespace eval ::clay::uuid {
}
if {![info exists ::clay::idle_destroy]} {
  set ::clay::idle_destroy {}
}
namespace eval ::clay::uuid {
    namespace export uuid
}
proc ::clay::uuid::generate_tcl_machinfo {} {
  variable machinfo
  if {[info exists machinfo]} {
    return $machinfo
  }
  lappend machinfo [clock seconds]; # timestamp
  lappend machinfo [clock clicks];  # system incrementing counter
  lappend machinfo [info hostname]; # spatial unique id (poor)
  lappend machinfo [pid];           # additional entropy
  lappend machinfo [array get ::tcl_platform]

  ###
  # If we have /dev/urandom just stream 128 bits from that
  ###
  if {[file exists /dev/urandom]} {
    set fin [open /dev/urandom r]
    binary scan [read $fin 128] H* machinfo
    close $fin
  } elseif {[catch {package require nettool}]} {
    # More spatial information -- better than hostname.
    # bug 1150714: opening a server socket may raise a warning messagebox
    #   with WinXP firewall, using ipconfig will return all IP addresses
    #   including ipv6 ones if available. ipconfig is OK on win98+
    if {[string equal $::tcl_platform(platform) "windows"]} {
      catch {exec ipconfig} config
      lappend machinfo $config
    } else {
      catch {
          set s [socket -server void -myaddr [info hostname] 0]
          ::clay::K [fconfigure $s -sockname] [close $s]
      } r
      lappend machinfo $r
    }

    if {[package provide Tk] != {}} {
      lappend machinfo [winfo pointerxy .]
      lappend machinfo [winfo id .]
    }
  } else {
    ###
    # If the nettool package works on this platform
    # use the stream of hardware ids from it
    ###
    lappend machinfo {*}[::nettool::hwid_list]
  }
  return $machinfo
}
if {[info commands irmmd5] ne {}} {
proc ::clay::uuid::generate {{type {}}} {
    variable nextuuid
    set s [irmmd5 "$type [incr nextuuid(type)] [generate_tcl_machinfo]"]
    foreach {a b} {0 7 8 11 12 15 16 19 20 31} {
         append r [string range $s $a $b] -
     }
     return [string tolower [string trimright $r -]]
}
proc ::clay::uuid::short {{type {}}} {
  variable nextuuid
  set r [irmmd5 "$type [incr nextuuid(type)] [generate_tcl_machinfo]"]
  return [string range $r 0 16]
}

} else {
package require md5 2
proc ::clay::uuid::raw {{type {}}} {
    variable nextuuid
    set tok [md5::MD5Init]
    md5::MD5Update $tok "$type [incr nextuuid($type)] [generate_tcl_machinfo]"
    set r [md5::MD5Final $tok]
    return $r
    #return [::clay::uuid::tostring $r]
}
proc ::clay::uuid::generate {{type {}}} {
    return [::clay::uuid::tostring [::clay::uuid::raw  $type]]
}
proc ::clay::uuid::short {{type {}}} {
  set r [::clay::uuid::raw $type]
  binary scan $r H* s
  return [string range $s 0 16]
}
}
proc ::clay::uuid::tostring {uuid} {
    binary scan $uuid H* s
    foreach {a b} {0 7 8 11 12 15 16 19 20 31} {
        append r [string range $s $a $b] -
    }
    return [string tolower [string trimright $r -]]
}
proc ::clay::uuid::fromstring {uuid} {
    return [binary format H* [string map {- {}} $uuid]]
}
proc ::clay::uuid::equal {left right} {
    set l [fromstring $left]
    set r [fromstring $right]
    return [string equal $l $r]
}
proc ::clay::uuid {cmd args} {
    switch -exact -- $cmd {
        generate {
           return [::clay::uuid::generate {*}$args]
        }
        short {
          set uuid [::clay::uuid::short {*}$args]
        }
        equal {
            tailcall ::clay::uuid::equal {*}$args
        }
        default {
            return -code error "bad option \"$cmd\":\
                must be generate or equal"
        }
    }
}
::clay::PROC ::tcl::dict::getnull {dictionary args} {
  if {[exists $dictionary {*}$args]} {
    get $dictionary {*}$args
  }
} {
  namespace ensemble configure dict -map [dict replace\
      [namespace ensemble configure dict -map] getnull ::tcl::dict::getnull]
}
::clay::PROC ::tcl::dict::is_dict { d } {
  # is it a dict, or can it be treated like one?
  if {[catch {dict size $d} err]} {
    #::set ::errorInfo {}
    return 0
  }
  return 1
} {
  namespace ensemble configure dict -map [dict replace\
      [namespace ensemble configure dict -map] is_dict ::tcl::dict::is_dict]
}
::clay::PROC ::tcl::dict::rmerge {args} {
  ::set result [dict create . {}]
  # Merge b into a, and handle nested dicts appropriately
  ::foreach b $args {
    for { k v } $b {
      ::set field [string trim $k :/]
      if {![::clay::tree::is_branch $b $k]} {
        # Element names that end in ":" are assumed to be literals
        set result $k $v
      } elseif { [exists $result $k] } {
        # key exists in a and b?  let's see if both values are dicts
        # both are dicts, so merge the dicts
        if { [is_dict [get $result $k]] && [is_dict $v] } {
          set result $k [rmerge [get $result $k] $v]
        } else {
          set result $k $v
        }
      } else {
        set result $k $v
      }
    }
  }
  return $result
} {
  namespace ensemble configure dict -map [dict replace\
      [namespace ensemble configure dict -map] rmerge ::tcl::dict::rmerge]
}
::clay::PROC ::clay::tree::is_branch { dict path } {
  set field [lindex $path end]
  if {[string index $field end] eq ":"} {
    return 0
  }
  if {[string index $field 0] eq "."} {
    return 0
  }
  if {[string index $field end] eq "/"} {
    return 1
  }
  return [dict exists $dict {*}$path .]
}
::clay::PROC ::clay::tree::print {dict} {
  ::set result {}
  ::set level -1
  ::clay::tree::_dictputb $level result $dict
  return $result
}
::clay::PROC ::clay::tree::_dictputb {level varname dict} {
  upvar 1 $varname result
  incr level
  dict for {field value} $dict {
    if {$field eq "."} continue
    if {[clay::tree::is_branch $dict $field]} {
      putb result "[string repeat "  " $level]$field \{"
      _dictputb $level result $value
      putb result "[string repeat "  " $level]\}"
    } else {
      putb result "[string repeat "  " $level][list $field $value]"
    }
  }
}
proc ::clay::tree::sanitize {dict} {
  ::set result {}
  ::set level -1
  ::clay::tree::_sanitizeb {} result $dict
  return $result
}
proc ::clay::tree::_sanitizeb {path varname dict} {
  upvar 1 $varname result
  dict for {field value} $dict {
    if {$field eq "."} continue
    if {[clay::tree::is_branch $dict $field]} {
      _sanitizeb [list {*}$path $field] result $value
    } else {
      dict set result {*}$path $field $value
    }
  }
}
proc ::clay::tree::storage {rawpath} {
  set isleafvar 0
  set path {}
  set tail [string index $rawpath end]
  foreach element $rawpath {
    set items [split [string trim $element /] /]
    foreach item $items {
      if {$item eq {}} continue
      lappend path $item
    }
  }
  return $path
}
proc ::clay::tree::dictset {varname args} {
  upvar 1 $varname result
  if {[llength $args] < 2} {
    error "Usage: ?path...? path value"
  } elseif {[llength $args]==2} {
    set rawpath [lindex $args 0]
  } else {
    set rawpath  [lrange $args 0 end-1]
  }
  set value [lindex $args end]
  set path [storage $rawpath]
  set dot .
  set one {}
  dict set result $dot $one
  set dpath {}
  foreach item [lrange $path 0 end-1] {
    set field $item
    lappend dpath [string trim $item /]
    dict set result {*}$dpath $dot $one
  }
  set field [lindex $rawpath end]
  set ext   [string index $field end]
  if {$ext eq {:} || ![dict is_dict $value]} {
    dict set result {*}$path $value
    return
  }
  if {$ext eq {/} && ![dict exists $result {*}$path $dot]} {
    dict set result {*}$path $dot $one
  }
  if {[dict exists $result {*}$path $dot]} {
    dict set result {*}$path [::clay::tree::merge [dict get $result {*}$path] $value]
    return
  }
  dict set result {*}$path $value
}
proc ::clay::tree::dictmerge {varname args} {
  upvar 1 $varname result
  set dot .
  set one {}
  dict set result $dot $one
  foreach dict $args {
    dict for {f v} $dict {
      set field [string trim $f /]
      set bbranch [clay::tree::is_branch $dict $f]
      if {![dict exists $result $field]} {
        dict set result $field $v
        if {$bbranch} {
          dict set result $field [clay::tree::merge $v]
        } else {
          dict set result $field $v
        }
      } elseif {[dict exists $result $field $dot]} {
        if {$bbranch} {
          dict set result $field [clay::tree::merge [dict get $result $field] $v]
        } else {
          dict set result $field $v
        }
      }
    }
  }
  return $result
}
proc ::clay::tree::merge {args} {
  ###
  # The result of a merge is always a dict with branches
  ###
  set dot .
  set one {}
  dict set result $dot $one
  set argument 0
  foreach b $args {
    # Merge b into a, and handle nested dicts appropriately
    if {![dict is_dict $b]} {
      error "Element $b is not a dictionary"
    }
    dict for { k v } $b {
      if {$k eq $dot} {
        dict set result $dot $one
        continue
      }
      set bbranch [is_branch $b $k]
      set field [string trim $k /]
      if { ![dict exists $result $field] } {
        if {$bbranch} {
          dict set result $field [merge $v]
        } else {
          dict set result $field $v
        }
      } else {
        set abranch [dict exists $result $field $dot]
        if {$abranch && $bbranch} {
          dict set result $field [merge [dict get $result $field] $v]
        } else {
          dict set result $field $v
          if {$bbranch} {
            dict set result $field $dot $one
          }
        }
      }
    }
  }
  return $result
}
::clay::PROC ::tcl::dict::isnull {dictionary args} {
  if {![exists $dictionary {*}$args]} {return 1}
  return [expr {[get $dictionary {*}$args] in {{} NULL null}}]
} {
  namespace ensemble configure dict -map [dict replace\
      [namespace ensemble configure dict -map] isnull ::tcl::dict::isnull]
}
::clay::PROC ::clay::ladd {varname args} {
  upvar 1 $varname var
  if ![info exists var] {
      set var {}
  }
  foreach item $args {
    if {$item in $var} continue
    lappend var $item
  }
  return $var
}
::clay::PROC ::clay::ldelete {varname args} {
  upvar 1 $varname var
  if ![info exists var] {
      return
  }
  foreach item [lsort -unique $args] {
    while {[set i [lsearch $var $item]]>=0} {
      set var [lreplace $var $i $i]
    }
  }
  return $var
}
::clay::PROC ::clay::lrandom list {
  set len [llength $list]
  set idx [expr int(rand()*$len)]
  return [lindex $list $idx]
}
namespace eval ::dictargs {
}
if {[info commands ::dictargs::parse] eq {}} {
  proc ::dictargs::parse {argdef argdict} {
    set result {}
    dict for {field info} $argdef {
      if {![string is alnum [string index $field 0]]} {
        error "$field is not a simple variable name"
      }
      upvar 1 $field _var
      set aliases {}
      if {[dict exists $argdict $field]} {
        set _var [dict get $argdict $field]
        continue
      }
      if {[dict exists $info aliases:]} {
        set found 0
        foreach {name} [dict get $info aliases:] {
          if {[dict exists $argdict $name]} {
            set _var [dict get $argdict $name]
            set found 1
            break
          }
        }
        if {$found} continue
      }
      if {[dict exists $info default:]} {
        set _var [dict get $info default:]
        continue
      }
      set mandatory 1
      if {[dict exists $info mandatory:]} {
        set mandatory [dict get $info mandatory:]
      }
      if {$mandatory} {
        error "$field is required"
      }
    }
  }
}
proc ::dictargs::proc {name argspec body} {
  set result {}
  append result "::dictargs::parse \{$argspec\} \$args" \;
  append result $body
  uplevel 1 [list ::proc $name [list [list args [list dictargs $argspec]]] $result]
}
proc ::dictargs::method {name argspec body} {
  set class [lindex [::info level -1] 1]
  set result {}
  append result "::dictargs::parse \{$argspec\} \$args" \;
  append result $body
  oo::define $class method $name [list [list args [list dictargs $argspec]]] $result
}
namespace eval ::clay::dialect {
  namespace export create
  foreach {flag test} {
    tip470 {package vsatisfies [package provide Tcl] 8.7}
  } {
    if {![info exists ::clay::dialect::has($flag)]} {
      set ::clay::dialect::has($flag) [eval $test]
    }
  }
}
proc ::clay::dialect::Push {class} {
  ::variable class_stack
  lappend class_stack $class
}
proc ::clay::dialect::Peek {} {
  ::variable class_stack
  return [lindex $class_stack end]
}
proc ::clay::dialect::Pop {} {
  ::variable class_stack
  set class_stack [lrange $class_stack 0 end-1]
}
if {$::clay::dialect::has(tip470)} {
proc ::clay::dialect::current_class {} {
  return [uplevel 1 self]
}
} else {
proc ::clay::dialect::current_class {} {
  tailcall Peek
}
}
proc ::clay::dialect::create {name {parent ""}} {
  variable has
  set NSPACE [NSNormalize [uplevel 1 {namespace current}] $name]
  ::namespace eval $NSPACE {::namespace eval define {}}
  ###
  # Build the "define" namespace
  ###

  if {$parent eq ""} {
    ###
    # With no "parent" language, begin with all of the keywords in
    # oo::define
    ###
    foreach command [info commands ::oo::define::*] {
      set procname [namespace tail $command]
      interp alias {} ${NSPACE}::define::$procname {} \
        ::clay::dialect::DefineThunk $procname
    }
    # Create an empty dynamic_methods proc
    proc ${NSPACE}::dynamic_methods {class} {}
    namespace eval $NSPACE {
      ::namespace export dynamic_methods
      ::namespace eval define {::namespace export *}
    }
    set ANCESTORS {}
  } else {
    ###
    # If we have a parent language, that language already has the
    # [oo::define] keywords as well as additional keywords and behaviors.
    # We should begin with that
    ###
    set pnspace [NSNormalize [uplevel 1 {namespace current}] $parent]
    apply [list parent {
      ::namespace export dynamic_methods
      ::namespace import -force ${parent}::dynamic_methods
    } $NSPACE] $pnspace

    apply [list parent {
      ::namespace import -force ${parent}::define::*
      ::namespace export *
    } ${NSPACE}::define] $pnspace
      set ANCESTORS [list ${pnspace}::object]
  }
  ###
  # Build our dialect template functions
  ###
  proc ${NSPACE}::define {oclass args} [string map [list %NSPACE% $NSPACE] {
  ###
  # To facilitate library reloading, allow
  # a dialect to create a class from DEFINE
  ###
  set class [::clay::dialect::NSNormalize [uplevel 1 {namespace current}] $oclass]
    if {[info commands $class] eq {}} {
      %NSPACE%::class create $class {*}${args}
    } else {
      ::clay::dialect::Define %NSPACE% $class {*}${args}
    }
}]
  interp alias {} ${NSPACE}::define::current_class {} \
    ::clay::dialect::current_class
  interp alias {} ${NSPACE}::define::aliases {} \
    ::clay::dialect::Aliases $NSPACE
  interp alias {} ${NSPACE}::define::superclass {} \
    ::clay::dialect::SuperClass $NSPACE

  if {[info command ${NSPACE}::class] ne {}} {
    ::rename ${NSPACE}::class {}
  }
  ###
  # Build the metaclass for our language
  ###
  ::oo::class create ${NSPACE}::class {
    superclass ::clay::dialect::MotherOfAllMetaClasses
  }
  # Wire up the create method to add in the extra argument we need; the
  # MotherOfAllMetaClasses will know what to do with it.
  ::oo::objdefine ${NSPACE}::class \
    method create {name {definitionScript ""}} \
      "next \$name [list ${NSPACE}::define] \$definitionScript"

  ###
  # Build the mother of all classes. Note that $ANCESTORS is already
  # guaranteed to be a list in canonical form.
  ###
  uplevel #0 [string map [list %NSPACE% [list $NSPACE] %name% [list $name] %ANCESTORS% $ANCESTORS] {
    %NSPACE%::class create %NSPACE%::object {
     superclass %ANCESTORS%
      # Put MOACish stuff in here
    }
  }]
  if { "${NSPACE}::class" ni $::clay::dialect::core_classes } {
    lappend ::clay::dialect::core_classes "${NSPACE}::class"
  }
  if { "${NSPACE}::object" ni $::clay::dialect::core_classes } {
    lappend ::clay::dialect::core_classes "${NSPACE}::object"
  }
}
proc ::clay::dialect::NSNormalize {namespace qualname} {
  if {![string match ::* $qualname]} {
    set qualname ${namespace}::$qualname
  }
  regsub -all {::+} $qualname "::"
}
proc ::clay::dialect::DefineThunk {target args} {
  tailcall ::oo::define [Peek] $target {*}$args
}
proc ::clay::dialect::Canonical {namespace NSpace class} {
  namespace upvar $namespace cname cname
  #if {[string match ::* $class]} {
  #  return $class
  #}
  if {[info exists cname($class)]} {
    return $cname($class)
  }
  if {[info exists ::clay::dialect::cname($class)]} {
    return $::clay::dialect::cname($class)
  }
  if {[info exists ::clay::dialect::cname(${NSpace}::${class})]} {
    return $::clay::dialect::cname(${NSpace}::${class})
  }
  foreach item [list "${NSpace}::$class" "::$class"] {
    if {[info commands $item] ne {}} {
      return $item
    }
  }
  return ${NSpace}::$class
}
proc ::clay::dialect::Define {namespace class args} {
  Push $class
  try {
  	if {[llength $args]==1} {
      namespace eval ${namespace}::define [lindex $args 0]
    } else {
      ${namespace}::define::[lindex $args 0] {*}[lrange $args 1 end]
    }
  	${namespace}::dynamic_methods $class
  } finally {
    Pop
  }
}
proc ::clay::dialect::Aliases {namespace args} {
  set class [Peek]
  namespace upvar $namespace cname cname
  set NSpace [join [lrange [split $class ::] 1 end-2] ::]
  set cname($class) $class
  foreach name $args {
    set cname($name) $class
    #set alias $name
    set alias [NSNormalize $NSpace $name]
    # Add a local metaclass reference
    if {![info exists ::clay::dialect::cname($alias)]} {
      lappend ::clay::dialect::aliases($class) $alias
      ##
      # Add a global reference, first come, first served
      ##
      set ::clay::dialect::cname($alias) $class
    }
  }
}
proc ::clay::dialect::SuperClass {namespace args} {
  set class [Peek]
  namespace upvar $namespace class_info class_info
  dict set class_info($class) superclass 1
  set ::clay::dialect::cname($class) $class
  set NSpace [join [lrange [split $class ::] 1 end-2] ::]
  set unique {}
  foreach item $args {
    set Item [Canonical $namespace $NSpace $item]
    dict set unique $Item $item
  }
  set root ${namespace}::object
  if {$class ne $root} {
    dict set unique $root $root
  }
  tailcall ::oo::define $class superclass {*}[dict keys $unique]
}
if {[info command ::clay::dialect::MotherOfAllMetaClasses] eq {}} {
::oo::class create ::clay::dialect::MotherOfAllMetaClasses {
  superclass ::oo::class
  constructor {define definitionScript} {
    $define [self] {
      superclass
    }
    $define [self] $definitionScript
  }
  method aliases {} {
    if {[info exists ::clay::dialect::aliases([self])]} {
      return $::clay::dialect::aliases([self])
    }
  }
}
}
namespace eval ::clay::dialect {
  variable core_classes {::oo::class ::oo::object}
}
::clay::dialect::create ::clay
proc ::clay::dynamic_methods class {
  foreach command [info commands [namespace current]::dynamic_methods_*] {
    $command $class
  }
}
proc ::clay::dynamic_methods_class {thisclass} {
  set methods {}
  set mdata [$thisclass clay find class_typemethod]
  foreach {method info} $mdata {
    if {$method eq {.}} continue
    set method [string trimright $method :/-]
    if {$method in $methods} continue
    lappend methods $method
    set arglist [dict getnull $info arglist]
    set body    [dict getnull $info body]
    ::oo::objdefine $thisclass method $method $arglist $body
  }
}
proc ::clay::define::Array {name {values {}}} {
  set class [current_class]
  set name [string trim $name :/]
  $class clay branch array $name
  dict for {var val} $values {
    $class clay set array/ $name $var $val
  }
}
proc ::clay::define::Delegate {name info} {
  set class [current_class]
  foreach {field value} $info {
    $class clay set component/ [string trim $name :/]/ $field $value
  }
}
proc ::clay::define::constructor {arglist rawbody} {
  set body {
my variable DestroyEvent
set DestroyEvent 0
::clay::object_create [self] [info object class [self]]
# Initialize public variables and options
my InitializePublic
  }
  append body $rawbody
  set class [current_class]
  ::oo::define $class constructor $arglist $body
}
proc ::clay::define::Class_Method {name arglist body} {
  set class [current_class]
  $class clay set class_typemethod/ [string trim $name :/] [dict create arglist $arglist body $body]
}
proc ::clay::define::class_method {name arglist body} {
  set class [current_class]
  $class clay set class_typemethod/ [string trim $name :/] [dict create arglist $arglist body $body]
}
proc ::clay::define::clay {args} {
  set class [current_class]
  if {[lindex $args 0] in "cget set branch"} {
    $class clay {*}$args
  } else {
    $class clay set {*}$args
  }
}
proc ::clay::define::destructor rawbody {
  set body {
# Run the destructor once and only once
set self [self]
my variable DestroyEvent
if {$DestroyEvent} return
set DestroyEvent 1
}
  append body $rawbody
  ::oo::define [current_class] destructor $body
}
proc ::clay::define::Dict {name {values {}}} {
  set class [current_class]
  set name [string trim $name :/]
  $class clay branch dict $name
  foreach {var val} $values {
    $class clay set dict/ $name/ $var $val
  }
}
proc ::clay::define::Option {name args} {
  set class [current_class]
  set dictargs {default {}}
  foreach {var val} [::clay::args_to_dict {*}$args] {
    dict set dictargs [string trim $var -:/] $val
  }
  set name [string trimleft $name -]

  ###
  # Option Class handling
  ###
  set optclass [dict getnull $dictargs class]
  if {$optclass ne {}} {
    foreach {f v} [$class clay find option_class $optclass] {
      if {![dict exists $dictargs $f]} {
        dict set dictargs $f $v
      }
    }
    if {$optclass eq "variable"} {
      variable $name [dict getnull $dictargs default]
    }
  }
  foreach {f v} $dictargs {
    $class clay set option $name $f $v
  }
}
proc ::clay::define::Method {name argstyle argspec body} {
  set class [current_class]
  set result {}
  switch $argstyle {
    dictargs {
      append result "::dictargs::parse \{$argspec\} \$args" \;
    }
  }
  append result $body
  oo::define $class method $name [list [list args [list dictargs $argspec]]] $result
}
proc ::clay::define::Option_Class {name args} {
  set class [current_class]
  set dictargs {default {}}
  set name [string trimleft $name -:]
  foreach {f v} [::clay::args_to_dict {*}$args] {
    $class clay set option_class $name [string trim $f -/:] $v
  }
}
proc ::clay::define::Variable {name {default {}}} {
  set class [current_class]
  set name [string trimright $name :/]
  $class clay set variable/ $name $default
}
::namespace eval ::clay::define {
}
proc ::clay::ensemble_methodbody {ensemble einfo} {
  set default standard
  set preamble {}
  set eswitch {}
  set Ensemble [string totitle $ensemble]
  if {$Ensemble eq "."} continue
  foreach {msubmethod minfo} [lsort -dictionary -stride 2 $einfo] {
    if {$msubmethod eq "."} continue
    if {![dict exists $minfo body:]} {
      continue
    }
    set submethod [string trim $msubmethod :/-]
    if {$submethod eq "default"} {
      set default [dict get $minfo body:]
    } else {
      dict set eswitch $submethod [dict get $minfo body:]
    }
    if {[dict exists $submethod aliases:]} {
      foreach alias [dict get $minfo aliases:] {
        if {![dict exists $eswitch $alias]} {
          dict set eswitch $alias [dict get $minfo body:]
        }
      }
    }
  }
  set methodlist [lsort -dictionary [dict keys $eswitch]]
  if {![dict exists $eswitch <list>]} {
    dict set eswitch <list> {return $methodlist}
  }
  if {$default eq "standard"} {
    set default "error \"unknown method $ensemble \$method. Valid: \$methodlist\""
  }
  dict set eswitch default $default
  set mbody {}
  append mbody \n [list set methodlist $methodlist]
  append mbody \n "switch -- \$method \{$eswitch\}" \n
  return $mbody
}
::proc ::clay::define::Ensemble {rawmethod args} {
  if {[llength $args]==2} {
    lassign $args argspec body
    set argstyle tcl
  } elseif {[llength $args]==3} {
    lassign $args argstyle argspec body
  } else {
    error "Usage: Ensemble name ?argstyle? argspec body"
  }
  set class [current_class]
  #if {$::clay::trace>2} {
  #  puts [list $class Ensemble $rawmethod $argspec $body]
  #}
  set mlist [split $rawmethod "::"]
  set ensemble [string trim [lindex $mlist 0] :/]
  set method   [string trim [lindex $mlist 2] :/]
  if {[string index $method 0] eq "_"} {
    $class clay set method_ensemble $ensemble $method $body
    return
  }
  set realmethod  [string totitle $ensemble]_${method}
  set realbody {}
  if {$argstyle eq "dictargs"} {
    append realbody "::dictargs::parse \{$argspec\} \$args" \n
  }
  if {[$class clay exists method_ensemble $ensemble _preamble]} {
    append realbody [$class clay get method_ensemble $ensemble _preamble] \n
  }
  append realbody $body
  if {$method eq "default"} {
    $class clay set method_ensemble $ensemble $method: "tailcall my $realmethod \$method {*}\$args"
    if {$argstyle eq "dictargs"} {
      oo::define $class method $realmethod [list method [list args $argspec]] $realbody
    } else {
      oo::define $class method $realmethod [list method {*}$argspec] $realbody
    }
  } else {
    $class clay set method_ensemble $ensemble $method: "tailcall my $realmethod {*}\$args"
    if {$argstyle eq "dictargs"} {
      oo::define $class method $realmethod [list [list args $argspec]] $realbody
    } else {
      oo::define $class method $realmethod $argspec $realbody
    }
  }
  if {$::clay::trace>2} {
    puts [list $class clay set method_ensemble/ $ensemble [string trim $method :/]  ...]
  }
}
::oo::define ::clay::class {
  method clay {submethod args} {
    my variable clay
    if {![info exists clay]} {
      set clay {}
    }
    switch $submethod {
      ancestors {
        tailcall ::clay::ancestors [self]
      }
      branch {
        set path [::clay::tree::storage $args]
        if {![dict exists $clay {*}$path .]} {
          dict set clay {*}$path . {}
        }
      }
      exists {
        if {![info exists clay]} {
          return 0
        }
        set path [::clay::tree::storage $args]
        if {[dict exists $clay {*}$path]} {
          return 1
        }
        if {[dict exists $clay {*}[lrange $path 0 end-1] [lindex $path end]:]} {
          return 1
        }
        return 0
      }
      dump {
        return $clay
      }
      dget {
         if {![info exists clay]} {
          return {}
        }
        set path [::clay::tree::storage $args]
        if {[dict exists $clay {*}$path]} {
          return [dict get $clay {*}$path]
        }
        if {[dict exists $clay {*}[lrange $path 0 end-1] [lindex $path end]:]} {
          return [dict get $clay {*}[lrange $path 0 end-1] [lindex $path end]:]
        }
        return {}
      }
      is_branch {
        set path [::clay::tree::storage $args]
        return [dict exists $clay {*}$path .]
      }
      getnull -
      get {
        if {![info exists clay]} {
          return {}
        }
        set path [::clay::tree::storage $args]
        if {[llength $path]==0} {
          return $clay
        }
        if {[dict exists $clay {*}$path .]} {
          return [::clay::tree::sanitize [dict get $clay {*}$path]]
        }
        if {[dict exists $clay {*}$path]} {
          return [dict get $clay {*}$path]
        }
        if {[dict exists $clay {*}[lrange $path 0 end-1] [lindex $path end]:]} {
          return [dict get $clay {*}[lrange $path 0 end-1] [lindex $path end]:]
        }
        return {}
      }
      find {
        set path [::clay::tree::storage $args]
        if {![info exists clay]} {
          set clay {}
        }
        set clayorder [::clay::ancestors [self]]
        set found 0
        if {[llength $path]==0} {
          set result [dict create . {}]
          foreach class $clayorder {
            ::clay::tree::dictmerge result [$class clay dump]
          }
          return [::clay::tree::sanitize $result]
        }
        foreach class $clayorder {
          if {[$class clay exists {*}$path .]} {
            # Found a branch break
            set found 1
            break
          }
          if {[$class clay exists {*}$path]} {
            # Found a leaf. Return that value immediately
            return [$class clay get {*}$path]
          }
          if {[dict exists $clay {*}[lrange $path 0 end-1] [lindex $path end]:]} {
            return [dict get $clay {*}[lrange $path 0 end-1] [lindex $path end]:]
          }
        }
        if {!$found} {
          return {}
        }
        set result {}
        # Leaf searches return one data field at a time
        # Search in our local dict
        # Search in the in our list of classes for an answer
        foreach class [lreverse $clayorder] {
          ::clay::tree::dictmerge result [$class clay dget {*}$path]
        }
        return [::clay::tree::sanitize $result]
      }
      merge {
        foreach arg $args {
          ::clay::tree::dictmerge clay {*}$arg
        }
      }
      noop {
        # Do nothing. Used as a sign of clay savviness
      }
      search {
        foreach aclass [::clay::ancestors [self]] {
          if {[$aclass clay exists {*}$args]} {
            return [$aclass clay get {*}$args]
          }
        }
      }
      set {
        ::clay::tree::dictset clay {*}$args
      }
      unset {
        dict unset clay {*}$args
      }
      default {
        dict $submethod clay {*}$args
      }
    }
  }
}
::oo::define ::clay::object {
  method clay {submethod args} {
    my variable clay claycache clayorder config option_canonical
    if {![info exists clay]} {set clay {}}
    if {![info exists claycache]} {set claycache {}}
    if {![info exists config]} {set config {}}
    if {![info exists clayorder] || [llength $clayorder]==0} {
      set clayorder {}
      if {[dict exists $clay cascade]} {
        dict for {f v} [dict get $clay cascade] {
          if {$f eq "."} continue
          if {[info commands $v] ne {}} {
            lappend clayorder $v
          }
        }
      }
      lappend clayorder {*}[::clay::ancestors [info object class [self]] {*}[lreverse [info object mixins [self]]]]
    }
    switch $submethod {
      ancestors {
        return $clayorder
      }
      branch {
        set path [::clay::tree::storage $args]
        if {![dict exists $clay {*}$path .]} {
          dict set clay {*}$path . {}
        }
      }
      busy {
        my variable clay_busy
        if {[llength $args]} {
          set clay_busy [string is true [lindex $args 0]]
          set claycache {}
        }
        if {![info exists clay_busy]} {
          set clay_busy 0
        }
        return $clay_busy
      }
      cache {
        set path [lindex $args 0]
        set value [lindex $args 1]
        dict set claycache $path $value
      }
      cget {
        # Leaf searches return one data field at a time
        # Search in our local dict
        if {[llength $args]==1} {
          set field [string trim [lindex $args 0] -:/]
          if {[info exists option_canonical($field)]} {
            set field $option_canonical($field)
          }
          if {[dict exists $config $field]} {
            return [dict get $config $field]
          }
        }
        set path [::clay::tree::storage $args]
        if {[dict exists $clay {*}$path]} {
          return [dict get $clay {*}$path]
        }
        # Search in our local cache
        if {[dict exists $claycache {*}$path]} {
          if {[dict exists $claycache {*}$path .]} {
            return [dict remove [dict get $claycache {*}$path] .]
          } else {
            return [dict get $claycache {*}$path]
          }
        }
        # Search in the in our list of classes for an answer
        foreach class $clayorder {
          if {[$class clay exists {*}$path]} {
            set value [$class clay get {*}$path]
            dict set claycache {*}$path $value
            return $value
          }
          if {[$class clay exists const {*}$path]} {
            set value [$class clay get const {*}$path]
            dict set claycache {*}$path $value
            return $value
          }
          if {[$class clay exists option {*}$path default]} {
            set value [$class clay get option {*}$path default]
            dict set claycache {*}$path $value
            return $value
          }
        }
        return {}
      }
      delegate {
        if {![dict exists $clay .delegate <class>]} {
          dict set clay .delegate <class> [info object class [self]]
        }
        if {[llength $args]==0} {
          return [dict get $clay .delegate]
        }
        if {[llength $args]==1} {
          set stub <[string trim [lindex $args 0] <>]>
          if {![dict exists $clay .delegate $stub]} {
            return {}
          }
          return [dict get $clay .delegate $stub]
        }
        if {([llength $args] % 2)} {
          error "Usage: delegate
    OR
    delegate stub
    OR
    delegate stub OBJECT ?stub OBJECT? ..."
        }
        foreach {stub object} $args {
          set stub <[string trim $stub <>]>
          dict set clay .delegate $stub $object
          oo::objdefine [self] forward ${stub} $object
          oo::objdefine [self] export ${stub}
        }
      }
      dump {
        # Do a full dump of clay data
        set result {}
        # Search in the in our list of classes for an answer
        foreach class $clayorder {
          ::clay::tree::dictmerge result [$class clay dump]
        }
        ::clay::tree::dictmerge result $clay
        return $result
      }
      ensemble_map {
        set path [::clay::tree::storage method_ensemble]
        if {[dict exists $claycache {*}$path]} {
          return [dict get $claycache {*}$path]
        }
        set emap {}
        foreach class $clayorder {
          if {![$class clay exists {*}$path .]} continue
          dict for {ensemble einfo} [$class clay dget {*}$path] {
            if {$ensemble eq "."} continue
            dict for {method body} $einfo {
              if {$method eq "."} continue
              dict set emap $ensemble $method class: $class
              dict set emap $ensemble $method body: $body
            }
          }
        }
        if {[dict exists $clay {*}$path]} {
          dict for {ensemble einfo} [dict get $clay {*}$path] {
            dict for {method body} $einfo {
              if {$method eq "."} continue
              dict set emap $ensemble $method class: $class
              dict set emap $ensemble $method body: $body
            }
          }
        }
        dict set claycache {*}$path $emap
        return $emap
      }
      eval {
        set script [lindex $args 0]
        set buffer {}
        set thisline {}
        foreach line [split $script \n] {
          append thisline $line
          if {![info complete $thisline]} {
            append thisline \n
            continue
          }
          set thisline [string trim $thisline]
          if {[string index $thisline 0] eq "#"} continue
          if {[string length $thisline]==0} continue
          if {[lindex $thisline 0] eq "my"} {
            # Line already calls out "my", accept verbatim
            append buffer $thisline \n
          } elseif {[string range $thisline 0 2] eq "::"} {
            # Fully qualified commands accepted verbatim
            append buffer $thisline \n
          } elseif {
            append buffer "my $thisline" \n
          }
          set thisline {}
        }
        eval $buffer
      }
      evolve -
      initialize {
        my InitializePublic
      }
      exists {
        # Leaf searches return one data field at a time
        # Search in our local dict
        set path [::clay::tree::storage $args]
        if {[dict exists $clay {*}$path]} {
          return 1
        }
        # Search in our local cache
        if {[dict exists $claycache {*}$path]} {
          return 2
        }
        set count 2
        # Search in the in our list of classes for an answer
        foreach class $clayorder {
          incr count
          if {[$class clay exists {*}$path]} {
            return $count
          }
        }
        return 0
      }
      flush {
        set claycache {}
        set clayorder [::clay::ancestors [info object class [self]] {*}[lreverse [info object mixins [self]]]]
      }
      forward {
        oo::objdefine [self] forward {*}$args
      }
      dget {
        set path [::clay::tree::storage $args]
        if {[llength $path]==0} {
          # Do a full dump of clay data
          set result {}
          # Search in the in our list of classes for an answer
          foreach class $clayorder {
            ::clay::tree::dictmerge result [$class clay dump]
          }
          ::clay::tree::dictmerge result $clay
          return $result
        }
        if {[dict exists $clay {*}$path] && ![dict exists $clay {*}$path .]} {
          # Path is a leaf
          return [dict get $clay {*}$path]
        }
        # Search in our local cache
        if {[my clay search $path value isleaf]} {
          return $value
        }

        set found 0
        set branch [dict exists $clay {*}$path .]
        foreach class $clayorder {
          if {[$class clay exists {*}$path .]} {
            set found 1
            break
          }
          if {!$branch && [$class clay exists {*}$path]} {
            set result [$class clay dget {*}$path]
            my clay cache $path $result
            return $result
          }
        }
        # Path is a branch
        set result [dict getnull $clay {*}$path]
        foreach class $clayorder {
          if {![$class clay exists {*}$path .]} continue
          ::clay::tree::dictmerge result [$class clay dget {*}$path]
        }
        #if {[dict exists $clay {*}$path .]} {
        #  ::clay::tree::dictmerge result
        #}
        my clay cache $path $result
        return $result
      }
      getnull -
      get {
        set path [::clay::tree::storage $args]
        if {[llength $path]==0} {
          # Do a full dump of clay data
          set result {}
          # Search in the in our list of classes for an answer
          foreach class $clayorder {
            ::clay::tree::dictmerge result [$class clay dump]
          }
          ::clay::tree::dictmerge result $clay
          return [::clay::tree::sanitize $result]
        }
        if {[dict exists $clay {*}$path] && ![dict exists $clay {*}$path .]} {
          # Path is a leaf
          return [dict get $clay {*}$path]
        }
        # Search in our local cache
        if {[my clay search $path value isleaf]} {
          if {!$isleaf} {
            return [clay::tree::sanitize $value]
          } else {
            return $value
          }
        }
        set found 0
        set branch [dict exists $clay {*}$path .]
        foreach class $clayorder {
          if {[$class clay exists {*}$path .]} {
            set found 1
            break
          }
          if {!$branch && [$class clay exists {*}$path]} {
            set result [$class clay dget {*}$path]
            my clay cache $path $result
            return $result
          }
        }
        # Path is a branch
        set result [dict getnull $clay {*}$path]
        #foreach class [lreverse $clayorder] {
        #  if {![$class clay exists {*}$path .]} continue
        #  ::clay::tree::dictmerge result [$class clay dget {*}$path]
        #}
        foreach class $clayorder {
          if {![$class clay exists {*}$path .]} continue
          ::clay::tree::dictmerge result [$class clay dget {*}$path]
        }
        #if {[dict exists $clay {*}$path .]} {
        #  ::clay::tree::dictmerge result [dict get $clay {*}$path]
        #}
        my clay cache $path $result
        return [clay::tree::sanitize $result]
      }
      leaf {
        # Leaf searches return one data field at a time
        # Search in our local dict
        set path [::clay::tree::storage $args]
        if {[dict exists $clay {*}$path .]} {
          return [clay::tree::sanitize [dict get $clay {*}$path]]
        }
        if {[dict exists $clay {*}$path]} {
          return [dict get $clay {*}$path]
        }
        # Search in our local cache
        if {[my clay search $path value isleaf]} {
          if {!$isleaf} {
            return [clay::tree::sanitize $value]
          } else {
            return $value
          }
        }
        # Search in the in our list of classes for an answer
        foreach class $clayorder {
          if {[$class clay exists {*}$path]} {
            set value [$class clay get {*}$path]
            my clay cache $path $value
            return $value
          }
        }
      }
      merge {
        foreach arg $args {
          ::clay::tree::dictmerge clay {*}$arg
        }
      }
      mixin {
        ###
        # Mix in the class
        ###
        my clay flush
        set prior  [info object mixins [self]]
        set newmixin {}
        foreach item $args {
          lappend newmixin ::[string trimleft $item :]
        }
        set newmap $args
        foreach class $prior {
          if {$class ni $newmixin} {
            set script [$class clay search mixin/ unmap-script]
            if {[string length $script]} {
              if {[catch $script err errdat]} {
                puts stderr "[self] MIXIN ERROR POPPING $class:\n[dict get $errdat -errorinfo]"
              }
            }
          }
        }
        ::oo::objdefine [self] mixin {*}$args
        ###
        # Build a compsite map of all ensembles defined by the object's current
        # class as well as all of the classes being mixed in
        ###
        my InitializePublic
        foreach class $newmixin {
          if {$class ni $prior} {
            set script [$class clay search mixin/ map-script]
            if {[string length $script]} {
              if {[catch $script err errdat]} {
                puts stderr "[self] MIXIN ERROR PUSHING $class:\n[dict get $errdat -errorinfo]"
              }
            }
          }
        }
        foreach class $newmixin {
          set script [$class clay search mixin/ react-script]
          if {[string length $script]} {
            if {[catch $script err errdat]} {
              puts stderr "[self] MIXIN ERROR PEEKING $class:\n[dict get $errdat -errorinfo]"
            }
            break
          }
        }
      }
      mixinmap {
        if {![dict exists $clay .mixin]} {
          dict set clay .mixin {}
        }
        if {[llength $args]==0} {
          return [dict get $clay .mixin]
        } elseif {[llength $args]==1} {
          return [dict getnull $clay .mixin [lindex $args 0]]
        } else {
          dict for {slot classes} $args {
            dict set clay .mixin $slot $classes
          }
          set classlist {}
          dict for {item class} [dict get $clay .mixin] {
            if {$class ne {}} {
              lappend classlist $class
            }
          }
          my clay mixin {*}[lreverse $classlist]
        }
      }
      provenance {
        if {[dict exists $clay {*}$args]} {
          return self
        }
        foreach class $clayorder {
          if {[$class clay exists {*}$args]} {
            return $class
          }
        }
        return {}
      }
      refcount {
        my variable refcount
        if {![info exists refcount]} {
          return 0
        }
        return $refcount
      }
      refcount_incr {
        my variable refcount
        incr refcount
      }
      refcount_decr {
        my variable refcount
        incr refcount -1
        if {$refcount <= 0} {
          ::clay::object_destroy [self]
        }
      }
      replace {
        set clay [lindex $args 0]
      }
      search {
        set path [lindex $args 0]
        upvar 1 [lindex $args 1] value [lindex $args 2] isleaf
        set isleaf [expr {![dict exists $claycache $path .]}]
        if {[dict exists $claycache $path]} {
          set value [dict get $claycache $path]
          return 1
        }
        return 0
      }
      source {
        source [lindex $args 0]
      }
      set {
        #puts [list [self] clay SET {*}$args]
        ::clay::tree::dictset clay {*}$args
      }
      default {
        dict $submethod clay {*}$args
      }
    }
  }
  method InitializePublic {} {
    my variable clayorder clay claycache config option_canonical clay_busy
    if {[info exists clay_busy] && $clay_busy} {
      # Avoid repeated calls to InitializePublic if we know that someone is
      # going to invoke it at the end of whatever process is going on
      return
    }
    set claycache {}
    set clayorder [::clay::ancestors [info object class [self]] {*}[lreverse [info object mixins [self]]]]
    if {![info exists clay]} {
      set clay {}
    }
    if {![info exists config]} {
      set config {}
    }
    dict for {var value} [my clay get variable] {
      if { $var in {. clay} } continue
      set var [string trim $var :/]
      my variable $var
      if {![info exists $var]} {
        if {$::clay::trace>2} {puts [list initialize variable $var $value]}
        set $var $value
      }
    }
    dict for {var value} [my clay get dict/] {
      if { $var in {. clay} } continue
      set var [string trim $var :/]
      my variable $var
      if {![info exists $var]} {
        set $var {}
      }
      foreach {f v} $value {
        if {$f eq "."} continue
        if {![dict exists ${var} $f]} {
          if {$::clay::trace>2} {puts [list initialize dict $var $f $v]}
          dict set ${var} $f $v
        }
      }
    }
    foreach {var value} [my clay get array/] {
      if { $var in {. clay} } continue
      set var [string trim $var :/]
      if { $var eq {clay} } continue
      my variable $var
      if {![info exists $var]} { array set $var {} }
      foreach {f v} $value {
        if {![array exists ${var}($f)]} {
          if {$f eq "."} continue
          if {$::clay::trace>2} {puts [list initialize array $var\($f\) $v]}
          set ${var}($f) $v
        }
      }
    }
    foreach {field info} [my clay get option/] {
      if { $field in {. clay} } continue
      set field [string trim $field -/:]
      foreach alias [dict getnull $info aliases] {
        set option_canonical($alias) $field
      }
      if {[dict exists $config $field]} continue
      set getcmd [dict getnull $info default-command]
      if {$getcmd ne {}} {
        set value [{*}[string map [list %field% $field %self% [namespace which my]] $getcmd]]
      } else {
        set value [dict getnull $info default]
      }
      dict set config $field $value
      set setcmd [dict getnull $info set-command]
      if {$setcmd ne {}} {
        {*}[string map [list %field% [list $field] %value% [list $value] %self% [namespace which my]] $setcmd]
      }
    }

    foreach {ensemble einfo} [my clay ensemble_map] {
      #if {[dict exists $einfo _body]} continue
      if {$ensemble eq "."} continue
      set body [::clay::ensemble_methodbody $ensemble $einfo]
      if {$::clay::trace>2} {
        set rawbody $body
        set body {puts [list [self] <object> [self method]]}
        append body \n $rawbody
      }
      oo::objdefine [self] method $ensemble {{method default} args} $body
    }
  }
}
::clay::object clay branch array
::clay::object clay branch mixin
::clay::object clay branch option
::clay::object clay branch dict clay
::clay::object clay set variable DestroyEvent 0
proc ::clay::singleton {name script} {
  if {[info commands $name] eq {}} {
    ::clay::object create $name
  }
  oo::objdefine $name {
method SingletonProcs {} {
proc class class {
  uplevel 1 "oo::objdefine \[self\] class $class"
  my clay delegate class $class
}
proc clay args {
  my clay {*}$args
}
proc Ensemble {rawmethod args} {
  if {[llength $args]==2} {
    lassign $args argspec body
    set argstyle tcl
  } elseif {[llength $args]==3} {
    lassign $args argstyle argspec body
  } else {
    error "Usage: Ensemble name ?argstyle? argspec body"
  }
  set class [uplevel 1 self]
  #if {$::clay::trace>2} {
  #  puts [list $class Ensemble $rawmethod $argspec $body]
  #}
  set mlist [split $rawmethod "::"]
  set ensemble [string trim [lindex $mlist 0] :/]
  set method   [string trim [lindex $mlist 2] :/]
  if {[string index $method 0] eq "_"} {
    $class clay set method_ensemble $ensemble $method $body
    return
  }
  set realmethod  [string totitle $ensemble]_${method}
  set realbody {}
  if {$argstyle eq "dictargs"} {
    append realbody "::dictargs::parse \{$argspec\} \$args" \n
  }
  if {[$class clay exists method_ensemble $ensemble _preamble]} {
    append realbody [$class clay get method_ensemble $ensemble _preamble] \n
  }
  append realbody $body
  if {$method eq "default"} {
    $class clay set method_ensemble $ensemble $method: "tailcall my $realmethod \$method {*}\$args"
    if {$argstyle eq "dictargs"} {
      oo::objdefine $class method $realmethod [list method [list args $argspec]] $realbody
    } else {
      oo::objdefine $class method $realmethod [list method {*}$argspec] $realbody
    }
  } else {
    $class clay set method_ensemble $ensemble $method: "tailcall my $realmethod {*}\$args"
    if {$argstyle eq "dictargs"} {
      oo::objdefine $class method $realmethod [list [list args $argspec]] $realbody
    } else {
      oo::objdefine $class method $realmethod $argspec $realbody
    }
  }
  if {$::clay::trace>2} {
    puts [list $class clay set method_ensemble/ $ensemble [string trim $method :/]  ...]
  }
}
proc method args {
  uplevel 1 "oo::objdefine \[self\] method {*}$args"
}
}
method script script {
  my clay busy 1
  my SingletonProcs
  eval $script
  my clay busy 0
  my InitializePublic
}
}
  $name script $script
  return $name
}
namespace eval ::clay {
  namespace export *
}

###
# END: clay/clay.tcl
###
###
# START: setup.tcl
###





package require TclOO



set tcllib_path {}
foreach path {.. ../.. ../../..} {
  foreach path [glob -nocomplain [file join [file normalize $path] tcllib* modules]] {
    set tclib_path $path
    lappend ::auto_path $path
    break
  }
  if {$tcllib_path ne {}} break
}
namespace eval ::practcl {
}
namespace eval ::practcl::OBJECT {
}

###
# END: setup.tcl
###
###
# START: doctool.tcl
###
namespace eval ::practcl {
}
proc ::practcl::cat fname {
    if {![file exists $fname]} {
       return
    }
    set fin [open $fname r]
    set data [read $fin]
    close $fin
    return $data
}
proc ::practcl::docstrip text {
  set result {}
  foreach line [split $text \n] {
    append thisline $line \n
    if {![info complete $thisline]} continue
    set outline $thisline
    set thisline {}
    if {[string trim $outline] eq {}} {
      continue
    }
    if {[string index [string trim $outline] 0] eq "#"} continue
    set cmd [string trim [lindex $outline 0] :]
    if {$cmd eq "namespace" && [lindex $outline 1] eq "eval"} {
      append result [list {*}[lrange $outline 0 end-1]] " " \{ \n [docstrip [lindex $outline end]]\} \n
      continue
    }
    if {[string match "*::define" $cmd] && [llength $outline]==3} {
      append result [list {*}[lrange $outline 0 end-1]] " " \{ \n [docstrip [lindex $outline end]]\} \n
      continue
    }
    if {$cmd eq "oo::class" && [lindex $outline 1] eq "create"} {
      append result [list {*}[lrange $outline 0 end-1]] " " \{ \n [docstrip [lindex $outline end]]\} \n
      continue
    }
    append result $outline
  }
  return $result
}
proc ::putb {buffername args} {
  upvar 1 $buffername buffer
  switch [llength $args] {
    1 {
      append buffer [lindex $args 0] \n
    }
    2 {
      append buffer [string map {*}$args] \n
    }
    default {
      error "usage: putb buffername ?map? string"
    }
  }
}
::oo::class create ::practcl::doctool {
  constructor {} {
    my reset
  }
  method argspec {argspec} {
    set result [dict create]
    foreach arg $argspec {
      set name [lindex $arg 0]
      dict set result $name positional 1
      dict set result $name mandatory  1
      if {$name in {args dictargs}} {
        switch [llength $arg] {
          1 {
            dict set result $name mandatory 0
          }
          2 {
            dict for {optname optinfo} [lindex $arg 1] {
              set optname [string trim $optname -:]
              dict set result $optname {positional 1 mandatory 0}
              dict for {f v} $optinfo {
                dict set result $optname [string trim $f -:] $v
              }
            }
          }
          default {
            error "Bad argument"
          }
        }
      } else {
        switch [llength $arg] {
          1 {
            dict set result $name mandatory 1
          }
          2 {
            dict set result $name mandatory 0
            dict set result $name default   [lindex $arg 1]
          }
          default {
            error "Bad argument"
          }
        }
      }
    }
    return $result
  }
  method comment block {
    set count 0
    set field description
    set result [dict create description {}]
    foreach line [split $block \n] {
      set sline [string trim $line]
      set fwidx [string first " " $sline]
      if {$fwidx < 0} {
        set firstword [string range $sline 0 end]
        set restline {}
      } else {
        set firstword [string range $sline 0 [expr {$fwidx-1}]]
        set restline [string range $sline [expr {$fwidx+1}] end]
      }
      if {[string index $firstword end] eq ":"} {
        set field [string tolower [string trim $firstword -:]]
        switch $field {
          dictargs -
          arglist {
            set field argspec
          }
          desc {
            set field description
          }
        }
        if {[string length $restline]} {
          dict append result $field "$restline\n"
        }
      } else {
        dict append result $field "$line\n"
      }
    }
    return $result
  }
  method keyword.Annotation {resultvar commentblock type name body} {
    upvar 1 $resultvar result
    set name [string trim $name :]
    if {[dict exists $result $type $name]} {
      set info [dict get $result $type $name]
    } else {
      set info [my comment $commentblock]
    }
    foreach {f v} $body {
      dict set info $f $v
    }
    dict set result $type $name $info
  }
  method keyword.Class {resultvar commentblock name body} {
    upvar 1 $resultvar result
    set name [string trim $name :]
    if {[dict exists $result class $name]} {
      set info [dict get $result class $name]
    } else {
      set info [my comment $commentblock]
    }
    set commentblock {}
    foreach line [split $body \n] {
      append thisline $line \n
      if {![info complete $thisline]} continue
      set thisline [string trim $thisline]
      if {[string index $thisline 0] eq "#"} {
        append commentblock [string trimleft $thisline #] \n
        set thisline {}
        continue
      }
      set cmd [string trim [lindex $thisline 0] ":"]
      switch $cmd {
        Option -
        option {
          my keyword.Annotation info $commentblock option [lindex $thisline 1] [lindex $thisline 2]
          set commentblock {}
        }
        variable -
        Variable {
          my keyword.Annotation info $commentblock variable [lindex $thisline 1] [list type scaler default [lindex $thisline 2]]
          set commentblock {}
        }
        Dict -
        Array {
          set iinfo [lindex $thisline 2]
          dict set iinfo type [string tolower $cmd]
          my keyword.Annotation info $commentblock variable [lindex $thisline 1] $iinfo
          set commentblock {}
        }
        Componant -
        Delegate {
          my keyword.Annotation info $commentblock delegate [lindex $thisline 1] [lindex $thisline 2]
          set commentblock {}
        }
        method -
        Ensemble {
          my keyword.Class_Method info $commentblock  {*}[lrange $thisline 1 end-1]
          set commentblock {}
        }
      }
      set thisline {}
    }
    dict set result class $name $info
  }
  method keyword.class {resultvar commentblock name body} {
    upvar 1 $resultvar result
    set name [string trim $name :]
    if {[dict exists $result class $name]} {
      set info [dict get $result class $name]
    } else {
      set info [my comment $commentblock]
    }
    set commentblock {}
    foreach line [split $body \n] {
      append thisline $line \n
      if {![info complete $thisline]} continue
      set thisline [string trim $thisline]
      if {[string index $thisline 0] eq "#"} {
        append commentblock [string trimleft $thisline #] \n
        set thisline {}
        continue
      }
      set cmd [string trim [lindex $thisline 0] ":"]
      switch $cmd {
        Option -
        option {
          puts [list keyword.Annotation $cmd $thisline]
          my keyword.Annotation info $commentblock option [lindex $thisline 1] [lindex $thisline 2]
          set commentblock {}
        }
        variable -
        Variable {
          my keyword.Annotation info $commentblock variable [lindex $thisline 1] [list default [lindex $thisline 2]]
          set commentblock {}
        }
        Dict -
        Array {
          set iinfo [lindex $thisline 2]
          dict set iinfo type [string tolower $cmd]
          my keyword.Annotation info $commentblock variable [lindex $thisline 1] $iinfo
          set commentblock {}
        }
        Componant -
        Delegate {
          my keyword.Annotation info $commentblock delegate [lindex $thisline 1] [lindex $thisline 2]
          set commentblock {}
        }
        superclass {
          dict set info ancestors [lrange $thisline 1 end]
          set commentblock {}
        }
        classmethod -
        class_method -
        Class_Method {
          my keyword.Class_Method info $commentblock  {*}[lrange $thisline 1 end-1]
          set commentblock {}
        }
        destructor -
        constructor {
          my keyword.method info $commentblock {*}[lrange $thisline 0 end-1]
          set commentblock {}
        }
        method -
        Ensemble {
          my keyword.method info $commentblock  {*}[lrange $thisline 1 end-1]
          set commentblock {}
        }
      }
      set thisline {}
    }
    dict set result class $name $info
  }
  method keyword.Class_Method {resultvar commentblock name args} {
    upvar 1 $resultvar result
    set info [my comment $commentblock]
    if {[dict exists $info show_body] && [dict get $info show_body]} {
      dict set info internals [lindex $args end]
    }
    if {[dict exists $info ensemble]} {
      dict for {method minfo} [dict get $info ensemble] {
        dict set result Class_Method "${name} $method" $minfo
      }
    } else {
      switch [llength $args] {
        1 {
          set argspec [lindex $args 0]
        }
        0 {
          set argspec dictargs
          #set body [lindex $args 0]
        }
        default {error "could not interpret method $name {*}$args"}
      }
      if {![dict exists $info argspec]} {
        dict set info argspec [my argspec $argspec]
      }
      dict set result Class_Method [string trim $name :] $info
    }
  }
  method keyword.method {resultvar commentblock name args} {
    upvar 1 $resultvar result
    set info [my comment $commentblock]
    if {[dict exists $info show_body] && [dict get $info show_body]} {
      dict set info internals [lindex $args end]
    }
    if {[dict exists $info ensemble]} {
      dict for {method minfo} [dict get $info ensemble] {
        dict set result method "\"${name} $method\"" $minfo
      }
    } else {
      switch [llength $args] {
        1 {
          set argspec [lindex $args 0]
        }
        0 {
          set argspec dictargs
          #set body [lindex $args 0]
        }
        default {error "could not interpret method $name {*}$args"}
      }
      if {![dict exists $info argspec]} {
        dict set info argspec [my argspec $argspec]
      }
      dict set result method "\"[split [string trim $name :] ::]\"" $info
    }
  }
  method keyword.proc {commentblock name argspec} {
    set info [my comment $commentblock]
    if {![dict exists $info argspec]} {
      dict set info argspec [my argspec $argspec]
    }
    return $info
  }
  method reset {} {
    my variable coro
    set coro [info object namespace [self]]::coro
    oo::objdefine [self] forward coro $coro
    if {[info command $coro] ne {}} {
      rename $coro {}
    }
    coroutine $coro {*}[namespace code {my Main}]
  }
  method Main {} {

    my variable info
    set info [dict create]
    yield [info coroutine]
    set thisline {}
    set commentblock {}
    set linec 0
    while 1 {
      set line [yield]
      append thisline $line \n
      if {![info complete $thisline]} continue
      set thisline [string trim $thisline]
      if {[string index $thisline 0] eq "#"} {
        append commentblock [string trimleft $thisline #] \n
        set thisline {}
        continue
      }
      set cmd [string trim [lindex $thisline 0] ":"]
      switch $cmd {
        dictargs::proc {
          set procinfo [my keyword.proc $commentblock [lindex $thisline 1] [list args [list dictargs [lindex $thisline 2]]]]
          if {[dict exists $procinfo show_body] && [dict get $procinfo show_body]} {
            dict set procinfo internals [lindex $thisline end]
          }
          dict set info proc [string trim [lindex $thisline 1] :] $procinfo
          set commentblock {}
        }
        tcllib::PROC -
        PROC -
        Proc -
        proc {
          set procinfo [my keyword.proc $commentblock {*}[lrange $thisline 1 2]]
          if {[dict exists $procinfo show_body] && [dict get $procinfo show_body]} {
            dict set procinfo internals [lindex $thisline end]
          }
          dict set info proc [string trim [lindex $thisline 1] :] $procinfo
          set commentblock {}
        }
        oo::objdefine {
          if {[llength $thisline]==3} {
            lassign $thisline tcmd name body
            my keyword.Class info $commentblock $name $body
          } else {
            puts "Warning: bare oo::define in library"
          }
        }
        oo::define {
          if {[llength $thisline]==3} {
            lassign $thisline tcmd name body
            my keyword.class info $commentblock $name $body
          } else {
            puts "Warning: bare oo::define in library"
          }
        }
        tao::define -
        clay::define -
        tool::define {
          lassign $thisline tcmd name body
          my keyword.class info $commentblock $name $body
          set commentblock {}
        }
        oo::class {
          lassign $thisline tcmd mthd name body
          my keyword.class info $commentblock $name $body
          set commentblock {}
        }
        default {
          if {[lindex [split $cmd ::] end] eq "define"} {
            lassign $thisline tcmd name body
            my keyword.class info $commentblock $name $body
            set commentblock {}
          }
          set commentblock {}
        }
      }
      set thisline {}
    }
  }
  method section.method {keyword method minfo} {
    set result {}
    set line "\[call $keyword \[cmd $method\]"
    if {[dict exists $minfo argspec]} {
      dict for {argname arginfo} [dict get $minfo argspec] {
        set positional 1
        set mandatory  1
        set repeating 0
        dict with arginfo {}
        if {$mandatory==0} {
          append line " \[opt \""
        } else {
          append line " "
        }
        if {$positional} {
          append line "\[arg $argname"
        } else {
          append line "\[option \"$argname"
          if {[dict exists $arginfo type]} {
            append line " \[emph [dict get $arginfo type]\]"
          } else {
            append line " \[emph value\]"
          }
          append line "\""
        }
        append line "\]"
        if {$mandatory==0} {
          if {[dict exists $arginfo default]} {
            append line " \[const \"[dict get $arginfo default]\"\]"
          }
          append line "\"\]"
        }
        if {$repeating} {
          append line " \[opt \[option \"$argname...\"\]\]"
        }
      }
    }
    append line \]
    putb result $line
    if {[dict exists $minfo description]} {
      putb result [dict get $minfo description]
    }
    if {[dict exists $minfo example]} {
      putb result "\[para\]Example: \[example [list [dict get $minfo example]]\]"
    }
    if {[dict exists $minfo internals]} {
      putb result "\[para\]Internals: \[example [list [dict get $minfo internals]]\]"
    }
    return $result
  }
  method section.annotation {type name iinfo} {
    set result "\[call $type \[cmd $name\]\]"
    if {[dict exists $iinfo description]} {
      putb result [dict get $iinfo description]
    }
    if {[dict exists $iinfo example]} {
      putb result "\[para\]Example: \[example [list [dict get $minfo example]]\]"
    }
    return $result
  }
  method section.class {class_name class_info} {
    set result {}
    putb result "\[subsection \{Class  $class_name\}\]"
    if {[dict exists $class_info ancestors]} {
      set line "\[emph \"ancestors\"\]:"
      foreach {c} [dict get $class_info ancestors] {
        append line " \[class [string trim $c :]\]"
      }
      putb result $line
      putb result {[para]}
    }
    dict for {f v} $class_info {
      if {$f in {Class_Method method description ancestors example option variable delegate}} continue
      putb result "\[emph \"$f\"\]: $v"
      putb result {[para]}
    }
    if {[dict exists $class_info example]} {
      putb result "\[example \{[list [dict get $class_info example]]\}\]"
      putb result {[para]}
    }
    if {[dict exists $class_info description]} {
      putb result [dict get $class_info description]
      putb result {[para]}
    }
    dict for {f v} $class_info {
      if {$f ni {option variable delegate}} continue
      putb result "\[class \{[string totitle $f]\}\]"
      #putb result "Methods on the class object itself."
      putb result {[list_begin definitions]}
      dict for {item iinfo} [dict get $class_info $f] {
        putb result [my section.annotation $f $item $iinfo]
      }
      putb result {[list_end]}
      putb result {[para]}
    }
    if {[dict exists $class_info Class_Method]} {
      putb result "\[class \{Class Methods\}\]"
      #putb result "Methods on the class object itself."
      putb result {[list_begin definitions]}
      dict for {method minfo} [dict get $class_info Class_Method] {
        putb result [my section.method classmethod $method $minfo]
      }
      putb result {[list_end]}
      putb result {[para]}
    }
    if {[dict exists $class_info method]} {
      putb result "\[class {Methods}\]"
      putb result {[list_begin definitions]}
      dict for {method minfo} [dict get $class_info method] {
        putb result [my section.method method $method $minfo]
      }
      putb result {[list_end]}
      putb result {[para]}
    }
    return $result
  }
  method section.command {procinfo} {
    set result {}
    putb result "\[section \{Commands\}\]"
    putb result {[list_begin definitions]}
    dict for {method minfo} $procinfo {
      putb result [my section.method proc $method $minfo]
    }
    putb result {[list_end]}
    return $result
  }
  method manpage args {
    my variable info
    set map {%version% 0.0 %module% {Your_Module_Here}}
    set result {}
    set header {}
    set footer {}
    set authors {}
    dict with args {}
    dict set map %keyword% comment
    putb result $map {[%keyword% {-*- tcl -*- doctools manpage}]
[vset PACKAGE_VERSION %version%]
[manpage_begin %module% n [vset PACKAGE_VERSION]]}
    putb result $map $header

    dict for {sec_type sec_info} $info {
      switch $sec_type {
        proc {
          putb result [my section.command $sec_info]
        }
        class {
          putb result "\[section Classes\]"
          dict for {class_name class_info} $sec_info {
            putb result [my section.class $class_name $class_info]
          }
        }
        default {
          putb result "\[section [list $sec_type $sec_name]\]"
          if {[dict exists $sec_info description]} {
            putb result [dict get $sec_info description]
          }
        }
      }
    }
    if {[llength $authors]} {
      putb result {[section AUTHORS]}
      foreach {name email} $authors {
        putb result "$name \[uri mailto:$email\]\[para\]"
      }
    }
    putb result $footer
    putb result {[manpage_end]}
    return $result
  }
  method scan_text {text} {
    my variable linecount coro
    set linecount 0
    foreach line [split $text \n] {
      incr linecount
      $coro $line
    }
  }
  method scan_file {filename} {
    my variable linecount coro
    set fin [open $filename r]
    set linecount 0
    while {[gets $fin line]>=0} {
      incr linecount
      $coro $line
    }
    close $fin
  }
}

###
# END: doctool.tcl
###
###
# START: buildutil.tcl
###



proc Proc {name arglist body} {







  if {[info command $name] ne {}} return
  proc $name $arglist $body
}
Proc ::noop args {}
proc ::practcl::debug args {
  #puts $args
  ::practcl::cputs ::DEBUG_INFO $args
}




proc ::practcl::doexec args {
  puts [list {*}$args]
  exec {*}$args >&@ stdout
}

proc ::practcl::doexec_in {path args} {
  set PWD [pwd]
  cd $path
  puts [list {*}$args]
  exec {*}$args >&@ stdout
  cd $PWD
}

proc ::practcl::dotclexec args {
  puts [list [info nameofexecutable] {*}$args]
  exec [info nameofexecutable] {*}$args >&@ stdout
}

proc ::practcl::domake {path args} {
  set PWD [pwd]
  cd $path
  puts [list *** $path ***]
  puts [list make {*}$args]
  exec make {*}$args >&@ stdout
  cd $PWD
}

proc ::practcl::domake.tcl {path args} {
  set PWD [pwd]
  cd $path
  puts [list *** $path ***]
  puts [list make.tcl {*}$args]
  exec [info nameofexecutable] make.tcl {*}$args >&@ stdout
  cd $PWD
}

proc ::practcl::fossil {path args} {
  set PWD [pwd]
  cd $path
  puts [list {*}$args]
  exec fossil {*}$args >&@ stdout
  cd $PWD
}


proc ::practcl::fossil_status {dir} {
  if {[info exists ::fosdat($dir)]} {
    return $::fosdat($dir)
  }
  set result {
tags experimental
version {}
192
193
194
195
196
197
198
199
200
201
202



203



204
205
206
207
208
209
210
      dict set result tags $tags
      break
    }
  }
  set ::fosdat($dir) $result
  return $result
}

proc ::practcl::os {} {
  return [${::practcl::MAIN} define get TEACUP_OS]
}







if {[::package vcompare $::tcl_version 8.6] < 0} {
  # Approximate ::zipfile::mkzip with exec calls
  proc ::practcl::mkzip {exename barekit vfspath} {
    set path [file dirname [file normalize $exename]]
    set zipfile [file join $path [file rootname $exename].zip]
    file copy -force $barekit $exename
    set pwd [pwd]







<



>
>
>
|
>
>
>







2644
2645
2646
2647
2648
2649
2650

2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
      dict set result tags $tags
      break
    }
  }
  set ::fosdat($dir) $result
  return $result
}

proc ::practcl::os {} {
  return [${::practcl::MAIN} define get TEACUP_OS]
}
proc ::practcl::mkzip {exename barekit vfspath} {
  ::practcl::tcllib_require zipfile::mkzip
  ::zipfile::mkzip::mkzip $exename -runtime $barekit -directory $vfspath
}
proc ::practcl::sort_dict list {
  return [::lsort -stride 2 -dictionary $list]
}
if {[::package vcompare $::tcl_version 8.6] < 0} {
  # Approximate ::zipfile::mkzip with exec calls
  proc ::practcl::mkzip {exename barekit vfspath} {
    set path [file dirname [file normalize $exename]]
    set zipfile [file join $path [file rootname $exename].zip]
    file copy -force $barekit $exename
    set pwd [pwd]
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
  proc ::practcl::sort_dict list {
    set result {}
    foreach key [lsort -dictionary [dict keys $list]] {
      dict set result $key [dict get $list $key]
    }
    return $result
  }
} else {
  proc ::practcl::mkzip {exename barekit vfspath} {
    ::practcl::tcllib_require zipfile::mkzip
    ::zipfile::mkzip::mkzip $exename -runtime $barekit -directory $vfspath
  }
  proc ::practcl::sort_dict list {
    return [::lsort -stride 2 -dictionary $list]
  }
}

proc ::practcl::local_os {} {
  # If we have already run this command, return
  # a cached copy of the data
  if {[info exists ::practcl::LOCAL_INFO]} {
    return $::practcl::LOCAL_INFO
  }
  set result [array get ::practcl::CONFIG]







<
<
<
<
|
<
<
<
<
<







2680
2681
2682
2683
2684
2685
2686




2687





2688
2689
2690
2691
2692
2693
2694
  proc ::practcl::sort_dict list {
    set result {}
    foreach key [lsort -dictionary [dict keys $list]] {
      dict set result $key [dict get $list $key]
    }
    return $result
  }




}





proc ::practcl::local_os {} {
  # If we have already run this command, return
  # a cached copy of the data
  if {[info exists ::practcl::LOCAL_INFO]} {
    return $::practcl::LOCAL_INFO
  }
  set result [array get ::practcl::CONFIG]
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
  if {![dict exists result fossil_mirror] && [::info exists ::env(FOSSIL_MIRROR)]} {
    dict set result fossil_mirror $::env(FOSSIL_MIRROR)
  }

  set ::practcl::LOCAL_INFO $result
  return $result
}


###
# Detect local platform
###
proc ::practcl::config.tcl {path} {
   return [read_configuration $path]
}

proc ::practcl::read_configuration {path} {
  dict set result buildpath $path
  set result [local_os]
  set OS [dict get $result TEACUP_OS]
  set windows 0
  dict set result USEMSVC 0
  if {[file exists [file join $path config.tcl]]} {







<
<
<
<
<



<







2820
2821
2822
2823
2824
2825
2826





2827
2828
2829

2830
2831
2832
2833
2834
2835
2836
  if {![dict exists result fossil_mirror] && [::info exists ::env(FOSSIL_MIRROR)]} {
    dict set result fossil_mirror $::env(FOSSIL_MIRROR)
  }

  set ::practcl::LOCAL_INFO $result
  return $result
}





proc ::practcl::config.tcl {path} {
   return [read_configuration $path]
}

proc ::practcl::read_configuration {path} {
  dict set result buildpath $path
  set result [local_os]
  set OS [dict get $result TEACUP_OS]
  set windows 0
  dict set result USEMSVC 0
  if {[file exists [file join $path config.tcl]]} {
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
    }
    dict set result TEACUP_PROFILE win32-[dict get $result TEACUP_ARCH]
    dict set result TEACUP_OS windows
    dict set result EXEEXT .exe
  }
  return $result
}


###
# Convert an MSYS path to a windows native path
###
if {$::tcl_platform(platform) eq "windows"} {
proc ::practcl::msys_to_tclpath msyspath {
  return [exec sh -c "cd $msyspath ; pwd -W"]
}
proc ::practcl::tcl_to_myspath tclpath {
  set path [file normalize $tclpath]
  return "/[string index $path 0][string range $path 2 end]"
  #return [exec sh -c "cd $tclpath ; pwd"]
}
} else {
proc ::practcl::msys_to_tclpath msyspath {
  return [file normalize $msyspath]
}
proc ::practcl::tcl_to_myspath msyspath {
  return [file normalize $msyspath]
}
}


# Try to load  a package, and failing that
# retrieve tcllib
proc ::practcl::tcllib_require {pkg args} {
  # Try to load the package from the local environment
  if {[catch [list ::package require $pkg {*}$args] err]==0} {
    return $err
  }
  ::practcl::LOCAL tool tcllib env-load
  uplevel #0 [list ::package require $pkg {*}$args]
}

namespace eval ::practcl::platform {}

proc ::practcl::platform::tcl_core_options {os} {
  ###
  # Download our required packages
  ###
  set tcl_config_opts {}
  # Auto-guess options for the local operating system
  switch $os {
    windows {
      #lappend tcl_config_opts --disable-stubs
    }
    linux {
    }
    macosx {
      lappend tcl_config_opts --enable-corefoundation=yes  --enable-framework=no
    }
  }
  lappend tcl_config_opts --with-tzdata
  return $tcl_config_opts
}

proc ::practcl::platform::tk_core_options {os} {
  ###
  # Download our required packages
  ###
  set tk_config_opts {}

  # Auto-guess options for the local operating system
  switch $os {
    windows {
    }
    linux {
      lappend tk_config_opts --enable-xft=no --enable-xss=no
    }
    macosx {
      lappend tk_config_opts --enable-aqua=yes
    }
  }
  return $tk_config_opts
}

###
# Read a stylized key/value list stored in a file
###
proc ::practcl::read_rc_file {filename {localdat {}}} {
  set result $localdat
  set fin [open $filename r]
  set bufline {}
  set rawcount 0
  set linecount 0
  while {[gets $fin thisline]>=0} {







<
<
<
<
<

















<
<
<
<








<
|
|
















|


<



















<
<
<
<







2864
2865
2866
2867
2868
2869
2870





2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887




2888
2889
2890
2891
2892
2893
2894
2895

2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916

2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935




2936
2937
2938
2939
2940
2941
2942
    }
    dict set result TEACUP_PROFILE win32-[dict get $result TEACUP_ARCH]
    dict set result TEACUP_OS windows
    dict set result EXEEXT .exe
  }
  return $result
}





if {$::tcl_platform(platform) eq "windows"} {
proc ::practcl::msys_to_tclpath msyspath {
  return [exec sh -c "cd $msyspath ; pwd -W"]
}
proc ::practcl::tcl_to_myspath tclpath {
  set path [file normalize $tclpath]
  return "/[string index $path 0][string range $path 2 end]"
  #return [exec sh -c "cd $tclpath ; pwd"]
}
} else {
proc ::practcl::msys_to_tclpath msyspath {
  return [file normalize $msyspath]
}
proc ::practcl::tcl_to_myspath msyspath {
  return [file normalize $msyspath]
}
}




proc ::practcl::tcllib_require {pkg args} {
  # Try to load the package from the local environment
  if {[catch [list ::package require $pkg {*}$args] err]==0} {
    return $err
  }
  ::practcl::LOCAL tool tcllib env-load
  uplevel #0 [list ::package require $pkg {*}$args]
}

namespace eval ::practcl::platform {
}
proc ::practcl::platform::tcl_core_options {os} {
  ###
  # Download our required packages
  ###
  set tcl_config_opts {}
  # Auto-guess options for the local operating system
  switch $os {
    windows {
      #lappend tcl_config_opts --disable-stubs
    }
    linux {
    }
    macosx {
      lappend tcl_config_opts --enable-corefoundation=yes  --enable-framework=no
    }
  }
  lappend tcl_config_opts --with-tzdata --with-encoding utf-8
  return $tcl_config_opts
}

proc ::practcl::platform::tk_core_options {os} {
  ###
  # Download our required packages
  ###
  set tk_config_opts {}

  # Auto-guess options for the local operating system
  switch $os {
    windows {
    }
    linux {
      lappend tk_config_opts --enable-xft=no --enable-xss=no
    }
    macosx {
      lappend tk_config_opts --enable-aqua=yes
    }
  }
  return $tk_config_opts
}




proc ::practcl::read_rc_file {filename {localdat {}}} {
  set result $localdat
  set fin [open $filename r]
  set bufline {}
  set rawcount 0
  set linecount 0
  while {[gets $fin thisline]>=0} {
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
    #set key [lindex $line 0]
    #set value [lindex $line 1]
    #dict set result $key $value
  }
  close $fin
  return $result
}

###
# topic: e71f3f61c348d56292011eec83e95f0aacc1c618
# description: Converts a XXX.sh file into a series of Tcl variables
###
proc ::practcl::read_sh_subst {line info} {
  regsub -all {\x28} $line \x7B line
  regsub -all {\x29} $line \x7D line

  #set line [string map $key [string trim $line]]
  foreach {field value} $info {
    catch {set $field $value}
  }
  if [catch {subst $line} result] {
    return {}
  }
  set result [string trim $result]
  return [string trim $result ']
}

###
# topic: 03567140cca33c814664c7439570f669b9ab88e6
###
proc ::practcl::read_sh_file {filename {localdat {}}} {
  set fin [open $filename r]
  set result {}
  if {$localdat eq {}} {
    set top 1
    set local [array get ::env]
    dict set local EXE {}







<
<
<
<
<














<
<
<
<







2951
2952
2953
2954
2955
2956
2957





2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971




2972
2973
2974
2975
2976
2977
2978
    #set key [lindex $line 0]
    #set value [lindex $line 1]
    #dict set result $key $value
  }
  close $fin
  return $result
}





proc ::practcl::read_sh_subst {line info} {
  regsub -all {\x28} $line \x7B line
  regsub -all {\x29} $line \x7D line

  #set line [string map $key [string trim $line]]
  foreach {field value} $info {
    catch {set $field $value}
  }
  if [catch {subst $line} result] {
    return {}
  }
  set result [string trim $result]
  return [string trim $result ']
}




proc ::practcl::read_sh_file {filename {localdat {}}} {
  set fin [open $filename r]
  set result {}
  if {$localdat eq {}} {
    set top 1
    set local [array get ::env]
    dict set local EXE {}
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
      #puts $opts
      puts "Error reading line:\n$line\nerr: $err\n***"
      return $err {*}$opts
    }
  }
  return $result
}

###
# A simpler form of read_sh_file tailored
# to pulling data from (tcl|tk)Config.sh
###
proc ::practcl::read_Config.sh filename {
  set fin [open $filename r]
  set result {}
  set linecount 0
  while {[gets $fin line] >= 0} {
    set line [string trim $line]
    if {[string index $line 0] eq "#"} continue







<
<
<
<
<







3011
3012
3013
3014
3015
3016
3017





3018
3019
3020
3021
3022
3023
3024
      #puts $opts
      puts "Error reading line:\n$line\nerr: $err\n***"
      return $err {*}$opts
    }
  }
  return $result
}





proc ::practcl::read_Config.sh filename {
  set fin [open $filename r]
  set result {}
  set linecount 0
  while {[gets $fin line] >= 0} {
    set line [string trim $line]
    if {[string index $line 0] eq "#"} continue
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
      #puts $opts
      puts "Error reading line:\n$line\nerr: $err\n***"
      return $err {*}$opts
    }
  }
  return $result
}

###
# A simpler form of read_sh_file tailored
# to pulling data from a Makefile
###
proc ::practcl::read_Makefile filename {
  set fin [open $filename r]
  set result {}
  while {[gets $fin line] >= 0} {
    set line [string trim $line]
    if {[string index $line 0] eq "#"} continue
    if {$line eq {}} continue







<
<
<
<
<







3037
3038
3039
3040
3041
3042
3043





3044
3045
3046
3047
3048
3049
3050
      #puts $opts
      puts "Error reading line:\n$line\nerr: $err\n***"
      return $err {*}$opts
    }
  }
  return $result
}





proc ::practcl::read_Makefile filename {
  set fin [open $filename r]
  set result {}
  while {[gets $fin line] >= 0} {
    set line [string trim $line]
    if {[string index $line 0] eq "#"} continue
    if {$line eq {}} continue
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
    # the Compile field is about where most TEA files start getting silly
    if {$field eq "compile"} {
      break
    }
  }
  return $result
}

## Append arguments to a buffer
# The command works like puts in that each call will also insert
# a line feed. Unlike puts, blank links in the interstitial are
# suppressed
proc ::practcl::cputs {varname args} {
  upvar 1 $varname buffer
  if {[llength $args]==1 && [string length [string trim [lindex $args 0]]] == 0} {

  }
  if {[info exist buffer]} {
    if {[string index $buffer end] ne "\n"} {
      append buffer \n
    }
  } else {
    set buffer \n
  }
  # Trim leading \n's
  append buffer [string trimleft [lindex $args 0] \n] {*}[lrange $args 1 end]
}

proc ::practcl::tcl_to_c {body} {
  set result {}
  foreach rawline [split $body \n] {
    set line [string map [list \" \\\" \\ \\\\] $rawline]
    cputs result "\n        \"$line\\n\" \\"
  }
  return [string trimright $result \\]
}


proc ::practcl::_tagblock {text {style tcl} {note {}}} {
  if {[string length [string trim $text]]==0} {
    return {}
  }
  set output {}
  switch $style {
    tcl {







<
<
<
<
<















<








<
<







3087
3088
3089
3090
3091
3092
3093





3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108

3109
3110
3111
3112
3113
3114
3115
3116


3117
3118
3119
3120
3121
3122
3123
    # the Compile field is about where most TEA files start getting silly
    if {$field eq "compile"} {
      break
    }
  }
  return $result
}





proc ::practcl::cputs {varname args} {
  upvar 1 $varname buffer
  if {[llength $args]==1 && [string length [string trim [lindex $args 0]]] == 0} {

  }
  if {[info exist buffer]} {
    if {[string index $buffer end] ne "\n"} {
      append buffer \n
    }
  } else {
    set buffer \n
  }
  # Trim leading \n's
  append buffer [string trimleft [lindex $args 0] \n] {*}[lrange $args 1 end]
}

proc ::practcl::tcl_to_c {body} {
  set result {}
  foreach rawline [split $body \n] {
    set line [string map [list \" \\\" \\ \\\\] $rawline]
    cputs result "\n        \"$line\\n\" \\"
  }
  return [string trimright $result \\]
}


proc ::practcl::_tagblock {text {style tcl} {note {}}} {
  if {[string length [string trim $text]]==0} {
    return {}
  }
  set output {}
  switch $style {
    tcl {
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
    }
    default {
      ::practcl::cputs output "# END $note"
    }
  }
  return $output
}

proc ::practcl::de_shell {data} {
  set values {}
  foreach flag {DEFS TCL_DEFS TK_DEFS} {
    if {[dict exists $data $flag]} {
      #set value {}
      #foreach item [dict get $data $flag] {
      #  append value " " [string map {{ } {\ }} $item]







<







3140
3141
3142
3143
3144
3145
3146

3147
3148
3149
3150
3151
3152
3153
    }
    default {
      ::practcl::cputs output "# END $note"
    }
  }
  return $output
}

proc ::practcl::de_shell {data} {
  set values {}
  foreach flag {DEFS TCL_DEFS TK_DEFS} {
    if {[dict exists $data $flag]} {
      #set value {}
      #foreach item [dict get $data $flag] {
      #  append value " " [string map {{ } {\ }} $item]
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

###
# END: buildutil.tcl
###
###
# START: fileutil.tcl
###
###
# Bits stolen from fileutil
###
proc ::practcl::cat fname {
    if {![file exists $fname]} {
       return
    }
    set fin [open $fname r]
    set data [read $fin]
    close $fin
    return $data
}

proc ::practcl::grep {pattern {files {}}} {
    set result [list]
    if {[llength $files] == 0} {
	      # read from stdin
    	  set lnum 0
	      while {[gets stdin line] >= 0} {
	          incr lnum
    	      if {[regexp -- $pattern $line]} {
		            lappend result "${lnum}:${line}"
	          }
    	  }
    } else {
	      foreach filename $files {
            set file [open $filename r]
            set lnum 0
            while {[gets $file line] >= 0} {
                incr lnum
                if {[regexp -- $pattern $line]} {
                    lappend result "${filename}:${lnum}:${line}"
                }
            }
            close $file
    	  }
    }
    return $result
}

proc ::practcl::file_lexnormalize {sp} {
    set spx [file split $sp]

    # Resolution of embedded relative modifiers (., and ..).

    if {
	([lsearch -exact $spx . ] < 0) &&
	([lsearch -exact $spx ..] < 0)
    } {
	# Quick path out if there are no relative modifiers
	return $sp
    }

    set absolute [expr {![string equal [file pathtype $sp] relative]}]
    # A volumerelative path counts as absolute for our purposes.

    set sp $spx
    set np {}
    set noskip 1

    while {[llength $sp]} {
	set ele    [lindex $sp 0]
	set sp     [lrange $sp 1 end]
	set islast [expr {[llength $sp] == 0}]

	if {[string equal $ele ".."]} {
	    if {
		($absolute  && ([llength $np] >  1)) ||
		(!$absolute && ([llength $np] >= 1))
	    } {
		# .. : Remove the previous element added to the
		# new path, if there actually is enough to remove.
		set np [lrange $np 0 end-1]
	    }
	} elseif {[string equal $ele "."]} {
	    # Ignore .'s, they stay at the current location
	    continue
	} else {
	    # A regular element.
	    lappend np $ele
	}
    }
    if {[llength $np] > 0} {
	return [eval [linsert $np 0 file join]]
	# 8.5: return [file join {*}$np]
    }
    return {}
}

proc ::practcl::file_relative {base dst} {
    # Ensure that the link to directory 'dst' is properly done relative to
    # the directory 'base'.

    if {![string equal [file pathtype $base] [file pathtype $dst]]} {
	return -code error "Unable to compute relation for paths of different pathtypes: [file pathtype $base] vs. [file pathtype $dst], ($base vs. $dst)"
    }

    set base [file_lexnormalize [file join [pwd] $base]]
    set dst  [file_lexnormalize [file join [pwd] $dst]]

    set save $dst
    set base [file split $base]
    set dst  [file split $dst]

    while {[string equal [lindex $dst 0] [lindex $base 0]]} {
	set dst  [lrange $dst  1 end]
	set base [lrange $base 1 end]
	if {![llength $dst]} {break}
    }

    set dstlen  [llength $dst]
    set baselen [llength $base]

    if {($dstlen == 0) && ($baselen == 0)} {
	# Cases:
	# (a) base == dst

	set dst .
    } else {
	# Cases:
	# (b) base is: base/sub = sub
	#     dst  is: base     = {}

	# (c) base is: base     = {}
	#     dst  is: base/sub = sub

	while {$baselen > 0} {
	    set dst [linsert $dst 0 ..]
	    incr baselen -1
	}
	# 8.5: set dst [file join {*}$dst]
	set dst [eval [linsert $dst 0 file join]]
    }

    return $dst
}






















proc ::practcl::log {fname comment} {
  set fname [file normalize $fname]
  if {[info exists ::practcl::logchan($fname)]} {
    set fout $::practcl::logchan($fname)
    after cancel $::practcl::logevent($fname)
  } else {
    set fout [open $fname a]
  }
  puts $fout $comment
  # Defer close until idle
  set ::practcl::logevent($fname) [after idle "close $fout ; unset ::practcl::logchan($fname)"]
}

###
# END: fileutil.tcl
###
###
# START: installutil.tcl
###
###
# Installer tools
###
proc ::practcl::_isdirectory name {










  return [file isdirectory $name]
}
###

# Return true if the pkgindex file contains






# any statement other than "package ifneeded"



# and/or if any package ifneeded loads a DLL
###










proc ::practcl::_pkgindex_directory {path} {
  set buffer {}
  set pkgidxfile [file join $path pkgIndex.tcl]

  if {![file exists $pkgidxfile]} {











    # No pkgIndex file, read the source
    foreach file [glob -nocomplain $path/*.tm] {
      set file [file normalize $file]
      set fname [file rootname [file tail $file]]
      ###
      # We used to be able to ... Assume the package is correct in the filename
      # No hunt for a "package provides"







<
<
<
<
<
<
<
<
<
<
<
<
<



|
|
|
|
|
|
|
|

|









|



<






|
|

|
|










|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


|
|



<





|










|
|
|






|
|

|

|
|
|

|
|

|
|
|
|
|
|




>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>



















<
<
<
|
>
>
>
>
>
>
>
>
>
>
|
|
<
>
|
>
>
>
>
>
>
|
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>


|
>
|
>
>
>
>
>
>
>
>
>
>
>







3198
3199
3200
3201
3202
3203
3204













3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230

3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278

3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366



3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379

3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392

3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425

###
# END: buildutil.tcl
###
###
# START: fileutil.tcl
###













proc ::practcl::grep {pattern {files {}}} {
    set result [list]
    if {[llength $files] == 0} {
            # read from stdin
            set lnum 0
            while {[gets stdin line] >= 0} {
                incr lnum
                if {[regexp -- $pattern $line]} {
                        lappend result "${lnum}:${line}"
                }
            }
    } else {
            foreach filename $files {
            set file [open $filename r]
            set lnum 0
            while {[gets $file line] >= 0} {
                incr lnum
                if {[regexp -- $pattern $line]} {
                    lappend result "${filename}:${lnum}:${line}"
                }
            }
            close $file
            }
    }
    return $result
}

proc ::practcl::file_lexnormalize {sp} {
    set spx [file split $sp]

    # Resolution of embedded relative modifiers (., and ..).

    if {
      ([lsearch -exact $spx . ] < 0) &&
      ([lsearch -exact $spx ..] < 0)
    } {
      # Quick path out if there are no relative modifiers
      return $sp
    }

    set absolute [expr {![string equal [file pathtype $sp] relative]}]
    # A volumerelative path counts as absolute for our purposes.

    set sp $spx
    set np {}
    set noskip 1

    while {[llength $sp]} {
      set ele    [lindex $sp 0]
      set sp     [lrange $sp 1 end]
      set islast [expr {[llength $sp] == 0}]

      if {[string equal $ele ".."]} {
          if {
            ($absolute  && ([llength $np] >  1)) ||
            (!$absolute && ([llength $np] >= 1))
          } {
            # .. : Remove the previous element added to the
            # new path, if there actually is enough to remove.
            set np [lrange $np 0 end-1]
          }
      } elseif {[string equal $ele "."]} {
          # Ignore .'s, they stay at the current location
          continue
      } else {
          # A regular element.
          lappend np $ele
      }
    }
    if {[llength $np] > 0} {
      return [eval [linsert $np 0 file join]]
      # 8.5: return [file join {*}$np]
    }
    return {}
}

proc ::practcl::file_relative {base dst} {
    # Ensure that the link to directory 'dst' is properly done relative to
    # the directory 'base'.

    if {![string equal [file pathtype $base] [file pathtype $dst]]} {
      return -code error "Unable to compute relation for paths of different pathtypes: [file pathtype $base] vs. [file pathtype $dst], ($base vs. $dst)"
    }

    set base [file_lexnormalize [file join [pwd] $base]]
    set dst  [file_lexnormalize [file join [pwd] $dst]]

    set save $dst
    set base [file split $base]
    set dst  [file split $dst]

    while {[string equal [lindex $dst 0] [lindex $base 0]]} {
      set dst  [lrange $dst  1 end]
      set base [lrange $base 1 end]
      if {![llength $dst]} {break}
    }

    set dstlen  [llength $dst]
    set baselen [llength $base]

    if {($dstlen == 0) && ($baselen == 0)} {
      # Cases:
      # (a) base == dst

      set dst .
    } else {
      # Cases:
      # (b) base is: base/sub = sub
      #     dst  is: base     = {}

      # (c) base is: base     = {}
      #     dst  is: base/sub = sub

      while {$baselen > 0} {
          set dst [linsert $dst 0 ..]
          incr baselen -1
      }
      # 8.5: set dst [file join {*}$dst]
      set dst [eval [linsert $dst 0 file join]]
    }

    return $dst
}
proc ::practcl::findByPattern {basedir patterns} {
    set queue $basedir
    set result {}
    while {[llength $queue]} {
      set item [lindex $queue 0]
      set queue [lrange $queue 1 end]
      if {[file isdirectory $item]} {
        foreach path [glob -nocomplain [file join $item *]] {
          lappend queue $path
        }
        continue
      }
      foreach pattern $patterns {
        set fname [file tail $item]
        if {[string match $pattern $fname]} {
          lappend result $item
          break
        }
      }
    }
    return $result
}
proc ::practcl::log {fname comment} {
  set fname [file normalize $fname]
  if {[info exists ::practcl::logchan($fname)]} {
    set fout $::practcl::logchan($fname)
    after cancel $::practcl::logevent($fname)
  } else {
    set fout [open $fname a]
  }
  puts $fout $comment
  # Defer close until idle
  set ::practcl::logevent($fname) [after idle "close $fout ; unset ::practcl::logchan($fname)"]
}

###
# END: fileutil.tcl
###
###
# START: installutil.tcl
###



proc ::practcl::_pkgindex_simpleIndex {path} {
set buffer {}
  set pkgidxfile    [file join $path pkgIndex.tcl]
  set modfile       [file join $path [file tail $path].tcl]
  set use_pkgindex  [file exists $pkgidxfile]
  set tclfiles      {}
  set found 0
  set mlist [list pkgIndex.tcl index.tcl [file tail $modfile] version_info.tcl]
  foreach file [glob -nocomplain [file join $path *.tcl]] {
    if {[file tail $file] ni $mlist} {
      #puts [list NONMODFILE $file]
      return {}
    }

  }
  foreach file [glob -nocomplain [file join $path *.tcl]] {
    if { [file tail $file] == "version_info.tcl" } continue
    set fin [open $file r]
    set dat [read $fin]
    close $fin
    if {![regexp "package provide" $dat]} continue
    set fname [file rootname [file tail $file]]
    # Look for a package provide statement
    foreach line [split $dat \n] {
      set line [string trim $line]
      if { [string range $line 0 14] != "package provide" } continue
      set package [lindex $line 2]

      set version [lindex $line 3]
      if {[string index $package 0] in "\$ \[ @"} continue
      if {[string index $version 0] in "\$ \[ @"} continue
      #puts "PKGLINE $line"
      append buffer "package ifneeded $package $version \[list source \[file join %DIR% [file tail $file]\]\]" \n
      break
    }
  }
  return $buffer
}
proc ::practcl::_pkgindex_directory {path} {
  set buffer {}
  set pkgidxfile    [file join $path pkgIndex.tcl]
  set modfile       [file join $path [file tail $path].tcl]
  set use_pkgindex  [file exists $pkgidxfile]
  set tclfiles      {}
  if {$use_pkgindex && [file exists $modfile]} {
    set use_pkgindex 0
    set mlist [list pkgIndex.tcl [file tail $modfile]]
    foreach file [glob -nocomplain [file join $path *.tcl]] {
      lappend tclfiles [file tail $file]
      if {[file tail $file] in $mlist} continue
      incr use_pkgindex
    }
  }
  if {!$use_pkgindex} {
    # No pkgIndex file, read the source
    foreach file [glob -nocomplain $path/*.tm] {
      set file [file normalize $file]
      set fname [file rootname [file tail $file]]
      ###
      # We used to be able to ... Assume the package is correct in the filename
      # No hunt for a "package provides"
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
    }
    append buffer $thisline \n
    set thisline {}
  }
  if {$trace} {puts [list [file dirname $pkgidxfile] $buffer]}
  return $buffer
}


proc ::practcl::_pkgindex_path_subdir {path} {
  set result {}
  if {[file exists [file join $path src build.tcl]]} {
    # Tool style module, don't dive into subdirectories
    return $path
  }
  foreach subpath [glob -nocomplain [file join $path *]] {
    if {[file isdirectory $subpath]} {
      if {[file tail $subpath] eq "build" && [file exists [file join $subpath build.tcl]]} continue
      lappend result $subpath {*}[_pkgindex_path_subdir $subpath]
    }
  }
  return $result
}
###
# Index all paths given as though they will end up in the same
# virtual file system
###
proc ::practcl::pkgindex_path {args} {
  set stack {}
  set buffer {
lappend ::PATHSTACK $dir
set IDXPATH [lindex $::PATHSTACK end]
  }
  set preindexed {}







<
<














<
<
<
<







3508
3509
3510
3511
3512
3513
3514


3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528




3529
3530
3531
3532
3533
3534
3535
    }
    append buffer $thisline \n
    set thisline {}
  }
  if {$trace} {puts [list [file dirname $pkgidxfile] $buffer]}
  return $buffer
}


proc ::practcl::_pkgindex_path_subdir {path} {
  set result {}
  if {[file exists [file join $path src build.tcl]]} {
    # Tool style module, don't dive into subdirectories
    return $path
  }
  foreach subpath [glob -nocomplain [file join $path *]] {
    if {[file isdirectory $subpath]} {
      if {[file tail $subpath] eq "build" && [file exists [file join $subpath build.tcl]]} continue
      lappend result $subpath {*}[_pkgindex_path_subdir $subpath]
    }
  }
  return $result
}




proc ::practcl::pkgindex_path {args} {
  set stack {}
  set buffer {
lappend ::PATHSTACK $dir
set IDXPATH [lindex $::PATHSTACK end]
  }
  set preindexed {}
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
        set path_indexed($path) 0
      }
    } else {
      puts [list WARNING: NO PATHS FOUND IN $base]
    }
    set path_indexed($base) 1
    set path_indexed([file join $base boot tcl]) 1













    foreach path $paths {
      if {$path_indexed($path)} continue
      set thisdir [file_relative $base $path]
      set idxbuf [::practcl::_pkgindex_directory $path]
      if {[string length $idxbuf]} {
        incr path_indexed($path)
        append buffer "set dir \[set PKGDIR \[file join \[lindex \$::PATHSTACK end\] $thisdir\]\]" \n
        append buffer [string map {$dir $PKGDIR} [string trimright $idxbuf]] \n
      }
    }
  }
  append buffer {
set dir [lindex $::PATHSTACK end]
set ::PATHSTACK [lrange $::PATHSTACK 0 end-1]
}
  return $buffer
}

proc ::practcl::installDir {d1 d2} {
  puts [format {%*sCreating %s} [expr {4 * [info level]}] {} [file tail $d2]]
  file delete -force -- $d2
  file mkdir $d2

  foreach ftail [glob -directory $d1 -nocomplain -tails *] {
    set f [file join $d1 $ftail]







>
>
>
>
>
>
>
>
>
>
>
>
>

















<







3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602

3603
3604
3605
3606
3607
3608
3609
        set path_indexed($path) 0
      }
    } else {
      puts [list WARNING: NO PATHS FOUND IN $base]
    }
    set path_indexed($base) 1
    set path_indexed([file join $base boot tcl]) 1
    append buffer \n {# SINGLE FILE MODULES BEGIN} \n {set dir [lindex $::PATHSTACK end]} \n
    foreach path $paths {
      if {$path_indexed($path)} continue
      set thisdir [file_relative $base $path]
      set simpleIdx [_pkgindex_simpleIndex $path]
      if {[string length $simpleIdx]==0} continue
      incr path_indexed($path)
      if {[string length $simpleIdx]} {
        incr path_indexed($path)
        append buffer [string map [list %DIR% "\$dir \{$thisdir\}"] [string trimright $simpleIdx]] \n
      }
    }
    append buffer {# SINGLE FILE MODULES END} \n
    foreach path $paths {
      if {$path_indexed($path)} continue
      set thisdir [file_relative $base $path]
      set idxbuf [::practcl::_pkgindex_directory $path]
      if {[string length $idxbuf]} {
        incr path_indexed($path)
        append buffer "set dir \[set PKGDIR \[file join \[lindex \$::PATHSTACK end\] $thisdir\]\]" \n
        append buffer [string map {$dir $PKGDIR} [string trimright $idxbuf]] \n
      }
    }
  }
  append buffer {
set dir [lindex $::PATHSTACK end]
set ::PATHSTACK [lrange $::PATHSTACK 0 end-1]
}
  return $buffer
}

proc ::practcl::installDir {d1 d2} {
  puts [format {%*sCreating %s} [expr {4 * [info level]}] {} [file tail $d2]]
  file delete -force -- $d2
  file mkdir $d2

  foreach ftail [glob -directory $d1 -nocomplain -tails *] {
    set f [file join $d1 $ftail]
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187

  if {$::tcl_platform(platform) eq {unix}} {
    file attributes $d2 -permissions 0755
  } else {
    file attributes $d2 -readonly 1
  }
}

proc ::practcl::copyDir {d1 d2 {toplevel 1}} {
  #if {$toplevel} {
  #  puts [list ::practcl::copyDir $d1 -> $d2]
  #}
  #file delete -force -- $d2
  file mkdir $d2
  if {[file isfile $d1]} {







<







3621
3622
3623
3624
3625
3626
3627

3628
3629
3630
3631
3632
3633
3634

  if {$::tcl_platform(platform) eq {unix}} {
    file attributes $d2 -permissions 0755
  } else {
    file attributes $d2 -readonly 1
  }
}

proc ::practcl::copyDir {d1 d2 {toplevel 1}} {
  #if {$toplevel} {
  #  puts [list ::practcl::copyDir $d1 -> $d2]
  #}
  #file delete -force -- $d2
  file mkdir $d2
  if {[file isfile $d1]} {
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
        } else {
          file attributes [file join $d2 $ftail] -readonly 1
        }
      }
    }
  }
}
















































###
# END: installutil.tcl
###
###
# START: makeutil.tcl
###
###
# Backward compatible Make facilities
# These were used early in development and are consdiered deprecated
###

proc ::practcl::trigger {args} {
  ::practcl::LOCAL make trigger {*}$args
  foreach {name obj} [::practcl::LOCAL make objects] {
    set ::make($name) [$obj do]
  }
}

proc ::practcl::depends {args} {
  ::practcl::LOCAL make depends {*}$args
}

proc ::practcl::target {name info {action {}}} {
  set obj [::practcl::LOCAL make task $name $info $action]
  set ::make($name) 0
  set filename [$obj define get filename]
  if {$filename ne {}} {
    set ::target($name) $filename
  }
}

###
# END: makeutil.tcl
###
###
# START: class metaclass.tcl
###
::oo::class create ::practcl::metaclass {
  superclass ::oo::object

  method _MorphPatterns {} {
    return {{@name@} {::practcl::@name@} {::practcl::*@name@} {::practcl::*@name@*}}
  }

  method define {submethod args} {
    my variable define
    switch $submethod {
      dump {
        return [array get define]
      }
      add {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







<
<
<
<
<






<



<








>






|
<
<



<







3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711





3712
3713
3714
3715
3716
3717

3718
3719
3720

3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736


3737
3738
3739

3740
3741
3742
3743
3744
3745
3746
        } else {
          file attributes [file join $d2 $ftail] -readonly 1
        }
      }
    }
  }
}
proc ::practcl::buildModule {modpath} {
  set buildscript [file join $modpath build build.tcl]
  if {![file exists $buildscript]} return
  set pkgIndexFile [file join $modpath pkgIndex.tcl]
  if {[file exists $pkgIndexFile]} {
    set latest 0
    foreach file [::practcl::findByPattern [file dirname $buildscript] *.tcl] {
      set mtime [file mtime $file]
      if {$mtime>$latest} {
        set latest $mtime
      }
    }
    set IdxTime [file mtime $pkgIndexFile]
    if {$latest<$IdxTime} return
  }
  ::practcl::dotclexec $buildscript
}
proc ::practcl::installModule {modpath DEST} {
  if {[file exists [file join $DEST modules]]} {
    set dpath [file join $DEST modules [file tail $modpath]]
  } else {
    set dpath $DEST
  }
  if {[file exists $dpath] && [file type $dpath] eq "link"} return
  if {[file exists [file join $modpath index.tcl]]} {
    # IRM/Tao style modules non-amalgamated
    ::practcl::installDir $modpath $dpath
    return
  }
  buildModule $modpath
  set files [glob -nocomplain [file join $modpath *.tcl]]
  if {[llength $files]} {
    if {[llength $files]>1} {
      if {![file exists [file join $modpath pkgIndex.tcl]]} {
        pkg_mkIndex $modpath
      }
    }
    file delete -force $dpath
    file mkdir $dpath
    foreach file $files {
      file copy $file $dpath
    }
  }
  if {[file exists [file join $modpath htdocs]]} {
    ::practcl::copyDir [file join $modpath htdocs] [file join $dpath htdocs]
  }
}

###
# END: installutil.tcl
###
###
# START: makeutil.tcl
###





proc ::practcl::trigger {args} {
  ::practcl::LOCAL make trigger {*}$args
  foreach {name obj} [::practcl::LOCAL make objects] {
    set ::make($name) [$obj do]
  }
}

proc ::practcl::depends {args} {
  ::practcl::LOCAL make depends {*}$args
}

proc ::practcl::target {name info {action {}}} {
  set obj [::practcl::LOCAL make task $name $info $action]
  set ::make($name) 0
  set filename [$obj define get filename]
  if {$filename ne {}} {
    set ::target($name) $filename
  }
}

###
# END: makeutil.tcl
###
###
# START: class metaclass.tcl
###
::clay::define ::practcl::metaclass {


  method _MorphPatterns {} {
    return {{@name@} {::practcl::@name@} {::practcl::*@name@} {::practcl::*@name@*}}
  }

  method define {submethod args} {
    my variable define
    switch $submethod {
      dump {
        return [array get define]
      }
      add {
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
        }
      }
      default {
        array $submethod define {*}$args
      }
    }
  }


  method meta {submethod args} {
    my variable meta
    if {![info exists meta]} {
      set meta {}
    }
    switch $submethod {
      dump {
        return $meta
      }
      add {
        set field [lindex $args 0]
        if {![dict exists $meta $field]} {
          dict set meta $field {}
        }
        foreach arg [lrange $args 1 end] {
          if {$arg ni [dict get $meta $field]} {
            dict lappend meta $field $arg
          }
        }
        return [dict get $meta $field]
      }
      remove {
        set field [lindex $args 0]
        if {![dict exists meta $field]} {
          return
        }
        set rlist [lrange $args 1 end]
        set olist [dict get $meta $field]
        set nlist {}
        foreach arg $olist {
          if {$arg in $rlist} continue
          lappend nlist $arg
        }
        dict set meta $field $nlist
        return $nlist
      }
      exists {
        return [dict exists $meta {*}$args]
      }
      getnull -
      get {
        if {[dict exists $meta {*}$args]} {
          return [dict get $meta {*}$args]
        }
        return {}
      }
      cget {
        set field [lindex $args 0]
        if {[dict exists $meta $field]} {
          return [dict get $meta $field]
        }
        return [lindex $args 1]
      }
      set {
        if {[llength $args]==1} {
          foreach {field value} $args {
            dict set meta [string trimright $field :]: $value
          }
        } else {
          set field [lindex $args end-1]
          set value [lindex $args end]
          dict set meta {*}[lrange $args 0 end-2] [string trimright $field :]: $value
        }
      }
      default {
        error "Valid: add cget dump exists get getnull remove set"
      }
    }
  }
  
  method graft args {
    my variable organs
    if {[llength $args] == 1} {
      error "Need two arguments"
    }
    set object {}
    foreach {stub object} $args {
      dict set organs $stub $object
      oo::objdefine [self] forward <${stub}> $object
      oo::objdefine [self] export <${stub}>
    }
    return $object
  }

  method initialize {} {}


  method link {command args} {
    my variable links
    switch $command {
      object {
        foreach obj $args {
          foreach linktype [$obj linktype] {
            my link add $linktype $obj







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
|

<

<
<







3795
3796
3797
3798
3799
3800
3801








































































3802










3803
3804

3805


3806
3807
3808
3809
3810
3811
3812
        }
      }
      default {
        array $submethod define {*}$args
      }
    }
  }








































































  method graft args {










    return [my clay delegate {*}$args]
  }

  method initialize {} {}


  method link {command args} {
    my variable links
    switch $command {
      object {
        foreach obj $args {
          foreach linktype [$obj linktype] {
            my link add $linktype $obj
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
        return $links($linktype)
      }
      dump {
        return [array get links]
      }
    }
  }

  method morph classname {
    my variable define
    if {$classname ne {}} {
      set map [list @name@ $classname]
      foreach pattern [string map $map [my _MorphPatterns]] {
        set pattern [string trim $pattern]
        set matches [info commands $pattern]







<







3853
3854
3855
3856
3857
3858
3859

3860
3861
3862
3863
3864
3865
3866
        return $links($linktype)
      }
      dump {
        return [array get links]
      }
    }
  }

  method morph classname {
    my variable define
    if {$classname ne {}} {
      set map [list @name@ $classname]
      foreach pattern [string map $map [my _MorphPatterns]] {
        set pattern [string trim $pattern]
        set matches [info commands $pattern]
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
      } {
        if {[string match $pattern $class]} {
           set mixinslot $slot
           break
        }
      }
      if {$mixinslot ne {}} {
        my mixin $mixinslot $class
      } elseif {[info command $class] ne {}} {
        if {[info object class [self]] ne $class} {
          ::oo::objdefine [self] class $class
          ::practcl::debug [self] morph $class
           my define set class $class
        }
      } else {
        error "[self] Could not detect class for $classname"
      }
    }
    if {[::info exists define(oodefine)]} {
      ::oo::objdefine [self] $define(oodefine)
      #unset define(oodefine)
    }
  }

  method mixin {slot classname} {
    my variable mixinslot
    set class {}
    set map [list @slot@ $slot @name@ $classname]
    foreach pattern [split [string map $map {
      @name@
      @slot@.@name@
      ::practcl::@name@
      ::practcl::@slot@.@name@
      ::practcl::@slot@*@name@
      ::practcl::*@name@*
    }] \n] {
      set pattern [string trim $pattern]
      set matches [info commands $pattern]
      if {![llength $matches]} continue
      set class [lindex $matches 0]
      break
    }
    ::practcl::debug [self] mixin $slot $class
    dict set mixinslot $slot $class
    set mixins {}
    foreach {s c} $mixinslot {
      if {$c eq {}} continue
      lappend mixins $c
    }
    oo::objdefine [self] mixin {*}$mixins
  }

  method organ {{stub all}} {
    my variable organs
    if {![info exists organs]} {
      return {}
    }
    if { $stub eq "all" } {
      return $organs
    }
    if {[dict exists $organs $stub]} {
      return [dict get $organs $stub]
    }
  }

  method script script {
    eval $script
  }

  method select {} {
    my variable define
    if {[info exists define(class)]} {
      my morph $define(class)
    } else {
      if {[::info exists define(oodefine)]} {
        ::oo::objdefine [self] $define(oodefine)
        #unset define(oodefine)
      }
    }
  }

  method source filename {
    source $filename
  }
}

###
# END: class metaclass.tcl
###
###
# START: class toolset baseclass.tcl
###
###
# Ancestor-less class intended to be a mixin
# which defines a family of build related behaviors
# that are modified when targetting either gcc or msvc
###
oo::class create ::practcl::toolset {
  ###
  # find or fake a key/value list describing this project
  ###
  method config.sh {} {
    return [my read_configuration]
  }
  
  method BuildDir {PWD} {
    set name [my define get name]
    set debug [my define get debug 0]
    if {[my <project> define get LOCAL 0]} {
      return [my define get builddir [file join $PWD local $name]]
    }
    if {$debug} {
      return [my define get builddir [file join $PWD debug $name]]
    } else {
      return [my define get builddir [file join $PWD pkg $name]]
    }
  }
  
  method MakeDir {srcdir} {
    return $srcdir
  }
  
  method read_configuration {} {
    my variable conf_result
    if {[info exists conf_result]} {
      return $conf_result
    }
    set result {}
    set name [my define get name]







|















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



<











<











<
<
<
<
<
|
<
<
<



<












<



<







3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898










































3899
3900
3901

3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912

3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923





3924



3925
3926
3927

3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939

3940
3941
3942

3943
3944
3945
3946
3947
3948
3949
      } {
        if {[string match $pattern $class]} {
           set mixinslot $slot
           break
        }
      }
      if {$mixinslot ne {}} {
        my clay mixinmap $mixinslot $class
      } elseif {[info command $class] ne {}} {
        if {[info object class [self]] ne $class} {
          ::oo::objdefine [self] class $class
          ::practcl::debug [self] morph $class
           my define set class $class
        }
      } else {
        error "[self] Could not detect class for $classname"
      }
    }
    if {[::info exists define(oodefine)]} {
      ::oo::objdefine [self] $define(oodefine)
      #unset define(oodefine)
    }
  }










































  method script script {
    eval $script
  }

  method select {} {
    my variable define
    if {[info exists define(class)]} {
      my morph $define(class)
    } else {
      if {[::info exists define(oodefine)]} {
        ::oo::objdefine [self] $define(oodefine)
        #unset define(oodefine)
      }
    }
  }

  method source filename {
    source $filename
  }
}

###
# END: class metaclass.tcl
###
###
# START: class toolset baseclass.tcl
###





::clay::define ::practcl::toolset {



  method config.sh {} {
    return [my read_configuration]
  }

  method BuildDir {PWD} {
    set name [my define get name]
    set debug [my define get debug 0]
    if {[my <project> define get LOCAL 0]} {
      return [my define get builddir [file join $PWD local $name]]
    }
    if {$debug} {
      return [my define get builddir [file join $PWD debug $name]]
    } else {
      return [my define get builddir [file join $PWD pkg $name]]
    }
  }

  method MakeDir {srcdir} {
    return $srcdir
  }

  method read_configuration {} {
    my variable conf_result
    if {[info exists conf_result]} {
      return $conf_result
    }
    set result {}
    set name [my define get name]
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
      }
      set conf_result $result
      return $result
    }
    ###
    # Oh man... we have to guess
    ###



    set filename [file join $builddir Makefile]
    if {![file exists $filename]} {
      error "Could not locate any configuration data in $srcdir"
    }
    foreach {field dat} [::practcl::read_Makefile $filename] {
      dict set result $field $dat
    }
    if {![dict exists $result PRACTCL_PKG_LIBS] && [dict exists $result LIBS]} {
      dict set result PRACTCL_PKG_LIBS [dict get $result LIBS]
    }
    set conf_result $result
    cd $PWD
    return $result
  }

  ## method DEFS
  # This method populates 4 variables:
  # name - The name of the package
  # version - The version of the package
  # defs - C flags passed to the compiler
  # includedir - A list of paths to feed to the compiler for finding headers
  #
  method build-cflags {PROJECT DEFS namevar versionvar defsvar} {
    upvar 1 $namevar name $versionvar version NAME NAME $defsvar defs
    set name [string tolower [${PROJECT} define get name [${PROJECT} define get pkg_name]]]
    set NAME [string toupper $name]
    set version [${PROJECT} define get version [${PROJECT} define get pkg_vers]]
    if {$version eq {}} {
      set version 0.1a







>
>
>














<
<
<
<
<
<
<
<







3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007








4008
4009
4010
4011
4012
4013
4014
      }
      set conf_result $result
      return $result
    }
    ###
    # Oh man... we have to guess
    ###
    if {![file exists [file join $builddir Makefile]]} {
      my Configure
    }
    set filename [file join $builddir Makefile]
    if {![file exists $filename]} {
      error "Could not locate any configuration data in $srcdir"
    }
    foreach {field dat} [::practcl::read_Makefile $filename] {
      dict set result $field $dat
    }
    if {![dict exists $result PRACTCL_PKG_LIBS] && [dict exists $result LIBS]} {
      dict set result PRACTCL_PKG_LIBS [dict get $result LIBS]
    }
    set conf_result $result
    cd $PWD
    return $result
  }








  method build-cflags {PROJECT DEFS namevar versionvar defsvar} {
    upvar 1 $namevar name $versionvar version NAME NAME $defsvar defs
    set name [string tolower [${PROJECT} define get name [${PROJECT} define get pkg_name]]]
    set NAME [string toupper $name]
    set version [${PROJECT} define get version [${PROJECT} define get pkg_vers]]
    if {$version eq {}} {
      set version 0.1a
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751

1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
        set defs "$predef $postdef"
      }
    }
    append defs " -DPACKAGE_NAME=\"${name}\" -DPACKAGE_VERSION=\"${version}\""
    append defs " -DPACKAGE_TARNAME=\"${name}\" -DPACKAGE_STRING=\"${name}\x5c\x20${version}\""
    return $defs
  }

  method critcl args {
    if {![info exists critcl]} {
      ::practcl::LOCAL tool critcl env-load
      set critcl [file join [::practcl::LOCAL tool critcl define get srcdir] main.tcl
    }
    set srcdir [my SourceRoot]
    set PWD [pwd]
    cd $srcdir
    ::practcl::dotclexec $critcl {*}$args
    cd $PWD
  }
  
  method make-autodetect {} {}
}


oo::objdefine ::practcl::toolset {


  method select object {
    ###
    # Select the toolset to use for this project
    ###
    if {[$object define exists toolset]} {
      return [$object define get toolset]
    }
    set class [$object define get toolset]
    if {$class ne {}} {
      $object mixin toolset $class
    } else {
      if {[info exists ::env(VisualStudioVersion)]} {
        $object mixin toolset ::practcl::toolset.msvc
      } else {
        $object mixin toolset ::practcl::toolset.gcc
      }
    }
  }
}

###
# END: class toolset baseclass.tcl
###
###
# START: class toolset gcc.tcl
###

::oo::class create ::practcl::toolset.gcc {
  superclass ::practcl::toolset

  method Autoconf {} {
    ###
    # Re-run autoconf for this project
    # Not a good idea in practice... but in the right hands it can be useful
    ###
    set pwd [pwd]
    set srcdir [file normalize [my define get srcdir]]

    cd $srcdir
    foreach template {configure.ac configure.in} {
      set input [file join $srcdir $template]
      if {[file exists $input]} {
        puts "autoconf -f $input > [file join $srcdir configure]"
        exec autoconf -f $input > [file join $srcdir configure]
      }
    }
    cd $pwd
  }

  method BuildDir {PWD} {
    set name [my define get name]
    set debug [my define get debug 0]
    if {[my <project> define get LOCAL 0]} {
      return [my define get builddir [file join $PWD local $name]]
    }
    if {$debug} {
      return [my define get builddir [file join $PWD debug $name]]
    } else {
      return [my define get builddir [file join $PWD pkg $name]]
    }
  }

  method ConfigureOpts {} {
    set opts {}
    set builddir [my define get builddir]

    if {[my define get broken_destroot 0]} {
      set PREFIX [my <project> define get prefix_broken_destdir]
    } else {







<











|
<
<
<
<

|
<









|


|

|











<
|

<







>
|









<












<







4027
4028
4029
4030
4031
4032
4033

4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045




4046
4047

4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073

4074
4075

4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093

4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105

4106
4107
4108
4109
4110
4111
4112
        set defs "$predef $postdef"
      }
    }
    append defs " -DPACKAGE_NAME=\"${name}\" -DPACKAGE_VERSION=\"${version}\""
    append defs " -DPACKAGE_TARNAME=\"${name}\" -DPACKAGE_STRING=\"${name}\x5c\x20${version}\""
    return $defs
  }

  method critcl args {
    if {![info exists critcl]} {
      ::practcl::LOCAL tool critcl env-load
      set critcl [file join [::practcl::LOCAL tool critcl define get srcdir] main.tcl
    }
    set srcdir [my SourceRoot]
    set PWD [pwd]
    cd $srcdir
    ::practcl::dotclexec $critcl {*}$args
    cd $PWD
  }
}




oo::objdefine ::practcl::toolset {
  # Perform the selection for the toolset mixin

  method select object {
    ###
    # Select the toolset to use for this project
    ###
    if {[$object define exists toolset]} {
      return [$object define get toolset]
    }
    set class [$object define get toolset]
    if {$class ne {}} {
      $object clay mixinmap toolset $class
    } else {
      if {[info exists ::env(VisualStudioVersion)]} {
        $object clay mixinmap toolset ::practcl::toolset.msvc
      } else {
        $object clay mixinmap toolset ::practcl::toolset.gcc
      }
    }
  }
}

###
# END: class toolset baseclass.tcl
###
###
# START: class toolset gcc.tcl
###

::clay::define ::practcl::toolset.gcc {
  superclass ::practcl::toolset

  method Autoconf {} {
    ###
    # Re-run autoconf for this project
    # Not a good idea in practice... but in the right hands it can be useful
    ###
    set pwd [pwd]
    set srcdir [file normalize [my define get srcdir]]
    set localsrcdir [my MakeDir $srcdir]
    cd $localsrcdir
    foreach template {configure.ac configure.in} {
      set input [file join $srcdir $template]
      if {[file exists $input]} {
        puts "autoconf -f $input > [file join $srcdir configure]"
        exec autoconf -f $input > [file join $srcdir configure]
      }
    }
    cd $pwd
  }

  method BuildDir {PWD} {
    set name [my define get name]
    set debug [my define get debug 0]
    if {[my <project> define get LOCAL 0]} {
      return [my define get builddir [file join $PWD local $name]]
    }
    if {$debug} {
      return [my define get builddir [file join $PWD debug $name]]
    } else {
      return [my define get builddir [file join $PWD pkg $name]]
    }
  }

  method ConfigureOpts {} {
    set opts {}
    set builddir [my define get builddir]

    if {[my define get broken_destroot 0]} {
      set PREFIX [my <project> define get prefix_broken_destdir]
    } else {
1791
1792
1793
1794
1795
1796
1797


1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815



1816
1817






1818


1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
      }
    }
    if {[my <project> define get CONFIG_SITE] != {}} {
      lappend opts --host=[my <project> define get HOST]
    }
    set inside_msys [string is true -strict [my <project> define get MSYS_ENV 0]]
    lappend opts --with-tclsh=[info nameofexecutable]


    if {![my <project> define get LOCAL 0]} {
      set obj [my <project> tclcore]
      if {$obj ne {}} {
        if {$inside_msys} {
          lappend opts --with-tcl=[::practcl::file_relative [file normalize $builddir] [$obj define get builddir]]
        } else {
          lappend opts --with-tcl=[file normalize [$obj define get builddir]]
        }
      }
      if {[my define get tk 0]} {
        set obj [my <project> tkcore]
        if {$obj ne {}} {
          if {$inside_msys} {
            lappend opts --with-tk=[::practcl::file_relative [file normalize $builddir] [$obj define get builddir]]
          } else {
            lappend opts --with-tk=[file normalize [$obj define get builddir]]
          }
        }



      }
    } else {






      lappend opts --with-tcl=[file join $PREFIX lib]


      if {[my define get tk 0]} {
        lappend opts --with-tk=[file join $PREFIX lib]
      }
    }

    lappend opts {*}[my define get config_opts]
    if {![regexp -- "--prefix" $opts]} {
      lappend opts --prefix=$PREFIX --exec-prefix=$PREFIX
    }
    if {[my define get debug 0]} {







>
>
|
|
|
|
|
|
|
|
|
<








>
>
>


>
>
>
>
>
>
|
>
>
|
|








4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138

4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
      }
    }
    if {[my <project> define get CONFIG_SITE] != {}} {
      lappend opts --host=[my <project> define get HOST]
    }
    set inside_msys [string is true -strict [my <project> define get MSYS_ENV 0]]
    lappend opts --with-tclsh=[info nameofexecutable]

    if {[my define get tk 0]} {
      if {![my <project> define get LOCAL 0]} {
        set obj [my <project> tclcore]
        if {$obj ne {}} {
          if {$inside_msys} {
            lappend opts --with-tcl=[::practcl::file_relative [file normalize $builddir] [$obj define get builddir]]
          } else {
            lappend opts --with-tcl=[file normalize [$obj define get builddir]]
          }
        }

        set obj [my <project> tkcore]
        if {$obj ne {}} {
          if {$inside_msys} {
            lappend opts --with-tk=[::practcl::file_relative [file normalize $builddir] [$obj define get builddir]]
          } else {
            lappend opts --with-tk=[file normalize [$obj define get builddir]]
          }
        }
      } else {
        lappend opts --with-tcl=[file join $PREFIX lib]
        lappend opts --with-tk=[file join $PREFIX lib]
      }
    } else {
      if {![my <project> define get LOCAL 0]} {
        set obj [my <project> tclcore]
        if {$obj ne {}} {
          if {$inside_msys} {
            lappend opts --with-tcl=[::practcl::file_relative [file normalize $builddir] [$obj define get builddir]]
          } else {
            lappend opts --with-tcl=[file normalize [$obj define get builddir]]
          }
        }
      } else {
        lappend opts --with-tcl=[file join $PREFIX lib]
      }
    }

    lappend opts {*}[my define get config_opts]
    if {![regexp -- "--prefix" $opts]} {
      lappend opts --prefix=$PREFIX --exec-prefix=$PREFIX
    }
    if {[my define get debug 0]} {
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859





1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880



1881
1882
1883
1884
1885
1886
1887
      #--disable-stubs
      #
    } else {
      lappend opts --enable-shared
    }
    return $opts
  }

  # Detect what directory contains the Makefile template
  method MakeDir {srcdir} {
    set localsrcdir $srcdir
    if {[file exists [file join $srcdir generic]]} {
      my define add include_dir [file join $srcdir generic]
    }
    set os [my <project> define get TEACUP_OS]
    switch $os {
      windows {
        if {[file exists [file join $srcdir win]]} {
          my define add include_dir [file join $srcdir win]
        }
        if {[file exists [file join $srcdir win Makefile.in]]} {
          set localsrcdir [file join $srcdir win]
        }





      }
      default {
        if {[file exists [file join $srcdir $os]]} {
          my define add include_dir [file join $srcdir $os]
        }
        if {[file exists [file join $srcdir unix]]} {
          my define add include_dir [file join $srcdir unix]
        }
        if {[file exists [file join $srcdir $os Makefile.in]]} {
          set localsrcdir [file join $srcdir $os]
        } elseif {[file exists [file join $srcdir unix Makefile.in]]} {
          set localsrcdir [file join $srcdir unix]
        }
      }
    }
    return $localsrcdir
  }

  method make-autodetect {} {
    set srcdir [my define get srcdir]
    set localsrcdir [my define get localsrcdir]



    if {$srcdir eq $localsrcdir} {
      if {![file exists [file join $srcdir tclconfig install-sh]]} {
        # ensure we have tclconfig with all of the trimmings
        set teapath {}
        if {[file exists [file join $srcdir .. tclconfig install-sh]]} {
          set teapath [file join $srcdir .. tclconfig]
        } else {







<
<














>
>
>
>
>

















<
|

|
>
>
>







4179
4180
4181
4182
4183
4184
4185


4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221

4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
      #--disable-stubs
      #
    } else {
      lappend opts --enable-shared
    }
    return $opts
  }


  method MakeDir {srcdir} {
    set localsrcdir $srcdir
    if {[file exists [file join $srcdir generic]]} {
      my define add include_dir [file join $srcdir generic]
    }
    set os [my <project> define get TEACUP_OS]
    switch $os {
      windows {
        if {[file exists [file join $srcdir win]]} {
          my define add include_dir [file join $srcdir win]
        }
        if {[file exists [file join $srcdir win Makefile.in]]} {
          set localsrcdir [file join $srcdir win]
        }
      }
      macosx {
        if {[file exists [file join $srcdir unix Makefile.in]]} {
          set localsrcdir [file join $srcdir unix]
        }
      }
      default {
        if {[file exists [file join $srcdir $os]]} {
          my define add include_dir [file join $srcdir $os]
        }
        if {[file exists [file join $srcdir unix]]} {
          my define add include_dir [file join $srcdir unix]
        }
        if {[file exists [file join $srcdir $os Makefile.in]]} {
          set localsrcdir [file join $srcdir $os]
        } elseif {[file exists [file join $srcdir unix Makefile.in]]} {
          set localsrcdir [file join $srcdir unix]
        }
      }
    }
    return $localsrcdir
  }

  Ensemble make::autodetect {} {
    set srcdir [my define get srcdir]
    set localsrcdir [my MakeDir $srcdir]
    if {$localsrcdir eq {}} {
      set localsrcdir $srcdir
    }
    if {$srcdir eq $localsrcdir} {
      if {![file exists [file join $srcdir tclconfig install-sh]]} {
        # ensure we have tclconfig with all of the trimmings
        set teapath {}
        if {[file exists [file join $srcdir .. tclconfig install-sh]]} {
          set teapath [file join $srcdir .. tclconfig]
        } else {
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
    cd $builddir
    if {[my <project> define get CONFIG_SITE] ne {}} {
      set ::env(CONFIG_SITE) [my <project> define get CONFIG_SITE]
    }
    catch {exec sh [file join $localsrcdir configure] {*}$opts >>& [file join $builddir autoconf.log]}
    cd $::CWD
  }

  method make-clean {} {
    set builddir [file normalize [my define get builddir]]
    catch {::practcl::domake $builddir clean}
  }

  method make-compile {} {
    set name [my define get name]
    set srcdir [my define get srcdir]
    if {[my define get static 1]} {
      puts "BUILDING Static $name $srcdir"
    } else {
      puts "BUILDING Dynamic $name $srcdir"
    }







<
|



<
|







4261
4262
4263
4264
4265
4266
4267

4268
4269
4270
4271

4272
4273
4274
4275
4276
4277
4278
4279
    cd $builddir
    if {[my <project> define get CONFIG_SITE] ne {}} {
      set ::env(CONFIG_SITE) [my <project> define get CONFIG_SITE]
    }
    catch {exec sh [file join $localsrcdir configure] {*}$opts >>& [file join $builddir autoconf.log]}
    cd $::CWD
  }

  Ensemble make::clean {} {
    set builddir [file normalize [my define get builddir]]
    catch {::practcl::domake $builddir clean}
  }

  Ensemble make::compile {} {
    set name [my define get name]
    set srcdir [my define get srcdir]
    if {[my define get static 1]} {
      puts "BUILDING Static $name $srcdir"
    } else {
      puts "BUILDING Dynamic $name $srcdir"
    }
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
      } else {
        ::practcl::domake.tcl $builddir all
      }
    } else {
      ::practcl::domake $builddir all
    }
  }

  method make-install DEST {
    set PWD [pwd]
    set builddir [my define get builddir]
    if {[my <project> define get LOCAL 0] || $DEST eq {}} {
      if {[file exists [file join $builddir make.tcl]]} {
        puts "[self] Local INSTALL (Practcl)"
        ::practcl::domake.tcl $builddir install
      } elseif {[my define get broken_destroot 0] == 0} {







<
|







4289
4290
4291
4292
4293
4294
4295

4296
4297
4298
4299
4300
4301
4302
4303
      } else {
        ::practcl::domake.tcl $builddir all
      }
    } else {
      ::practcl::domake $builddir all
    }
  }

  Ensemble make::install DEST {
    set PWD [pwd]
    set builddir [my define get builddir]
    if {[my <project> define get LOCAL 0] || $DEST eq {}} {
      if {[file exists [file join $builddir make.tcl]]} {
        puts "[self] Local INSTALL (Practcl)"
        ::practcl::domake.tcl $builddir install
      } elseif {[my define get broken_destroot 0] == 0} {
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
        ::practcl::domake $builddir $install
        ::practcl::copyDir $BROKENROOT  [file join $DEST [string trimleft $PREFIX /]]
        file delete -force $BROKENROOT
      }
    }
    cd $PWD
  }

  method build-compile-sources {PROJECT COMPILE CPPCOMPILE INCLUDES} {
    set objext [my define get OBJEXT o]
    set EXTERN_OBJS {}
    set OBJECTS {}
    set result {}
    set builddir [$PROJECT define get builddir]
    file mkdir [file join $builddir objs]







<







4324
4325
4326
4327
4328
4329
4330

4331
4332
4333
4334
4335
4336
4337
        ::practcl::domake $builddir $install
        ::practcl::copyDir $BROKENROOT  [file join $DEST [string trimleft $PREFIX /]]
        file delete -force $BROKENROOT
      }
    }
    cd $PWD
  }

  method build-compile-sources {PROJECT COMPILE CPPCOMPILE INCLUDES} {
    set objext [my define get OBJEXT o]
    set EXTERN_OBJS {}
    set OBJECTS {}
    set result {}
    set builddir [$PROJECT define get builddir]
    file mkdir [file join $builddir objs]
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
          continue
        }
        error "Failed to produce $filename"
      }
    }
    return $result
  }

method build-Makefile {path PROJECT} {
  array set proj [$PROJECT define dump]
  set path $proj(builddir)
  cd $path
  set includedir .
  set objext [my define get OBJEXT o]








<







4420
4421
4422
4423
4424
4425
4426

4427
4428
4429
4430
4431
4432
4433
          continue
        }
        error "Failed to produce $filename"
      }
    }
    return $result
  }

method build-Makefile {path PROJECT} {
  array set proj [$PROJECT define dump]
  set path $proj(builddir)
  cd $path
  set includedir .
  set objext [my define get OBJEXT o]

2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186








2187

2188
2189
2190
2191







2192
2193
2194
2195
2196
2197
2198
  $PROJECT define set static_library $outfile
  dict set map %OUTFILE% $outfile
  ::practcl::cputs result "$outfile: \$(${NAME}_OBJS)"
  ::practcl::cputs result "\t[string map $map [$PROJECT define get PRACTCL_STATIC_LIB]]"
  ::practcl::cputs result {}
  return $result
}

###
# Produce a static or dynamic library
###
method build-library {outfile PROJECT} {
  array set proj [$PROJECT define dump]
  set path $proj(builddir)
  cd $path
  set includedir .
  #lappend includedir [::practcl::file_relative $path $proj(TCL_INCLUDES)]
  lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TCL_SRC_DIR) generic]]]








  lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(srcdir) generic]]]

  if {[$PROJECT define get tk 0]} {
    lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) generic]]]
    lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) ttk]]]
    lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) xlib]]]







    lappend includedir [::practcl::file_relative $path [file normalize $proj(TK_BIN_DIR)]]
  }
  foreach include [$PROJECT toolset-include-directory] {
    set cpath [::practcl::file_relative $path [file normalize $include]]
    if {$cpath ni $includedir} {
      lappend includedir $cpath
    }







<
<
<
<







>
>
>
>
>
>
>
>

>




>
>
>
>
>
>
>







4511
4512
4513
4514
4515
4516
4517




4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
  $PROJECT define set static_library $outfile
  dict set map %OUTFILE% $outfile
  ::practcl::cputs result "$outfile: \$(${NAME}_OBJS)"
  ::practcl::cputs result "\t[string map $map [$PROJECT define get PRACTCL_STATIC_LIB]]"
  ::practcl::cputs result {}
  return $result
}




method build-library {outfile PROJECT} {
  array set proj [$PROJECT define dump]
  set path $proj(builddir)
  cd $path
  set includedir .
  #lappend includedir [::practcl::file_relative $path $proj(TCL_INCLUDES)]
  lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TCL_SRC_DIR) generic]]]
  if {[$PROJECT define get TEA_PRIVATE_TCL_HEADERS 0]} {
    if {[$PROJECT define get TEA_PLATFORM] eq "windows"} {
      lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TCL_SRC_DIR) win]]]
    } else {
      lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TCL_SRC_DIR) unix]]]
    }
  }

  lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(srcdir) generic]]]

  if {[$PROJECT define get tk 0]} {
    lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) generic]]]
    lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) ttk]]]
    lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) xlib]]]
    if {[$PROJECT define get TEA_PRIVATE_TK_HEADERS 0]} {
      if {[$PROJECT define get TEA_PLATFORM] eq "windows"} {
        lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) win]]]
      } else {
        lappend includedir [::practcl::file_relative $path [file normalize [file join $proj(TK_SRC_DIR) unix]]]
      }
    }
    lappend includedir [::practcl::file_relative $path [file normalize $proj(TK_BIN_DIR)]]
  }
  foreach include [$PROJECT toolset-include-directory] {
    set cpath [::practcl::file_relative $path [file normalize $include]]
    if {$cpath ni $includedir} {
      lappend includedir $cpath
    }
2250
2251
2252
2253
2254
2255
2256














2257
2258
2259
2260
2261
2262



2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276


2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
    exec {*}$cmd >&@ stdout
  }
  set ranlib [$PROJECT define get RANLIB]
  if {$ranlib ni {{} :}} {
    catch {exec $ranlib $outfile}
  }
}















###
# Produce a static executable
###
method build-tclsh {outfile PROJECT} {
  puts " BUILDING STATIC TCLSH "



  set TCLOBJ [$PROJECT tclcore]
  ::practcl::toolset select $TCLOBJ
  set PKG_OBJS {}
  foreach item [$PROJECT link list core.library] {
    if {[string is true [$item define get static]]} {
      lappend PKG_OBJS $item
    }
  }
  foreach item [$PROJECT link list package] {
    if {[string is true [$item define get static]]} {
      lappend PKG_OBJS $item
    }
  }
  array set TCL [$TCLOBJ read_configuration]



  set TKOBJ  [$PROJECT tkcore]
  if {[info command $TKOBJ] eq {}} {
    set TKOBJ ::noop
    $PROJECT define set static_tk 0
  } else {
    ::practcl::toolset select $TKOBJ
    array set TK  [$TKOBJ read_configuration]
    set do_tk [$TKOBJ define get static]
    $PROJECT define set static_tk $do_tk
    $PROJECT define set tk $do_tk
    set TKSRCDIR [$TKOBJ define get srcdir]
  }
  set path [file dirname $outfile]
  cd $path
  ###
  # For a static Tcl shell, we need to build all local sources
  # with the same DEFS flags as the tcl core was compiled with.
  # The DEFS produced by a TEA extension aren't intended to operate
  # with the internals of a staticly linked Tcl
  ###







>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
|
<
<
|
>
>
>














>
>
|
<
|
|
<
<
<
<
<
<
<
<

<







4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625

4626


4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647

4648
4649








4650

4651
4652
4653
4654
4655
4656
4657
    exec {*}$cmd >&@ stdout
  }
  set ranlib [$PROJECT define get RANLIB]
  if {$ranlib ni {{} :}} {
    catch {exec $ranlib $outfile}
  }
}
method build-tclsh {outfile PROJECT {path {auto}}} {
  if {[my define get tk 0] && [my define get static_tk 0]} {
    puts " BUILDING STATIC TCL/TK EXE $PROJECT"
    set TKOBJ  [$PROJECT tkcore]
    if {[info command $TKOBJ] eq {}} {
      set TKOBJ ::noop
      $PROJECT define set static_tk 0
    } else {
      ::practcl::toolset select $TKOBJ
      array set TK  [$TKOBJ read_configuration]
      set do_tk [$TKOBJ define get static]
      $PROJECT define set static_tk $do_tk
      $PROJECT define set tk $do_tk
      set TKSRCDIR [$TKOBJ define get srcdir]
    }

  } else {


    puts " BUILDING STATIC TCL EXE $PROJECT"
    set TKOBJ ::noop
    my define set static_tk 0
  }
  set TCLOBJ [$PROJECT tclcore]
  ::practcl::toolset select $TCLOBJ
  set PKG_OBJS {}
  foreach item [$PROJECT link list core.library] {
    if {[string is true [$item define get static]]} {
      lappend PKG_OBJS $item
    }
  }
  foreach item [$PROJECT link list package] {
    if {[string is true [$item define get static]]} {
      lappend PKG_OBJS $item
    }
  }
  array set TCL [$TCLOBJ read_configuration]
  if {$path in {{} auto}} {
    set path [file dirname [file normalize $outfile]]
  }

  if {$path eq "."} {
    set path [pwd]








  }

  cd $path
  ###
  # For a static Tcl shell, we need to build all local sources
  # with the same DEFS flags as the tcl core was compiled with.
  # The DEFS produced by a TEA extension aren't intended to operate
  # with the internals of a staticly linked Tcl
  ###
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352

2353
2354
2355
2356
2357
2358
2359
2360
2361



2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372



2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383



2384
2385
2386
2387
2388
2389
2390
  append COMPILE " " $defs
  lappend OBJECTS {*}[my build-compile-sources $PROJECT $COMPILE $COMPILE $INCLUDES]

  set TCLSRC [file normalize $TCLSRCDIR]

  if {[${PROJECT} define get TEACUP_OS] eq "windows"} {
    set windres [$PROJECT define get RC windres]
    set RSOBJ [file join $path build tclkit.res.o]
    set RCSRC [${PROJECT} define get kit_resource_file]
    set RCMAN [${PROJECT} define get kit_manifest_file]


    set cmd [list $windres -o $RSOBJ -DSTATIC_BUILD --include [::practcl::file_relative $path [file join $TCLSRC generic]]]
    if {[$PROJECT define get static_tk]} {
      if {$RCSRC eq {} || ![file exists $RCSRC]} {
        set RCSRC [file join $TKSRCDIR win rc wish.rc]
      }
      if {$RCMAN eq {} || ![file exists $RCMAN]} {
        set RCMAN [file join [$TKOBJ define get builddir] wish.exe.manifest]
      }



      set TKSRC [file normalize $TKSRCDIR]
      lappend cmd --include [::practcl::file_relative $path [file join $TKSRC generic]] \
        --include [::practcl::file_relative $path [file join $TKSRC win]] \
        --include [::practcl::file_relative $path [file join $TKSRC win rc]]
    } else {
      if {$RCSRC eq {} || ![file exists $RCSRC]} {
        set RCSRC [file join $TCLSRCDIR tclsh.rc]
      }
      if {$RCMAN eq {} || ![file exists $RCMAN]} {
        set RCMAN [file join [$TCLOBJ define get builddir] tclsh.exe.manifest]
      }



    }
    foreach item [${PROJECT} define get resource_include] {
      lappend cmd --include [::practcl::file_relative $path [file normalize $item]]
    }
    lappend cmd [file tail $RCSRC]
    if {![file exists [file join $path [file tail $RCSRC]]]} {
      file copy -force $RCSRC [file join $path [file tail $RCSRC]]
    }
    if {![file exists [file join $path [file tail $RCMAN]]]} {
      file copy -force $RCMAN [file join $path [file tail $RCMAN]]
    }



    ::practcl::doexec {*}$cmd
    lappend OBJECTS $RSOBJ
  }
  puts "***"
  set cmd "$TCL(cc)"
  if {$debug} {
   append cmd " $TCL(cflags_debug)"







|


>









>
>
>






|




>
>
>











>
>
>







4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
  append COMPILE " " $defs
  lappend OBJECTS {*}[my build-compile-sources $PROJECT $COMPILE $COMPILE $INCLUDES]

  set TCLSRC [file normalize $TCLSRCDIR]

  if {[${PROJECT} define get TEACUP_OS] eq "windows"} {
    set windres [$PROJECT define get RC windres]
    set RSOBJ [file join $path objs tclkit.res.o]
    set RCSRC [${PROJECT} define get kit_resource_file]
    set RCMAN [${PROJECT} define get kit_manifest_file]
    set RCICO [${PROJECT} define get kit_icon_file]

    set cmd [list $windres -o $RSOBJ -DSTATIC_BUILD --include [::practcl::file_relative $path [file join $TCLSRC generic]]]
    if {[$PROJECT define get static_tk]} {
      if {$RCSRC eq {} || ![file exists $RCSRC]} {
        set RCSRC [file join $TKSRCDIR win rc wish.rc]
      }
      if {$RCMAN eq {} || ![file exists $RCMAN]} {
        set RCMAN [file join [$TKOBJ define get builddir] wish.exe.manifest]
      }
      if {$RCICO eq {} || ![file exists $RCICO]} {
        set RCICO [file join $TKSRCDIR win rc wish.ico]
      }
      set TKSRC [file normalize $TKSRCDIR]
      lappend cmd --include [::practcl::file_relative $path [file join $TKSRC generic]] \
        --include [::practcl::file_relative $path [file join $TKSRC win]] \
        --include [::practcl::file_relative $path [file join $TKSRC win rc]]
    } else {
      if {$RCSRC eq {} || ![file exists $RCSRC]} {
        set RCSRC [file join $TCLSRCDIR win tclsh.rc]
      }
      if {$RCMAN eq {} || ![file exists $RCMAN]} {
        set RCMAN [file join [$TCLOBJ define get builddir] tclsh.exe.manifest]
      }
      if {$RCICO eq {} || ![file exists $RCICO]} {
        set RCICO [file join $TCLSRCDIR win tclsh.ico]
      }
    }
    foreach item [${PROJECT} define get resource_include] {
      lappend cmd --include [::practcl::file_relative $path [file normalize $item]]
    }
    lappend cmd [file tail $RCSRC]
    if {![file exists [file join $path [file tail $RCSRC]]]} {
      file copy -force $RCSRC [file join $path [file tail $RCSRC]]
    }
    if {![file exists [file join $path [file tail $RCMAN]]]} {
      file copy -force $RCMAN [file join $path [file tail $RCMAN]]
    }
    if {![file exists [file join $path [file tail $RCICO]]]} {
      file copy -force $RCICO [file join $path [file tail $RCICO]]
    }
    ::practcl::doexec {*}$cmd
    lappend OBJECTS $RSOBJ
  }
  puts "***"
  set cmd "$TCL(cc)"
  if {$debug} {
   append cmd " $TCL(cflags_debug)"
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
    set LDFLAGS_CONSOLE {-mconsole -pipe -static-libgcc}
    set LDFLAGS_WINDOW  {-mwindows -pipe -static-libgcc}
    append cmd " $LDFLAGS_CONSOLE"
  }
  puts "LINK: $cmd"
  exec {*}[string map [list "\n" " " "  " " "] $cmd] >&@ stdout
}

}

###
# END: class toolset gcc.tcl
###
###
# START: class toolset msvc.tcl
###
::oo::class create ::practcl::toolset.msvc {
  superclass ::practcl::toolset

  # MSVC always builds in the source directory
  method BuildDir {PWD} {
    set srcdir [my define get srcdir]
    return $srcdir
  }

  
  # Do nothing
  method make-autodetect {} {
  }
  
  method make-clean {} {
    set PWD [pwd]
    set srcdir [my define get srcdir]
    cd $srcdir
    catch {::practcl::doexec nmake -f makefile.vc clean}
    cd $PWD
  }
  
  method make-compile {} {
    set srcdir [my define get srcdir]
    if {[my define get static 1]} {
      puts "BUILDING Static $name $srcdir"
    } else {
      puts "BUILDING Dynamic $name $srcdir"
    }
    cd $srcdir







<








|

<
<




<
<
<
|

<
|






<
|







4839
4840
4841
4842
4843
4844
4845

4846
4847
4848
4849
4850
4851
4852
4853
4854
4855


4856
4857
4858
4859



4860
4861

4862
4863
4864
4865
4866
4867
4868

4869
4870
4871
4872
4873
4874
4875
4876
    set LDFLAGS_CONSOLE {-mconsole -pipe -static-libgcc}
    set LDFLAGS_WINDOW  {-mwindows -pipe -static-libgcc}
    append cmd " $LDFLAGS_CONSOLE"
  }
  puts "LINK: $cmd"
  exec {*}[string map [list "\n" " " "  " " "] $cmd] >&@ stdout
}

}

###
# END: class toolset gcc.tcl
###
###
# START: class toolset msvc.tcl
###
::clay::define ::practcl::toolset.msvc {
  superclass ::practcl::toolset


  method BuildDir {PWD} {
    set srcdir [my define get srcdir]
    return $srcdir
  }



  Ensemble make::autodetect {} {
  }

  Ensemble make::clean {} {
    set PWD [pwd]
    set srcdir [my define get srcdir]
    cd $srcdir
    catch {::practcl::doexec nmake -f makefile.vc clean}
    cd $PWD
  }

  Ensemble make::compile {} {
    set srcdir [my define get srcdir]
    if {[my define get static 1]} {
      puts "BUILDING Static $name $srcdir"
    } else {
      puts "BUILDING Dynamic $name $srcdir"
    }
    cd $srcdir
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
        cd [file join $srcdir win]
        ::practcl::doexec nmake -f makefile.vc INSTALLDIR=[my <project> define get installdir]  {*}[my NmakeOpts] release
      } else {
        error "No make.tcl or makefile.vc found for project $name"
      }
    }
  }
  
  method make-install DEST {
    set PWD [pwd]
    set srcdir [my define get srcdir]
    cd $srcdir
    if {$DEST eq {}} {
      error "No destination given"
    }
    if {[my <project> define get LOCAL 0] || $DEST eq {}} {







<
|







4887
4888
4889
4890
4891
4892
4893

4894
4895
4896
4897
4898
4899
4900
4901
        cd [file join $srcdir win]
        ::practcl::doexec nmake -f makefile.vc INSTALLDIR=[my <project> define get installdir]  {*}[my NmakeOpts] release
      } else {
        error "No make.tcl or makefile.vc found for project $name"
      }
    }
  }

  Ensemble make::install DEST {
    set PWD [pwd]
    set srcdir [my define get srcdir]
    cd $srcdir
    if {$DEST eq {}} {
      error "No destination given"
    }
    if {[my <project> define get LOCAL 0] || $DEST eq {}} {
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
      } else {
        puts "[self] VFS INSTALL $DEST"
        ::practcl::doexec nmake -f makefile.vc INSTALLDIR=$DEST {*}[my NmakeOpts] install
      }
    }
    cd $PWD
  }
  
  # Detect what directory contains the Makefile template
  method MakeDir {srcdir} {
    set localsrcdir $srcdir
    if {[file exists [file join $srcdir generic]]} {
      my define add include_dir [file join $srcdir generic]
    }
    if {[file exists [file join $srcdir win]]} {
       my define add include_dir [file join $srcdir win]
    }
    if {[file exists [file join $srcdir makefile.vc]]} {
      set localsrcdir [file join $srcdir win]
    }
    return $localsrcdir
  }
  
  method NmakeOpts {} {
    set opts {}
    set builddir [file normalize [my define get builddir]]

    if {[my <project> define exists tclsrcdir]} {
      ###
      # On Windows we are probably running under MSYS, which doesn't deal with







<
<













<







4915
4916
4917
4918
4919
4920
4921


4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934

4935
4936
4937
4938
4939
4940
4941
      } else {
        puts "[self] VFS INSTALL $DEST"
        ::practcl::doexec nmake -f makefile.vc INSTALLDIR=$DEST {*}[my NmakeOpts] install
      }
    }
    cd $PWD
  }


  method MakeDir {srcdir} {
    set localsrcdir $srcdir
    if {[file exists [file join $srcdir generic]]} {
      my define add include_dir [file join $srcdir generic]
    }
    if {[file exists [file join $srcdir win]]} {
       my define add include_dir [file join $srcdir win]
    }
    if {[file exists [file join $srcdir makefile.vc]]} {
      set localsrcdir [file join $srcdir win]
    }
    return $localsrcdir
  }

  method NmakeOpts {} {
    set opts {}
    set builddir [file normalize [my define get builddir]]

    if {[my <project> define exists tclsrcdir]} {
      ###
      # On Windows we are probably running under MSYS, which doesn't deal with
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639

###
# END: class toolset msvc.tcl
###
###
# START: class target.tcl
###

::oo::class create ::practcl::make_obj {
  superclass ::practcl::metaclass

  constructor {module_object name info {action_body {}}} {
    my variable define triggered domake
    set triggered 0
    set domake 0
    set define(name) $name
    set define(action) {}
    array set define $info
    my select
    my initialize
    foreach {stub obj} [$module_object child organs] {
      my graft $stub $obj
    }
    if {$action_body ne {}} {
      set define(action) $action_body
    }
  }

  method do {} {
    my variable domake
    return $domake
  }

  method check {} {
    my variable needs_make domake
    if {$domake} {
      return 1
    }
    if {[info exists needs_make]} {
      return $needs_make







<
|

<
















<




<







4958
4959
4960
4961
4962
4963
4964

4965
4966

4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982

4983
4984
4985
4986

4987
4988
4989
4990
4991
4992
4993

###
# END: class toolset msvc.tcl
###
###
# START: class target.tcl
###

::clay::define ::practcl::make_obj {
  superclass ::practcl::metaclass

  constructor {module_object name info {action_body {}}} {
    my variable define triggered domake
    set triggered 0
    set domake 0
    set define(name) $name
    set define(action) {}
    array set define $info
    my select
    my initialize
    foreach {stub obj} [$module_object child organs] {
      my graft $stub $obj
    }
    if {$action_body ne {}} {
      set define(action) $action_body
    }
  }

  method do {} {
    my variable domake
    return $domake
  }

  method check {} {
    my variable needs_make domake
    if {$domake} {
      return 1
    }
    if {[info exists needs_make]} {
      return $needs_make
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
        if {$filename ne {} && ![file exists $filename]} {
          set needs_make 1
        }
      }
    }
    return $needs_make
  }
  
  method output {} {
    set result {}
    set filename [my define get filename]
    if {$filename ne {}} {
      lappend result $filename
    }
    foreach filename [my define get files] {
      if {$filename ne {}} {
        lappend result $filename
      }
    }
    return $result
  }

  method reset {} {
    my variable triggered domake needs_make
    set triggerd 0
    set domake 0
    set needs_make 0
  }
  
  method triggers {} {
    my variable triggered domake define
    if {$triggered} {
      return $domake
    }
    set triggered 1
    set make_objects [my <module> make objects]







<













<






<







5010
5011
5012
5013
5014
5015
5016

5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029

5030
5031
5032
5033
5034
5035

5036
5037
5038
5039
5040
5041
5042
        if {$filename ne {} && ![file exists $filename]} {
          set needs_make 1
        }
      }
    }
    return $needs_make
  }

  method output {} {
    set result {}
    set filename [my define get filename]
    if {$filename ne {}} {
      lappend result $filename
    }
    foreach filename [my define get files] {
      if {$filename ne {}} {
        lappend result $filename
      }
    }
    return $result
  }

  method reset {} {
    my variable triggered domake needs_make
    set triggerd 0
    set domake 0
    set needs_make 0
  }

  method triggers {} {
    my variable triggered domake define
    if {$triggered} {
      return $domake
    }
    set triggered 1
    set make_objects [my <module> make objects]
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815

###
# END: class target.tcl
###
###
# START: class object.tcl
###
::oo::class create ::practcl::object {
  superclass ::practcl::metaclass

  constructor {parent args} {
    my variable links define
    set organs [$parent child organs]
    my graft {*}$organs
    array set define $organs
    array set define [$parent child define]
    array set links {}
    if {[llength $args]==1 && [file exists [lindex $args 0]]} {
      my define set filename [lindex $args 0]
      ::practcl::product select [self]
    } elseif {[llength $args] == 1} {
      set data  [uplevel 1 [list subst [lindex $args 0]]]
      array set define $data
      my select
    } else {
      array set define [uplevel 1 [list subst $args]]
      my select
    }
    my initialize

  }

  method child {method} {
    return {}
  }

  method go {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable links
    foreach {linktype objs} [array get links] {
      foreach obj $objs {
        $obj go
      }
    }
    ::practcl::debug [list /[self] [self method] [self class]]
  }
}

###
# END: class object.tcl
###
###
# START: class dynamic.tcl
###

###
# Dynamic blocks do not generate their own .c files,
# instead the contribute to the amalgamation
# of the main library file
###
::oo::class create ::practcl::dynamic {

  ###
  # Parser functions
  ###

  method cstructure {name definition {argdat {}}} {
    my variable cstruct
    dict set cstruct $name body $definition
    foreach {f v} $argdat {
      dict set cstruct $name $f $v
    }
    if {![dict exists $cstruct $name public]} {
      dict set cstruct $name public 1
    }
  }
  
  method include header {
    my define add include $header
  }

  method include_dir args {
    my define add include_dir {*}$args
  }

  method include_directory args {
    my define add include_dir {*}$args
  }

  method c_header body {
    my variable code
    ::practcl::cputs code(header) $body
  }

  method c_code body {
    my variable code
    ::practcl::cputs code(funct) $body
  }

  method c_function {header body {info {}}} {
    set header [string map "\t \  \n \ \ \  \ " $header]
    my variable code cfunct
    foreach regexp {
         {(.*) ([a-zA-Z_][a-zA-Z0-9_]*) *\((.*)\)}
         {(.*) (\x2a[a-zA-Z_][a-zA-Z0-9_]*) *\((.*)\)}
    } {







|

<



|

















<



<


















<
<
<
<
<
<
|
<
<
<
<
<










<



<



<



<




<




<







5061
5062
5063
5064
5065
5066
5067
5068
5069

5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090

5091
5092
5093

5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111






5112





5113
5114
5115
5116
5117
5118
5119
5120
5121
5122

5123
5124
5125

5126
5127
5128

5129
5130
5131

5132
5133
5134
5135

5136
5137
5138
5139

5140
5141
5142
5143
5144
5145
5146

###
# END: class target.tcl
###
###
# START: class object.tcl
###
::clay::define ::practcl::object {
  superclass ::practcl::metaclass

  constructor {parent args} {
    my variable links define
    set organs [$parent child organs]
    my clay delegate {*}$organs
    array set define $organs
    array set define [$parent child define]
    array set links {}
    if {[llength $args]==1 && [file exists [lindex $args 0]]} {
      my define set filename [lindex $args 0]
      ::practcl::product select [self]
    } elseif {[llength $args] == 1} {
      set data  [uplevel 1 [list subst [lindex $args 0]]]
      array set define $data
      my select
    } else {
      array set define [uplevel 1 [list subst $args]]
      my select
    }
    my initialize

  }

  method child {method} {
    return {}
  }

  method go {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable links
    foreach {linktype objs} [array get links] {
      foreach obj $objs {
        $obj go
      }
    }
    ::practcl::debug [list /[self] [self method] [self class]]
  }
}

###
# END: class object.tcl
###
###
# START: class dynamic.tcl
###






::clay::define ::practcl::dynamic {





  method cstructure {name definition {argdat {}}} {
    my variable cstruct
    dict set cstruct $name body $definition
    foreach {f v} $argdat {
      dict set cstruct $name $f $v
    }
    if {![dict exists $cstruct $name public]} {
      dict set cstruct $name public 1
    }
  }

  method include header {
    my define add include $header
  }

  method include_dir args {
    my define add include_dir {*}$args
  }

  method include_directory args {
    my define add include_dir {*}$args
  }

  method c_header body {
    my variable code
    ::practcl::cputs code(header) $body
  }

  method c_code body {
    my variable code
    ::practcl::cputs code(funct) $body
  }

  method c_function {header body {info {}}} {
    set header [string map "\t \  \n \ \ \  \ " $header]
    my variable code cfunct
    foreach regexp {
         {(.*) ([a-zA-Z_][a-zA-Z0-9_]*) *\((.*)\)}
         {(.*) (\x2a[a-zA-Z_][a-zA-Z0-9_]*) *\((.*)\)}
    } {
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
    }
    puts "WARNING: NON CONFORMING FUNCTION DEFINITION: $headers $body"
    ::practcl::cputs code(header) "$header\;"
    # Could not parse that block as a function
    # append it verbatim to our c_implementation
    ::practcl::cputs code(funct) "$header [list $body]"
  }

  method c_tcloomethod {name body {arginfo {}}} {
    my variable methods code
    foreach {f v} $arginfo {
      dict set methods $name $f $v
    }
    dict set methods $name body "Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
$body"
  }

  # Alias to classic name
  method cmethod {name body {arginfo {}}} {
    my variable methods code
    foreach {f v} $arginfo {
      dict set methods $name $f $v
    }
    dict set methods $name body "Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
$body"
  }

  method c_tclproc_nspace nspace {
    my variable code
    if {![info exists code(nspace)]} {
      set code(nspace) {}
    }
    if {$nspace ni $code(nspace)} {
      lappend code(nspace) $nspace
    }
  }

  method c_tclcmd {name body {arginfo {}}} {
    my variable tclprocs code

    foreach {f v} $arginfo {
      dict set tclprocs $name $f $v
    }
    dict set tclprocs $name body $body
  }

  # Alias to classic name
  method c_tclproc_raw {name body {arginfo {}}} {
    my variable tclprocs code

    foreach {f v} $arginfo {
      dict set tclprocs $name $f $v
    }
    dict set tclprocs $name body $body
  }

  method tcltype {name argdat} {
    my variable tcltype
    foreach {f v} $argdat {
      dict set tcltype $name $f $v
    }
    if {![dict exists tcltype $name cname]} {
      dict set tcltype $name cname [string tolower $name]_tclobjtype







<








<
<








<









<








<
<








<







5180
5181
5182
5183
5184
5185
5186

5187
5188
5189
5190
5191
5192
5193
5194


5195
5196
5197
5198
5199
5200
5201
5202

5203
5204
5205
5206
5207
5208
5209
5210
5211

5212
5213
5214
5215
5216
5217
5218
5219


5220
5221
5222
5223
5224
5225
5226
5227

5228
5229
5230
5231
5232
5233
5234
    }
    puts "WARNING: NON CONFORMING FUNCTION DEFINITION: $headers $body"
    ::practcl::cputs code(header) "$header\;"
    # Could not parse that block as a function
    # append it verbatim to our c_implementation
    ::practcl::cputs code(funct) "$header [list $body]"
  }

  method c_tcloomethod {name body {arginfo {}}} {
    my variable methods code
    foreach {f v} $arginfo {
      dict set methods $name $f $v
    }
    dict set methods $name body "Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
$body"
  }


  method cmethod {name body {arginfo {}}} {
    my variable methods code
    foreach {f v} $arginfo {
      dict set methods $name $f $v
    }
    dict set methods $name body "Tcl_Object thisObject = Tcl_ObjectContextObject(objectContext); /* The current connection object */
$body"
  }

  method c_tclproc_nspace nspace {
    my variable code
    if {![info exists code(nspace)]} {
      set code(nspace) {}
    }
    if {$nspace ni $code(nspace)} {
      lappend code(nspace) $nspace
    }
  }

  method c_tclcmd {name body {arginfo {}}} {
    my variable tclprocs code

    foreach {f v} $arginfo {
      dict set tclprocs $name $f $v
    }
    dict set tclprocs $name body $body
  }


  method c_tclproc_raw {name body {arginfo {}}} {
    my variable tclprocs code

    foreach {f v} $arginfo {
      dict set tclprocs $name $f $v
    }
    dict set tclprocs $name body $body
  }

  method tcltype {name argdat} {
    my variable tcltype
    foreach {f v} $argdat {
      dict set tcltype $name $f $v
    }
    if {![dict exists tcltype $name cname]} {
      dict set tcltype $name cname [string tolower $name]_tclobjtype
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
      # We were given a function name to call
      if {[llength $body] eq 1} continue
      set fname [string map [list @Name@ [string totitle $name]] $fpat]
      my c_function [string map [list @FNAME@ $fname] $template] [string map $map $body]
      dict set tcltype $name $func $fname
    }
  }

  ###
  # Module interactions
  ###


  method project-compile-products {} {
    set filename [my define get output_c]
    set result {}
    if {$filename ne {}} {
      ::practcl::debug [self] [self class] [self method] project-compile-products $filename

      if {[my define exists ofile]} {







<
<
<
<
<
<







5251
5252
5253
5254
5255
5256
5257






5258
5259
5260
5261
5262
5263
5264
      # We were given a function name to call
      if {[llength $body] eq 1} continue
      set fname [string map [list @Name@ [string totitle $name]] $fpat]
      my c_function [string map [list @FNAME@ $fname] $template] [string map $map $body]
      dict set tcltype $name $func $fname
    }
  }






  method project-compile-products {} {
    set filename [my define get output_c]
    set result {}
    if {$filename ne {}} {
      ::practcl::debug [self] [self class] [self method] project-compile-products $filename

      if {[my define exists ofile]} {
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
      }
    }
    foreach item [my link list subordinate] {
      lappend result {*}[$item project-compile-products]
    }
    return $result
  }


  method implement path {
    my go
    my Collate_Source $path
    if {[my define get output_c] eq {}} return
    set filename [file join $path [my define get output_c]]
    ::practcl::debug [self] [my define get filename] WANTS TO GENERATE $filename
    my define set cfile $filename
    set fout [open $filename w]
    puts $fout [my generate-c]
    if {[my define get initfunc] ne {}} {
      puts $fout "extern int DLLEXPORT [my define get initfunc]( Tcl_Interp *interp ) \x7B"
      puts $fout [my generate-loader-module]
      if {[my define get pkg_name] ne {}} {
        puts $fout "   Tcl_PkgProvide(interp, \"[my define get pkg_name]\", \"[my define get pkg_vers]\");"
      }
      puts $fout "  return TCL_OK\;"
      puts $fout "\x7D"
    }
    close $fout
  }



  ###
  # Practcl internals
  ###

  method initialize {} {
    set filename [my define get filename]
    if {$filename eq {}} {
      return
    }
    if {[my define get name] eq {}} {
      my define set name [file tail [file rootname $filename]]
    }
    if {[my define get localpath] eq {}} {
      my define set localpath [my <module> define get localpath]_[my define get name]
    }
    ::source $filename
  }

  method linktype {} {
    return {subordinate product dynamic}
  }

  method generate-cfile-constant {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}
    my variable code cstruct methods tcltype
    if {[info exists code(constant)]} {
      ::practcl::cputs result "/* [my define get filename] CONSTANT */"
      ::practcl::cputs result $code(constant)







<
<




















<
<
<
<
<
<
<













<



<







5282
5283
5284
5285
5286
5287
5288


5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308







5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321

5322
5323
5324

5325
5326
5327
5328
5329
5330
5331
      }
    }
    foreach item [my link list subordinate] {
      lappend result {*}[$item project-compile-products]
    }
    return $result
  }


  method implement path {
    my go
    my Collate_Source $path
    if {[my define get output_c] eq {}} return
    set filename [file join $path [my define get output_c]]
    ::practcl::debug [self] [my define get filename] WANTS TO GENERATE $filename
    my define set cfile $filename
    set fout [open $filename w]
    puts $fout [my generate-c]
    if {[my define get initfunc] ne {}} {
      puts $fout "extern int DLLEXPORT [my define get initfunc]( Tcl_Interp *interp ) \x7B"
      puts $fout [my generate-loader-module]
      if {[my define get pkg_name] ne {}} {
        puts $fout "   Tcl_PkgProvide(interp, \"[my define get pkg_name]\", \"[my define get pkg_vers]\");"
      }
      puts $fout "  return TCL_OK\;"
      puts $fout "\x7D"
    }
    close $fout
  }







  method initialize {} {
    set filename [my define get filename]
    if {$filename eq {}} {
      return
    }
    if {[my define get name] eq {}} {
      my define set name [file tail [file rootname $filename]]
    }
    if {[my define get localpath] eq {}} {
      my define set localpath [my <module> define get localpath]_[my define get name]
    }
    ::source $filename
  }

  method linktype {} {
    return {subordinate product dynamic}
  }

  method generate-cfile-constant {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}
    my variable code cstruct methods tcltype
    if {[info exists code(constant)]} {
      ::practcl::cputs result "/* [my define get filename] CONSTANT */"
      ::practcl::cputs result $code(constant)
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
    foreach obj [my link list product] {
      # Exclude products that will generate their own C files
      if {[$obj define get output_c] ne {}} continue
      ::practcl::cputs result [$obj generate-cfile-constant]
    }
    return $result
  }

  method generate-cfile-header {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cfunct cstruct methods tcltype tclprocs
    set result {}
    if {[info exists code(header)]} {
      ::practcl::cputs result $code(header)
    }







<







5402
5403
5404
5405
5406
5407
5408

5409
5410
5411
5412
5413
5414
5415
    foreach obj [my link list product] {
      # Exclude products that will generate their own C files
      if {[$obj define get output_c] ne {}} continue
      ::practcl::cputs result [$obj generate-cfile-constant]
    }
    return $result
  }

  method generate-cfile-header {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cfunct cstruct methods tcltype tclprocs
    set result {}
    if {[info exists code(header)]} {
      ::practcl::cputs result $code(header)
    }
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
        ::practcl::cputs result "/* BEGIN [$obj define get filename] generate-cfile-header */"
        ::practcl::cputs result $dat
        ::practcl::cputs result "/* END [$obj define get filename] generate-cfile-header */"
      }
    }
    return $result
  }

  ###
  # Generate code that provides implements Tcl API
  # calls
  ###
  method generate-cfile-tclapi {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code methods tclprocs
    set result {}
    if {[info exists code(method)]} {
      ::practcl::cputs result $code(method)
    }







<
<
<
<
<







5447
5448
5449
5450
5451
5452
5453





5454
5455
5456
5457
5458
5459
5460
        ::practcl::cputs result "/* BEGIN [$obj define get filename] generate-cfile-header */"
        ::practcl::cputs result $dat
        ::practcl::cputs result "/* END [$obj define get filename] generate-cfile-header */"
      }
    }
    return $result
  }





  method generate-cfile-tclapi {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code methods tclprocs
    set result {}
    if {[info exists code(method)]} {
      ::practcl::cputs result $code(method)
    }
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
    foreach obj [my link list product] {
      # Exclude products that will generate their own C files
      if {[$obj define get output_c] ne {}} continue
      ::practcl::cputs result [$obj generate-cfile-tclapi]
    }
    return $result
  }

  ###
  # Generate code that runs when the package/module is
  # initialized into the interpreter
  ###
  method generate-loader-module {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}
    my variable code methods tclprocs
    if {[info exists code(nspace)]} {
      ::practcl::cputs result "  \{\n    Tcl_Namespace *modPtr;"
      foreach nspace $code(nspace) {







<
<
<
<
<







5536
5537
5538
5539
5540
5541
5542





5543
5544
5545
5546
5547
5548
5549
    foreach obj [my link list product] {
      # Exclude products that will generate their own C files
      if {[$obj define get output_c] ne {}} continue
      ::practcl::cputs result [$obj generate-cfile-tclapi]
    }
    return $result
  }





  method generate-loader-module {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}
    my variable code methods tclprocs
    if {[info exists code(nspace)]} {
      ::practcl::cputs result "  \{\n    Tcl_Namespace *modPtr;"
      foreach nspace $code(nspace) {
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
        ::practcl::cputs result [$obj generate-loader-external]
      } else {
        ::practcl::cputs result [$obj generate-loader-module]
      }
    }
    return $result
  }

  method Collate_Source CWD {
    my variable methods code cstruct tclprocs
    if {[info exists methods]} {
      ::practcl::debug [self] methods [my define get cclass]
      set thisclass [my define get cclass]
      foreach {name info} $methods {
        # Provide a callproc







<







5598
5599
5600
5601
5602
5603
5604

5605
5606
5607
5608
5609
5610
5611
        ::practcl::cputs result [$obj generate-loader-external]
      } else {
        ::practcl::cputs result [$obj generate-loader-module]
      }
    }
    return $result
  }

  method Collate_Source CWD {
    my variable methods code cstruct tclprocs
    if {[info exists methods]} {
      ::practcl::debug [self] methods [my define get cclass]
      set thisclass [my define get cclass]
      foreach {name info} $methods {
        # Provide a callproc
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
        }
        if {[dict exists $info body] && ![dict exists $info header]} {
          dict set tclprocs $name header "static int ${callproc}(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv\[\])"
        }
      }
    }
  }

  # Once an object marks itself as some
  # flavor of dynamic, stop trying to morph
  # it into something else
  method select {} {}

}



###
# END: class dynamic.tcl
###
###
# START: class product.tcl
###

::oo::class create ::practcl::product {


  method code {section body} {
    my variable code
    ::practcl::cputs code($section) $body
  }

  method Collate_Source CWD {}

  method project-compile-products {} {
    set result {}
    noop {
    set filename [my define get filename]
    if {$filename ne {}} {
      ::practcl::debug [self] [self class] [self method] project-compile-products $filename
      if {[my define exists ofile]} {
        set ofile [my define get ofile]
      } else {
        set ofile [my Ofile $filename]
        my define set ofile $ofile
      }
      lappend result $ofile [list cfile $filename include [my define get include]  extra [my define get extra] external [string is true -strict [my define get external]] object [self]]
    }
    }
    foreach item [my link list subordinate] {
      lappend result {*}[$item project-compile-products]
    }
    return $result
  }

  method generate-debug {{spaces {}}} {
    set result {}
    ::practcl::cputs result "$spaces[list [self] [list class [info object class [self]] filename [my define get filename]] links [my link list]]"
    foreach item [my link list subordinate] {
      practcl::cputs result [$item generate-debug "$spaces  "]
    }
    return $result
  }

  method generate-cfile-constant {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}
    my variable code cstruct methods tcltype
    if {[info exists code(constant)]} {
      ::practcl::cputs result "/* [my define get filename] CONSTANT */"
      ::practcl::cputs result $code(constant)
    }
    foreach obj [my link list product] {
      # Exclude products that will generate their own C files
      if {[$obj define get output_c] ne {}} continue
      ::practcl::cputs result [$obj generate-cfile-constant]
    }
    return $result
  }

  ###
  # Populate const static data structures
  ###
  method generate-cfile-public-structure {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cstruct methods tcltype
    set result {}
    if {[info exists code(struct)]} {
      ::practcl::cputs result $code(struct)
    }
    foreach obj [my link list product] {
      # Exclude products that will generate their own C files
      if {[$obj define get output_c] ne {}} continue
      ::practcl::cputs result [$obj generate-cfile-public-structure]
    }
    return $result
  }

  method generate-cfile-header {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cfunct cstruct methods tcltype tclprocs
    set result {}
    if {[info exists code(header)]} {
      ::practcl::cputs result $code(header)
    }
    foreach obj [my link list product] {
      # Exclude products that will generate their own C files
      if {[$obj define get output_c] ne {}} continue
      set dat [$obj generate-cfile-header]
      if {[string length [string trim $dat]]} {
        ::practcl::cputs result "/* BEGIN [$obj define get filename] generate-cfile-header */"
        ::practcl::cputs result $dat
        ::practcl::cputs result "/* END [$obj define get filename] generate-cfile-header */"
      }
    }
    return $result
  }

  method generate-cfile-global {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cfunct cstruct methods tcltype tclprocs
    set result {}
    if {[info exists code(global)]} {
      ::practcl::cputs result $code(global)
    }
    foreach obj [my link list product] {
      # Exclude products that will generate their own C files
      if {[$obj define get output_c] ne {}} continue
      set dat [$obj generate-cfile-global]
      if {[string length [string trim $dat]]} {
        ::practcl::cputs result "/* BEGIN [$obj define get filename] generate-cfile-global */"
        ::practcl::cputs result $dat
        ::practcl::cputs result "/* END [$obj define get filename] generate-cfile-global */"
      }
    }
    return $result
  }

  method generate-cfile-private-typedef {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cstruct
    set result {}
    if {[info exists code(private-typedef)]} {
      ::practcl::cputs result $code(private-typedef)
    }







<
<
<
<

|
<
<
<







<
|
<
<




<

<




















<








<















<
<
<
<














<



















<



















<







5640
5641
5642
5643
5644
5645
5646




5647
5648



5649
5650
5651
5652
5653
5654
5655

5656


5657
5658
5659
5660

5661

5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681

5682
5683
5684
5685
5686
5687
5688
5689

5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704




5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718

5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737

5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756

5757
5758
5759
5760
5761
5762
5763
        }
        if {[dict exists $info body] && ![dict exists $info header]} {
          dict set tclprocs $name header "static int ${callproc}(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv\[\])"
        }
      }
    }
  }




  method select {} {}
}




###
# END: class dynamic.tcl
###
###
# START: class product.tcl
###

::clay::define ::practcl::product {


  method code {section body} {
    my variable code
    ::practcl::cputs code($section) $body
  }

  method Collate_Source CWD {}

  method project-compile-products {} {
    set result {}
    noop {
    set filename [my define get filename]
    if {$filename ne {}} {
      ::practcl::debug [self] [self class] [self method] project-compile-products $filename
      if {[my define exists ofile]} {
        set ofile [my define get ofile]
      } else {
        set ofile [my Ofile $filename]
        my define set ofile $ofile
      }
      lappend result $ofile [list cfile $filename include [my define get include]  extra [my define get extra] external [string is true -strict [my define get external]] object [self]]
    }
    }
    foreach item [my link list subordinate] {
      lappend result {*}[$item project-compile-products]
    }
    return $result
  }

  method generate-debug {{spaces {}}} {
    set result {}
    ::practcl::cputs result "$spaces[list [self] [list class [info object class [self]] filename [my define get filename]] links [my link list]]"
    foreach item [my link list subordinate] {
      practcl::cputs result [$item generate-debug "$spaces  "]
    }
    return $result
  }

  method generate-cfile-constant {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}
    my variable code cstruct methods tcltype
    if {[info exists code(constant)]} {
      ::practcl::cputs result "/* [my define get filename] CONSTANT */"
      ::practcl::cputs result $code(constant)
    }
    foreach obj [my link list product] {
      # Exclude products that will generate their own C files
      if {[$obj define get output_c] ne {}} continue
      ::practcl::cputs result [$obj generate-cfile-constant]
    }
    return $result
  }




  method generate-cfile-public-structure {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cstruct methods tcltype
    set result {}
    if {[info exists code(struct)]} {
      ::practcl::cputs result $code(struct)
    }
    foreach obj [my link list product] {
      # Exclude products that will generate their own C files
      if {[$obj define get output_c] ne {}} continue
      ::practcl::cputs result [$obj generate-cfile-public-structure]
    }
    return $result
  }

  method generate-cfile-header {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cfunct cstruct methods tcltype tclprocs
    set result {}
    if {[info exists code(header)]} {
      ::practcl::cputs result $code(header)
    }
    foreach obj [my link list product] {
      # Exclude products that will generate their own C files
      if {[$obj define get output_c] ne {}} continue
      set dat [$obj generate-cfile-header]
      if {[string length [string trim $dat]]} {
        ::practcl::cputs result "/* BEGIN [$obj define get filename] generate-cfile-header */"
        ::practcl::cputs result $dat
        ::practcl::cputs result "/* END [$obj define get filename] generate-cfile-header */"
      }
    }
    return $result
  }

  method generate-cfile-global {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cfunct cstruct methods tcltype tclprocs
    set result {}
    if {[info exists code(global)]} {
      ::practcl::cputs result $code(global)
    }
    foreach obj [my link list product] {
      # Exclude products that will generate their own C files
      if {[$obj define get output_c] ne {}} continue
      set dat [$obj generate-cfile-global]
      if {[string length [string trim $dat]]} {
        ::practcl::cputs result "/* BEGIN [$obj define get filename] generate-cfile-global */"
        ::practcl::cputs result $dat
        ::practcl::cputs result "/* END [$obj define get filename] generate-cfile-global */"
      }
    }
    return $result
  }

  method generate-cfile-private-typedef {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cstruct
    set result {}
    if {[info exists code(private-typedef)]} {
      ::practcl::cputs result $code(private-typedef)
    }
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-cfile-private-typedef]
    }
    return $result
  }

  method generate-cfile-private-structure {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cstruct
    set result {}
    if {[info exists code(private-structure)]} {
      ::practcl::cputs result $code(private-structure)
    }







<







5775
5776
5777
5778
5779
5780
5781

5782
5783
5784
5785
5786
5787
5788
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-cfile-private-typedef]
    }
    return $result
  }

  method generate-cfile-private-structure {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cstruct
    set result {}
    if {[info exists code(private-structure)]} {
      ::practcl::cputs result $code(private-structure)
    }
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-cfile-private-structure]
    }
    return $result
  }


  ###
  # Generate code that provides subroutines called by
  # Tcl API methods
  ###
  method generate-cfile-functions {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cfunct
    set result {}
    if {[info exists code(funct)]} {
      ::practcl::cputs result $code(funct)
    }







<
<
<
<
<
<







5797
5798
5799
5800
5801
5802
5803






5804
5805
5806
5807
5808
5809
5810
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-cfile-private-structure]
    }
    return $result
  }






  method generate-cfile-functions {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cfunct
    set result {}
    if {[info exists code(funct)]} {
      ::practcl::cputs result $code(funct)
    }
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
      if {[$obj define get output_c] ne {}} {
        continue
      }
      ::practcl::cputs result [$obj generate-cfile-functions]
    }
    return $result
  }

  ###
  # Generate code that provides implements Tcl API
  # calls
  ###
  method generate-cfile-tclapi {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code methods tclprocs
    set result {}
    if {[info exists code(method)]} {
      ::practcl::cputs result $code(method)
    }
    foreach obj [my link list product] {
      # Exclude products that will generate their own C files
      if {[$obj define get output_c] ne {}} continue
      ::practcl::cputs result [$obj generate-cfile-tclapi]
    }
    return $result
  }


  method generate-hfile-public-define {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code
    set result {}
    if {[info exists code(public-define)]} {
      ::practcl::cputs result $code(public-define)
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-hfile-public-define]
    }
    return $result
  }

  method generate-hfile-public-macro {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code
    set result {}
    if {[info exists code(public-macro)]} {
      ::practcl::cputs result $code(public-macro)
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-hfile-public-macro]
    }
    return $result
  }

  method generate-hfile-public-typedef {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cstruct
    set result {}
    if {[info exists code(public-typedef)]} {
      ::practcl::cputs result $code(public-typedef)
    }







<
<
<
<
<














<
<













<













<







5823
5824
5825
5826
5827
5828
5829





5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843


5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856

5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869

5870
5871
5872
5873
5874
5875
5876
      if {[$obj define get output_c] ne {}} {
        continue
      }
      ::practcl::cputs result [$obj generate-cfile-functions]
    }
    return $result
  }





  method generate-cfile-tclapi {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code methods tclprocs
    set result {}
    if {[info exists code(method)]} {
      ::practcl::cputs result $code(method)
    }
    foreach obj [my link list product] {
      # Exclude products that will generate their own C files
      if {[$obj define get output_c] ne {}} continue
      ::practcl::cputs result [$obj generate-cfile-tclapi]
    }
    return $result
  }


  method generate-hfile-public-define {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code
    set result {}
    if {[info exists code(public-define)]} {
      ::practcl::cputs result $code(public-define)
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-hfile-public-define]
    }
    return $result
  }

  method generate-hfile-public-macro {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code
    set result {}
    if {[info exists code(public-macro)]} {
      ::practcl::cputs result $code(public-macro)
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-hfile-public-macro]
    }
    return $result
  }

  method generate-hfile-public-typedef {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cstruct
    set result {}
    if {[info exists code(public-typedef)]} {
      ::practcl::cputs result $code(public-typedef)
    }
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-hfile-public-typedef]
    }
    return $result
  }

  method generate-hfile-public-structure {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cstruct
    set result {}
    if {[info exists code(public-structure)]} {
      ::practcl::cputs result $code(public-structure)
    }







<







5888
5889
5890
5891
5892
5893
5894

5895
5896
5897
5898
5899
5900
5901
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-hfile-public-typedef]
    }
    return $result
  }

  method generate-hfile-public-structure {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cstruct
    set result {}
    if {[info exists code(public-structure)]} {
      ::practcl::cputs result $code(public-structure)
    }
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-hfile-public-structure]
    }
    return $result
  }

  method generate-hfile-public-headers {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code tcltype
    set result {}
    if {[info exists code(public-header)]} {
      ::practcl::cputs result $code(public-header)
    }







<







5910
5911
5912
5913
5914
5915
5916

5917
5918
5919
5920
5921
5922
5923
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-hfile-public-structure]
    }
    return $result
  }

  method generate-hfile-public-headers {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code tcltype
    set result {}
    if {[info exists code(public-header)]} {
      ::practcl::cputs result $code(public-header)
    }
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-hfile-public-headers]
    }
    return $result
  }

  method generate-hfile-public-function {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cfunct tcltype
    set result {}

    if {[my define get initfunc] ne {}} {
      ::practcl::cputs result "int [my define get initfunc](Tcl_Interp *interp);"
    }
    if {[info exists cfunct]} {
      foreach {funcname info} $cfunct {
        if {![dict get $info public]} continue
        ::practcl::cputs result "[dict get $info header]\;"
      }
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-hfile-public-function]
    }
    return $result
  }

  method generate-hfile-public-includes {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set includes {}
    foreach item [my define get public-include] {
      if {$item ni $includes} {
        lappend includes $item
      }
    }
    foreach mod [my link list product] {
      foreach item [$mod generate-hfile-public-includes] {
        if {$item ni $includes} {
          lappend includes $item
        }
      }
    }
    return $includes
  }

  method generate-hfile-public-verbatim {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set includes {}
    foreach item [my define get public-verbatim] {
      if {$item ni $includes} {
        lappend includes $item
      }
    }
    foreach mod [my link list subordinate] {
      foreach item [$mod generate-hfile-public-verbatim] {
        if {$item ni $includes} {
          lappend includes $item
        }
      }
    }
    return $includes
  }

  method generate-loader-external {} {
    if {[my define get initfunc] eq {}} {
      return "/*  [my define get filename] declared not initfunc */"
    }
    return "  if([my define get initfunc](interp)) return TCL_ERROR\;"
  }

  method generate-loader-module {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code
    set result {}
    if {[info exists code(cinit)]} {
      ::practcl::cputs result $code(cinit)
    }
    if {[my define get initfunc] ne {}} {
      ::practcl::cputs result "  if([my define get initfunc](interp)!=TCL_OK) return TCL_ERROR\;"
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach item [my link list product] {
      if {[$item define get output_c] ne {}} {
        ::practcl::cputs result [$item generate-loader-external]
      } else {
        ::practcl::cputs result [$item generate-loader-module]
      }
    }
    return $result
  }

  method generate-stub-function {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cfunct tcltype
    set result {}
    foreach mod [my link list product] {
      foreach {funct def} [$mod generate-stub-function] {
        dict set result $funct $def
      }
    }
    if {[info exists cfunct]} {
      foreach {funcname info} $cfunct {
        if {![dict get $info export]} continue
        dict set result $funcname [dict get $info header]
      }
    }
    return $result
  }


  method IncludeAdd {headervar args} {
    upvar 1 $headervar headers
    foreach inc $args {
      if {[string index $inc 0] ni {< \"}} {
        set inc "\"$inc\""
      }
      if {$inc ni $headers} {
        lappend headers $inc
      }
    }
  }

  method generate-tcl-loader {} {
    set result {}
    set PKGINIT [my define get pkginit]
    set PKG_NAME [my define get name [my define get pkg_name]]
    set PKG_VERSION [my define get pkg_vers [my define get version]]
    if {[string is true [my define get SHARED_BUILD 0]]} {
      set LIBFILE [my define get libfile]







<




















<

















<

















<






<




















<

















<
<











<







5937
5938
5939
5940
5941
5942
5943

5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963

5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980

5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997

5998
5999
6000
6001
6002
6003

6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023

6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040


6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051

6052
6053
6054
6055
6056
6057
6058
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-hfile-public-headers]
    }
    return $result
  }

  method generate-hfile-public-function {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cfunct tcltype
    set result {}

    if {[my define get initfunc] ne {}} {
      ::practcl::cputs result "int [my define get initfunc](Tcl_Interp *interp);"
    }
    if {[info exists cfunct]} {
      foreach {funcname info} $cfunct {
        if {![dict get $info public]} continue
        ::practcl::cputs result "[dict get $info header]\;"
      }
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-hfile-public-function]
    }
    return $result
  }

  method generate-hfile-public-includes {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set includes {}
    foreach item [my define get public-include] {
      if {$item ni $includes} {
        lappend includes $item
      }
    }
    foreach mod [my link list product] {
      foreach item [$mod generate-hfile-public-includes] {
        if {$item ni $includes} {
          lappend includes $item
        }
      }
    }
    return $includes
  }

  method generate-hfile-public-verbatim {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set includes {}
    foreach item [my define get public-verbatim] {
      if {$item ni $includes} {
        lappend includes $item
      }
    }
    foreach mod [my link list subordinate] {
      foreach item [$mod generate-hfile-public-verbatim] {
        if {$item ni $includes} {
          lappend includes $item
        }
      }
    }
    return $includes
  }

  method generate-loader-external {} {
    if {[my define get initfunc] eq {}} {
      return "/*  [my define get filename] declared not initfunc */"
    }
    return "  if([my define get initfunc](interp)) return TCL_ERROR\;"
  }

  method generate-loader-module {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code
    set result {}
    if {[info exists code(cinit)]} {
      ::practcl::cputs result $code(cinit)
    }
    if {[my define get initfunc] ne {}} {
      ::practcl::cputs result "  if([my define get initfunc](interp)!=TCL_OK) return TCL_ERROR\;"
    }
    set result [::practcl::_tagblock $result c [my define get filename]]
    foreach item [my link list product] {
      if {[$item define get output_c] ne {}} {
        ::practcl::cputs result [$item generate-loader-external]
      } else {
        ::practcl::cputs result [$item generate-loader-module]
      }
    }
    return $result
  }

  method generate-stub-function {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    my variable code cfunct tcltype
    set result {}
    foreach mod [my link list product] {
      foreach {funct def} [$mod generate-stub-function] {
        dict set result $funct $def
      }
    }
    if {[info exists cfunct]} {
      foreach {funcname info} $cfunct {
        if {![dict get $info export]} continue
        dict set result $funcname [dict get $info header]
      }
    }
    return $result
  }


  method IncludeAdd {headervar args} {
    upvar 1 $headervar headers
    foreach inc $args {
      if {[string index $inc 0] ni {< \"}} {
        set inc "\"$inc\""
      }
      if {$inc ni $headers} {
        lappend headers $inc
      }
    }
  }

  method generate-tcl-loader {} {
    set result {}
    set PKGINIT [my define get pkginit]
    set PKG_NAME [my define get name [my define get pkg_name]]
    set PKG_VERSION [my define get pkg_vers [my define get version]]
    if {[string is true [my define get SHARED_BUILD 0]]} {
      set LIBFILE [my define get libfile]
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922

3923
3924
3925
3926
3927
3928
3929
# Tclkit Style
load {} @PKGINIT@
package provide @PKG_NAME@ @PKG_VERSION@
}]
    }
    return $result
  }

  ###
  # This methods generates any Tcl script file
  # which is required to pre-initialize the C library
  ###
  method generate-tcl-pre {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}
    my variable code
    if {[info exists code(tcl)]} {
      set result [::practcl::_tagblock $code(tcl) tcl [my define get filename]]
    }
    if {[info exists code(tcl-pre)]} {
      set result [::practcl::_tagblock $code(tcl) tcl [my define get filename]]
    }
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-tcl-pre]
    }
    return $result
  }

  method generate-tcl-post {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}
    my variable code
    if {[info exists code(tcl-post)]} {
      set result [::practcl::_tagblock $code(tcl-post) tcl [my define get filename]]
    }
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-tcl-post]
    }
    return $result
  }


  method linktype {} {
    return {subordinate product}
  }

  method Ofile filename {
    set lpath [my <module> define get localpath]
    if {$lpath eq {}} {
      set lpath [my <module> define get name]
    }
    return ${lpath}_[file rootname [file tail $filename]]
  }

  ###
  # Methods called by the master project
  ###

  method project-static-packages {} {
    set result [my define get static_packages]
    set initfunc [my define get initfunc]
    if {$initfunc ne {}} {
      set pkg_name [my define get pkg_name]
      if {$pkg_name ne {}} {
        dict set result $pkg_name initfunc $initfunc
        dict set result $pkg_name version [my define get version [my define get pkg_vers]]
        dict set result $pkg_name autoload [my define get autoload 0]
      }
    }
    foreach item [my link list subordinate] {
      foreach {pkg info} [$item project-static-packages] {
        dict set result $pkg $info
      }
    }
    return $result
  }

  ###
  # Methods called by the toolset
  ###

  method toolset-include-directory {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result [my define get include_dir]
    foreach obj [my link list product] {
      foreach path [$obj toolset-include-directory] {
        lappend result $path
      }
    }
    return $result
  }

  method target {method args} {
    switch $method {
      is_unix { return [expr {$::tcl_platform(platform) eq "unix"}] }
    }
  }

}

oo::objdefine ::practcl::product {

  method select {object} {
    set class [$object define get class]
    set mixin [$object define get product]
    if {$class eq {} && $mixin eq {}} {
      set filename [$object define get filename]
      if {$filename ne {} && [file exists $filename]} {
        switch [file extension $filename] {







<
<
<
<
<















<












<
<



<







<
<
<
<
<


















<
<
<
<
<










<





|
<
<

>







6068
6069
6070
6071
6072
6073
6074





6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089

6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101


6102
6103
6104

6105
6106
6107
6108
6109
6110
6111





6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129





6130
6131
6132
6133
6134
6135
6136
6137
6138
6139

6140
6141
6142
6143
6144
6145


6146
6147
6148
6149
6150
6151
6152
6153
6154
# Tclkit Style
load {} @PKGINIT@
package provide @PKG_NAME@ @PKG_VERSION@
}]
    }
    return $result
  }





  method generate-tcl-pre {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}
    my variable code
    if {[info exists code(tcl)]} {
      set result [::practcl::_tagblock $code(tcl) tcl [my define get filename]]
    }
    if {[info exists code(tcl-pre)]} {
      set result [::practcl::_tagblock $code(tcl) tcl [my define get filename]]
    }
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-tcl-pre]
    }
    return $result
  }

  method generate-tcl-post {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}
    my variable code
    if {[info exists code(tcl-post)]} {
      set result [::practcl::_tagblock $code(tcl-post) tcl [my define get filename]]
    }
    foreach mod [my link list product] {
      ::practcl::cputs result [$mod generate-tcl-post]
    }
    return $result
  }


  method linktype {} {
    return {subordinate product}
  }

  method Ofile filename {
    set lpath [my <module> define get localpath]
    if {$lpath eq {}} {
      set lpath [my <module> define get name]
    }
    return ${lpath}_[file rootname [file tail $filename]]
  }





  method project-static-packages {} {
    set result [my define get static_packages]
    set initfunc [my define get initfunc]
    if {$initfunc ne {}} {
      set pkg_name [my define get pkg_name]
      if {$pkg_name ne {}} {
        dict set result $pkg_name initfunc $initfunc
        dict set result $pkg_name version [my define get version [my define get pkg_vers]]
        dict set result $pkg_name autoload [my define get autoload 0]
      }
    }
    foreach item [my link list subordinate] {
      foreach {pkg info} [$item project-static-packages] {
        dict set result $pkg $info
      }
    }
    return $result
  }





  method toolset-include-directory {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result [my define get include_dir]
    foreach obj [my link list product] {
      foreach path [$obj toolset-include-directory] {
        lappend result $path
      }
    }
    return $result
  }

  method target {method args} {
    switch $method {
      is_unix { return [expr {$::tcl_platform(platform) eq "unix"}] }
    }
  }
}


oo::objdefine ::practcl::product {

  method select {object} {
    set class [$object define get class]
    set mixin [$object define get product]
    if {$class eq {} && $mixin eq {}} {
      set filename [$object define get filename]
      if {$filename ne {} && [file exists $filename]} {
        switch [file extension $filename] {
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
          .a {
            set mixin ::practcl::product.clibrary
          }
        }
      }
    }
    if {$class ne {}} {
      $object morph $class
    }
    if {$mixin ne {}} {
      $object mixin product $mixin
    }
  }
}

###
# Flesh out several trivial varieties of product
###
::oo::class create ::practcl::product.cheader {
  superclass ::practcl::product

  method project-compile-products {} {}
  method generate-loader-module {} {}
}

::oo::class create ::practcl::product.csource {
  superclass ::practcl::product

  method project-compile-products {} {
    set result {}
    set filename [my define get filename]
    if {$filename ne {}} {
      ::practcl::debug [self] [self class] [self method] project-compile-products $filename
      if {[my define exists ofile]} {
        set ofile [my define get ofile]
      } else {
        set ofile [my Ofile $filename]
        my define set ofile $ofile
      }
      lappend result $ofile [list cfile $filename extra [my define get extra] external [string is true -strict [my define get external]] object [self]]
    }
    foreach item [my link list subordinate] {
      lappend result {*}[$item project-compile-products]
    }
    return $result
  }
}

::oo::class create ::practcl::product.clibrary {
  superclass ::practcl::product

  method linker-products {configdict} {
    return [my define get filename]
  }

}

::oo::class create ::practcl::product.dynamic {
  superclass ::practcl::dynamic ::practcl::product

  method initialize {} {
    set filename [my define get filename]
    if {$filename eq {}} {
      return
    }
    if {[my define get name] eq {}} {
      my define set name [file tail [file rootname $filename]]







|


|



<
<
<
<
|

<



<
|

<



















<
|

<



|
<
<
|

<







6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190




6191
6192

6193
6194
6195

6196
6197

6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216

6217
6218

6219
6220
6221
6222


6223
6224

6225
6226
6227
6228
6229
6230
6231
          .a {
            set mixin ::practcl::product.clibrary
          }
        }
      }
    }
    if {$class ne {}} {
      $object clay mixinmap core $class
    }
    if {$mixin ne {}} {
      $object clay mixinmap product $mixin
    }
  }
}




::clay::define ::practcl::product.cheader {
  superclass ::practcl::product

  method project-compile-products {} {}
  method generate-loader-module {} {}
}

::clay::define ::practcl::product.csource {
  superclass ::practcl::product

  method project-compile-products {} {
    set result {}
    set filename [my define get filename]
    if {$filename ne {}} {
      ::practcl::debug [self] [self class] [self method] project-compile-products $filename
      if {[my define exists ofile]} {
        set ofile [my define get ofile]
      } else {
        set ofile [my Ofile $filename]
        my define set ofile $ofile
      }
      lappend result $ofile [list cfile $filename extra [my define get extra] external [string is true -strict [my define get external]] object [self]]
    }
    foreach item [my link list subordinate] {
      lappend result {*}[$item project-compile-products]
    }
    return $result
  }
}

::clay::define ::practcl::product.clibrary {
  superclass ::practcl::product

  method linker-products {configdict} {
    return [my define get filename]
  }
}


::clay::define ::practcl::product.dynamic {
  superclass ::practcl::dynamic ::practcl::product

  method initialize {} {
    set filename [my define get filename]
    if {$filename eq {}} {
      return
    }
    if {[my define get name] eq {}} {
      my define set name [file tail [file rootname $filename]]
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081

4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191

4192
4193
4194
4195
4196
4197

4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211

4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
    ::source $filename
    if {[my define get output_c] ne {}} {
      # Turn into a module if we have an output_c file
      my morph ::practcl::module
    }
  }
}

::oo::class create ::practcl::product.critcl {
  superclass ::practcl::dynamic ::practcl::product
}


###
# END: class product.tcl
###
###
# START: class module.tcl
###

###
# In the end, all C code must be loaded into a module
# This will either be a dynamically loaded library implementing
# a tcl extension, or a compiled in segment of a custom shell/app
###
::oo::class create ::practcl::module {
  superclass ::practcl::object ::practcl::product.dynamic

  method _MorphPatterns {} {
    return {{@name@} {::practcl::module.@name@} ::practcl::module}
  }
  
  method add args {
    my variable links
    set object [::practcl::object new [self] {*}$args]
    foreach linktype [$object linktype] {
      lappend links($linktype) $object
    }
    return $object
  }
  
  
  method install-headers args {}
  
  ###
  # Target handling
  ###
  method make {command args} {
    my variable make_object
    if {![info exists make_object]} {
      set make_object {}
    }
    switch $command {

      pkginfo {
        ###
        # Build local variables needed for install
        ###
        package require platform
        set result {}
        set dat [my define dump]
        set PKG_DIR [dict get $dat name][dict get $dat version]
        dict set result PKG_DIR $PKG_DIR
        dict with dat {}
        if {![info exists DESTDIR]} {
          set DESTDIR {}
        }
        dict set result profile [::platform::identify]
        dict set result os $::tcl_platform(os)
        dict set result platform $::tcl_platform(platform)
        foreach {field value} $dat {
          switch $field {
            includedir -
            mandir -
            datadir -
            libdir -
            libfile -
            name -
            output_tcl -
            version -
            authors -
            license -
            requires {
              dict set result $field $value
            }
            TEA_PLATFORM {
              dict set result platform $value
            }
            TEACUP_OS {
              dict set result os $value
            }
            TEACUP_PROFILE {
              dict set result profile $value
            }
            TEACUP_ZIPFILE {
              dict set result zipfile $value
            }
          }
        }
        if {![dict exists $result zipfile]} {
          dict set result zipfile "[dict get $result name]-[dict get $result version]-[dict get $result profile].zip"
        }
        return $result
      }
      objects {
        return $make_object
      }
      object {
        set name [lindex $args 0]
        if {[dict exists $make_object $name]} {
          return [dict get $make_object $name]
        }
        return {}
      }
      reset {
        foreach {name obj} $make_object {
          $obj reset
        }
      }
      trigger {
        foreach {name obj} $make_object {
          if {$name in $args} {
            $obj triggers
          }
        }
      }
      depends {
        foreach {name obj} $make_object {
          if {$name in $args} {
            $obj check
          }
        }
      }
      filename {
        set name [lindex $args 0]
        if {[dict exists $make_object $name]} {
          return [[dict get $make_object $name] define get filename]
        }
      }
      task -
      target -
      add {
        set name [lindex $args 0]
        set info [uplevel #0 [list subst [lindex $args 1]]]
        set body [lindex $args 2]
        
        set nspace [namespace current]
        if {[dict exist $make_object $name]} {
          set obj [dict get $$make_object $name]
        } else {
          set obj [::practcl::make_obj new [self] $name $info $body]
          dict set make_object $name $obj
          dict set target_make $name 0
          dict set target_trigger $name 0
        }
        if {[dict exists $info aliases]} {
          foreach item [dict get $info aliases] {
            if {![dict exists $make_object $item]} {
              dict set make_object $item $obj
            }
          }
        }
        return $obj
      }

      todo {
         foreach {name obj} $make_object {
          if {[$obj do]} {
            lappend result $name
          }
        }       

      }
      do {
        global CWD SRCDIR project SANDBOX
        foreach {name obj} $make_object {
          if {[$obj do]} {
            eval [$obj define get action]
          }
        }
      }
    }
  }
  
  method child which {
    switch $which {

      organs {
        return [list project [my define get project] module [self]]
      }
    }
  }

 ###
  # This methods generates the contents of an amalgamated .c file
  # which implements the loader for a batch of tools
  ###
  method generate-c {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {
/* This file was generated by practcl */
    }
    set includes {}








<
|


<







<
<
<
<
<
<
|

|



<








<
<

|
<
<
<
<




<
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
<
|
<
<
|
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
<
<
<


>





<
<
<
<
<







6242
6243
6244
6245
6246
6247
6248

6249
6250
6251

6252
6253
6254
6255
6256
6257
6258






6259
6260
6261
6262
6263
6264

6265
6266
6267
6268
6269
6270
6271
6272


6273
6274




6275
6276
6277
6278

6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333

6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358

6359
6360
6361
6362

6363


6364


6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399



6400
6401
6402
6403
6404
6405
6406
6407





6408
6409
6410
6411
6412
6413
6414
    ::source $filename
    if {[my define get output_c] ne {}} {
      # Turn into a module if we have an output_c file
      my morph ::practcl::module
    }
  }
}

::clay::define ::practcl::product.critcl {
  superclass ::practcl::dynamic ::practcl::product
}


###
# END: class product.tcl
###
###
# START: class module.tcl
###






::clay::define ::practcl::module {
  superclass ::practcl::object ::practcl::product.dynamic
  Dict make_object {}
  method _MorphPatterns {} {
    return {{@name@} {::practcl::module.@name@} ::practcl::module}
  }

  method add args {
    my variable links
    set object [::practcl::object new [self] {*}$args]
    foreach linktype [$object linktype] {
      lappend links($linktype) $object
    }
    return $object
  }


  method install-headers args {}
  Ensemble make::_preamble {} {




    my variable make_object
    if {![info exists make_object]} {
      set make_object {}
    }

  }
  Ensemble make::pkginfo {} {
    ###
    # Build local variables needed for install
    ###
    package require platform
    set result {}
    set dat [my define dump]
    set PKG_DIR [dict get $dat name][dict get $dat version]
    dict set result PKG_DIR $PKG_DIR
    dict with dat {}
    if {![info exists DESTDIR]} {
      set DESTDIR {}
    }
    dict set result profile [::platform::identify]
    dict set result os $::tcl_platform(os)
    dict set result platform $::tcl_platform(platform)
    foreach {field value} $dat {
      switch $field {
        includedir -
        mandir -
        datadir -
        libdir -
        libfile -
        name -
        output_tcl -
        version -
        authors -
        license -
        requires {
          dict set result $field $value
        }
        TEA_PLATFORM {
          dict set result platform $value
        }
        TEACUP_OS {
          dict set result os $value
        }
        TEACUP_PROFILE {
          dict set result profile $value
        }
        TEACUP_ZIPFILE {
          dict set result zipfile $value
        }
      }
    }
    if {![dict exists $result zipfile]} {
      dict set result zipfile "[dict get $result name]-[dict get $result version]-[dict get $result profile].zip"
    }
    return $result
  }
  Ensemble make::objects {} {
    return $make_object
  }
  Ensemble make::object name {

    if {[dict exists $make_object $name]} {
      return [dict get $make_object $name]
    }
    return {}
  }
  Ensemble make::reset {} {
    foreach {name obj} $make_object {
      $obj reset
    }
  }
  Ensemble make::trigger args {
    foreach {name obj} $make_object {
      if {$name in $args} {
        $obj triggers
      }
    }
  }
  Ensemble make::depends args {
    foreach {name obj} $make_object {
      if {$name in $args} {
        $obj check
      }
    }
  }
  Ensemble make::filename name {

    if {[dict exists $make_object $name]} {
      return [[dict get $make_object $name] define get filename]
    }
  }

  Ensemble make::target {name Info body} {


    set info [uplevel #0 [list subst $Info]]


    set nspace [namespace current]
    if {[dict exist $make_object $name]} {
      set obj [dict get $$make_object $name]
    } else {
      set obj [::practcl::make_obj new [self] $name $info $body]
      dict set make_object $name $obj
      dict set target_make $name 0
      dict set target_trigger $name 0
    }
    if {[dict exists $info aliases]} {
      foreach item [dict get $info aliases] {
        if {![dict exists $make_object $item]} {
          dict set make_object $item $obj
        }
      }
    }
    return $obj
  }
  clay set method_ensemble make target aliases {target add}
  Ensemble make::todo {} {
    foreach {name obj} $make_object {
      if {[$obj do]} {
        lappend result $name
      }
    }
    return $result
  }
  Ensemble make::do {} {
    global CWD SRCDIR project SANDBOX
    foreach {name obj} $make_object {
      if {[$obj do]} {
        eval [$obj define get action]
      }
    }
  }



  method child which {
    switch $which {
      delegate -
      organs {
        return [list project [my define get project] module [self]]
      }
    }
  }





  method generate-c {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {
/* This file was generated by practcl */
    }
    set includes {}

4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278








4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
        ::practcl::cputs result $dat
        ::practcl::cputs result "/* END $method [my define get filename] */"
      }
    }
    ::practcl::debug [list /[self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    return $result
  }


  ###
  # This methods generates the contents of an amalgamated .h file
  # which describes the public API of this module
  ###
  method generate-h {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}








    set includes [my generate-hfile-public-includes]
    foreach inc $includes {
      if {[string index $inc 0] ni {< \"}} {
        ::practcl::cputs result "#include \"$inc\""
      } else {
        ::practcl::cputs result "#include $inc"
      }
    }

    foreach method {
      generate-hfile-public-define
      generate-hfile-public-macro
      generate-hfile-public-typedef
      generate-hfile-public-structure
    } {
      ::practcl::cputs result "/* BEGIN SECTION $method */"
      ::practcl::cputs result [my $method]
      ::practcl::cputs result "/* END SECTION $method */"
    }







<
<
<
<
<
<



>
>
>
>
>
>
>
>








<

<
<







6449
6450
6451
6452
6453
6454
6455






6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474

6475


6476
6477
6478
6479
6480
6481
6482
        ::practcl::cputs result $dat
        ::practcl::cputs result "/* END $method [my define get filename] */"
      }
    }
    ::practcl::debug [list /[self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    return $result
  }






  method generate-h {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}
    foreach method {
      generate-hfile-public-define
      generate-hfile-public-macro
    } {
      ::practcl::cputs result "/* BEGIN SECTION $method */"
      ::practcl::cputs result [my $method]
      ::practcl::cputs result "/* END SECTION $method */"
    }
    set includes [my generate-hfile-public-includes]
    foreach inc $includes {
      if {[string index $inc 0] ni {< \"}} {
        ::practcl::cputs result "#include \"$inc\""
      } else {
        ::practcl::cputs result "#include $inc"
      }
    }

    foreach method {


      generate-hfile-public-typedef
      generate-hfile-public-structure
    } {
      ::practcl::cputs result "/* BEGIN SECTION $method */"
      ::practcl::cputs result [my $method]
      ::practcl::cputs result "/* END SECTION $method */"
    }
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
    } {
      ::practcl::cputs result "/* BEGIN SECTION $method */"
      ::practcl::cputs result [my $method]
      ::practcl::cputs result "/* END SECTION $method */"
    }
    return $result
  }

  method generate-loader {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}
    if {[my define get initfunc] eq {}} return
    ::practcl::cputs result  "
extern int DLLEXPORT [my define get initfunc]( Tcl_Interp *interp ) \{"
    ::practcl::cputs result  {







<







6493
6494
6495
6496
6497
6498
6499

6500
6501
6502
6503
6504
6505
6506
    } {
      ::practcl::cputs result "/* BEGIN SECTION $method */"
      ::practcl::cputs result [my $method]
      ::practcl::cputs result "/* END SECTION $method */"
    }
    return $result
  }

  method generate-loader {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set result {}
    if {[my define get initfunc] eq {}} return
    ::practcl::cputs result  "
extern int DLLEXPORT [my define get initfunc]( Tcl_Interp *interp ) \{"
    ::practcl::cputs result  {
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
    if {[my define get localpath] eq {}} {
      my define set localpath [my <project> define get name]_[my define get name]
    }
    my graft module [self]
    ::practcl::debug [self] SOURCE $filename
    my source $filename
  }

  method implement path {
    my go
    my Collate_Source $path
    set errs {}
    foreach item [my link list dynamic] {
      if {[catch {$item implement $path} err errdat]} {
        lappend errs "Skipped $item: [$item define get filename] $err"







<







6540
6541
6542
6543
6544
6545
6546

6547
6548
6549
6550
6551
6552
6553
    if {[my define get localpath] eq {}} {
      my define set localpath [my <project> define get name]_[my define get name]
    }
    my graft module [self]
    ::practcl::debug [self] SOURCE $filename
    my source $filename
  }

  method implement path {
    my go
    my Collate_Source $path
    set errs {}
    foreach item [my link list dynamic] {
      if {[catch {$item implement $path} err errdat]} {
        lappend errs "Skipped $item: [$item define get filename] $err"
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
          lappend errs [dict get $errdat -errorinfo]
        } else {
          lappend errs $errdat
        }
      }
    }
    if {[llength $errs]} {
      set logfile [file join $::CWD practcl.log]      
      ::practcl::log $logfile "*** ERRORS ***"
      foreach {item trace} $errs {
        ::practcl::log $logfile "###\n# ERROR\n###\n$item"
       ::practcl::log $logfile "###\n# TRACE\n###\n$trace"
      }
      ::practcl::log $logfile "*** DEBUG INFO ***"
      ::practcl::log $logfile $::DEBUG_INFO







|







6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
          lappend errs [dict get $errdat -errorinfo]
        } else {
          lappend errs $errdat
        }
      }
    }
    if {[llength $errs]} {
      set logfile [file join $::CWD practcl.log]
      ::practcl::log $logfile "*** ERRORS ***"
      foreach {item trace} $errs {
        ::practcl::log $logfile "###\n# ERROR\n###\n$item"
       ::practcl::log $logfile "###\n# TRACE\n###\n$trace"
      }
      ::practcl::log $logfile "*** DEBUG INFO ***"
      ::practcl::log $logfile $::DEBUG_INFO
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
** any changes will be overwritten the next time it is run
*/}]
    puts $cout [my generate-c]
    puts $cout [my generate-loader]
    close $cout
    ::practcl::debug [list /[self] [self method] [self class]]
  }

  method linktype {} {
    return {subordinate product dynamic module}
  }
}

###
# END: class module.tcl
###
###
# START: class project baseclass.tcl
###

::oo::class create ::practcl::project {
  superclass ::practcl::module

  method _MorphPatterns {} {
    return {{@name@} {::practcl::@name@} {::practcl::project.@name@} {::practcl::project}}
  }

  constructor args {
    my variable define
    if {[llength $args] == 1} {
      set rawcontents [lindex $args 0]
    } else {
      set rawcontents $args
    }







<











<
|

<



<







6592
6593
6594
6595
6596
6597
6598

6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609

6610
6611

6612
6613
6614

6615
6616
6617
6618
6619
6620
6621
** any changes will be overwritten the next time it is run
*/}]
    puts $cout [my generate-c]
    puts $cout [my generate-loader]
    close $cout
    ::practcl::debug [list /[self] [self method] [self class]]
  }

  method linktype {} {
    return {subordinate product dynamic module}
  }
}

###
# END: class module.tcl
###
###
# START: class project baseclass.tcl
###

::clay::define ::practcl::project {
  superclass ::practcl::module

  method _MorphPatterns {} {
    return {{@name@} {::practcl::@name@} {::practcl::project.@name@} {::practcl::project}}
  }

  constructor args {
    my variable define
    if {[llength $args] == 1} {
      set rawcontents [lindex $args 0]
    } else {
      set rawcontents $args
    }
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
      }
    }
    my graft module [self]
    array set define $contents
    ::practcl::toolset select [self]
    my initialize
  }

  method add_object object {
    my link object $object
  }

  method add_project {pkg info {oodefine {}}} {
    ::practcl::debug [self] add_project $pkg $info
    set os [my define get TEACUP_OS]
    if {$os eq {}} {
      set os [::practcl::os]
      my define set os $os
    }







<



<







6639
6640
6641
6642
6643
6644
6645

6646
6647
6648

6649
6650
6651
6652
6653
6654
6655
      }
    }
    my graft module [self]
    array set define $contents
    ::practcl::toolset select [self]
    my initialize
  }

  method add_object object {
    my link object $object
  }

  method add_project {pkg info {oodefine {}}} {
    ::practcl::debug [self] add_project $pkg $info
    set os [my define get TEACUP_OS]
    if {$os eq {}} {
      set os [::practcl::os]
      my define set os $os
    }
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
    }
    my link object $obj
    oo::objdefine $obj $oodefine
    $obj define set masterpath $::CWD
    $obj go
    return $obj
  }

  method add_tool {pkg info {oodefine {}}} {
    ::practcl::debug [self] add_tool $pkg $info
    set info [dict merge [::practcl::local_os] $info]

    set os [dict get $info TEACUP_OS]
    set fossilinfo [list download [my define get download] tag trunk sandbox [my define get sandbox]]
    if {[dict exists $info os] && ($os ni [dict get $info os])} return







<







6669
6670
6671
6672
6673
6674
6675

6676
6677
6678
6679
6680
6681
6682
    }
    my link object $obj
    oo::objdefine $obj $oodefine
    $obj define set masterpath $::CWD
    $obj go
    return $obj
  }

  method add_tool {pkg info {oodefine {}}} {
    ::practcl::debug [self] add_tool $pkg $info
    set info [dict merge [::practcl::local_os] $info]

    set os [dict get $info TEACUP_OS]
    set fossilinfo [list download [my define get download] tag trunk sandbox [my define get sandbox]]
    if {[dict exists $info os] && ($os ni [dict get $info os])} return
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553

4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
    }
    my link add tool $obj
    oo::objdefine $obj $oodefine
    $obj define set masterpath $::CWD
    $obj go
    return $obj
  }

  method build-tclcore {} {
    set os [my define get TEACUP_OS]
    set tcl_config_opts [::practcl::platform::tcl_core_options $os]
    set tk_config_opts  [::practcl::platform::tk_core_options $os]

    lappend tcl_config_opts --prefix [my define get prefix] --exec-prefix [my define get prefix]
    set tclobj [my tclcore]
    if {[my define get debug 0]} {
      $tclobj define set debug 1
      lappend tcl_config_opts --enable-symbols=true
    }
    $tclobj define set config_opts $tcl_config_opts
    $tclobj go
    $tclobj compile

    set _TclSrcDir [$tclobj define get localsrcdir]
    my define set tclsrcdir $_TclSrcDir

    set tkobj [my tkcore]
    lappend tk_config_opts --with-tcl=[::practcl::file_relative [$tkobj define get builddir]  [$tclobj define get builddir]]
    if {[my define get debug 0]} {
      $tkobj define set debug 1
      lappend tk_config_opts --enable-symbols=true
    }
    $tkobj define set config_opts $tk_config_opts
    $tkobj compile
  }

  method child which {
    switch $which {

      organs {
	# A library can be a project, it can be a module. Any
	# subordinate modules will indicate their existance
        return [list project [self] module [self]]
      }
    }
  }

  method linktype {} {
    return project
  }


  # Exercise the methods of a sub-object
  method project {pkg args} {
    set obj [namespace current]::PROJECT.$pkg
    if {[llength $args]==0} {
      return $obj
    }
    ${obj} {*}$args
  }


  method tclcore {} {
    if {[info commands [set obj [my organ tclcore]]] ne {}} {
      return $obj
    }
    if {[info commands [set obj [my project TCLCORE]]] ne {}} {
      my graft tclcore $obj
      return $obj
    }
    if {[info commands [set obj [my project tcl]]] ne {}} {







<

















|
|
|
|
|
|
|
|
|
|
|


>







<



<
<
<







<
<

|







6692
6693
6694
6695
6696
6697
6698

6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736

6737
6738
6739



6740
6741
6742
6743
6744
6745
6746


6747
6748
6749
6750
6751
6752
6753
6754
6755
    }
    my link add tool $obj
    oo::objdefine $obj $oodefine
    $obj define set masterpath $::CWD
    $obj go
    return $obj
  }

  method build-tclcore {} {
    set os [my define get TEACUP_OS]
    set tcl_config_opts [::practcl::platform::tcl_core_options $os]
    set tk_config_opts  [::practcl::platform::tk_core_options $os]

    lappend tcl_config_opts --prefix [my define get prefix] --exec-prefix [my define get prefix]
    set tclobj [my tclcore]
    if {[my define get debug 0]} {
      $tclobj define set debug 1
      lappend tcl_config_opts --enable-symbols=true
    }
    $tclobj define set config_opts $tcl_config_opts
    $tclobj go
    $tclobj compile

    set _TclSrcDir [$tclobj define get localsrcdir]
    my define set tclsrcdir $_TclSrcDir
    if {[my define get tk 0]} {
      set tkobj [my tkcore]
      lappend tk_config_opts --with-tcl=[::practcl::file_relative [$tkobj define get builddir]  [$tclobj define get builddir]]
      if {[my define get debug 0]} {
        $tkobj define set debug 1
        lappend tk_config_opts --enable-symbols=true
      }
      $tkobj define set config_opts $tk_config_opts
      $tkobj compile
    }
  }
  method child which {
    switch $which {
      delegate -
      organs {
	# A library can be a project, it can be a module. Any
	# subordinate modules will indicate their existance
        return [list project [self] module [self]]
      }
    }
  }

  method linktype {} {
    return project
  }



  method project {pkg args} {
    set obj [namespace current]::PROJECT.$pkg
    if {[llength $args]==0} {
      return $obj
    }
    ${obj} {*}$args
  }


  method tclcore {} {
    if {[info commands [set obj [my clay delegate tclcore]]] ne {}} {
      return $obj
    }
    if {[info commands [set obj [my project TCLCORE]]] ne {}} {
      my graft tclcore $obj
      return $obj
    }
    if {[info commands [set obj [my project tcl]]] ne {}} {
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
    set obj [my add_tool tcl {
      tag release class subproject.core
      fossil_url http://core.tcl.tk/tcl
    }]
    my graft tclcore $obj
    return $obj
  }

  method tkcore {} {
    if {[set obj [my organ tkcore]] ne {}} {
      return $obj
    }
    if {[set obj [my project tk]] ne {}} {
      my graft tkcore $obj
      return $obj
    }
    if {[set obj [my tool tk]] ne {}} {
      my graft tkcore $obj
      return $obj
    }
    # Provide a fallback
    set obj [my add_tool tk {
      tag release class tool.core
      fossil_url http://core.tcl.tk/tk
    }]
    my graft tkcore $obj
    return $obj
  }

  method tool {pkg args} {
    set obj ::practcl::OBJECT::TOOL.$pkg
    if {[llength $args]==0} {
      return $obj
    }
    ${obj} {*}$args
  }
}

###
# END: class project baseclass.tcl
###
###
# START: class project library.tcl
###

::oo::class create ::practcl::library {
  superclass ::practcl::project


  method clean {PATH} {
    set objext [my define get OBJEXT o]
    foreach {ofile info} [my project-compile-products] {
      if {[file exists [file join $PATH objs $ofile].${objext}]} {
        file delete [file join $PATH objs $ofile].${objext}
      }
    }
    foreach ofile [glob -nocomplain [file join $PATH *.${objext}]] {
      file delete $ofile
    }
    foreach ofile [glob -nocomplain [file join $PATH objs *]] {
      file delete $ofile
    }
    set libfile [my define get libfile]
    if {[file exists [file join $PATH $libfile]]} {
      file delete [file join $PATH $libfile]
    }
    my implement $PATH
  }

  method project-compile-products {} {
    set result {}
    foreach item [my link list subordinate] {
      lappend result {*}[$item project-compile-products]
    }
    set filename [my define get output_c]
    if {$filename ne {}} {
      ::practcl::debug [self] [self class] [self method] project-compile-products $filename
      set ofile [file rootname [file tail $filename]]_main
      lappend result $ofile [list cfile $filename extra [my define get extra] external [string is true -strict [my define get external]]]
    }
    return $result
  }


  method go {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set name [my define getnull name]
    if {$name eq {}} {
      set name generic
      my define name generic
    }







<

|


















<















<
|

<
<



















<













<
<







6764
6765
6766
6767
6768
6769
6770

6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790

6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805

6806
6807


6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826

6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839


6840
6841
6842
6843
6844
6845
6846
    set obj [my add_tool tcl {
      tag release class subproject.core
      fossil_url http://core.tcl.tk/tcl
    }]
    my graft tclcore $obj
    return $obj
  }

  method tkcore {} {
    if {[set obj [my clay delegate tkcore]] ne {}} {
      return $obj
    }
    if {[set obj [my project tk]] ne {}} {
      my graft tkcore $obj
      return $obj
    }
    if {[set obj [my tool tk]] ne {}} {
      my graft tkcore $obj
      return $obj
    }
    # Provide a fallback
    set obj [my add_tool tk {
      tag release class tool.core
      fossil_url http://core.tcl.tk/tk
    }]
    my graft tkcore $obj
    return $obj
  }

  method tool {pkg args} {
    set obj ::practcl::OBJECT::TOOL.$pkg
    if {[llength $args]==0} {
      return $obj
    }
    ${obj} {*}$args
  }
}

###
# END: class project baseclass.tcl
###
###
# START: class project library.tcl
###

::clay::define ::practcl::library {
  superclass ::practcl::project


  method clean {PATH} {
    set objext [my define get OBJEXT o]
    foreach {ofile info} [my project-compile-products] {
      if {[file exists [file join $PATH objs $ofile].${objext}]} {
        file delete [file join $PATH objs $ofile].${objext}
      }
    }
    foreach ofile [glob -nocomplain [file join $PATH *.${objext}]] {
      file delete $ofile
    }
    foreach ofile [glob -nocomplain [file join $PATH objs *]] {
      file delete $ofile
    }
    set libfile [my define get libfile]
    if {[file exists [file join $PATH $libfile]]} {
      file delete [file join $PATH $libfile]
    }
    my implement $PATH
  }

  method project-compile-products {} {
    set result {}
    foreach item [my link list subordinate] {
      lappend result {*}[$item project-compile-products]
    }
    set filename [my define get output_c]
    if {$filename ne {}} {
      ::practcl::debug [self] [self class] [self method] project-compile-products $filename
      set ofile [file rootname [file tail $filename]]_main
      lappend result $ofile [list cfile $filename extra [my define get extra] external [string is true -strict [my define get external]]]
    }
    return $result
  }


  method go {} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set name [my define getnull name]
    if {$name eq {}} {
      set name generic
      my define name generic
    }
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
    foreach {linktype objs} [array get links] {
      foreach obj $objs {
        $obj go
      }
    }
    ::practcl::debug [list /[self] [self method] [self class] -- [my define get filename] [info object class [self]]]
  }


  method generate-decls {pkgname path} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set outfile [file join $path/$pkgname.decls]

    ###
    # Build the decls file
    ## #







<
<







6881
6882
6883
6884
6885
6886
6887


6888
6889
6890
6891
6892
6893
6894
    foreach {linktype objs} [array get links] {
      foreach obj $objs {
        $obj go
      }
    }
    ::practcl::debug [list /[self] [self method] [self class] -- [my define get filename] [info object class [self]]]
  }


  method generate-decls {pkgname path} {
    ::practcl::debug [list [self] [self method] [self class] -- [my define get filename] [info object class [self]]]
    set outfile [file join $path/$pkgname.decls]

    ###
    # Build the decls file
    ## #
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
    return NULL;
  }
  return actualVersion;
}
}]
    close $cout
  }

  method implement path {
    my go
    my Collate_Source $path
    set errs {}
    foreach item [my link list dynamic] {
      if {[catch {$item implement $path} err errdat]} {
        lappend errs "Skipped $item: [$item define get filename] $err"







<







6974
6975
6976
6977
6978
6979
6980

6981
6982
6983
6984
6985
6986
6987
    return NULL;
  }
  return actualVersion;
}
}]
    close $cout
  }

  method implement path {
    my go
    my Collate_Source $path
    set errs {}
    foreach item [my link list dynamic] {
      if {[catch {$item implement $path} err errdat]} {
        lappend errs "Skipped $item: [$item define get filename] $err"
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
###"
      puts $tclout [my generate-tcl-pre]
      puts $tclout [my generate-tcl-loader]
      puts $tclout [my generate-tcl-post]
      close $tclout
    }
  }

  # Backward compadible call
  method generate-make path {
    my build-Makefile $path [self]
  }

  method linktype {} {
    return library
  }

  # Create a "package ifneeded"
  # Args are a list of aliases for which this package will answer to
  method package-ifneeded {args} {
    set result {}
    set name [my define get pkg_name [my define get name]]
    set version [my define get pkg_vers [my define get version]]
    if {$version eq {}} {
      set version 0.1a
    }
    set output_tcl [my define get output_tcl]
    if {$output_tcl ne {}} {
      set script "\[list source \[file join \$dir $output_tcl\]\]"
    } elseif {[string is true -strict [my define get SHARED_BUILD]]} {
      set script "\[list load \[file join \$dir [my define get libfile]\] $name\]"
    } else {
      # Provide a null passthrough
      set script "\[list package provide $name $version\]"
    }
    set result "package ifneeded [list $name] [list $version] $script"
    foreach alias $args {
      set script "package require $name $version \; package provide $alias $version"
      append result \n\n [list package ifneeded $alias $version $script]
    }
    return $result
  }


  method shared_library {{filename {}}} {
    set name [string tolower [my define get name [my define get pkg_name]]]
    set NAME [string toupper $name]
    set version [my define get version [my define get pkg_vers]]
    set map {}
    lappend map %LIBRARY_NAME% $name
    lappend map %LIBRARY_VERSION% $version
    lappend map %LIBRARY_VERSION_NODOTS% [string map {. {}} $version]
    lappend map %LIBRARY_PREFIX% [my define getnull libprefix]
    set outfile [string map $map [my define get PRACTCL_NAME_LIBRARY]][my define get SHLIB_SUFFIX]
    return $outfile
  }

  method static_library {{filename {}}} {
    set name [string tolower [my define get name [my define get pkg_name]]]
    set NAME [string toupper $name]
    set version [my define get version [my define get pkg_vers]]
    set map {}
    lappend map %LIBRARY_NAME% $name
    lappend map %LIBRARY_VERSION% $version
    lappend map %LIBRARY_VERSION_NODOTS% [string map {. {}} $version]
    lappend map %LIBRARY_PREFIX% [my define getnull libprefix]
    set outfile [string map $map [my define get PRACTCL_NAME_LIBRARY]].a
    return $outfile
  }
}

###
# END: class project library.tcl
###
###
# START: class project tclkit.tcl
###


::oo::class create ::practcl::tclkit {
  superclass ::practcl::library

  method build-tclkit_main {PROJECT PKG_OBJS} {
    ###
    # Build static package list
    ###
    set statpkglist {}
    foreach cobj [list {*}${PKG_OBJS} $PROJECT] {
      foreach {pkg info} [$cobj project-static-packages] {







<
<



<



<
<
<










|












<
<












<




















<
<
|

<







7044
7045
7046
7047
7048
7049
7050


7051
7052
7053

7054
7055
7056



7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079


7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091

7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111


7112
7113

7114
7115
7116
7117
7118
7119
7120
###"
      puts $tclout [my generate-tcl-pre]
      puts $tclout [my generate-tcl-loader]
      puts $tclout [my generate-tcl-post]
      close $tclout
    }
  }


  method generate-make path {
    my build-Makefile $path [self]
  }

  method linktype {} {
    return library
  }



  method package-ifneeded {args} {
    set result {}
    set name [my define get pkg_name [my define get name]]
    set version [my define get pkg_vers [my define get version]]
    if {$version eq {}} {
      set version 0.1a
    }
    set output_tcl [my define get output_tcl]
    if {$output_tcl ne {}} {
      set script "\[list source \[file join \$dir $output_tcl\]\]"
    } elseif {[my define get SHARED_BUILD 0]} {
      set script "\[list load \[file join \$dir [my define get libfile]\] $name\]"
    } else {
      # Provide a null passthrough
      set script "\[list package provide $name $version\]"
    }
    set result "package ifneeded [list $name] [list $version] $script"
    foreach alias $args {
      set script "package require $name $version \; package provide $alias $version"
      append result \n\n [list package ifneeded $alias $version $script]
    }
    return $result
  }


  method shared_library {{filename {}}} {
    set name [string tolower [my define get name [my define get pkg_name]]]
    set NAME [string toupper $name]
    set version [my define get version [my define get pkg_vers]]
    set map {}
    lappend map %LIBRARY_NAME% $name
    lappend map %LIBRARY_VERSION% $version
    lappend map %LIBRARY_VERSION_NODOTS% [string map {. {}} $version]
    lappend map %LIBRARY_PREFIX% [my define getnull libprefix]
    set outfile [string map $map [my define get PRACTCL_NAME_LIBRARY]][my define get SHLIB_SUFFIX]
    return $outfile
  }

  method static_library {{filename {}}} {
    set name [string tolower [my define get name [my define get pkg_name]]]
    set NAME [string toupper $name]
    set version [my define get version [my define get pkg_vers]]
    set map {}
    lappend map %LIBRARY_NAME% $name
    lappend map %LIBRARY_VERSION% $version
    lappend map %LIBRARY_VERSION_NODOTS% [string map {. {}} $version]
    lappend map %LIBRARY_PREFIX% [my define getnull libprefix]
    set outfile [string map $map [my define get PRACTCL_NAME_LIBRARY]].a
    return $outfile
  }
}

###
# END: class project library.tcl
###
###
# START: class project tclkit.tcl
###


::clay::define ::practcl::tclkit {
  superclass ::practcl::library

  method build-tclkit_main {PROJECT PKG_OBJS} {
    ###
    # Build static package list
    ###
    set statpkglist {}
    foreach cobj [list {*}${PKG_OBJS} $PROJECT] {
      foreach {pkg info} [$cobj project-static-packages] {
5027
5028
5029
5030
5031
5032
5033


5034
5035
5036


5037
5038
5039
5040
5041
5042
5043

    set map {}
    foreach var {
      vfsroot mainhook mainfunc vfs_main
    } {
      dict set map %${var}% [set $var]
    }


    set preinitscript {
set ::odie(boot_vfs) %vfsroot%
set ::SRCDIR $::odie(boot_vfs)


if {[file exists [file join %vfsroot% tcl_library init.tcl]]} {
  set ::tcl_library [file join %vfsroot% tcl_library]
  set ::auto_path {}
}
if {[file exists [file join %vfsroot% tk_library tk.tcl]]} {
  set ::tk_library [file join %vfsroot% tk_library]
}







>
>



>
>







7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194

    set map {}
    foreach var {
      vfsroot mainhook mainfunc vfs_main
    } {
      dict set map %${var}% [set $var]
    }
    set thread_init_script {namespace eval ::starkit {}}
    append thread_init_script \n [list set ::starkit::topdir $vfsroot]
    set preinitscript {
set ::odie(boot_vfs) %vfsroot%
set ::SRCDIR $::odie(boot_vfs)
namespace eval ::starkit {}
set ::starkit::topdir %vfsroot%
if {[file exists [file join %vfsroot% tcl_library init.tcl]]} {
  set ::tcl_library [file join %vfsroot% tcl_library]
  set ::auto_path {}
}
if {[file exists [file join %vfsroot% tk_library tk.tcl]]} {
  set ::tk_library [file join %vfsroot% tk_library]
}
5142
5143
5144
5145
5146
5147
5148
5149

5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163


5164
5165
5166
5167
5168


5169


5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
      if {![dict exists $info version]} {
        error "$statpkg HAS NO VERSION"
      }
      # We employ a NULL to prevent the package system from thinking the
      # package is actually loaded into the interpreter
      $PROJECT code header "extern Tcl_PackageInitProc $initfunc\;\n"
      set script [list package ifneeded $statpkg [dict get $info version] [list ::load {} $statpkg]]
      append main_init_script \n [list set ::kitpkg(${statpkg}) $script]

      if {[dict get $info autoload]} {
        ::practcl::cputs appinit "  if(${initfunc}(interp)) return TCL_ERROR\;"
        ::practcl::cputs appinit "  Tcl_StaticPackage(interp,\"$statpkg\",$initfunc,NULL)\;"
      } else {
        ::practcl::cputs appinit "\n  Tcl_StaticPackage(NULL,\"$statpkg\",$initfunc,NULL)\;"
        append main_init_script \n $script
      }
    }
    append main_init_script \n {
if {[file exists [file join $::SRCDIR packages.tcl]]} {
  #In a wrapped exe, we don't go out to the environment
  set dir $::SRCDIR
  source [file join $::SRCDIR packages.tcl]
}


# Specify a user-specific startup file to invoke if the application
# is run interactively.  Typically the startup file is "~/.apprc"
# where "app" is the name of the application.  If this line is deleted
# then no user-specific startup file will be run under any conditions.
}


    append main_init_script \n [list set tcl_rcFileName [$PROJECT define get tcl_rcFileName ~/.tclshrc]]


    practcl::cputs appinit "  Tcl_Eval(interp,[::practcl::tcl_to_c  $main_init_script]);"
    practcl::cputs appinit {  return TCL_OK;}
    $PROJECT c_function [string map $map "int %mainfunc%(Tcl_Interp *interp)"] [string map $map $appinit]
  }

  method Collate_Source CWD {
    next $CWD
    set name [my define get name]
    # Assume a static shell
    if {[my define exists SHARED_BUILD]} {
      my define set SHARED_BUILD 0
    }
    if {![my define exists TCL_LOCAL_APPINIT]} {
      my define set TCL_LOCAL_APPINIT Tclkit_AppInit
    }
    if {![my define exists TCL_LOCAL_MAIN_HOOK]} {
      my define set TCL_LOCAL_MAIN_HOOK Tclkit_MainHook
    }
    set PROJECT [self]
    set os [$PROJECT define get TEACUP_OS]
    if {[my define get SHARED_BUILD]} {
      puts [list BUILDING TCLSH FOR OS $os]
    } else {
      puts [list BUILDING KIT FOR OS $os]
    }
    set TCLOBJ [$PROJECT tclcore]
    ::practcl::toolset select $TCLOBJ








|
>









|

|
|
|
>
>





>
>

>
>
|



<















|







7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331

7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
      if {![dict exists $info version]} {
        error "$statpkg HAS NO VERSION"
      }
      # We employ a NULL to prevent the package system from thinking the
      # package is actually loaded into the interpreter
      $PROJECT code header "extern Tcl_PackageInitProc $initfunc\;\n"
      set script [list package ifneeded $statpkg [dict get $info version] [list ::load {} $statpkg]]
      append main_init_script \n [list set ::starkit::static_packages(${statpkg}) $script]

      if {[dict get $info autoload]} {
        ::practcl::cputs appinit "  if(${initfunc}(interp)) return TCL_ERROR\;"
        ::practcl::cputs appinit "  Tcl_StaticPackage(interp,\"$statpkg\",$initfunc,NULL)\;"
      } else {
        ::practcl::cputs appinit "\n  Tcl_StaticPackage(NULL,\"$statpkg\",$initfunc,NULL)\;"
        append main_init_script \n $script
      }
    }
    append main_init_script \n {
if {[file exists [file join $::starkit::topdir pkgIndex.tcl]]} {
  #In a wrapped exe, we don't go out to the environment
  set dir $::starkit::topdir
  source [file join $::starkit::topdir pkgIndex.tcl]
}}
    append thread_init_script $main_init_script
    append main_init_script \n {
# Specify a user-specific startup file to invoke if the application
# is run interactively.  Typically the startup file is "~/.apprc"
# where "app" is the name of the application.  If this line is deleted
# then no user-specific startup file will be run under any conditions.
}
    append thread_init_script \n [list set ::starkit::thread_init $thread_init_script]
    append main_init_script \n [list set ::starkit::thread_init $thread_init_script]
    append main_init_script \n [list set tcl_rcFileName [$PROJECT define get tcl_rcFileName ~/.tclshrc]]


    practcl::cputs appinit "  Tcl_Eval(interp,[::practcl::tcl_to_c  $thread_init_script]);"
    practcl::cputs appinit {  return TCL_OK;}
    $PROJECT c_function [string map $map "int %mainfunc%(Tcl_Interp *interp)"] [string map $map $appinit]
  }

  method Collate_Source CWD {
    next $CWD
    set name [my define get name]
    # Assume a static shell
    if {[my define exists SHARED_BUILD]} {
      my define set SHARED_BUILD 0
    }
    if {![my define exists TCL_LOCAL_APPINIT]} {
      my define set TCL_LOCAL_APPINIT Tclkit_AppInit
    }
    if {![my define exists TCL_LOCAL_MAIN_HOOK]} {
      my define set TCL_LOCAL_MAIN_HOOK Tclkit_MainHook
    }
    set PROJECT [self]
    set os [$PROJECT define get TEACUP_OS]
    if {[my define get SHARED_BUILD 0]} {
      puts [list BUILDING TCLSH FOR OS $os]
    } else {
      puts [list BUILDING KIT FOR OS $os]
    }
    set TCLOBJ [$PROJECT tclcore]
    ::practcl::toolset select $TCLOBJ

5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
      if {[string is true [$item define get static]]} {
        lappend PKG_OBJS $item
      }
    }
    # Arrange to build an main.c that utilizes TCL_LOCAL_APPINIT and TCL_LOCAL_MAIN_HOOK
    if {$os eq "windows"} {
      set PLATFORM_SRC_DIR win
      if {[my define get SHARED_BUILD]} {
        my add class csource filename [file join $TCLSRCDIR win tclWinReg.c] initfunc Registry_Init pkg_name registry pkg_vers 1.3.1 autoload 1
        my add class csource filename [file join $TCLSRCDIR win tclWinDde.c] initfunc Dde_Init pkg_name dde pkg_vers 1.4.0 autoload 1
      }
      my add class csource ofile [my define get name]_appinit.o filename [file join $TCLSRCDIR win tclAppInit.c] extra [list -DTCL_LOCAL_MAIN_HOOK=[my define get TCL_LOCAL_MAIN_HOOK Tclkit_MainHook] -DTCL_LOCAL_APPINIT=[my define get TCL_LOCAL_APPINIT Tclkit_AppInit]]
    } else {
      set PLATFORM_SRC_DIR unix
      my add class csource ofile [my define get name]_appinit.o filename [file join $TCLSRCDIR unix tclAppInit.c] extra [list -DTCL_LOCAL_MAIN_HOOK=[my define get TCL_LOCAL_MAIN_HOOK Tclkit_MainHook] -DTCL_LOCAL_APPINIT=[my define get TCL_LOCAL_APPINIT Tclkit_AppInit]]
    }

    if {[my define get SHARED_BUILD]} {
      ###
      # Add local static Zlib implementation
      ###
      set cdir [file join $TCLSRCDIR compat zlib]
      foreach file {
        adler32.c compress.c crc32.c
        deflate.c infback.c inffast.c







|









|







7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
      if {[string is true [$item define get static]]} {
        lappend PKG_OBJS $item
      }
    }
    # Arrange to build an main.c that utilizes TCL_LOCAL_APPINIT and TCL_LOCAL_MAIN_HOOK
    if {$os eq "windows"} {
      set PLATFORM_SRC_DIR win
      if {![my define get SHARED_BUILD 0]} {
        my add class csource filename [file join $TCLSRCDIR win tclWinReg.c] initfunc Registry_Init pkg_name registry pkg_vers 1.3.1 autoload 1
        my add class csource filename [file join $TCLSRCDIR win tclWinDde.c] initfunc Dde_Init pkg_name dde pkg_vers 1.4.0 autoload 1
      }
      my add class csource ofile [my define get name]_appinit.o filename [file join $TCLSRCDIR win tclAppInit.c] extra [list -DTCL_LOCAL_MAIN_HOOK=[my define get TCL_LOCAL_MAIN_HOOK Tclkit_MainHook] -DTCL_LOCAL_APPINIT=[my define get TCL_LOCAL_APPINIT Tclkit_AppInit]]
    } else {
      set PLATFORM_SRC_DIR unix
      my add class csource ofile [my define get name]_appinit.o filename [file join $TCLSRCDIR unix tclAppInit.c] extra [list -DTCL_LOCAL_MAIN_HOOK=[my define get TCL_LOCAL_MAIN_HOOK Tclkit_MainHook] -DTCL_LOCAL_APPINIT=[my define get TCL_LOCAL_APPINIT Tclkit_AppInit]]
    }

    if {![my define get SHARED_BUILD 0]} {
      ###
      # Add local static Zlib implementation
      ###
      set cdir [file join $TCLSRCDIR compat zlib]
      foreach file {
        adler32.c compress.c crc32.c
        deflate.c infback.c inffast.c
5246
5247
5248
5249
5250
5251
5252


5253
5254



5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288

5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
    if {[file exists $zipfs]} {
      $TCLOBJ define set tip_430 1
      my define set tip_430 1
    } else {
      # The Tclconfig project maintains a mirror of the version
      # released with the Tcl core
      my define set tip_430 0


      ::practcl::LOCAL tool tclconfig unpack
      set COMPATSRCROOT [::practcl::LOCAL tool tclconfig define get srcdir]



      my add class csource ofile tclZipfs.o filename [file join $COMPATSRCROOT compat tclZipfs.c] extra -I[::practcl::file_relative $CWD [file join $TCLSRCDIR compat zlib contrib minizip]]
    }

    my define add include_dir [file join $TCLSRCDIR generic]
    my define add include_dir [file join $TCLSRCDIR $PLATFORM_SRC_DIR]
    # This file will implement TCL_LOCAL_APPINIT and TCL_LOCAL_MAIN_HOOK
    my build-tclkit_main $PROJECT $PKG_OBJS
  }

  ## Wrap an executable
  #
  method wrap {PWD exename vfspath args} {
    cd $PWD
    if {![file exists $vfspath]} {
      file mkdir $vfspath
    }
    foreach item [my link list core.library] {
      set name  [$item define get name]
      set libsrcdir [$item define get srcdir]
      if {[file exists [file join $libsrcdir library]]} {
        ::practcl::copyDir [file join $libsrcdir library] [file join $vfspath ${name}_library]
      }
    }
    # Assume the user will populate the VFS path
    #if {[my define get installdir] ne {}} {
    #  ::practcl::copyDir [file join [my define get installdir] [string trimleft [my define get prefix] /] lib] [file join $vfspath lib]
    #}
    foreach arg $args {
       ::practcl::copyDir $arg $vfspath
    }

    set fout [open [file join $vfspath packages.tcl] w]
    puts $fout [string map [list %platform% [my define get TEACUP_PROFILE]] {set ::tcl_teapot_profile {%platform%}}]
    puts $fout {

set ::PKGIDXFILE [info script]
set dir [file dirname $::PKGIDXFILE]
if {$::tcl_platform(platform) eq "windows"} {
  set ::g(HOME) [file join [file normalize $::env(LOCALAPPDATA)] tcl]
} else {
  set ::g(HOME) [file normalize ~/tcl]
}
set ::tcl_teapot [file join $::g(HOME) teapot $::tcl_teapot_profile]
lappend ::auto_path $::tcl_teapot
}
    puts $fout [list proc installDir [info args ::practcl::installDir] [info body ::practcl::installDir]]
    set buffer [::practcl::pkgindex_path $vfspath]
    puts $fout $buffer
    puts $fout {
# Advertise statically linked packages
foreach {pkg script} [array get ::kitpkg] {
  eval $script
}
}
    puts $fout {
###
# Cache binary packages distributed as dynamic libraries in a known location
###







>
>
|
|
>
>
>
|







<
<
<




















|


>



|

|

|







|







7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424



7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
    if {[file exists $zipfs]} {
      $TCLOBJ define set tip_430 1
      my define set tip_430 1
    } else {
      # The Tclconfig project maintains a mirror of the version
      # released with the Tcl core
      my define set tip_430 0
      set tclzipfs_c [my define get tclzipfs_c]
      if {![file exists $tclzipfs_c]} {
        ::practcl::LOCAL tool tclconfig unpack
        set COMPATSRCROOT [::practcl::LOCAL tool tclconfig define get srcdir]
        set tclzipfs_c [file join $COMPATSRCROOT compat tclZipfs.c]
      }
      my add class csource ofile tclZipfs.o filename $tclzipfs_c \
        extra -I[::practcl::file_relative $CWD [file join $TCLSRCDIR compat zlib contrib minizip]]
    }

    my define add include_dir [file join $TCLSRCDIR generic]
    my define add include_dir [file join $TCLSRCDIR $PLATFORM_SRC_DIR]
    # This file will implement TCL_LOCAL_APPINIT and TCL_LOCAL_MAIN_HOOK
    my build-tclkit_main $PROJECT $PKG_OBJS
  }



  method wrap {PWD exename vfspath args} {
    cd $PWD
    if {![file exists $vfspath]} {
      file mkdir $vfspath
    }
    foreach item [my link list core.library] {
      set name  [$item define get name]
      set libsrcdir [$item define get srcdir]
      if {[file exists [file join $libsrcdir library]]} {
        ::practcl::copyDir [file join $libsrcdir library] [file join $vfspath ${name}_library]
      }
    }
    # Assume the user will populate the VFS path
    #if {[my define get installdir] ne {}} {
    #  ::practcl::copyDir [file join [my define get installdir] [string trimleft [my define get prefix] /] lib] [file join $vfspath lib]
    #}
    foreach arg $args {
       ::practcl::copyDir $arg $vfspath
    }

    set fout [open [file join $vfspath pkgIndex.tcl] w]
    puts $fout [string map [list %platform% [my define get TEACUP_PROFILE]] {set ::tcl_teapot_profile {%platform%}}]
    puts $fout {
namespace eval ::starkit {}
set ::PKGIDXFILE [info script]
set dir [file dirname $::PKGIDXFILE]
if {$::tcl_platform(platform) eq "windows"} {
  set ::starkit::localHome [file join [file normalize $::env(LOCALAPPDATA)] tcl]
} else {
  set ::starkit::localHome [file normalize ~/tcl]
}
set ::tcl_teapot [file join $::starkit::localHome teapot $::tcl_teapot_profile]
lappend ::auto_path $::tcl_teapot
}
    puts $fout [list proc installDir [info args ::practcl::installDir] [info body ::practcl::installDir]]
    set buffer [::practcl::pkgindex_path $vfspath]
    puts $fout $buffer
    puts $fout {
# Advertise statically linked packages
foreach {pkg script} [array get ::starkit::static_packages] {
  eval $script
}
}
    puts $fout {
###
# Cache binary packages distributed as dynamic libraries in a known location
###
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423

###
# END: class project tclkit.tcl
###
###
# START: class distro baseclass.tcl
###

###
# Standalone class to manage code distribution
# This class is intended to be mixed into another class
# (Thus the lack of ancestors)
###
oo::class create ::practcl::distribution {

  method scm_info {} {
    return {
      scm  None
      hash {}
      maxdate {}
      tags {}
      isodate {}
    }
  }
  
  method DistroMixIn {} {
    my define set scm none
  }

  method Sandbox {} {
    if {[my define exists sandbox]} {
      return [my define get sandbox]
    }
    if {[my organ project] ni {::noop {}}} {
      set sandbox [my <project> define get sandbox]
      if {$sandbox ne {}} {
        my define set sandbox $sandbox
        return $sandbox
      }
    }
    set sandbox [file normalize [file join $::CWD ..]]
    my define set sandbox $sandbox
    return $sandbox
  }

  method SrcDir {} {
    set pkg [my define get name]
    if {[my define exists srcdir]} {
      return [my define get srcdir]
    }
    set sandbox [my Sandbox]
    set srcdir [file join [my Sandbox] $pkg]
    my define set srcdir $srcdir
    return $srcdir
  }

  method ScmTag    {} {}
  method ScmClone  {} {}
  method ScmUnpack {} {}
  method ScmUpdate {} {}

  method Unpack {} {
    set srcdir [my SrcDir]
    if {[file exists $srcdir]} {
      return
    }
    set pkg [my define get name]
    if {[my define exists download]} {
      # Utilize a staged download
      set download [my define get download]
      if {[file exists [file join $download $pkg.zip]]} {
        ::practcl::tcllib_require zipfile::decode
        ::zipfile::decode::unzipfile [file join $download $pkg.zip] $srcdir
        return
      }
    }
    my ScmUnpack
  }
}

oo::objdefine ::practcl::distribution {

  method Sandbox {object} {
    if {[$object define exists sandbox]} {
      return [$object define get sandbox]
    }
    if {[$object organ project] ni {::noop {}}} {
      set sandbox [$object <project> define get sandbox]
      if {$sandbox ne {}} {
        $object define set sandbox $sandbox
        return $sandbox
      }
    }
    set pkg [$object define get name]







<
<
<
<
<
<
|
<









<



<




|










<










<




<


















<

<




|







7490
7491
7492
7493
7494
7495
7496






7497

7498
7499
7500
7501
7502
7503
7504
7505
7506

7507
7508
7509

7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524

7525
7526
7527
7528
7529
7530
7531
7532
7533
7534

7535
7536
7537
7538

7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556

7557

7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569

###
# END: class project tclkit.tcl
###
###
# START: class distro baseclass.tcl
###






::clay::define ::practcl::distribution {

  method scm_info {} {
    return {
      scm  None
      hash {}
      maxdate {}
      tags {}
      isodate {}
    }
  }

  method DistroMixIn {} {
    my define set scm none
  }

  method Sandbox {} {
    if {[my define exists sandbox]} {
      return [my define get sandbox]
    }
    if {[my clay delegate project] ni {::noop {}}} {
      set sandbox [my <project> define get sandbox]
      if {$sandbox ne {}} {
        my define set sandbox $sandbox
        return $sandbox
      }
    }
    set sandbox [file normalize [file join $::CWD ..]]
    my define set sandbox $sandbox
    return $sandbox
  }

  method SrcDir {} {
    set pkg [my define get name]
    if {[my define exists srcdir]} {
      return [my define get srcdir]
    }
    set sandbox [my Sandbox]
    set srcdir [file join [my Sandbox] $pkg]
    my define set srcdir $srcdir
    return $srcdir
  }

  method ScmTag    {} {}
  method ScmClone  {} {}
  method ScmUnpack {} {}
  method ScmUpdate {} {}

  method Unpack {} {
    set srcdir [my SrcDir]
    if {[file exists $srcdir]} {
      return
    }
    set pkg [my define get name]
    if {[my define exists download]} {
      # Utilize a staged download
      set download [my define get download]
      if {[file exists [file join $download $pkg.zip]]} {
        ::practcl::tcllib_require zipfile::decode
        ::zipfile::decode::unzipfile [file join $download $pkg.zip] $srcdir
        return
      }
    }
    my ScmUnpack
  }
}

oo::objdefine ::practcl::distribution {

  method Sandbox {object} {
    if {[$object define exists sandbox]} {
      return [$object define get sandbox]
    }
    if {[$object clay delegate project] ni {::noop {}}} {
      set sandbox [$object <project> define get sandbox]
      if {$sandbox ne {}} {
        $object define set sandbox $sandbox
        return $sandbox
      }
    }
    set pkg [$object define get name]
5439
5440
5441
5442
5443
5444
5445
5446

5447
5448
5449
5450
5451
5452
5453
5454

5455
5456
5457
5458
5459
5460

5461
5462
5463
5464
5465
5466
5467
5468
5469
5470

5471
5472
5473




5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
      $object define set srcdir $srcdir
    }

    set classprefix ::practcl::distribution.
    if {[file exists $srcdir]} {
      foreach class [::info commands ${classprefix}*] {
        if {[$class claim_path $srcdir]} {
          $object mixin distribution $class

          $object define set scm [string range $class [string length ::practcl::distribution.] end]
          return [$object define get scm]
        }
      }
    }
    foreach class [::info commands ${classprefix}*] {
      if {[$class claim_object $object]} {
        $object mixin distribution $class

        $object define set scm [string range $class [string length ::practcl::distribution.] end]
        return [$object define get scm]
      }
    }
    if {[$object define get scm] eq {} && [$object define exists file_url]} {
      set class ::practcl::distribution.snapshot

      $object define set scm snapshot
      $object mixin distribution $class
      return [$object define get scm]
    }
    error "Cannot determine source distribution method"
  }

  method claim_path path {
    return false
  }

  method claim_object object {
    return false
  }




}

###
# END: class distro baseclass.tcl
###
###
# START: class distro snapshot.tcl
###

oo::class create ::practcl::distribution.snapshot {
  superclass ::practcl::distribution

  method ScmUnpack {} {
    set srcdir [my SrcDir]
    if {[file exists [file join $srcdir .download]]} {
      return 0
    }
    set dpath [::practcl::LOCAL define get download]
    set url [my define get file_url]







|
>
|
|





|
>
|
|




>
|
|
|




|
|

>



>
>
>
>








<
|

<







7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635

7636
7637

7638
7639
7640
7641
7642
7643
7644
      $object define set srcdir $srcdir
    }

    set classprefix ::practcl::distribution.
    if {[file exists $srcdir]} {
      foreach class [::info commands ${classprefix}*] {
        if {[$class claim_path $srcdir]} {
          $object clay mixinmap distribution $class
          set name [$class claim_option]
          $object define set scm $name
          return $name
        }
      }
    }
    foreach class [::info commands ${classprefix}*] {
      if {[$class claim_object $object]} {
        $object clay mixinmap distribution $class
        set name [$class claim_option]
        $object define set scm $name
        return $name
      }
    }
    if {[$object define get scm] eq {} && [$object define exists file_url]} {
      set class ::practcl::distribution.snapshot
      set name [$class claim_option]
      $object define set scm $name
      $object clay mixinmap distribution $class
      return $name
    }
    error "Cannot determine source distribution method"
  }

  method claim_option {} {
    return Unknown
  }

  method claim_object object {
    return false
  }

  method claim_path path {
    return false
  }
}

###
# END: class distro baseclass.tcl
###
###
# START: class distro snapshot.tcl
###

::clay::define ::practcl::distribution.snapshot {
  superclass ::practcl::distribution

  method ScmUnpack {} {
    set srcdir [my SrcDir]
    if {[file exists [file join $srcdir .download]]} {
      return 0
    }
    set dpath [::practcl::LOCAL define get download]
    set url [my define get file_url]
5517
5518
5519
5520
5521
5522
5523

5524



5525




5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
    set fosdb [my ScmClone]
    set tag [my ScmTag]
    file mkdir $srcdir
    ::practcl::fossil $srcdir open $fosdb $tag
    return 1
  }
}





oo::objdefine ::practcl::distribution.snapshot {




  method claim_path path {
    if {[file exists [file join $path .download]]} {
      return true
    }
    return false
  }
  method claim_object object {
    return false
  }
}

###
# END: class distro snapshot.tcl
###
###
# START: class distro fossil.tcl
###

oo::class create ::practcl::distribution.fossil {
  superclass ::practcl::distribution

  method scm_info {} {
    set info [next]
    dict set info scm fossil
    foreach {field value} [::practcl::fossil_status [my define get srcdir]] {
      dict set info $field $value
    }
    return $info
  }
  
  # Clone the source
  method ScmClone  {} {
    set srcdir [my SrcDir]
    if {[file exists [file join $srcdir .fslckout]]} {
      return
    }
    if {[file exists [file join $srcdir _FOSSIL_]]} {
      return







>

>
>
>
|
>
>
>
>






<
<
<








<
|

<








<
<







7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691



7692
7693
7694
7695
7696
7697
7698
7699

7700
7701

7702
7703
7704
7705
7706
7707
7708
7709


7710
7711
7712
7713
7714
7715
7716
    set fosdb [my ScmClone]
    set tag [my ScmTag]
    file mkdir $srcdir
    ::practcl::fossil $srcdir open $fosdb $tag
    return 1
  }
}
oo::objdefine ::practcl::distribution.snapshot {

  method claim_object object {
    return false
  }

  method claim_option {} {
    return snapshot
  }

  method claim_path path {
    if {[file exists [file join $path .download]]} {
      return true
    }
    return false
  }



}

###
# END: class distro snapshot.tcl
###
###
# START: class distro fossil.tcl
###

::clay::define ::practcl::distribution.fossil {
  superclass ::practcl::distribution

  method scm_info {} {
    set info [next]
    dict set info scm fossil
    foreach {field value} [::practcl::fossil_status [my define get srcdir]] {
      dict set info $field $value
    }
    return $info
  }


  method ScmClone  {} {
    set srcdir [my SrcDir]
    if {[file exists [file join $srcdir .fslckout]]} {
      return
    }
    if {[file exists [file join $srcdir _FOSSIL_]]} {
      return
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678















5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749











5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771

5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023


6024
6025
6026



6027
6028
6029




































6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
        return $fosdb
      }
    }
    # Fall back to the fossil mirror on the island of misfit toys
    ::practcl::doexec fossil clone http://fossil.etoyoc.com/fossil/$pkg $fosdb
    return $fosdb
  }

  method ScmTag {} {
    if {[my define exists scm_tag]} {
      return [my define get scm_tag]
    }
    if {[my define exists tag]} {
      set tag [my define get tag]
    } else {
      set tag trunk
    }
    my define set scm_tag $tag
    return $tag
  }

  method ScmUnpack {} {
    set srcdir [my SrcDir]
    if {[file exists [file join $srcdir .fslckout]]} {
      return 0
    }
    if {[file exists [file join $srcdir _FOSSIL_]]} {
      return 0
    }
    set CWD [pwd]
    set fosdb [my ScmClone]
    set tag [my ScmTag]
    file mkdir $srcdir
    ::practcl::fossil $srcdir open $fosdb $tag
    return 1
  }

  method ScmUpdate {} {
    if {[my ScmUnpack]} {
      return
    }
    set srcdir [my SrcDir]
    set tag [my ScmTag]
    ::practcl::fossil $srcdir update $tag
  }
}

oo::objdefine ::practcl::distribution.fossil {

  # Check for markers in the source root
  method claim_path path {
    if {[file exists [file join $path .fslckout]]} {
      return true
    }
    if {[file exists [file join $path _FOSSIL_]]} {
      return true
    }
    return false
  }

  # Check for markers in the metadata
  method claim_object obj {
    set path [$obj define get srcdir]
    if {[my claim_path $path]} {
      return true
    }
    if {[$obj define get fossil_url] ne {}} {
      return true
    }
    return false
  }















}

###
# END: class distro fossil.tcl
###
###
# START: class distro git.tcl
###


oo::class create ::practcl::distribution.git {
  superclass ::practcl::distribution

  method ScmTag {} {
    if {[my define exists scm_tag]} {
      return [my define get scm_tag]
    }
    if {[my define exists tag]} {
      set tag [my define get tag]
    } else {
      set tag master
    }
    my define set scm_tag $tag
    return $tag
  }

  method ScmUnpack {} {
    set srcdir [my SrcDir]
    if {[file exists [file join $srcdir .git]]} {
      return 0
    }
    set CWD [pwd]
    set tag [my ScmTag]
    set pkg [my define get name]
    if {[my define exists git_url]} {
      ::practcl::doexec git clone --branch $tag [my define get git_url] $srcdir
    } else {
      ::practcl::doexec git clone --branch $tag https://github.com/eviltwinskippy/$pkg $srcdir
    }
    return 1
  }

  method ScmUpdate {} {
    if {[my ScmUnpack]} {
      return
    }
    set CWD [pwd]
    set srcdir [my SrcDir]
    set tag [my ScmTag]
    ::practcl::doexec_in $srcdir git pull
    cd $CWD
  }

}
oo::objdefine ::practcl::distribution.git {
  method claim_path path {
   if {[file exists [file join $path .git]]} {
      return true
    }
    return false
  }
  method claim_object obj {
    set path [$obj define get srcdir]
    if {[my claim_path $path]} {
      return true
    }
    if {[$obj define get git_url] ne {}} {
      return true
    }
    return false
  }











}

###
# END: class distro git.tcl
###
###
# START: class subproject baseclass.tcl
###
oo::class create ::practcl::subproject {
  superclass ::practcl::module

  method _MorphPatterns {} {
    return {{::practcl::subproject.@name@} {::practcl::@name@} {@name@} {::practcl::subproject}}
  }


  method BuildDir {PWD} {
    return [my define get srcdir]
  }

  method child which {
    switch $which {

      organs {
	# A library can be a project, it can be a module. Any
	# subordinate modules will indicate their existance
        return [list project [self] module [self]]
      }
    }
  }

  method compile {} {}


  method go {} {
    ::practcl::distribution select [self]
    set name [my define get name]
    my define set builddir [my BuildDir [my define get masterpath]]
    my define set builddir [my BuildDir [my define get masterpath]]
    my sources
  }

  # Install project into the local build system
  method install args {}

  method linktype {} {
    return {subordinate package}
  }

  method linker-products {configdict} {}

  method linker-external {configdict} {
    if {[dict exists $configdict PRACTCL_PKG_LIBS]} {
      return [dict get $configdict PRACTCL_PKG_LIBS]
    }
    if {[dict exists $configdict LIBS]} {
      return [dict get $configdict LIBS]
    }
  }

  method linker-extra {configdict} {
    if {[dict exists $configdict PRACTCL_LINKER_EXTRA]} {
      return [dict get $configdict PRACTCL_LINKER_EXTRA]
    }
    return {}
  }

  ###
  # Methods for packages/tools that can be downloaded
  # possibly built and used internally by this Practcl
  # process
  ###

  ###
  # Load the facility into the interpreter
  ###
  method env-bootstrap {} {
    set pkg [my define get pkg_name [my define get name]]
    package require $pkg
  }

  ###
  # Return a file path that exec can call
  ###
  method env-exec {} {}

  ###
  # Install the tool into the local environment
  ###
  method env-install {} {
    my unpack
  }

  ###
  # Do whatever is necessary to get the tool
  # into the local environment
  ###
  method env-load {} {
    my variable loaded
    if {[info exists loaded]} {
      return 0
    }
    if {![my env-present]} {
      my env-install
    }
    my env-bootstrap
    set loaded 1
  }

  ###
  # Check if tool is available for load/already loaded
  ###
  method env-present {} {
    set pkg [my define get pkg_name [my define get name]]
    if {[catch [list package require $pkg]]} {
      return 0
    }
    return 1
  }

  method sources {} {}

  method update {} {
    my ScmUpdate
  }

  method unpack {} {
    cd $::CWD
    ::practcl::distribution select [self]
    my Unpack
    ::practcl::toolset select [self]
    cd $::CWD
  }
}

###
# Trivial implementations
###


###
# A project which the kit compiles and integrates
# the source for itself
###
oo::class create ::practcl::subproject.source {
  superclass ::practcl::subproject ::practcl::library

  method env-bootstrap {} {
    set LibraryRoot [file join [my define get srcdir] [my define get module_root modules]]
    if {[file exists $LibraryRoot] && $LibraryRoot ni $::auto_path} {
      set ::auto_path [linsert $::auto_path 0 $LibraryRoot]
    }
  }

  method env-present {} {
    set path [my define get srcdir]
    return [file exists $path]
  }

  method linktype {} {
    return {subordinate package source}
  }

}

# a copy from the teapot
oo::class create ::practcl::subproject.teapot {
  superclass ::practcl::subproject

  method env-bootstrap {} {
    set pkg [my define get pkg_name [my define get name]]
    package require $pkg
  }

  method env-install {} {
    set pkg [my define get pkg_name [my define get name]]
    set download [my <project> define get download]
    my unpack
    set prefix [string trimleft [my <project> define get prefix] /]
    ::practcl::tcllib_require zipfile::decode
    ::zipfile::decode::unzipfile [file join $download $pkg.zip] [file join $prefix lib $pkg]
  }

  method env-present {} {
    set pkg [my define get pkg_name [my define get name]]
    if {[catch [list package require $pkg]]} {
      return 0
    }
    return 1
  }

  method install DEST {
    set pkg [my define get pkg_name [my define get name]]
    set download [my <project> define get download]
    my unpack
    set prefix [string trimleft [my <project> define get prefix] /]
    ::practcl::tcllib_require zipfile::decode
    ::zipfile::decode::unzipfile [file join $download $pkg.zip] [file join $DEST $prefix lib $pkg]
  }
}

oo::class create ::practcl::subproject.kettle {
  superclass ::practcl::subproject

  method kettle {path args} {
    my variable kettle
    if {![info exists kettle]} {
      ::practcl::LOCAL tool kettle env-load
      set kettle [file join [::practcl::LOCAL tool kettle define get srcdir] kettle]
    }
    set srcdir [my SourceRoot]
    ::practcl::dotclexec $kettle -f [file join $srcdir build.tcl] {*}$args
  }

  method install DEST {
    my kettle reinstall --prefix $DEST
  }
}

oo::class create ::practcl::subproject.critcl {
  superclass ::practcl::subproject

  method install DEST {
    my critcl -pkg [my define get name]
    set srcdir [my SourceRoot]
    ::practcl::copyDir [file join $srcdir [my define get name]] [file join $DEST lib [my define get name]]
  }
}


oo::class create ::practcl::subproject.sak {
  superclass ::practcl::subproject

  method env-bootstrap {} {
    set LibraryRoot [file join [my define get srcdir] [my define get module_root modules]]
    if {[file exists $LibraryRoot] && $LibraryRoot ni $::auto_path} {
      set ::auto_path [linsert $::auto_path 0 $LibraryRoot]
    }
  }

  method env-install {} {
    ###
    # Handle teapot installs
    ###
    set pkg [my define get pkg_name [my define get name]]
    my unpack
    set prefix [my <project> define get prefix [file normalize [file join ~ tcl]]]
    set srcdir [my define get srcdir]
    ::practcl::dotclexec [file join $srcdir installer.tcl] \
      -apps -app-path [file join $prefix apps] \
      -html -html-path [file join $prefix doc html $pkg] \
      -pkg-path [file join $prefix lib $pkg]  \
      -no-nroff -no-wait -no-gui
  }

  method env-present {} {
    set path [my define get srcdir]
    return [file exists $path]
  }

  method install DEST {
    ###
    # Handle teapot installs
    ###
    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
  }

  method install-module {DEST args} {


    set pkg [my define get pkg_name [my define get name]]
    set prefix [my <project> define get prefix [file normalize [file join ~ tcl]]]
    set pkgpath [file join $prefix lib $pkg]



    foreach module $args {
      ::practcl::installDir [file join $pkgpath $module] [file join $DEST $module]
    }




































  }
}

###
# END: class subproject baseclass.tcl
###
###
# START: class subproject binary.tcl
###

###
# A binary package
###
oo::class create ::practcl::subproject.binary {
  superclass ::practcl::subproject

  method clean {} {
    set builddir [file normalize [my define get builddir]]
    if {![file exists $builddir]} return
    if {[file exists [file join $builddir make.tcl]]} {
      ::practcl::domake.tcl $builddir clean
    } else {
      catch {::practcl::domake $builddir clean}
    }
  }

 method env-install {} {
    ###
    # Handle tea installs
    ###
    set pkg [my define get pkg_name [my define get name]]
    set os [::practcl::local_os]
    my define set os $os
    my unpack
    set prefix [my <project> define get prefix [file normalize [file join ~ tcl]]]
    set srcdir [my define get srcdir]
    lappend options --prefix $prefix --exec-prefix $prefix
    my define set config_opts $options
    my go
    my clean
    my compile
    my make-install {}
  }

  method project-compile-products {} {}

  method ComputeInstall {} {
    if {[my define exists install]} {
      switch [my define get install] {
        static {
          my define set static 1
          my define set autoload 0
        }







<












<















<









<


<
<
<
<
<
<
<
<
<
<
<











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








<
<
|

<












<















<










|
<

<
<
<
|
<
<










>
>
>
>
>
>
>
>
>
>
>








|

<



<
<



<


>







<

<
<







<
<

<



<

<








<






<
<
<
<
<
<
<
<
<
<




<
<
<
<

<
<
<
<



<
<
<
<
<











<
<
<
<







<

<



<








<
<
<
<
<
<
<
<
<
<
|

<






<




<



|
<
<
<
|

<




<








<







<









<
|

<









<




<
|

<






<
<
|

<






<














<




<













<

>
>
|
|
|
>
>
>
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









<
<
<
<
|

<









<















|

<

<







7761
7762
7763
7764
7765
7766
7767

7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779

7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794

7795
7796
7797
7798
7799
7800
7801
7802
7803

7804
7805











7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839


7840
7841

7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853

7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868

7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879

7880



7881


7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912

7913
7914
7915


7916
7917
7918

7919
7920
7921
7922
7923
7924
7925
7926
7927
7928

7929


7930
7931
7932
7933
7934
7935
7936


7937

7938
7939
7940

7941

7942
7943
7944
7945
7946
7947
7948
7949

7950
7951
7952
7953
7954
7955










7956
7957
7958
7959




7960




7961
7962
7963





7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974




7975
7976
7977
7978
7979
7980
7981

7982

7983
7984
7985

7986
7987
7988
7989
7990
7991
7992
7993










7994
7995

7996
7997
7998
7999
8000
8001

8002
8003
8004
8005

8006
8007
8008
8009



8010
8011

8012
8013
8014
8015

8016
8017
8018
8019
8020
8021
8022
8023

8024
8025
8026
8027
8028
8029
8030

8031
8032
8033
8034
8035
8036
8037
8038
8039

8040
8041

8042
8043
8044
8045
8046
8047
8048
8049
8050

8051
8052
8053
8054

8055
8056

8057
8058
8059
8060
8061
8062


8063
8064

8065
8066
8067
8068
8069
8070

8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084

8085
8086
8087
8088

8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101

8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152
8153
8154
8155
8156
8157
8158




8159
8160

8161
8162
8163
8164
8165
8166
8167
8168
8169

8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186

8187

8188
8189
8190
8191
8192
8193
8194
        return $fosdb
      }
    }
    # Fall back to the fossil mirror on the island of misfit toys
    ::practcl::doexec fossil clone http://fossil.etoyoc.com/fossil/$pkg $fosdb
    return $fosdb
  }

  method ScmTag {} {
    if {[my define exists scm_tag]} {
      return [my define get scm_tag]
    }
    if {[my define exists tag]} {
      set tag [my define get tag]
    } else {
      set tag trunk
    }
    my define set scm_tag $tag
    return $tag
  }

  method ScmUnpack {} {
    set srcdir [my SrcDir]
    if {[file exists [file join $srcdir .fslckout]]} {
      return 0
    }
    if {[file exists [file join $srcdir _FOSSIL_]]} {
      return 0
    }
    set CWD [pwd]
    set fosdb [my ScmClone]
    set tag [my ScmTag]
    file mkdir $srcdir
    ::practcl::fossil $srcdir open $fosdb $tag
    return 1
  }

  method ScmUpdate {} {
    if {[my ScmUnpack]} {
      return
    }
    set srcdir [my SrcDir]
    set tag [my ScmTag]
    ::practcl::fossil $srcdir update $tag
  }
}

oo::objdefine ::practcl::distribution.fossil {












  # Check for markers in the metadata
  method claim_object obj {
    set path [$obj define get srcdir]
    if {[my claim_path $path]} {
      return true
    }
    if {[$obj define get fossil_url] ne {}} {
      return true
    }
    return false
  }

  method claim_option {} {
    return fossil
  }

  # Check for markers in the source root
  method claim_path path {
    if {[file exists [file join $path .fslckout]]} {
      return true
    }
    if {[file exists [file join $path _FOSSIL_]]} {
      return true
    }
    return false
  }
}

###
# END: class distro fossil.tcl
###
###
# START: class distro git.tcl
###


::clay::define ::practcl::distribution.git {
  superclass ::practcl::distribution

  method ScmTag {} {
    if {[my define exists scm_tag]} {
      return [my define get scm_tag]
    }
    if {[my define exists tag]} {
      set tag [my define get tag]
    } else {
      set tag master
    }
    my define set scm_tag $tag
    return $tag
  }

  method ScmUnpack {} {
    set srcdir [my SrcDir]
    if {[file exists [file join $srcdir .git]]} {
      return 0
    }
    set CWD [pwd]
    set tag [my ScmTag]
    set pkg [my define get name]
    if {[my define exists git_url]} {
      ::practcl::doexec git clone --branch $tag [my define get git_url] $srcdir
    } else {
      ::practcl::doexec git clone --branch $tag https://github.com/eviltwinskippy/$pkg $srcdir
    }
    return 1
  }

  method ScmUpdate {} {
    if {[my ScmUnpack]} {
      return
    }
    set CWD [pwd]
    set srcdir [my SrcDir]
    set tag [my ScmTag]
    ::practcl::doexec_in $srcdir git pull
    cd $CWD
  }
}

oo::objdefine ::practcl::distribution.git {






  method claim_object obj {
    set path [$obj define get srcdir]
    if {[my claim_path $path]} {
      return true
    }
    if {[$obj define get git_url] ne {}} {
      return true
    }
    return false
  }

  method claim_option {} {
    return git
  }

  method claim_path path {
   if {[file exists [file join $path .git]]} {
      return true
    }
    return false
  }
}

###
# END: class distro git.tcl
###
###
# START: class subproject baseclass.tcl
###
::clay::define ::practcl::subproject {
  superclass ::practcl::module

  method _MorphPatterns {} {
    return {{::practcl::subproject.@name@} {::practcl::@name@} {@name@} {::practcl::subproject}}
  }


  method BuildDir {PWD} {
    return [my define get srcdir]
  }

  method child which {
    switch $which {
      delegate -
      organs {
	# A library can be a project, it can be a module. Any
	# subordinate modules will indicate their existance
        return [list project [self] module [self]]
      }
    }
  }

  method compile {} {}


  method go {} {
    ::practcl::distribution select [self]
    set name [my define get name]
    my define set builddir [my BuildDir [my define get masterpath]]
    my define set builddir [my BuildDir [my define get masterpath]]
    my sources
  }


  method install args {}

  method linktype {} {
    return {subordinate package}
  }

  method linker-products {configdict} {}

  method linker-external {configdict} {
    if {[dict exists $configdict PRACTCL_PKG_LIBS]} {
      return [dict get $configdict PRACTCL_PKG_LIBS]
    }
    if {[dict exists $configdict LIBS]} {
      return [dict get $configdict LIBS]
    }
  }

  method linker-extra {configdict} {
    if {[dict exists $configdict PRACTCL_LINKER_EXTRA]} {
      return [dict get $configdict PRACTCL_LINKER_EXTRA]
    }
    return {}
  }










  method env-bootstrap {} {
    set pkg [my define get pkg_name [my define get name]]
    package require $pkg
  }




  method env-exec {} {}




  method env-install {} {
    my unpack
  }





  method env-load {} {
    my variable loaded
    if {[info exists loaded]} {
      return 0
    }
    if {![my env-present]} {
      my env-install
    }
    my env-bootstrap
    set loaded 1
  }




  method env-present {} {
    set pkg [my define get pkg_name [my define get name]]
    if {[catch [list package require $pkg]]} {
      return 0
    }
    return 1
  }

  method sources {} {}

  method update {} {
    my ScmUpdate
  }

  method unpack {} {
    cd $::CWD
    ::practcl::distribution select [self]
    my Unpack
    ::practcl::toolset select [self]
    cd $::CWD
  }
}










::clay::define ::practcl::subproject.source {
  superclass ::practcl::subproject ::practcl::library

  method env-bootstrap {} {
    set LibraryRoot [file join [my define get srcdir] [my define get module_root modules]]
    if {[file exists $LibraryRoot] && $LibraryRoot ni $::auto_path} {
      set ::auto_path [linsert $::auto_path 0 $LibraryRoot]
    }
  }

  method env-present {} {
    set path [my define get srcdir]
    return [file exists $path]
  }

  method linktype {} {
    return {subordinate package source}
  }
}



::clay::define ::practcl::subproject.teapot {
  superclass ::practcl::subproject

  method env-bootstrap {} {
    set pkg [my define get pkg_name [my define get name]]
    package require $pkg
  }

  method env-install {} {
    set pkg [my define get pkg_name [my define get name]]
    set download [my <project> define get download]
    my unpack
    set prefix [string trimleft [my <project> define get prefix] /]
    ::practcl::tcllib_require zipfile::decode
    ::zipfile::decode::unzipfile [file join $download $pkg.zip] [file join $prefix lib $pkg]
  }

  method env-present {} {
    set pkg [my define get pkg_name [my define get name]]
    if {[catch [list package require $pkg]]} {
      return 0
    }
    return 1
  }

  method install DEST {
    set pkg [my define get pkg_name [my define get name]]
    set download [my <project> define get download]
    my unpack
    set prefix [string trimleft [my <project> define get prefix] /]
    ::practcl::tcllib_require zipfile::decode
    ::zipfile::decode::unzipfile [file join $download $pkg.zip] [file join $DEST $prefix lib $pkg]
  }
}

::clay::define ::practcl::subproject.kettle {
  superclass ::practcl::subproject

  method kettle {path args} {
    my variable kettle
    if {![info exists kettle]} {
      ::practcl::LOCAL tool kettle env-load
      set kettle [file join [::practcl::LOCAL tool kettle define get srcdir] kettle]
    }
    set srcdir [my SourceRoot]
    ::practcl::dotclexec $kettle -f [file join $srcdir build.tcl] {*}$args
  }

  method install DEST {
    my kettle reinstall --prefix $DEST
  }
}

::clay::define ::practcl::subproject.critcl {
  superclass ::practcl::subproject

  method install DEST {
    my critcl -pkg [my define get name]
    set srcdir [my SourceRoot]
    ::practcl::copyDir [file join $srcdir [my define get name]] [file join $DEST lib [my define get name]]
  }
}


::clay::define ::practcl::subproject.sak {
  superclass ::practcl::subproject

  method env-bootstrap {} {
    set LibraryRoot [file join [my define get srcdir] [my define get module_root modules]]
    if {[file exists $LibraryRoot] && $LibraryRoot ni $::auto_path} {
      set ::auto_path [linsert $::auto_path 0 $LibraryRoot]
    }
  }

  method env-install {} {
    ###
    # Handle teapot installs
    ###
    set pkg [my define get pkg_name [my define get name]]
    my unpack
    set prefix [my <project> define get prefix [file normalize [file join ~ tcl]]]
    set srcdir [my define get srcdir]
    ::practcl::dotclexec [file join $srcdir installer.tcl] \
      -apps -app-path [file join $prefix apps] \
      -html -html-path [file join $prefix doc html $pkg] \
      -pkg-path [file join $prefix lib $pkg]  \
      -no-nroff -no-wait -no-gui
  }

  method env-present {} {
    set path [my define get srcdir]
    return [file exists $path]
  }

  method install DEST {
    ###
    # Handle teapot installs
    ###
    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
  }

  method install-module {DEST args} {
    set srcdir [my define get srcdir]
    if {[llength $args]==1 && [lindex $args 0] in {* all}} {
      set pkg [my define get pkg_name [my define get name]]
      ::practcl::dotclexec [file join $srcdir installer.tcl] \
        -pkg-path [file join $DEST $pkg]  \
        -no-examples -no-html -no-nroff \
        -no-wait -no-gui -no-apps
    } else {
      foreach module $args {
        ::practcl::installModule [file join $srcdir modules $module] [file join $DEST $module]
      }
    }
  }
}
::clay::define ::practcl::subproject.practcl {
  superclass ::practcl::subproject
  method env-bootstrap {} {
    set LibraryRoot [file join [my define get srcdir] [my define get module_root modules]]
    if {[file exists $LibraryRoot] && $LibraryRoot ni $::auto_path} {
      set ::auto_path [linsert $::auto_path 0 $LibraryRoot]
    }
  }
  method env-install {} {
    ###
    # Handle teapot installs
    ###
    set pkg [my define get pkg_name [my define get name]]
    my unpack
    set prefix [my <project> define get prefix [file normalize [file join ~ tcl]]]
    set srcdir [my define get srcdir]
    ::practcl::dotclexec [file join $srcdir make.tcl] install [file join $prefix lib $pkg]
  }
  method install DEST {
    ###
    # Handle teapot installs
    ###
    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]
    puts [list INSTALLING  [my define get name] to [file join $DEST $prefix lib $pkg]]
    ::practcl::dotclexec [file join $srcdir make.tcl] install [file join $DEST $prefix lib $pkg]
  }
  method install-module {DEST args} {
    set pkg [my define get pkg_name [my define get name]]
    set srcdir [my define get srcdir]
    ::practcl::dotclexec [file join $srcdir make.tcl] install-module $DEST {*}$args
  }
}

###
# END: class subproject baseclass.tcl
###
###
# START: class subproject binary.tcl
###




::clay::define ::practcl::subproject.binary {
  superclass ::practcl::subproject

  method clean {} {
    set builddir [file normalize [my define get builddir]]
    if {![file exists $builddir]} return
    if {[file exists [file join $builddir make.tcl]]} {
      ::practcl::domake.tcl $builddir clean
    } else {
      catch {::practcl::domake $builddir clean}
    }
  }

 method env-install {} {
    ###
    # Handle tea installs
    ###
    set pkg [my define get pkg_name [my define get name]]
    set os [::practcl::local_os]
    my define set os $os
    my unpack
    set prefix [my <project> define get prefix [file normalize [file join ~ tcl]]]
    set srcdir [my define get srcdir]
    lappend options --prefix $prefix --exec-prefix $prefix
    my define set config_opts $options
    my go
    my clean
    my compile
    my make install {}
  }

  method project-compile-products {} {}

  method ComputeInstall {} {
    if {[my define exists install]} {
      switch [my define get install] {
        static {
          my define set static 1
          my define set autoload 0
        }
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
        }
        default {

        }
      }
    }
  }

  method go {} {
    next
    ::practcl::distribution select [self]
    my ComputeInstall
    my define set builddir [my BuildDir [my define get masterpath]]
  }

  method linker-products {configdict} {
    if {![my define get static 0]} {
      return {}
    }
    set srcdir [my define get builddir]
    if {[dict exists $configdict libfile]} {
      return " [file join $srcdir [dict get $configdict libfile]]"
    }
  }

  method project-static-packages {} {
    if {![my define get static 0]} {
      return {}
    }
    set result [my define get static_packages]
    set statpkg  [my define get static_pkg]
    set initfunc [my define get initfunc]







<






<









<







8208
8209
8210
8211
8212
8213
8214

8215
8216
8217
8218
8219
8220

8221
8222
8223
8224
8225
8226
8227
8228
8229

8230
8231
8232
8233
8234
8235
8236
        }
        default {

        }
      }
    }
  }

  method go {} {
    next
    ::practcl::distribution select [self]
    my ComputeInstall
    my define set builddir [my BuildDir [my define get masterpath]]
  }

  method linker-products {configdict} {
    if {![my define get static 0]} {
      return {}
    }
    set srcdir [my define get builddir]
    if {[dict exists $configdict libfile]} {
      return " [file join $srcdir [dict get $configdict libfile]]"
    }
  }

  method project-static-packages {} {
    if {![my define get static 0]} {
      return {}
    }
    set result [my define get static_packages]
    set statpkg  [my define get static_pkg]
    set initfunc [my define get initfunc]
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
    foreach item [my link list subordinate] {
      foreach {pkg info} [$item project-static-packages] {
        dict set result $pkg $info
      }
    }
    return $result
  }

  method BuildDir {PWD} {
    set name [my define get name]
    set debug [my define get debug 0]
    if {[my <project> define get LOCAL 0]} {
      return [my define get builddir [file join $PWD local $name]]
    }
    if {$debug} {
      return [my define get builddir [file join $PWD debug $name]]
    } else {
      return [my define get builddir [file join $PWD pkg $name]]
    }
  }

  method compile {} {
    set name [my define get name]
    set PWD $::CWD
    cd $PWD
    my unpack
    set srcdir [file normalize [my SrcDir]]
    set localsrcdir [my MakeDir $srcdir]
    my define set localsrcdir $localsrcdir
    my Collate_Source $PWD
    ###
    # Build a starter VFS for both Tcl and wish
    ###
    set srcdir [my define get srcdir]
    if {[my define get static 1]} {
      puts "BUILDING Static $name $srcdir"
    } else {
      puts "BUILDING Dynamic $name $srcdir"
    }
    my make-compile
    cd $PWD
  }

  method Configure {} {
    cd $::CWD
    my unpack
    ::practcl::toolset select [self]
    set srcdir [file normalize [my define get srcdir]]
    set builddir [file normalize [my define get builddir]]
    file mkdir $builddir
    my make-autodetect
  }

  method install DEST {
    set PWD [pwd]
    set PREFIX  [my <project> define get prefix]
    ###
    # Handle teapot installs
    ###
    set pkg [my define get pkg_name [my define get name]]
    if {[my <project> define get teapot] ne {}} {
      set TEAPOT [my <project> define get teapot]
      set found 0
      foreach ver [my define get pkg_vers [my define get version]] {
        set teapath [file join $TEAPOT $pkg$ver]
        if {[file exists $teapath]} {
          set dest  [file join $DEST [string trimleft $PREFIX /] lib [file tail $teapath]]
          ::practcl::copyDir $teapath $dest
          return
        }
      }
    }
    my compile
    my make-install $DEST
    cd $PWD
  }
}

oo::class create ::practcl::subproject.tea {
  superclass ::practcl::subproject.binary

}

oo::class create ::practcl::subproject.library {
  superclass ::practcl::subproject.binary ::practcl::library
  method install DEST {
    my compile
  }
}

# An external library
oo::class create ::practcl::subproject.external {
  superclass ::practcl::subproject.binary
  method install DEST {
    my compile
  }
}

###
# END: class subproject binary.tcl
###
###
# START: class subproject core.tcl
###

oo::class create ::practcl::subproject.core {
  superclass ::practcl::subproject.binary

  method env-bootstrap {} {}

  method env-present {} {
    set PREFIX [my <project> define get prefix]
    set name [my define get name]
    set fname [file join $PREFIX lib ${name}Config.sh]
    return [file exists $fname]
  }

  method env-install {} {
    my unpack
    set os [::practcl::local_os]

    set prefix [my <project> define get prefix [file normalize [file join ~ tcl]]]
    lappend options --prefix $prefix --exec-prefix $prefix
    my define set config_opts $options
    puts [list [self] OS [dict get $os TEACUP_OS] options $options]
    my go
    my compile
    my make-install {}
  }

  method go {} {
    my define set core_binary 1
    next
  }

  method linktype {} {
    return {subordinate core.library}
  }
}

###
# END: class subproject core.tcl
###
###
# START: class tool.tcl
###
###
# Create an object to represent the local environment
###
set ::practcl::MAIN ::practcl::LOCAL
# Defer the creation of the ::practcl::LOCAL object until it is called
# in order to allow packages to
set ::auto_index(::practcl::LOCAL) {
  ::practcl::project create ::practcl::LOCAL
  ::practcl::LOCAL define set [::practcl::local_os]
  ::practcl::LOCAL define set LOCAL 1

  # Until something better comes along, use ::practcl::LOCAL
  # as our main project







<












<


















|


<







|

<




















|



<
|

|
<
<
|





<
<
|












<
|

<

<






<










|

<




<











<
<
<

<
<







8257
8258
8259
8260
8261
8262
8263

8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275

8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296

8297
8298
8299
8300
8301
8302
8303
8304
8305

8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329

8330
8331
8332


8333
8334
8335
8336
8337
8338


8339
8340
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
8351

8352
8353

8354

8355
8356
8357
8358
8359
8360

8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372

8373
8374
8375
8376

8377
8378
8379
8380
8381
8382
8383
8384
8385
8386
8387



8388


8389
8390
8391
8392
8393
8394
8395
    foreach item [my link list subordinate] {
      foreach {pkg info} [$item project-static-packages] {
        dict set result $pkg $info
      }
    }
    return $result
  }

  method BuildDir {PWD} {
    set name [my define get name]
    set debug [my define get debug 0]
    if {[my <project> define get LOCAL 0]} {
      return [my define get builddir [file join $PWD local $name]]
    }
    if {$debug} {
      return [my define get builddir [file join $PWD debug $name]]
    } else {
      return [my define get builddir [file join $PWD pkg $name]]
    }
  }

  method compile {} {
    set name [my define get name]
    set PWD $::CWD
    cd $PWD
    my unpack
    set srcdir [file normalize [my SrcDir]]
    set localsrcdir [my MakeDir $srcdir]
    my define set localsrcdir $localsrcdir
    my Collate_Source $PWD
    ###
    # Build a starter VFS for both Tcl and wish
    ###
    set srcdir [my define get srcdir]
    if {[my define get static 1]} {
      puts "BUILDING Static $name $srcdir"
    } else {
      puts "BUILDING Dynamic $name $srcdir"
    }
    my make compile
    cd $PWD
  }

  method Configure {} {
    cd $::CWD
    my unpack
    ::practcl::toolset select [self]
    set srcdir [file normalize [my define get srcdir]]
    set builddir [file normalize [my define get builddir]]
    file mkdir $builddir
    my make autodetect
  }

  method install DEST {
    set PWD [pwd]
    set PREFIX  [my <project> define get prefix]
    ###
    # Handle teapot installs
    ###
    set pkg [my define get pkg_name [my define get name]]
    if {[my <project> define get teapot] ne {}} {
      set TEAPOT [my <project> define get teapot]
      set found 0
      foreach ver [my define get pkg_vers [my define get version]] {
        set teapath [file join $TEAPOT $pkg$ver]
        if {[file exists $teapath]} {
          set dest  [file join $DEST [string trimleft $PREFIX /] lib [file tail $teapath]]
          ::practcl::copyDir $teapath $dest
          return
        }
      }
    }
    my compile
    my make install $DEST
    cd $PWD
  }
}

::clay::define ::practcl::subproject.tea {
  superclass ::practcl::subproject.binary
}


::clay::define ::practcl::subproject.library {
  superclass ::practcl::subproject.binary ::practcl::library
  method install DEST {
    my compile
  }
}


::clay::define ::practcl::subproject.external {
  superclass ::practcl::subproject.binary
  method install DEST {
    my compile
  }
}

###
# END: class subproject binary.tcl
###
###
# START: class subproject core.tcl
###

::clay::define ::practcl::subproject.core {
  superclass ::practcl::subproject.binary

  method env-bootstrap {} {}

  method env-present {} {
    set PREFIX [my <project> define get prefix]
    set name [my define get name]
    set fname [file join $PREFIX lib ${name}Config.sh]
    return [file exists $fname]
  }

  method env-install {} {
    my unpack
    set os [::practcl::local_os]

    set prefix [my <project> define get prefix [file normalize [file join ~ tcl]]]
    lappend options --prefix $prefix --exec-prefix $prefix
    my define set config_opts $options
    puts [list [self] OS [dict get $os TEACUP_OS] options $options]
    my go
    my compile
    my make install {}
  }

  method go {} {
    my define set core_binary 1
    next
  }

  method linktype {} {
    return {subordinate core.library}
  }
}

###
# END: class subproject core.tcl
###
###
# START: class tool.tcl
###



set ::practcl::MAIN ::practcl::LOCAL


set ::auto_index(::practcl::LOCAL) {
  ::practcl::project create ::practcl::LOCAL
  ::practcl::LOCAL define set [::practcl::local_os]
  ::practcl::LOCAL define set LOCAL 1

  # Until something better comes along, use ::practcl::LOCAL
  # as our main project

Added modules/practcl/practcl.test.













































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# practcl.test - Copyright (c) 2018 Sean Woods
# -------------------------------------------------------------------------

#source [file join  #	[file dirname [file dirname [file dirname [file join [pwd] [info script]]]]]  #	compat devtools testutilities.tcl]
set TestPwd [file dirname [file join [pwd] [info script]]]
source [file join  [file dirname [file dirname [file join [pwd] [info script]]]]  devtools testutilities.tcl]


testsNeedTcl     8.6
testsNeedTcltest 2
testsNeed        TclOO 1

support {
   use clay/clay.tcl           clay
}
testing {
    useLocal practcl.tcl practcl
}

proc makeFile path {
  file mkdir [file dirname $path]
  set fout [open $path w]
  puts $fout [list FILE $path]
  close $fout
}
file mkdir test

cd $TestPwd
makeFile test/one.tcl
makeFile test/sub/two.tcl
makeFile test/sub/sub/three.tcl

test dict-compare-001 {Test our testing method} {
  ::practcl::findByPattern test *.tcl
} {test/one.tcl test/sub/two.tcl test/sub/sub/three.tcl}

file delete -force test

Changes to modules/processman/processman.man.

66
67
68
69
70
71
72
73
74

Start a child process, identified by [arg id]. [arg cmd] is the name
of the command to execute. [arg args] are arguments to pass to that command.

[list_end]
[para]
[vset CATEGORY odie]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

66
67
68
69
70
71
72
73
74

Start a child process, identified by [arg id]. [arg cmd] is the name
of the command to execute. [arg args] are arguments to pass to that command.

[list_end]
[para]
[vset CATEGORY odie]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/profiler/pkgIndex.tcl.

1
2
if {![package vsatisfies [package provide Tcl] 8.3]} {return}
package ifneeded profiler 0.3 [list source [file join $dir profiler.tcl]]

|
1
2
if {![package vsatisfies [package provide Tcl] 8.3]} {return}
package ifneeded profiler 0.4 [list source [file join $dir profiler.tcl]]

Changes to modules/profiler/profiler.man.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

[comment {-*- tcl -*- doctools manpage}]
[manpage_begin profiler n 0.3]
[keywords performance]
[keywords profile]
[keywords speed]
[moddesc   {Tcl Profiler}]
[titledesc {Tcl source code profiler}]
[category  {Programming tools}]
[require Tcl 8.3]
[require profiler [opt 0.3]]
[description]
[para]

The [package profiler] package provides a simple Tcl source code
profiler.  It is a function-level profiler; that is, it collects only
function-level information, not the more detailed line-level
information.  It operates by redefining the Tcl [cmd proc] command.
>

|







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[vset VERSION 0.5]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin profiler n [vset VERSION]]
[keywords performance]
[keywords profile]
[keywords speed]
[moddesc   {Tcl Profiler}]
[titledesc {Tcl source code profiler}]
[category  {Programming tools}]
[require Tcl 8.3]
[require profiler [opt [vset VERSION]]]
[description]
[para]

The [package profiler] package provides a simple Tcl source code
profiler.  It is a function-level profiler; that is, it collects only
function-level information, not the more detailed line-level
information.  It operates by redefining the Tcl [cmd proc] command.
98
99
100
101
102
103
104














105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
[call [cmd ::profiler::resume] [opt [arg pattern]]]

Resume profiling for all functions matching [arg pattern].  If no
pattern is specified, profiling will be resumed for all functions.
This command should be invoked after suspending the profiler in the
code.















[call [cmd ::profiler::sortFunctions] [arg key]]

Return a list of functions sorted by a particular profiling statistic.
Supported values for [arg key] are: [const calls],

[const exclusiveTime], [const compileTime], [const nonCompileTime],
[const totalRuntime], [const avgExclusiveTime], and

[const avgRuntime].  The return result is a list of lists, where each
sublist consists of a function name and the value of [arg key] for
that function.

[list_end]

[vset CATEGORY profiler]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







>
>
>
>
>
>
>
>
>
>
>
>
>
>















|

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
[call [cmd ::profiler::resume] [opt [arg pattern]]]

Resume profiling for all functions matching [arg pattern].  If no
pattern is specified, profiling will be resumed for all functions.
This command should be invoked after suspending the profiler in the
code.

[call [cmd ::profiler::new-disabled]]

Change the initial profiling state for new procedures. Invoking this
command disables profiling for all procedures created after this
command until [cmd new-enabled] is invoked. Activate profiling of
specific procedures via [cmd resume].

[call [cmd ::profiler::new-enabled]]

Change the initial profiling state for new procedures. Invoking this
command enables profiling for all procedures created after this
command until [cmd new-disabled] is invoked. Prevent profiling of
specific procedures via [cmd suspend].

[call [cmd ::profiler::sortFunctions] [arg key]]

Return a list of functions sorted by a particular profiling statistic.
Supported values for [arg key] are: [const calls],

[const exclusiveTime], [const compileTime], [const nonCompileTime],
[const totalRuntime], [const avgExclusiveTime], and

[const avgRuntime].  The return result is a list of lists, where each
sublist consists of a function name and the value of [arg key] for
that function.

[list_end]

[vset CATEGORY profiler]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/profiler/profiler.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# profiler.tcl --
#
#	Tcl code profiler.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: profiler.tcl,v 1.29 2006/09/19 23:36:17 andreas_kupries Exp $

package require Tcl 8.3		;# uses [clock clicks -milliseconds]
package provide profiler 0.3

namespace eval ::profiler {
}

# ::profiler::tZero --
#
#	Start a named timer instance
#
# Arguments:
#	tag	name for the timer instance; if none is given, defaults to ""








|
<
<

|

|
<







1
2
3
4
5
6
7
8
9


10
11
12
13

14
15
16
17
18
19
20
# profiler.tcl --
#
#	Tcl code profiler.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.



package require Tcl 8.3		;# uses [clock clicks -milliseconds]
package provide profiler 0.5

namespace eval ::profiler {}


# ::profiler::tZero --
#
#	Start a named timer instance
#
# Arguments:
#	tag	name for the timer instance; if none is given, defaults to ""
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
#
# Results:
#	None

proc ::profiler::leaveHandler {name caller} {
    variable enabled




    if { !$enabled($name) } {
        return
    }

    set t [::profiler::tMark $name.$caller]
    lappend ::profiler::statTime($name) $t

    if { [incr ::profiler::callCount($name)] == 1 } {
        set ::profiler::compileTime($name) $t
    }
    incr ::profiler::totalRuntime($name) $t
    if { [catch {incr ::profiler::descendantTime($caller) $t}] } {
        set ::profiler::descendantTime($caller) $t
    }
    if { [catch {incr ::profiler::descendants($caller,$name)}] } {
        set ::profiler::descendants($caller,$name) 1
    }


}

# ::profiler::profProc --
#
#	Replacement for the proc command that adds rudimentary profiling
#	capabilities to Tcl.
#







>
>
>

|















>
>







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
#
# Results:
#	None

proc ::profiler::leaveHandler {name caller} {
    variable enabled

    # Tkt [0dd4b31bb8] Note that the result is pulled from the
    # caller's context as it is not passed into leaveHandler
    
    if { !$enabled($name) } {
	return [uplevel 1 {lindex $args 1}] ;# RETURN RESULT!
    }

    set t [::profiler::tMark $name.$caller]
    lappend ::profiler::statTime($name) $t

    if { [incr ::profiler::callCount($name)] == 1 } {
        set ::profiler::compileTime($name) $t
    }
    incr ::profiler::totalRuntime($name) $t
    if { [catch {incr ::profiler::descendantTime($caller) $t}] } {
        set ::profiler::descendantTime($caller) $t
    }
    if { [catch {incr ::profiler::descendants($caller,$name)}] } {
        set ::profiler::descendants($caller,$name) 1
    }

    return [uplevel 1 {lindex $args 1}] ;# RETURN RESULT!
}

# ::profiler::profProc --
#
#	Replacement for the proc command that adds rudimentary profiling
#	capabilities to Tcl.
#
394
395
396
397
398
399
400

401
402
403
404
405
406
407
408
#	pattern	pattern of the proc's to get info for; default is *.
#
# Results:
#	A human readable printout of info.

proc ::profiler::print {{pattern *}} {
    variable callCount


    set result ""
    foreach name [lsort [array names callCount $pattern]] {
	append result [printname $name]
    }
    return $result
}








>
|







396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
#	pattern	pattern of the proc's to get info for; default is *.
#
# Results:
#	A human readable printout of info.

proc ::profiler::print {{pattern *}} {
    variable callCount
    #parray callCount
    
    set result ""
    foreach name [lsort [array names callCount $pattern]] {
	append result [printname $name]
    }
    return $result
}

598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
# Results:
#	None.  Resets the `enabled($name)' variable to 0
#	       to suspend profiling

proc ::profiler::suspend {{pattern *}} {
    variable callCount
    variable enabled
    variable paused

    set paused 1
    foreach name [array names callCount $pattern] {
        set enabled($name) 0
    }

    return
}








<

<







601
602
603
604
605
606
607

608

609
610
611
612
613
614
615
# Results:
#	None.  Resets the `enabled($name)' variable to 0
#	       to suspend profiling

proc ::profiler::suspend {{pattern *}} {
    variable callCount
    variable enabled



    foreach name [array names callCount $pattern] {
        set enabled($name) 0
    }

    return
}

622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638





























# Results:
#	None.  Sets the `enabled($name)' variable to 1
#	       so as to enable the profiler.

proc ::profiler::resume {{pattern *}} {
    variable callCount
    variable enabled
    variable paused

    set paused 0
    foreach name [array names callCount $pattern] {
        set enabled($name) 1
    }

    return
}





































<

<







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# Results:
#	None.  Sets the `enabled($name)' variable to 1
#	       so as to enable the profiler.

proc ::profiler::resume {{pattern *}} {
    variable callCount
    variable enabled



    foreach name [array names callCount $pattern] {
        set enabled($name) 1
    }

    return
}

# ::profiler::new-disabled --
#
#	Start new procedures with profiling disabled
#
# Arguments:
#	None.
#
# Results:
#	None.

proc ::profiler::new-disabled {} {
    variable paused 1
    return
}

# ::profiler::new-enabled --
#
#	Start new procedures with profiling enabled
#
# Arguments:
#	None.
#
# Results:
#	None.

proc ::profiler::new-enabled {} {
    variable paused 0
    return
}

Changes to modules/profiler/profiler.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23






24
25

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

62

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

78

79
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

# Profiler tests.                                              -*- tcl -*-
#
# Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
# All rights reserved.
#
# RCS: @(#) $Id: profiler.test,v 1.20 2006/10/09 21:41:41 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.3
testsNeedTcltest 1.0

testing {
    useLocal profiler.tcl profiler
}







::tcltest::testConstraint tcl8.4only \
	[expr {![package vsatisfies [package provide Tcl] 8.5]}]


::tcltest::testConstraint tcl8.5only \
    [expr {
	   ![package vsatisfies [package provide Tcl] 8.6] &&
	   [package vsatisfies [package provide Tcl] 8.5]
       }]

# -------------------------------------------------------------------------

test profiler-1.0 {profiler::init redirects the proc command} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	list [interp alias {} proc] [info commands ::_oldProc]
    }]
    interp delete $c
    set result

} [list ::profiler::profProc ::_oldProc]

test profiler-2.0 {profiler creates two wrapper proc and real proc} {tcl8.3only} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	proc foo {} {
	    puts "foo!"
	}
	list [info commands foo] [info commands fooORIG]
    }]
    interp delete $c
    set result

} [list foo fooORIG]

test profiler-2.1 {profiler creates procs in correct scope} {tcl8.3only} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	namespace eval foo {}
	proc ::foo::foo {} {
	    puts "foo!"
	}
	list [info commands ::foo::foo] [info commands ::foo::fooORIG]
    }]
    interp delete $c
    set result

} [list ::foo::foo ::foo::fooORIG]

test profiler-2.2 {profiler creates procs in correct scope} {tcl8.3only} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	namespace eval foo {
	    proc foo {} {
		puts "foo!"
	    }
	}
	list [info commands ::foo::foo] [info commands ::foo::fooORIG]
    }]
    interp delete $c
    set result

} [list ::foo::foo ::foo::fooORIG]

test profiler-2.3 {profiler creates procs in correct scope} {tcl8.3only} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	namespace eval foo {
	    namespace eval bar {}
	    proc bar::foo {} {
		puts "foo!"
	    }
	}
	list [info commands ::foo::bar::foo] \
		[info commands ::foo::bar::fooORIG]
    }]
    interp delete $c
    set result

} [list ::foo::bar::foo ::foo::bar::fooORIG]

test profiler-2.4 {profiler creates procs in correct scope} {tcl8.3only} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	namespace eval foo {
	    proc ::foo {} {
		puts "foo!"
	    }
	}
	list [info commands ::foo] \
		[info commands ::fooORIG]
    }]
    interp delete $c
    set result

} [list ::foo ::fooORIG]

test profiler-3.1 {profiler wrappers do profiling} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	proc ::foo {} {
	    set foobar 0
	}
	foo
	foo
	foo
	foo
	profiler::dump ::foo
    }]
    interp delete $c
    array set bar $result
    array set foo $bar(::foo)
    list callCount $foo(callCount) callerDist $foo(callerDist)


} [list callCount 4 callerDist [list GLOBAL 4]]

test profiler::leaveHandler::initialize_descendent_time {} {
    # Verify that the profiler tracks descendent time correctly.  We'll make
    # a simple call tree, foo -> bar, then invoke foo, then check the profiler
    # stats to see that _some_ descendent time has been logged for the call 
    # to bar.  We won't be able to predict exactly how much time will get 
    # billed there, but it should be non-zero.

    set c [interp create]
    interp alias $c parentSet {} set
    array set stats [lindex [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler

	profiler::init
	proc ::foo {} {
	    ::bar
	}
        proc ::bar {} {
            after 300
        }
	foo

	profiler::dump ::foo
    }] 1]
    interp delete $c
    list descendantTime [expr {$stats(descendantTime) > 0}]
} {descendantTime 1}

test profiler::leaveHandler::increment_descendent_time {} {
    # Verify that the profiler increments descendent time each time a
    # a descendent is invoked.  We'll make a simple call tree, foo -> bar, then
    # invoke foo, check the descendent time for foo, then invoke foo again and
    # check the descendent time again.  It should have been incremented after
    # the second call.

    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	proc ::foo {} {
	    ::bar
	}
        proc ::bar {} {
            after 300
        }
	foo
        array set stats [lindex [profiler::dump ::foo] 1]
        set before $stats(descendantTime)
        foo
        array set stats [lindex [profiler::dump ::foo] 1]
        set after $stats(descendantTime)

        list before [expr {$before - $before}] \
            after [expr {($after - $before) > 0}]
    }]
    interp delete $c
    set result

} {before 0 after 1}

test profiler-4.1 {profiler::print produces nicer output than dump} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	proc ::foo {} {
	    set foobar 0
	}
	foo
	foo
	foo
	foo
	profiler::print ::foo
    }]
    interp delete $c
    regsub {Compile time:.*} $result {} result
    string trim $result
} "Profiling information for ::foo
============================================================
            Total calls:  4
    Caller distribution:
  GLOBAL:  4"


test profiler-5.1 {profiler respects suspend/resume} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	proc ::foo {} {
	    set foobar 0
	}
	foo
	foo
	foo
	foo
	profiler::suspend ::foo ; # note the qualification, has to match proc!
	foo
	foo
	set res [profiler::print ::foo]
	profiler::resume
	set res
    }]
    interp delete $c
    regsub {Compile time:.*} $result {} result
    string trim $result

} "Profiling information for ::foo
============================================================
            Total calls:  4
    Caller distribution:
  GLOBAL:  4"

test profiler-6.1 {profiler handles functions with funny names} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {


	set     auto_path [parentSet auto_path]
	lappend auto_path [file dirname [file dirname [info script]]]

	package require profiler






	profiler::init














	proc ::foo(bar) {} {
	    set foobar 0
	}
	foo(bar); foo(bar); foo(bar)
	profiler::dump ::foo(bar)
    }]
    interp delete $c
    array set bar $result
    array set foo ${bar(::foo(bar))}
    list callCount $foo(callCount) callerDist $foo(callerDist)


} [list callCount 3 callerDist [list GLOBAL 3]]

test profiler-7.1 {sortFunctions} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	catch {profiler::sortFunctions} res
	set res
    }]
    interp delete $c
    set result

} "unknown statistic \"\": should be calls, compileTime, exclusiveRuntime,\
nonCompileTime, totalRuntime, avgExclusiveRuntime, or avgRuntime"

test profiler-7.2 {sortFunctions} tcl8.4only {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {


	set auto_path [parentSet auto_path]
	package require profiler


	profiler::init





	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	profiler::sortFunctions calls
    }]
    interp delete $c
    set result

} [list [list ::bar 1] [list ::foo 2]]

test profiler-7.2-85 {sortFunctions} tcl8.5only {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	profiler::sortFunctions calls
    }]
    interp delete $c
    set result
} [list [list ::tcl::clock::scan 0] [list ::tcl::clock::format 0] [list ::tcl::clock::add 0] [list ::bar 1] [list ::foo 2]]

test profiler-7.2-86 {sortFunctions} tcl8.6plus {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	profiler::sortFunctions calls
    }]
    interp delete $c
    set result
} [list [list ::bar 1] [list ::foo 2]]

test profiler-7.3 {sortFunctions} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	catch {profiler::sortFunctions compileTime}
    }]
    interp delete $c
    set result

} 0

test profiler-7.4 {sortFunctions} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	catch {profiler::sortFunctions totalRuntime}
    }]
    interp delete $c
    set result

} 0

test profiler-7.5 {sortFunctions} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	catch {profiler::sortFunctions avgRuntime}
    }]
    interp delete $c
    set result

} 0

test profiler-8.1 {reset} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	profiler::reset
	profiler::dump ::foo
    }]
    interp delete $c
    array set bar $result
    array set foo $bar(::foo)
    list callCount $foo(callCount) callerDist $foo(callerDist)


} [list callCount 0 callerDist [list ]]

test profiler-8.2 {reset with a pattern} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	profiler::reset ::foo
	profiler::dump *
    }]
    interp delete $c
    array set data $result
    catch {unset foo}
    catch {unset bar}
    array set foo $data(::foo)
    array set bar $data(::bar)

    list [list callCount $foo(callCount) callerDist $foo(callerDist)] \
	    [list callCount $bar(callCount) callerDist $bar(callerDist)]



} [list [list callCount 0 callerDist [list ]] \
	[list callCount 1 callerDist [list GLOBAL 1]]]

test profiler-9.1 {dump for multiple functions} {
    set c [interp create]
    interp alias $c parentSet {} set
    set result [$c eval {
	set auto_path [parentSet auto_path]
	package require profiler
	profiler::init
	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	profiler::dump *
    }]
    interp delete $c
    array set data $result
    catch {unset foo}
    catch {unset bar}
    array set foo $data(::foo)
    array set bar $data(::bar)

    list [list callCount $foo(callCount) callerDist $foo(callerDist)] \
	    [list callCount $bar(callCount) callerDist $bar(callerDist)]



} [list [list callCount 2 callerDist [list GLOBAL 2]] \
	[list callCount 1 callerDist [list GLOBAL 1]]]



catch {unset foo}







catch {unset bar}





testsuiteCleanup








<
<














>
>
>
>
>
>
|
<
>
|
<
<
<
<
<




<
<
<
<
<
|

<
<
<
>


|
<
<
<
<
<
|




<
<
<
>

>
|
<
<
<
<
<
|





<
<
<
>

>

<
<
<
<
<
|






<
<
<
>

>

<
<
<
<
<
|






|
<
<
<
<
>

>

<
<
<
<
<
|





|
<
<
<
<
>



|
<
<
<
<
<









<
<

|
>
>









<
<
|
<
<
<
<










<


>







<
<
<
<
<
|












>
|
|
<
<
<
>



<
<
|
<
<
<









<


<
<
<
<
<
>


<
<
|
<
<
<














<


>
|
<
<
<
<

|
<
<
|
>
>
|
<
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>






<
<

|
>
>



<
<
<
<
<
|


<
<
<
>




|
|
|
>
>
|
<
>
>
|
>
>
>
>
>








<
<
<
>
|

|
<
<
<
<
<
|








<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



<
<
<
<
<
|








<
<
<
>

>

<
<
<
<
<
|








<
<
<
>

>

<
<
<
<
<
|








<
<
<
>



|
<
<
<
<
<










<
<

|
>
>

>

|
<
<
<
<
<










<
<
<
<


>
|
|
>
>
>
|
|


|
<
<
<
<
<









<
<
<
<


>
|
|
>
>
>
|
|

>
>
|
>
>
>
>
>
>
>
|
>
>

>
>

>
1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30





31
32
33
34





35
36



37
38
39
40





41
42
43
44
45



46
47
48
49





50
51
52
53
54
55



56
57
58
59





60
61
62
63
64
65
66



67
68
69
70





71
72
73
74
75
76
77
78




79
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
# Profiler tests.                                              -*- tcl -*-
#
# Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.3
testsNeedTcltest 1.0

testing {
    useLocal profiler.tcl profiler
}

proc do {script} {
    set c [interp create]
    interp alias $c parentSet {} set
    $c eval [list source [localPath profiler.tcl]]
    $c eval profiler::init
    set result [$c eval $script]
    interp delete $c

    set result
}






# -------------------------------------------------------------------------

test profiler-1.0 {profiler::init redirects the proc command} {





    do {
	list [interp alias {} proc] [info commands ::_oldProc]



    }
} [list ::profiler::profProc ::_oldProc]

test profiler-2.0 {profiler creates two wrapper proc and real proc} tcl8.3only {





    do {
	proc foo {} {
	    puts "foo!"
	}
	list [info commands foo] [info commands fooORIG]



    }
} [list foo fooORIG]

test profiler-2.1 {profiler creates procs in correct scope} tcl8.3only {





    do {
	namespace eval foo {}
	proc ::foo::foo {} {
	    puts "foo!"
	}
	list [info commands ::foo::foo] [info commands ::foo::fooORIG]



    }
} [list ::foo::foo ::foo::fooORIG]

test profiler-2.2 {profiler creates procs in correct scope} {tcl8.3only} {





    do {
	namespace eval foo {
	    proc foo {} {
		puts "foo!"
	    }
	}
	list [info commands ::foo::foo] [info commands ::foo::fooORIG]



    }
} [list ::foo::foo ::foo::fooORIG]

test profiler-2.3 {profiler creates procs in correct scope} {tcl8.3only} {





    do {
	namespace eval foo {
	    namespace eval bar {}
	    proc bar::foo {} {
		puts "foo!"
	    }
	}
	list [info commands ::foo::bar::foo] [info commands ::foo::bar::fooORIG]




    }
} [list ::foo::bar::foo ::foo::bar::fooORIG]

test profiler-2.4 {profiler creates procs in correct scope} {tcl8.3only} {





    do {
	namespace eval foo {
	    proc ::foo {} {
		puts "foo!"
	    }
	}
	list [info commands ::foo] [info commands ::fooORIG]




    }
} [list ::foo ::fooORIG]

test profiler-3.1 {profiler wrappers do profiling} {
    array set bar [do {





	proc ::foo {} {
	    set foobar 0
	}
	foo
	foo
	foo
	foo
	profiler::dump ::foo
    }]


    array set foo $bar(::foo)
    set result [list callCount $foo(callCount) callerDist $foo(callerDist)]
    unset foo bar
    set result
} [list callCount 4 callerDist [list GLOBAL 4]]

test profiler::leaveHandler::initialize_descendent_time {} {
    # Verify that the profiler tracks descendent time correctly.  We'll make
    # a simple call tree, foo -> bar, then invoke foo, then check the profiler
    # stats to see that _some_ descendent time has been logged for the call 
    # to bar.  We won't be able to predict exactly how much time will get 
    # billed there, but it should be non-zero.



    array set stats [lindex [do {




	proc ::foo {} {
	    ::bar
	}
        proc ::bar {} {
            after 300
        }
	foo

	profiler::dump ::foo
    }] 1]

    list descendantTime [expr {$stats(descendantTime) > 0}]
} {descendantTime 1}

test profiler::leaveHandler::increment_descendent_time {} {
    # Verify that the profiler increments descendent time each time a
    # a descendent is invoked.  We'll make a simple call tree, foo -> bar, then
    # invoke foo, check the descendent time for foo, then invoke foo again and
    # check the descendent time again.  It should have been incremented after
    # the second call.






    do {
	proc ::foo {} {
	    ::bar
	}
        proc ::bar {} {
            after 300
        }
	foo
        array set stats [lindex [profiler::dump ::foo] 1]
        set before $stats(descendantTime)
        foo
        array set stats [lindex [profiler::dump ::foo] 1]
        set after $stats(descendantTime)
        list \
	    before [expr {$before - $before}] \
            after  [expr {($after - $before) > 0}]



    }
} {before 0 after 1}

test profiler-4.1 {profiler::print produces nicer output than dump} {


    set result [do {



	proc ::foo {} {
	    set foobar 0
	}
	foo
	foo
	foo
	foo
	profiler::print ::foo
    }]

    regsub {Compile time:.*} $result {} result
    string trim $result





} [tcltest::viewFile [asset 4.1]]

test profiler-5.1 {profiler respects suspend/resume} {


    set result [do {



	proc ::foo {} {
	    set foobar 0
	}
	foo
	foo
	foo
	foo
	profiler::suspend ::foo ; # note the qualification, has to match proc!
	foo
	foo
	set res [profiler::print ::foo]
	profiler::resume
	set res
    }]

    regsub {Compile time:.*} $result {} result
    string trim $result
} [tcltest::viewFile [asset 5.1]]






test profiler-5.2 {profiler respects new-disabled/enabled} {


    set result [do {
	profiler::new-disabled
	proc ::bar {} {
	    set foobar 0

	}
	profiler::new-enabled
	proc ::foo {} {
	    set foobar 0
	}
	#---	
	foo
	bar
	profiler::resume
	bar
	#---
	set res [profiler::print ::foo]
	regsub {Compile time:.*} $res {} res
	set res [string trim $res]
	append res \n\n [profiler::print ::bar]
	regsub {Compile time:.*} $res {} res
	set res
    }]
    string trim $result
} [tcltest::viewFile [asset 5.2]]

test profiler-6.1 {profiler handles functions with funny names} {
    array set bar [do {
	proc ::foo(bar) {} {
	    set foobar 0
	}
	foo(bar); foo(bar); foo(bar)
	profiler::dump ::foo(bar)
    }]


    array set foo ${bar(::foo(bar))}
    set result [list callCount $foo(callCount) callerDist $foo(callerDist)]
    unset foo bar
    set result
} [list callCount 3 callerDist [list GLOBAL 3]]

test profiler-7.1 {sortFunctions} {





    do {
	catch {profiler::sortFunctions} res
	set res



    }
} "unknown statistic \"\": should be calls, compileTime, exclusiveRuntime,\
nonCompileTime, totalRuntime, avgExclusiveRuntime, or avgRuntime"

test profiler-7.2 {sortFunctions} tcl8.4only {
    do {
	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1

	}
	foo; foo; bar;
	profiler::sortFunctions calls
    }
} [list [list ::bar 1] [list ::foo 2]]

test profiler-7.2-85 {sortFunctions} tcl8.5only {
    do {
	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	profiler::sortFunctions calls



    }
} [list [list ::tcl::clock::scan 0] [list ::tcl::clock::format 0] [list ::tcl::clock::add 0] [list ::bar 1] [list ::foo 2]]

test profiler-7.2-86 {sortFunctions} tcl8.6plus {





    do {
	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	profiler::sortFunctions calls




    }


















} [list [list ::bar 1] [list ::foo 2]]

test profiler-7.3 {sortFunctions} {





    do {
	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	catch {profiler::sortFunctions compileTime}



    }
} 0

test profiler-7.4 {sortFunctions} {





    do {
	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	catch {profiler::sortFunctions totalRuntime}



    }
} 0

test profiler-7.5 {sortFunctions} {





    do {
	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	catch {profiler::sortFunctions avgRuntime}



    }
} 0

test profiler-8.1 {reset} {
    array set bar [do {





	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	profiler::reset
	profiler::dump ::foo
    }]


    array set foo $bar(::foo)
    set result [list callCount $foo(callCount) callerDist $foo(callerDist)]
    unset foo bar
    set result
} [list callCount 0 callerDist [list ]]

test profiler-8.2 {reset with a pattern} {
    array set data [do {





	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	profiler::reset ::foo
	profiler::dump *
    }]




    array set foo $data(::foo)
    array set bar $data(::bar)
    set result [list \
		    [list callCount $foo(callCount) callerDist $foo(callerDist)] \
		    [list callCount $bar(callCount) callerDist $bar(callerDist)]]
    unset foo bar data
    set result
} [list \
       [list callCount 0 callerDist [list ]] \
       [list callCount 1 callerDist [list GLOBAL 1]]]

test profiler-9.1 {dump for multiple functions} {
    array set data [do {





	proc ::foo {} {
	    set foobar 0
	}
	proc ::bar {} {
	    set foobar 1
	}
	foo; foo; bar;
	profiler::dump *
    }]




    array set foo $data(::foo)
    array set bar $data(::bar)
    set result [list \
		    [list callCount $foo(callCount) callerDist $foo(callerDist)] \
		    [list callCount $bar(callCount) callerDist $bar(callerDist)]]
    unset foo bar data
    set result
} [list \
       [list callCount 2 callerDist [list GLOBAL 2]] \
       [list callCount 1 callerDist [list GLOBAL 1]]]

test profiler-10.0-tkt-0dd4b31bb8 {result of leave handler} {
    join [do {
	set trace {}
	#
	proc echo   args { global trace; lappend trace $args; return $args }
	proc tracer args { global trace; lappend trace $args; return $args }
	#
	trace add execution echo leave tracer
	echo hi
	#
	set trace
    }] \n
} [viewFile [asset tkt-0dd4b31bb8]]

# -------------------------------------------------------------------------
rename do {}
testsuiteCleanup
return

Added modules/profiler/test-assets/4.1.











>
>
>
>
>
1
2
3
4
5
Profiling information for ::foo
============================================================
            Total calls:  4
    Caller distribution:
  GLOBAL:  4

Added modules/profiler/test-assets/5.1.











>
>
>
>
>
1
2
3
4
5
Profiling information for ::foo
============================================================
            Total calls:  4
    Caller distribution:
  GLOBAL:  4

Added modules/profiler/test-assets/5.2.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
Profiling information for ::foo
============================================================
            Total calls:  1
    Caller distribution:
  GLOBAL:  1

Profiling information for ::bar
============================================================
            Total calls:  1
    Caller distribution:
  GLOBAL:  1

Added modules/profiler/test-assets/tkt-0dd4b31bb8.





>
>
1
2
hi
{echo hi} 0 hi leave

Deleted modules/pt/configuration.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# configuration.tcl --
#
#	Generic configuration management, for use by import and export
#	managers.
#
# Copyright (c) 2009 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: configuration.tcl,v 1.1 2010/03/26 05:07:24 andreas_kupries Exp $

# Each object manages a set of configuration variables.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.5
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::configuration {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creating, destruction

    # Default constructor.
    # Default destructor.

    # ### ### ### ######### ######### #########
    ## Public methods. Reading and writing the configuration.

    method names {} {
	return [array names myconfiguration]
    }

    method get {} {
	return [array get myconfiguration]
    }

    method set {name {value {}}} {
	# 7 instead of 3 in the condition below, because of the 4
	# implicit arguments snit is providing to each method.
	if {[llength [info level 0]] == 7} {
	    set myconfiguration($name) $value
	} elseif {![info exists myconfiguration($name)]} {
	    return -code error "can't read \"$name\": no such variable"
	}
	return $myconfiguration($name)
    }

    method unset {args} {
	if {![llength $args]} { lappend args * }
	foreach pattern $args {
	    array unset myconfiguration $pattern
	}
	return
    }

    # ### ### ### ######### ######### #########
    ## Internal methods :: None.

    # ### ### ### ######### ######### #########
    ## State :: Configuration data, Tcl array

    variable myconfiguration -array {}

    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide configuration 1
return
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































































































































































Changes to modules/pt/include/feedback.inc.

1
2
3
[comment {--- Standard trailer for all manpages in this module --}]
[vset CATEGORY pt]
[include ../../doctools2base/include/feedback.inc]


|
1
2
3
[comment {--- Standard trailer for all manpages in this module --}]
[vset CATEGORY pt]
[include ../../common-text/feedback.inc]

Deleted modules/pt/paths.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# paths.tcl --
#
#	Generic path list management, for use by import management.
#
# Copyright (c) 2009 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: paths.tcl,v 1.1 2010/03/26 05:07:24 andreas_kupries Exp $

# Each object manages a list of paths.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.5
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::paths {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creation, destruction

    # Default constructor.
    # Default destructor.

    # ### ### ### ######### ######### #########
    ## Methods :: Querying and manipulating the list of paths.

    method paths {} {
	return $mypaths
    }

    method add {path} {
	if {$path in $mypaths} return
	lappend mypaths $path
	return
    }

    method remove {path} {
	set pos [lsearch $mypaths $path]
	if {$pos < 0} return
	set  mypaths [lreplace $mypaths $pos $pos]
	return
    }

    method clear {} {
	set mypaths {}
	return
    }

    # ### ### ### ######### ######### #########
    ## Internal methods :: None

    # ### ### ### ######### ######### #########
    ## State :: List of paths.

    variable mypaths {}

    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide paths 1
return
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






















































































































































Changes to modules/pt/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
if {![package vsatisfies [package provide Tcl] 8.5]} return

# General utilities.
package ifneeded char          1.0.1 [list source [file join $dir char.tcl]]
package ifneeded configuration 1 [list source [file join $dir configuration.tcl]]
package ifneeded paths         1 [list source [file join $dir paths.tcl]]
package ifneeded text::write   1 [list source [file join $dir text_write.tcl]]

# AST support
package ifneeded pt::ast     1.1 [list source [file join $dir pt_astree.tcl]]

# General parser support. Currently only conversion of structured
# syntax errors (or parts thereof) into a human-readable form.




<
<







1
2
3
4


5
6
7
8
9
10
11
if {![package vsatisfies [package provide Tcl] 8.5]} return

# General utilities.
package ifneeded char          1.0.1 [list source [file join $dir char.tcl]]


package ifneeded text::write   1 [list source [file join $dir text_write.tcl]]

# AST support
package ifneeded pt::ast     1.1 [list source [file join $dir pt_astree.tcl]]

# General parser support. Currently only conversion of structured
# syntax errors (or parts thereof) into a human-readable form.
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package ifneeded pt::peg::container     1 [list source [file join $dir pt_peg_container.tcl]]
package ifneeded pt::peg::interp    1.0.1 [list source [file join $dir pt_peg_interp.tcl]]
package ifneeded pt::peg::op        1.1.0 [list source [file join $dir pt_peg_op.tcl]]
package ifneeded pt::parse::peg     1.0.1 [list source [file join $dir pt_parse_peg.tcl]]


# Export/import managers. Assumes an untrusted environment.
package ifneeded pt::peg::export            1 [list source [file join $dir pt_peg_export.tcl]]
package ifneeded pt::peg::import            1 [list source [file join $dir pt_peg_import.tcl]]

# Export plugins, connecting manager to the core conversion packages.
package ifneeded pt::peg::export::container 1 [list source [file join $dir pt_peg_export_container.tcl]]
package ifneeded pt::peg::export::json      1 [list source [file join $dir pt_peg_export_json.tcl]]
package ifneeded pt::peg::export::peg       1 [list source [file join $dir pt_peg_export_peg.tcl]]

# Import plugins, connecting manager to the core conversion packages.







|
|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package ifneeded pt::peg::container     1 [list source [file join $dir pt_peg_container.tcl]]
package ifneeded pt::peg::interp    1.0.1 [list source [file join $dir pt_peg_interp.tcl]]
package ifneeded pt::peg::op        1.1.0 [list source [file join $dir pt_peg_op.tcl]]
package ifneeded pt::parse::peg     1.0.1 [list source [file join $dir pt_parse_peg.tcl]]


# Export/import managers. Assumes an untrusted environment.
package ifneeded pt::peg::export            1.0.1 [list source [file join $dir pt_peg_export.tcl]]
package ifneeded pt::peg::import            1.0.1 [list source [file join $dir pt_peg_import.tcl]]

# Export plugins, connecting manager to the core conversion packages.
package ifneeded pt::peg::export::container 1 [list source [file join $dir pt_peg_export_container.tcl]]
package ifneeded pt::peg::export::json      1 [list source [file join $dir pt_peg_export_json.tcl]]
package ifneeded pt::peg::export::peg       1 [list source [file join $dir pt_peg_export_peg.tcl]]

# Import plugins, connecting manager to the core conversion packages.

Changes to modules/pt/pt_peg_export.man.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[comment {-*- tcl -*- doctools manpage}]

[manpage_begin pt::peg::export n 1]
[include include/module.inc]
[titledesc {PEG Export}]
[require snit]
[require configuration]
[require pt::peg]
[require pluginmgr]
[require pt::peg::export [opt 1]]
[description]
[include include/ref_intro.inc]

This package provides a manager for parsing expression grammars, with
each instance handling a set of plugins for the export of them to
other formats, i.e. their conversion to, for example [term nroff],
[term HTML], etc.

>
|



|


|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[comment {-*- tcl -*- doctools manpage}]
[vset VERSION 1.0.1]
[manpage_begin pt::peg::export n [vset VERSION]]
[include include/module.inc]
[titledesc {PEG Export}]
[require snit]
[require struct::map]
[require pt::peg]
[require pluginmgr]
[require pt::peg::export [opt [vset VERSION]]]
[description]
[include include/ref_intro.inc]

This package provides a manager for parsing expression grammars, with
each instance handling a set of plugins for the export of them to
other formats, i.e. their conversion to, for example [term nroff],
[term HTML], etc.

Changes to modules/pt/pt_peg_export.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# pt_peg_export.tcl --
#
#	Exporting parsing expression grammars into other formats.
#
# Copyright (c) 2009 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: pt_peg_export.tcl,v 1.1 2010/03/26 05:07:24 andreas_kupries Exp $

# Each object manages a set of plugins for the conversion of parsing
# expression grammars into some textual representation. I.e. this
# object manages the conversion to specialized serializations of
# parsing expression grammars.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.5
package require configuration
package require pt::peg
package require pluginmgr
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::pt::peg::export {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creation, destruction.

    constructor {} {
	install myconfig using ::configuration ${selfns}::CONFIG
	return
    }

    destructor {
	$myconfig destroy
	# Clear the cache of loaded export plugins.
	foreach k [array names myplugin] {








<
<










|


|













|







1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# pt_peg_export.tcl --
#
#	Exporting parsing expression grammars into other formats.
#
# Copyright (c) 2009 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.



# Each object manages a set of plugins for the conversion of parsing
# expression grammars into some textual representation. I.e. this
# object manages the conversion to specialized serializations of
# parsing expression grammars.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.5
package require snit
package require pt::peg
package require pluginmgr
package require struct::map

# ### ### ### ######### ######### #########
## API

snit::type ::pt::peg::export {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creation, destruction.

    constructor {} {
	install myconfig using ::struct::map ${selfns}::CONFIG
	return
    }

    destructor {
	$myconfig destroy
	# Clear the cache of loaded export plugins.
	foreach k [array names myplugin] {
111
112
113
114
115
116
117
118
119
    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide pt::peg::export 1
return







|

109
110
111
112
113
114
115
116
117
    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide pt::peg::export 1.0.1
return

Changes to modules/pt/pt_peg_export.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
# -*- tcl -*-
# peg_export.test:  tests for the pt::peg::export package.
#
# Copyright (c) 2009 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: pt_peg_export.test,v 1.1 2010/03/26 05:07:24 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2

support {
    useAccel [useTcllibC] struct/sets.tcl  struct::set
    TestAccelInit                          struct::set

    use fileutil/fileutil.tcl      fileutil      ;# tests/common
    use snit/snit.tcl              snit
    use pluginmgr/pluginmgr.tcl    pluginmgr


    useLocal configuration.tcl     configuration
    useLocal pt_pexpression.tcl    pt::pe
    useLocal pt_pegrammar.tcl      pt::peg

    source [localPath tests/common]
}
testing {
    useLocalKeep pt_peg_export.tcl pt::peg::export



|

<
<

















>

<







1
2
3
4
5


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
# -*- tcl -*-
# peg_export.test:  tests for the pt::peg::export package.
#
# Copyright (c) 2009-2019 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2

support {
    useAccel [useTcllibC] struct/sets.tcl  struct::set
    TestAccelInit                          struct::set

    use fileutil/fileutil.tcl      fileutil      ;# tests/common
    use snit/snit.tcl              snit
    use pluginmgr/pluginmgr.tcl    pluginmgr
    use struct/map.tcl             struct::map


    useLocal pt_pexpression.tcl    pt::pe
    useLocal pt_pegrammar.tcl      pt::peg

    source [localPath tests/common]
}
testing {
    useLocalKeep pt_peg_export.tcl pt::peg::export

Changes to modules/pt/pt_peg_import.man.

1

2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
[comment {-*- tcl -*- doctools manpage}]

[manpage_begin pt::peg::import n 1]
[include include/module.inc]
[titledesc {PEG Import}]
[require snit]
[require configuration]

[require pt::peg]
[require pluginmgr]
[require pt::peg::import [opt 1]]
[description]
[include include/ref_intro.inc]

This package provides a manager for parsing expression grammars, with
each instance handling a set of plugins for the import of them from
other formats, i.e. their conversion from, for example [term peg],
[term container], [term json], etc.

>
|


|
|
>


|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[comment {-*- tcl -*- doctools manpage}]
[vset VERSION 1.0.1]
[manpage_begin pt::peg::import n [vset VERSION]]
[include include/module.inc]
[titledesc {PEG Import}]
[require Tcl 8.5]
[require snit]
[require fileutil::paths]
[require pt::peg]
[require pluginmgr]
[require pt::peg::import [opt [vset VERSION]]]
[description]
[include include/ref_intro.inc]

This package provides a manager for parsing expression grammars, with
each instance handling a set of plugins for the import of them from
other formats, i.e. their conversion from, for example [term peg],
[term container], [term json], etc.

Changes to modules/pt/pt_peg_import.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# import.tcl --
#
#	Importing parsing expression grammars from other formats.
#
# Copyright (c) 2009 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: pt_peg_import.tcl,v 1.1 2010/03/26 05:07:24 andreas_kupries Exp $

# Each object manages a set of plugins for the creation of parsing
# expression grammars from some textual representation. I.e. this
# object manages the conversion from specialized serializations of
# parsing expression grammars into their standard form.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.5
package require paths
package require pt::peg
package require pluginmgr
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::pt::peg::import {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creation, destruction.

    constructor {} {
	install myinclude using ::paths         ${selfns}::INCLUDE
	return
    }

    destructor {
	$myinclude destroy
	# Clear the cache of loaded import plugins.
	foreach k [array names myplugin] {




|



<
<









|
|
















|







1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# import.tcl --
#
#	Importing parsing expression grammars from other formats.
#
# Copyright (c) 2009-2019 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.



# Each object manages a set of plugins for the creation of parsing
# expression grammars from some textual representation. I.e. this
# object manages the conversion from specialized serializations of
# parsing expression grammars into their standard form.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.4
package require fileutil::paths
package require pt::peg
package require pluginmgr
package require snit

# ### ### ### ######### ######### #########
## API

snit::type ::pt::peg::import {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creation, destruction.

    constructor {} {
	install myinclude using ::fileutil::paths ${selfns}::INCLUDE
	return
    }

    destructor {
	$myinclude destroy
	# Clear the cache of loaded import plugins.
	foreach k [array names myplugin] {
182
183
184
185
186
187
188
189
190
    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide pt::peg::import 1
return







|

180
181
182
183
184
185
186
187
188
    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide pt::peg::import 1.0.1
return

Changes to modules/pt/pt_peg_import.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
# -*- tcl -*-
# peg_import.test:  tests for the pt::peg::import package.
#
# Copyright (c) 2009 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: pt_peg_import.test,v 1.1 2010/03/26 05:07:24 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2

support {
    use fileutil/fileutil.tcl      fileutil      ;# tests/common
    use snit/snit.tcl              snit

    use pluginmgr/pluginmgr.tcl    pluginmgr

    useLocal paths.tcl             paths
    useLocal pt_pexpression.tcl    pt::pe
    useLocal pt_pegrammar.tcl      pt::peg

    source [localPath tests/common]
}
testing {
    useLocalKeep pt_peg_import.tcl pt::peg::import



|

<
<













>


<







1
2
3
4
5


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
# -*- tcl -*-
# peg_import.test:  tests for the pt::peg::import package.
#
# Copyright (c) 2009-2019 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2

support {
    use fileutil/fileutil.tcl      fileutil      ;# tests/common
    use snit/snit.tcl              snit
    use fileutil/paths.tcl         fileutil::paths
    use pluginmgr/pluginmgr.tcl    pluginmgr


    useLocal pt_pexpression.tcl    pt::pe
    useLocal pt_pegrammar.tcl      pt::peg

    source [localPath tests/common]
}
testing {
    useLocalKeep pt_peg_import.tcl pt::peg::import

Changes to modules/pt/tests/pt_peg_export.tests.

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

test pt-peg-export-set:${setimpl}-5.0 {configuration names, wrong#args} -setup {
    pt::peg::export E
} -body {
    E configuration names X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::configuration::Snit_methodnames type selfns win self"}

test pt-peg-export-set:${setimpl}-6.0 {configuration get, wrong#args} -setup {
    pt::peg::export E
} -body {
    E configuration get X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::configuration::Snit_methodget type selfns win self"}

test pt-peg-export-set:${setimpl}-7.0 {configuration set, wrong#args} -setup {
    pt::peg::export E
} -body {
    E configuration set
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::configuration::Snit_methodset type selfns win self name ?value?"}

test pt-peg-export-set:${setimpl}-7.1 {configuration set, wrong#args} -setup {
    pt::peg::export E
} -body {
    E configuration set N V X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::configuration::Snit_methodset type selfns win self name ?value?"}

# -------------------------------------------------------------------------

test pt-peg-export-set:${setimpl}-12.0 {configuration set, define single var} -setup {
    pt::peg::export E
} -body {
    E configuration set N V







|







|







|







|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

test pt-peg-export-set:${setimpl}-5.0 {configuration names, wrong#args} -setup {
    pt::peg::export E
} -body {
    E configuration names X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodnames type selfns win self"}

test pt-peg-export-set:${setimpl}-6.0 {configuration get, wrong#args} -setup {
    pt::peg::export E
} -body {
    E configuration get X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodget type selfns win self"}

test pt-peg-export-set:${setimpl}-7.0 {configuration set, wrong#args} -setup {
    pt::peg::export E
} -body {
    E configuration set
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

test pt-peg-export-set:${setimpl}-7.1 {configuration set, wrong#args} -setup {
    pt::peg::export E
} -body {
    E configuration set N V X
} -cleanup {
    E destroy
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

# -------------------------------------------------------------------------

test pt-peg-export-set:${setimpl}-12.0 {configuration set, define single var} -setup {
    pt::peg::export E
} -body {
    E configuration set N V

Changes to modules/pt/tests/pt_peg_import.tests.

78
79
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
    I import object file O P F XXX
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::pt::peg::import::Snit_hmethodimport_object_file type selfns win self obj path ?format?"}

# config unset - accepts any number of arguments.




test pt-peg-import-5.0 {include paths, wrong#args} -setup {
    pt::peg::import I
} -body {
    I include paths X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::paths::Snit_methodpaths type selfns win self"}

test pt-peg-import-6.0 {include clear, wrong#args} -setup {
    pt::peg::import I
} -body {
    I include clear X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::paths::Snit_methodclear type selfns win self"}

test pt-peg-import-7.0 {include add, wrong#args} -setup {
    pt::peg::import I
} -body {
    I include add
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::paths::Snit_methodadd type selfns win self path"}

test pt-peg-import-7.1 {include add, wrong#args} -setup {
    pt::peg::import I
} -body {
    I include add P X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::paths::Snit_methodadd type selfns win self path"}

test pt-peg-import-8.0 {include remove, wrong#args} -setup {
    pt::peg::import I
} -body {
    I include remove
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::paths::Snit_methodremove type selfns win self path"}

test pt-peg-import-8.1 {include remove, wrong#args} -setup {
    pt::peg::import I
} -body {
    I include remove P X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::paths::Snit_methodremove type selfns win self path"}

# -------------------------------------------------------------------------

test pt-peg-import9.0 {include paths, empty} -setup {
    pt::peg::import I
} -body {
    I include paths







>
>
>






|







|







|







|







|







|







78
79
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
    I import object file O P F XXX
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::pt::peg::import::Snit_hmethodimport_object_file type selfns win self obj path ?format?"}

# config unset - accepts any number of arguments.

# -------------------------------------------------------------------------
## `include` component, provided via fileutil::paths, search path for includes

test pt-peg-import-5.0 {include paths, wrong#args} -setup {
    pt::peg::import I
} -body {
    I include paths X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodpaths type selfns win self"}

test pt-peg-import-6.0 {include clear, wrong#args} -setup {
    pt::peg::import I
} -body {
    I include clear X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodclear type selfns win self"}

test pt-peg-import-7.0 {include add, wrong#args} -setup {
    pt::peg::import I
} -body {
    I include add
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodadd type selfns win self path"}

test pt-peg-import-7.1 {include add, wrong#args} -setup {
    pt::peg::import I
} -body {
    I include add P X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodadd type selfns win self path"}

test pt-peg-import-8.0 {include remove, wrong#args} -setup {
    pt::peg::import I
} -body {
    I include remove
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodremove type selfns win self path"}

test pt-peg-import-8.1 {include remove, wrong#args} -setup {
    pt::peg::import I
} -body {
    I include remove P X
} -cleanup {
    I destroy
} -returnCodes error -result {wrong # args: should be "::fileutil::paths::Snit_methodremove type selfns win self path"}

# -------------------------------------------------------------------------

test pt-peg-import9.0 {include paths, empty} -setup {
    pt::peg::import I
} -body {
    I include paths

Changes to modules/rc4/rc4.man.

112
113
114
115
116
117
118
119
120
 rc4::rc4 -in $socket -command [list ::Finish $ApplicationState]
}]

[section "AUTHORS"]
Pat Thoyts

[vset CATEGORY rc4]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

112
113
114
115
116
117
118
119
120
 rc4::rc4 -in $socket -command [list ::Finish $ApplicationState]
}]

[section "AUTHORS"]
Pat Thoyts

[vset CATEGORY rc4]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/rcs/rcs.man.

322
323
324
325
326
327
328
329
330
[example {{{d 1 2} {d 4 1} {a 4 {The named is the mother of all things.

}} {a 11 {They both may be called deep and profound.
Deeper and more profound,
The door of all subtleties!}}}}]

[vset CATEGORY rcs]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

322
323
324
325
326
327
328
329
330
[example {{{d 1 2} {d 4 1} {a 4 {The named is the mother of all things.

}} {a 11 {They both may be called deep and profound.
Deeper and more profound,
The door of all subtleties!}}}}]

[vset CATEGORY rcs]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/report/report.man.

468
469
470
471
472
473
474
475
476
    +---+-------------------+-------+-------+--------+
    %
    % # alternate way of doing the above
    % m format 2string r
}]

[vset CATEGORY report]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

468
469
470
471
472
473
474
475
476
    +---+-------------------+-------+-------+--------+
    %
    % # alternate way of doing the above
    % m format 2string r
}]

[vset CATEGORY report]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/rest/rest.man.

545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
    package require tls
    http::register https 443 ::tls::socket
}]

[include ../common-text/tls-security-notes.inc]

[vset CATEGORY rest]
[include ../doctools2base/include/feedback.inc]
[comment {
TOKENS
     the value is substituted into the url at call time.
     tokens in the form of %name:default_value% will be
     an optional argument with a default value.
}]
[manpage_end]







|







545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
    package require tls
    http::register https 443 ::tls::socket
}]

[include ../common-text/tls-security-notes.inc]

[vset CATEGORY rest]
[include ../common-text/feedback.inc]
[comment {
TOKENS
     the value is substituted into the url at call time.
     tokens in the form of %name:default_value% will be
     an optional argument with a default value.
}]
[manpage_end]

Changes to modules/ripemd/ripemd128.man.

183
184
185
186
187
188
189
190
191
      Krawczyk, H., Bellare, M. and Canetti, R. "HMAC: Keyed-Hashing for
      Message Authentication", RFC 2104, February 1997.
	([uri http://www.rfc-editor.org/rfc/rfc2104.txt])

[list_end]

[vset CATEGORY ripemd]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

183
184
185
186
187
188
189
190
191
      Krawczyk, H., Bellare, M. and Canetti, R. "HMAC: Keyed-Hashing for
      Message Authentication", RFC 2104, February 1997.
	([uri http://www.rfc-editor.org/rfc/rfc2104.txt])

[list_end]

[vset CATEGORY ripemd]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/ripemd/ripemd160.man.

167
168
169
170
171
172
173
174
175
      Krawczyk, H., Bellare, M. and Canetti, R. "HMAC: Keyed-Hashing for
      Message Authentication", RFC 2104, February 1997.
	([uri http://www.rfc-editor.org/rfc/rfc2104.txt])

[list_end]

[vset CATEGORY ripemd]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

167
168
169
170
171
172
173
174
175
      Krawczyk, H., Bellare, M. and Canetti, R. "HMAC: Keyed-Hashing for
      Message Authentication", RFC 2104, February 1997.
	([uri http://www.rfc-editor.org/rfc/rfc2104.txt])

[list_end]

[vset CATEGORY ripemd]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/sasl/gtoken.man.

19
20
21
22
23
24
25
26
27

[include ../common-text/tls-security-notes.inc]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY sasl]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

19
20
21
22
23
24
25
26
27

[include ../common-text/tls-security-notes.inc]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY sasl]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/sasl/ntlm.man.

28
29
30
31
32
33
34
35
36

[list_end]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY sasl]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

28
29
30
31
32
33
34
35
36

[list_end]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY sasl]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/sasl/sasl.man.

332
333
334
335
336
337
338
339
340

[list_end]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY sasl]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

332
333
334
335
336
337
338
339
340

[list_end]

[section AUTHORS]
Pat Thoyts

[vset CATEGORY sasl]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/sasl/scram.man.

28
29
30
31
32
33
34
35
36

[list_end]

[section AUTHORS]
Sergei Golovan

[vset CATEGORY sasl]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

28
29
30
31
32
33
34
35
36

[list_end]

[section AUTHORS]
Sergei Golovan

[vset CATEGORY sasl]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/sha1/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded sha256 1.0.3 [list source [file join $dir sha256.tcl]]
package ifneeded sha1   2.0.3 [list source [file join $dir sha1.tcl]]
package ifneeded sha1   1.1.1 [list source [file join $dir sha1v1.tcl]]











|
|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded sha256 1.0.4 [list source [file join $dir sha256.tcl]]
package ifneeded sha1   2.0.4 [list source [file join $dir sha1.tcl]]
package ifneeded sha1   1.1.1 [list source [file join $dir sha1v1.tcl]]

Changes to modules/sha1/sha1.man.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

[manpage_begin sha1 n 2.0.3]
[see_also md4]
[see_also md5]
[see_also ripemd128]
[see_also ripemd160]
[keywords {FIPS 180-1}]
[keywords hashing]
[keywords message-digest]
[keywords {rfc 2104}]
[keywords security]
[keywords sha1]
[moddesc   {SHA-x Message-Digest Algorithm}]
[copyright {2005, Pat Thoyts <[email protected]>}]
[titledesc {SHA1 Message-Digest Algorithm}]
[category  {Hashes, checksums, and encryption}]
[require Tcl 8.2]
[require sha1 [opt 2.0.3]]
[description]
[para]

This package provides an implementation in Tcl of the SHA1
message-digest algorithm as specified by FIPS PUB 180-1 (1). This
algorithm takes a message and generates a 160-bit digest from the
input. The SHA1 algorithm is related to the MD4 algorithm (2) but has
>
|















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[vset VERSION 2.0.4]
[manpage_begin sha1 n [vset VERSION]]
[see_also md4]
[see_also md5]
[see_also ripemd128]
[see_also ripemd160]
[keywords {FIPS 180-1}]
[keywords hashing]
[keywords message-digest]
[keywords {rfc 2104}]
[keywords security]
[keywords sha1]
[moddesc   {SHA-x Message-Digest Algorithm}]
[copyright {2005, Pat Thoyts <[email protected]>}]
[titledesc {SHA1 Message-Digest Algorithm}]
[category  {Hashes, checksums, and encryption}]
[require Tcl 8.2]
[require sha1 [opt [vset VERSION]]]
[description]
[para]

This package provides an implementation in Tcl of the SHA1
message-digest algorithm as specified by FIPS PUB 180-1 (1). This
algorithm takes a message and generates a 160-bit digest from the
input. The SHA1 algorithm is related to the MD4 algorithm (2) but has
174
175
176
177
178
179
180
181
182
      Krawczyk, H., Bellare, M. and Canetti, R. "HMAC: Keyed-Hashing for
      Message Authentication", RFC 2104, February 1997.
	([uri http://www.rfc-editor.org/rfc/rfc2104.txt])

[list_end]

[vset CATEGORY sha1]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

175
176
177
178
179
180
181
182
183
      Krawczyk, H., Bellare, M. and Canetti, R. "HMAC: Keyed-Hashing for
      Message Authentication", RFC 2104, February 1997.
	([uri http://www.rfc-editor.org/rfc/rfc2104.txt])

[list_end]

[vset CATEGORY sha1]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/sha1/sha1.tcl.

640
641
642
643
644
645
646


647
648
649
650
651
652
653
654
655
656
657
658
659
# -------------------------------------------------------------------------

# fileevent handler for chunked file hashing.
#
proc ::sha1::Chunk {token channel {chunksize 4096}} {
    upvar #0 $token state
    


    if {[eof $channel]} {
        fileevent $channel readable {}
        set state(reading) 0
    }
        
    SHA1Update $token [read $channel $chunksize]
}

# -------------------------------------------------------------------------

proc ::sha1::sha1 {args} {
    array set opts {-hex 0 -filename {} -channel {} -chunksize 4096}
    if {[llength $args] == 1} {







>
>




|
<







640
641
642
643
644
645
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
# -------------------------------------------------------------------------

# fileevent handler for chunked file hashing.
#
proc ::sha1::Chunk {token channel {chunksize 4096}} {
    upvar #0 $token state
    
    SHA1Update $token [read $channel $chunksize]

    if {[eof $channel]} {
        fileevent $channel readable {}
        set state(reading) 0
    }
    return

}

# -------------------------------------------------------------------------

proc ::sha1::sha1 {args} {
    array set opts {-hex 0 -filename {} -channel {} -chunksize 4096}
    if {[llength $args] == 1} {
800
801
802
803
804
805
806
807
808
809
810
811
812
813
	    SwitchTo $e
	    break
	}
    }
    unset e
}

package provide sha1 2.0.3

# -------------------------------------------------------------------------
# Local Variables:
#   mode: tcl
#   indent-tabs-mode: nil
# End:







|






801
802
803
804
805
806
807
808
809
810
811
812
813
814
	    SwitchTo $e
	    break
	}
    }
    unset e
}

package provide sha1 2.0.4

# -------------------------------------------------------------------------
# Local Variables:
#   mode: tcl
#   indent-tabs-mode: nil
# End:

Changes to modules/sha1/sha256.man.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

[manpage_begin sha256 n 1.0.3]
[see_also md4]
[see_also md5]
[see_also ripemd128]
[see_also ripemd160]
[see_also sha1]
[keywords {FIPS 180-1}]
[keywords hashing]
[keywords message-digest]
[keywords {rfc 2104}]
[keywords security]
[keywords sha256]
[moddesc   {SHA-x Message-Digest Algorithm}]
[copyright {2008, Andreas Kupries <[email protected]>}]
[titledesc {SHA256 Message-Digest Algorithm}]
[category  {Hashes, checksums, and encryption}]
[require Tcl 8.2]
[require sha256 [opt 1.0.3]]
[description]
[para]

This package provides an implementation in Tcl of the SHA256 and
SHA224 message-digest algorithms as specified by FIPS PUB 180-1
(1). These algorithms take a message and generates a 256-bit (224-bit)
digest from the input. The SHA2 algorithms are related to the SHA1
>
|
















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[vset VERSION 1.0.4]
[manpage_begin sha256 n [vset VERSION]]
[see_also md4]
[see_also md5]
[see_also ripemd128]
[see_also ripemd160]
[see_also sha1]
[keywords {FIPS 180-1}]
[keywords hashing]
[keywords message-digest]
[keywords {rfc 2104}]
[keywords security]
[keywords sha256]
[moddesc   {SHA-x Message-Digest Algorithm}]
[copyright {2008, Andreas Kupries <[email protected]>}]
[titledesc {SHA256 Message-Digest Algorithm}]
[category  {Hashes, checksums, and encryption}]
[require Tcl 8.2]
[require sha256 [opt [vset VERSION]]]
[description]
[para]

This package provides an implementation in Tcl of the SHA256 and
SHA224 message-digest algorithms as specified by FIPS PUB 180-1
(1). These algorithms take a message and generates a 256-bit (224-bit)
digest from the input. The SHA2 algorithms are related to the SHA1
186
187
188
189
190
191
192
193
194
      Krawczyk, H., Bellare, M. and Canetti, R. "HMAC: Keyed-Hashing for
      Message Authentication", RFC 2104, February 1997.
	([uri http://www.rfc-editor.org/rfc/rfc2104.txt])

[list_end]

[vset CATEGORY sha1]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

187
188
189
190
191
192
193
194
195
      Krawczyk, H., Bellare, M. and Canetti, R. "HMAC: Keyed-Hashing for
      Message Authentication", RFC 2104, February 1997.
	([uri http://www.rfc-editor.org/rfc/rfc2104.txt])

[list_end]

[vset CATEGORY sha1]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/sha1/sha256.tcl.

27
28
29
30
31
32
33

34
35
36
37
38
39
40
namespace eval ::sha2 {
    variable  accel
    array set accel {tcl 0 critcl 0}
    variable  loaded {}

    namespace export sha256 hmac \
            SHA256Init SHA256Update SHA256Final


    variable uid
    if {![info exists uid]} {
        set uid 0
    }

    variable K







>







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
namespace eval ::sha2 {
    variable  accel
    array set accel {tcl 0 critcl 0}
    variable  loaded {}

    namespace export sha256 hmac \
            SHA256Init SHA256Update SHA256Final


    variable uid
    if {![info exists uid]} {
        set uid 0
    }

    variable K
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

    if {![string equal $loaded ""]} {
        foreach c {
            SHA256Init   SHA224Init
            SHA256Final  SHA224Final
            SHA256Update
        } {
            rename ::sha2::$c ::sha2::${c}-${loaded}
        }
    }

    # Activate the new implementation, if there is any.

    if {![string equal $key ""]} {
        foreach c {
            SHA256Init   SHA224Init
            SHA256Final  SHA224Final
            SHA256Update
        } {
            rename ::sha2::${c}-${key} ::sha2::$c
        }
    }

    # Remember the active implementation, for deactivation by future
    # switches.

    set loaded $key







|











|







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

    if {![string equal $loaded ""]} {
        foreach c {
            SHA256Init   SHA224Init
            SHA256Final  SHA224Final
            SHA256Update
        } {
            interp alias {} ::sha2::$c {}
        }
    }

    # Activate the new implementation, if there is any.

    if {![string equal $key ""]} {
        foreach c {
            SHA256Init   SHA224Init
            SHA256Final  SHA224Final
            SHA256Update
        } {
	    interp alias {} ::sha2::$c {} ::sha2::${c}-${key}
        }
    }

    # Remember the active implementation, for deactivation by future
    # switches.

    set loaded $key
655
656
657
658
659
660
661


662
663
664
665
666
667
668
669
670
671
672
673
674
# -------------------------------------------------------------------------

# fileevent handler for chunked file hashing.
#
proc ::sha2::Chunk {token channel {chunksize 4096}} {
    upvar #0 $token state
    


    if {[eof $channel]} {
        fileevent $channel readable {}
        set state(reading) 0
    }
        
    SHA256Update $token [read $channel $chunksize]
}

# -------------------------------------------------------------------------

proc ::sha2::_sha256 {ver args} {
    array set opts {-hex 0 -filename {} -channel {} -chunksize 4096}
    if {[llength $args] == 1} {







>
>




|
<







656
657
658
659
660
661
662
663
664
665
666
667
668
669

670
671
672
673
674
675
676
# -------------------------------------------------------------------------

# fileevent handler for chunked file hashing.
#
proc ::sha2::Chunk {token channel {chunksize 4096}} {
    upvar #0 $token state
    
    SHA256Update $token [read $channel $chunksize]

    if {[eof $channel]} {
        fileevent $channel readable {}
        set state(reading) 0
    }
    return

}

# -------------------------------------------------------------------------

proc ::sha2::_sha256 {ver args} {
    array set opts {-hex 0 -filename {} -channel {} -chunksize 4096}
    if {[llength $args] == 1} {
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709

    if {$opts(-filename) != {}} {
        set opts(-channel) [open $opts(-filename) r]
        fconfigure $opts(-channel) -translation binary
    }

    if {$opts(-channel) == {}} {

        if {[llength $args] != 1} {
            return -code error "wrong # args: should be\
                \"[namespace current]::sha$ver ?-hex|-bin? -filename file\
                | -channel channel | string\""
        }
        set tok [SHA${ver}Init]
        SHA${ver}Update $tok [lindex $args 0]







<







697
698
699
700
701
702
703

704
705
706
707
708
709
710

    if {$opts(-filename) != {}} {
        set opts(-channel) [open $opts(-filename) r]
        fconfigure $opts(-channel) -translation binary
    }

    if {$opts(-channel) == {}} {

        if {[llength $args] != 1} {
            return -code error "wrong # args: should be\
                \"[namespace current]::sha$ver ?-hex|-bin? -filename file\
                | -channel channel | string\""
        }
        set tok [SHA${ver}Init]
        SHA${ver}Update $tok [lindex $args 0]
819
820
821
822
823
824
825
826
827
828
829
830
831
832
	    SwitchTo $e
	    break
	}
    }
    unset e
}

package provide sha256 1.0.3

# -------------------------------------------------------------------------
# Local Variables:
#   mode: tcl
#   indent-tabs-mode: nil
# End:







|






820
821
822
823
824
825
826
827
828
829
830
831
832
833
	    SwitchTo $e
	    break
	}
    }
    unset e
}

package provide sha256 1.0.4

# -------------------------------------------------------------------------
# Local Variables:
#   mode: tcl
#   indent-tabs-mode: nil
# End:

Changes to modules/simulation/pkgIndex.tcl.

1
2
3
package ifneeded simulation::random 0.3.1 [list source [file join $dir random.tcl]]
package ifneeded simulation::montecarlo 0.1 [list source [file join $dir montecarlo.tcl]]
package ifneeded simulation::annealing 0.2 [list source [file join $dir annealing.tcl]]
|


1
2
3
package ifneeded simulation::random 0.4.0 [list source [file join $dir random.tcl]]
package ifneeded simulation::montecarlo 0.1 [list source [file join $dir montecarlo.tcl]]
package ifneeded simulation::annealing 0.2 [list source [file join $dir annealing.tcl]]

Changes to modules/simulation/random.tcl.

428
429
430
431
432
433
434




































































435
436
437
438
439
440
441
442
443
444
         set z [expr {DEPTH*rand()}]
         return [list $x $y $z]
    }]

    return $name
}





































































# Announce the package
#
package provide simulation::random 0.3.1


# main --
#     Test code
#
if { 0 } {
set bin [::simulation::random::prng_Bernoulli 0.2]







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|







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
         set z [expr {DEPTH*rand()}]
         return [list $x $y $z]
    }]

    return $name
}


# prng_Triangle --
#     Create a PRNG with a triangular distribution of points on an interval.
#     If the argument min is lower than the argument max, then smaller
#     values have higher probability and vice versa.
#
# Arguments:
#     min       Minimum value
#     max       Maximum value
#
# Result:
#     Name of a procedure that returns the random point
#
proc ::simulation::random::prng_Triangle {min max} {
    variable count

    incr count

    set name ::simulation::random::PRNG_$count

    set diff [expr {$max-$min}]

    if { $diff > 0.0 } {
        proc $name {} [string map [list MIN $min DIFF $diff] \
         {
            set r [expr {1.0 - sqrt(1.0 - rand())}]
            set x [expr {MIN + DIFF*$r}]
            return $x
        }]
    } else {
        proc $name {} [string map [list MAX $max DIFF $diff] \
         {
            set x [expr {MAX - DIFF*sqrt(rand())}]
            return $x
        }]
    }

    return $name
}


# prng_SymmetricTriangle --
#     Create a PRNG with a symmetric triangular distribution of points on an interval.
#
# Arguments:
#     min       Minimum value
#     max       Maximum value
#
# Result:
#     Name of a procedure that returns the random point
#
proc ::simulation::random::prng_SymmetricTriangle {min max} {
    variable count

    incr count

    set name ::simulation::random::PRNG_$count

    set diff2 [expr {0.5 *($max-$min)}]

    proc $name {} [string map [list MIN $min DIFF2 $diff2] \
     {
        return [expr {MIN + DIFF2 * (rand() + rand())}]
    }]

    return $name
}

# Announce the package
#
package provide simulation::random 0.4.0


# main --
#     Test code
#
if { 0 } {
set bin [::simulation::random::prng_Bernoulli 0.2]

Changes to modules/simulation/random.test.

230
231
232
233
234
235
236


































237
238
239

test "Block-1.0" "block generator with sides 10, 0.1 and 2.5" \
    -body {
    set p [::simulation::random::prng_Block 10 0.1 2.5]
    set rnd [$p]
    set result [llength $rnd]
} -result 3



































# End of test cases
testsuiteCleanup







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



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

test "Block-1.0" "block generator with sides 10, 0.1 and 2.5" \
    -body {
    set p [::simulation::random::prng_Block 10 0.1 2.5]
    set rnd [$p]
    set result [llength $rnd]
} -result 3

test "Triangle-1.0" "triangularly distributed numbers between -1.0 and 1.0" \
    -body {
    set p [::simulation::random::prng_Triangle -1.0 1.0]

    set okay 1
    for {set i 0} {$i < 1000} {incr i} {
        set rnd [$p]

        if { $rnd < -1.0 || $rnd > 1.0 } {
            set okay 0
            break
        }
    }

    set okay
} -result 1

test "Triangle-1.1" "triangularly distributed numbers between -1.0 and 1.0 (alternative)" \
    -body {
    set p [::simulation::random::prng_Triangle 1.0 -1.0]

    set okay 1
    for {set i 0} {$i < 1000} {incr i} {
        set rnd [$p]

        if { $rnd < -1.0 || $rnd > 1.0 } {
            set okay 0
            break
        }
    }

    set okay
} -result 1

# End of test cases
testsuiteCleanup

Changes to modules/simulation/simulation_random.man.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin simulation::random n 0.1]
[keywords math]
[keywords {random numbers}]
[keywords simulation]
[keywords {statistical distribution}]
[copyright {2004 Arjen Markus <[email protected]>}]
[moddesc   {Tcl Simulation Tools}]
[titledesc {Pseudo-random number generators}]
[category  Mathematics]
[require Tcl [opt 8.4]]
[require simulation::random 0.1]

[description]
[para]
This package consists of commands to generate pseudo-random number
generators. These new commands deliver

[list_begin itemized]

|









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin simulation::random n 0.4]
[keywords math]
[keywords {random numbers}]
[keywords simulation]
[keywords {statistical distribution}]
[copyright {2004 Arjen Markus <[email protected]>}]
[moddesc   {Tcl Simulation Tools}]
[titledesc {Pseudo-random number generators}]
[category  Mathematics]
[require Tcl [opt 8.4]]
[require simulation::random 0.4]

[description]
[para]
This package consists of commands to generate pseudo-random number
generators. These new commands deliver

[list_begin itemized]
77
78
79
80
81
82
83


























84
85
86
87
88
89
90
[list_begin definitions]

[call [cmd ::simulation::random::prng_Uniform] [arg min ] [arg max]]

Create a command (PRNG) that generates uniformly distributed numbers
between "min" and "max".



























[list_begin arguments]
[arg_def float min] Minimum number that will be generated
[arg_def float max] Maximum number that will be generated
[list_end]

[para]








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







77
78
79
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
[list_begin definitions]

[call [cmd ::simulation::random::prng_Uniform] [arg min ] [arg max]]

Create a command (PRNG) that generates uniformly distributed numbers
between "min" and "max".

[list_begin arguments]
[arg_def float min] Minimum number that will be generated
[arg_def float max] Maximum number that will be generated
[list_end]

[para]

[call [cmd ::simulation::random::prng_Triangular] [arg min ] [arg max]]

Create a command (PRNG) that generates triangularly distributed numbers
between "min" and "max". If the argument min is lower than the argument max, then smaller
values have higher probability and vice versa. In the first case the probability
density function is of the form [emph {f(x) = 2(1-x)}] and the other case it is of the form [emph {f(x) = 2x}].

[list_begin arguments]
[arg_def float min] Minimum number that will be generated
[arg_def float max] Maximum number that will be generated
[list_end]

[para]

[call [cmd ::simulation::random::prng_SymmTriangular] [arg min ] [arg max]]

Create a command (PRNG) that generates numbers distributed according to a symmetric triangle
around the mean of "min" and "max".

[list_begin arguments]
[arg_def float min] Minimum number that will be generated
[arg_def float max] Maximum number that will be generated
[list_end]

[para]

Changes to modules/smtpd/smtpd.man.

286
287
288
289
290
291
292
293
294

This software is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file
[file license.terms] for more details.

[vset CATEGORY smtpd]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

286
287
288
289
290
291
292
293
294

This software is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file
[file license.terms] for more details.

[vset CATEGORY smtpd]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/snit/snit.man.

2831
2832
2833
2834
2835
2836
2837
2838
2839
Andreas Kupries, Marty Backe, Andy Goth, Jeff Hobbs, Brian
Griffin, Donal Fellows, Miguel Sofer, Kenneth Green,
and Anton Kovalenko.
If I've forgotten anyone, my apologies; let me know and I'll add
your name to the list.

[vset CATEGORY snit]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

2831
2832
2833
2834
2835
2836
2837
2838
2839
Andreas Kupries, Marty Backe, Andy Goth, Jeff Hobbs, Brian
Griffin, Donal Fellows, Miguel Sofer, Kenneth Green,
and Anton Kovalenko.
If I've forgotten anyone, my apologies; let me know and I'll add
your name to the list.

[vset CATEGORY snit]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/snit/snitfaq.man.

4106
4107
4108
4109
4110
4111
4112
4113
4114

    mylib::propagate -background to {comp1 comp2 comp3}
    mylib::propagate -foreground to {comp1 comp2 comp3}
}
}]

[vset CATEGORY snit]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

4106
4107
4108
4109
4110
4111
4112
4113
4114

    mylib::propagate -background to {comp1 comp2 comp3}
    mylib::propagate -foreground to {comp1 comp2 comp3}
}
}]

[vset CATEGORY snit]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/soundex/soundex.man.

37
38
39
40
41
42
43
44
45

[example {
    % ::soundex::knuth Knuth
    K530
}]

[vset CATEGORY soundex]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

37
38
39
40
41
42
43
44
45

[example {
    % ::soundex::knuth Knuth
    K530
}]

[vset CATEGORY soundex]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/stooop/stooop.man.

215
216
217
218
219
220
221
222
223
[list_end]

[section EXAMPLES]

Please see the full HTML documentation in [uri stooop_man.html].

[vset CATEGORY stooop]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

215
216
217
218
219
220
221
222
223
[list_end]

[section EXAMPLES]

Please see the full HTML documentation in [uri stooop_man.html].

[vset CATEGORY stooop]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/stooop/switched.man.

320
321
322
323
324
325
326
327
328
    ...
}
}]

[list_end]

[vset CATEGORY stooop]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

320
321
322
323
324
325
326
327
328
    ...
}
}]

[list_end]

[vset CATEGORY stooop]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/string/token.man.

89
90
91
92
93
94
95
96
97
[para] Further note that all regex patterns are implicitly prefixed
with the constraint escape [const \A] to ensure that a match starts
exactly at the character index found in [arg startvar].

[list_end]

[vset CATEGORY textutil]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

89
90
91
92
93
94
95
96
97
[para] Further note that all regex patterns are implicitly prefixed
with the constraint escape [const \A] to ensure that a match starts
exactly at the character index found in [arg startvar].

[list_end]

[vset CATEGORY textutil]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/string/token_shell.man.

133
134
135
136
137
138
139
140
141

[para] Whitespace may occur before the first word, or after the last word. Whitespace must occur between adjacent words.

[list_end]
[list_end]

[vset CATEGORY textutil]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

133
134
135
136
137
138
139
140
141

[para] Whitespace may occur before the first word, or after the last word. Whitespace must occur between adjacent words.

[list_end]
[list_end]

[vset CATEGORY textutil]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/string/token_shell.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36


37
38
39
40
41
42


43
44
45
46
47
48
49
50
51
52


53
54
55
56
57
58
59
# -*- tcl -*-
# Testsuite string::token::shell
#
# Copyright (c) 2013 by Andreas Kupries <[email protected]>
# All rights reserved.

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2.0

support {
    use      fileutil/fileutil.tcl  fileutil
    useLocal token.tcl              string::token
}
testing {
    useLocal token_shell.tcl string::token::shell
}

if {[package vsatisfies [package provide Tcl] 8.6]} {
    proc E {a b} { return $b }
} else {
    proc E {a b} { return $a }
}

# -------------------------------------------------------------------------

test string-token-shell-1.0 "string token shell, wrong#args, not enough" -body {
    string token shell
} -returnCodes error -result [E \
  {wrong # args: should be "::string::token::shell ?-indices? ?-partial? ?--? text"} \
  {wrong # args: should be "shell ?-indices? ?-partial? ?--? text"}]



test string-token-shell-1.1 "string token shell, wrong#args, too many" -body {
    string token shell T X
} -returnCodes error -result [E \
  {wrong # args: should be "::string::token::shell ?-indices? ?-partial? ?--? text"} \
  {wrong # args: should be "shell ?-indices? ?-partial? ?--? text"}]



test string-token-shell-1.2 "string token shell, bad option" -body {
    string token shell -foo T
} -returnCodes error -result {Bad option -foo, expected one of -indices, or -partial}

test string-token-shell-1.3 "string token shell, wrong#args, too many" -body {
    string token shell -- T X
} -returnCodes error -result [E \
  {wrong # args: should be "::string::token::shell ?-indices? ?-partial? ?--? text"} \
  {wrong # args: should be "shell ?-indices? ?-partial? ?--? text"}]



# -------------------------------------------------------------------------

foreach {n label line tokens} {
    0  empty               {}          {}
    1  leading-whitespace  {  }        {}
    2  plain-words         {a}         {a}



|



















<
<
<
<
<
<




|
|
|
>
>



|
|
|
>
>







|
|
|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23






24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# -*- tcl -*-
# Testsuite string::token::shell
#
# Copyright (c) 2013,2019 by Andreas Kupries <[email protected]>
# All rights reserved.

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2.0

support {
    use      fileutil/fileutil.tcl  fileutil
    useLocal token.tcl              string::token
}
testing {
    useLocal token_shell.tcl string::token::shell
}







# -------------------------------------------------------------------------

test string-token-shell-1.0 "string token shell, wrong#args, not enough" -body {
    string token shell
} -returnCodes error -result [tcltest::byConstraint {
    tcl8.6.10plus {wrong # args: should be "::string::token::shell ?-indices? ?-partial? ?--? text"}
    tcl8.6not10   {wrong # args: should be "shell ?-indices? ?-partial? ?--? text"}
    tcl8.5minus   {wrong # args: should be "::string::token::shell ?-indices? ?-partial? ?--? text"}
}]

test string-token-shell-1.1 "string token shell, wrong#args, too many" -body {
    string token shell T X
} -returnCodes error -result [tcltest::byConstraint {
    tcl8.6.10plus {wrong # args: should be "::string::token::shell ?-indices? ?-partial? ?--? text"}
    tcl8.6not10   {wrong # args: should be "shell ?-indices? ?-partial? ?--? text"}
    tcl8.5minus   {wrong # args: should be "::string::token::shell ?-indices? ?-partial? ?--? text"}
}]

test string-token-shell-1.2 "string token shell, bad option" -body {
    string token shell -foo T
} -returnCodes error -result {Bad option -foo, expected one of -indices, or -partial}

test string-token-shell-1.3 "string token shell, wrong#args, too many" -body {
    string token shell -- T X
} -returnCodes error -result [tcltest::byConstraint {
    tcl8.6.10plus {wrong # args: should be "::string::token::shell ?-indices? ?-partial? ?--? text"}
    tcl8.6not10   {wrong # args: should be "shell ?-indices? ?-partial? ?--? text"}
    tcl8.5minus   {wrong # args: should be "::string::token::shell ?-indices? ?-partial? ?--? text"}
}]

# -------------------------------------------------------------------------

foreach {n label line tokens} {
    0  empty               {}          {}
    1  leading-whitespace  {  }        {}
    2  plain-words         {a}         {a}

Changes to modules/stringprep/stringprep.man.

143
144
145
146
147
148
149
150
151

[list_end]

[section "AUTHORS"]
Sergei Golovan

[vset CATEGORY stringprep]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

143
144
145
146
147
148
149
150
151

[list_end]

[section "AUTHORS"]
Sergei Golovan

[vset CATEGORY stringprep]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/stringprep/stringprep_data.man.

13
14
15
16
17
18
19
20
21
The [package stringprep::data] package is a helper for
[package stringprep], providing it with the data tables needed to
perform its functions. It is an [emph internal] package which should
not be accessed on its own. Because of that it has no publicly
documented API either. Its implementation is generated by a script.

[vset CATEGORY stringprep]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

13
14
15
16
17
18
19
20
21
The [package stringprep::data] package is a helper for
[package stringprep], providing it with the data tables needed to
perform its functions. It is an [emph internal] package which should
not be accessed on its own. Because of that it has no publicly
documented API either. Its implementation is generated by a script.

[vset CATEGORY stringprep]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/stringprep/unicode.man.

75
76
77
78
79
80
81
82
83

[list_end]

[section "AUTHORS"]
Sergei Golovan

[vset CATEGORY stringprep]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

75
76
77
78
79
80
81
82
83

[list_end]

[section "AUTHORS"]
Sergei Golovan

[vset CATEGORY stringprep]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/stringprep/unicode_data.man.

13
14
15
16
17
18
19
20
21
The [package unicode::data] package is a helper for
[package unicode], providing it with the data tables needed to
perform its functions. It is an [emph internal] package which should
not be accessed on its own. Because of that it has no publicly
documented API either. Its implementation is generated by a script.

[vset CATEGORY stringprep]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

13
14
15
16
17
18
19
20
21
The [package unicode::data] package is a helper for
[package unicode], providing it with the data tables needed to
perform its functions. It is an [emph internal] package which should
not be accessed on its own. Because of that it has no publicly
documented API either. Its implementation is generated by a script.

[vset CATEGORY stringprep]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/struct/disjointset.man.

228
229
230
231
232
233
234
235
236
[call [arg disjointsetName] [method destroy]]

Destroys the disjoint set object and all associated memory.

[list_end]

[vset CATEGORY {struct :: disjointset}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

228
229
230
231
232
233
234
235
236
[call [arg disjointsetName] [method destroy]]

Destroys the disjoint set object and all associated memory.

[list_end]

[vset CATEGORY {struct :: disjointset}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/struct/graph.man.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[comment {-*- tcl -*-}][vset VERSION 2.4.1]
[manpage_begin struct::graph n [vset VERSION]]
[keywords adjacent]
[keywords arc]
[keywords cgraph]
[keywords degree]
[keywords edge]
[keywords graph]
[keywords loop]
[keywords neighbour]
[keywords node]
[keywords serialization]
[keywords subgraph]
[keywords vertex]
[copyright {2002-2009 Andreas Kupries <[email protected]>}]
[moddesc   {Tcl Data Structures}]
[titledesc {Create and manipulate directed graph objects}]
[category  {Data structures}]
[require Tcl 8.4]
[require struct::graph [opt  [vset VERSION]]]
[require struct::list  [opt 1.5]]
[require struct::set   [opt 2.2.3]]
|













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[comment {-*- tcl -*-}][vset VERSION 2.4.3]
[manpage_begin struct::graph n [vset VERSION]]
[keywords adjacent]
[keywords arc]
[keywords cgraph]
[keywords degree]
[keywords edge]
[keywords graph]
[keywords loop]
[keywords neighbour]
[keywords node]
[keywords serialization]
[keywords subgraph]
[keywords vertex]
[copyright {2002-2009,2019 Andreas Kupries <[email protected]>}]
[moddesc   {Tcl Data Structures}]
[titledesc {Create and manipulate directed graph objects}]
[category  {Data structures}]
[require Tcl 8.4]
[require struct::graph [opt  [vset VERSION]]]
[require struct::list  [opt 1.5]]
[require struct::set   [opt 2.2.3]]
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
command can be used as well. The restrictions that involve connected
nodes take a variable number of nodes as argument, specified after the
name of the restriction itself.

[para]

The restrictions imposed by either [option -in], [option -out],
[option -adj], [option -inner], or [option -embedded] are applied
first. Specifying more than one of them is illegal.

[para]

After that the restrictions set via [option -key] (and
[option -value]) are applied. Specifying more than one [option -key]
(and [option -value]) is illegal. Specifying [option -value] alone,







|







393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
command can be used as well. The restrictions that involve connected
nodes take a variable number of nodes as argument, specified after the
name of the restriction itself.

[para]

The restrictions imposed by either [option -in], [option -out],
[option -adj], [option -inner], or [option -embedding] are applied
first. Specifying more than one of them is illegal.

[para]

After that the restrictions set via [option -key] (and
[option -value]) are applied. Specifying more than one [option -key]
(and [option -value]) is illegal. Specifying [option -value] alone,
444
445
446
447
448
449
450
















451
452
453
454
455
456
457

[def [option -embedding]]

Return a list of all arcs adjacent to exactly one of the nodes in the
set. This is the set of arcs connecting the subgraph spawned by the
specified nodes to the rest of the graph.

















[def "[option -key] [arg key]"]

Limit the list of arcs that are returned to those arcs that have an
associated key [arg key].

[def "[option -value] [arg value]"]








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

[def [option -embedding]]

Return a list of all arcs adjacent to exactly one of the nodes in the
set. This is the set of arcs connecting the subgraph spawned by the
specified nodes to the rest of the graph.

[list_end]

[emph Attention]: After the above options any word with a leading dash
which is not a valid option is treated as a node name instead of an
invalid option to error out on. This condition holds until either a
valid option terminates the list of nodes, or the end of the command
is reached, whichever comes first.

[para]

The remaining filter options are:

[para]

[list_begin definitions]

[def "[option -key] [arg key]"]

Limit the list of arcs that are returned to those arcs that have an
associated key [arg key].

[def "[option -value] [arg value]"]

605
606
607
608
609
610
611
612

613





614
615
616
617
618
619
620
621
of returned nodes based on neighboring nodes, or based on the keyed
values associated with the node. The restrictions that involve
neighboring nodes have a list of nodes as argument, specified after
the name of the restriction itself.

[para]

The possible restrictions are the same as for method

[method arcs]. The exact meanings change slightly, as they operate on





nodes instead of arcs. The command recognizes:

[list_begin definitions]
[def [option -in]]

Return a list of all nodes with at least one outgoing arc ending in a
node found in the specified set of nodes. Alternatively specified as
the set of source nodes for the [option -in] arcs of the node set. The







|
>
|
>
>
>
>
>
|







621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
of returned nodes based on neighboring nodes, or based on the keyed
values associated with the node. The restrictions that involve
neighboring nodes have a list of nodes as argument, specified after
the name of the restriction itself.

[para]

The possible restrictions are the same as for method [method arcs].

Note that while the exact meanings change slightly, as they operate on
nodes instead of arcs, the general behaviour is the same, especially
when it comes to the handling of words with a leading dash in node
lists.

[para]
The command recognizes:

[list_begin definitions]
[def [option -in]]

Return a list of all nodes with at least one outgoing arc ending in a
node found in the specified set of nodes. Alternatively specified as
the set of source nodes for the [option -in] arcs of the node set. The
934
935
936
937
938
939
940
941
942
Both methods [method arcs] and [method nodes] have been extended with
the ability to select arcs and nodes based on an arbitrary filtering
criterium.

[list_end]

[vset CATEGORY {struct :: graph}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

956
957
958
959
960
961
962
963
964
Both methods [method arcs] and [method nodes] have been extended with
the ability to select arcs and nodes based on an arbitrary filtering
criterium.

[list_end]

[vset CATEGORY {struct :: graph}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/struct/graph.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# graph.tcl --
#
#	Implementation of a graph data structure for Tcl.
#
# Copyright (c) 2000-2005 by Andreas Kupries
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: graph.tcl,v 1.33 2009/09/24 16:23:47 andreas_kupries Exp $

# @mdgen EXCLUDE: graph_c.tcl

package require Tcl 8.4

namespace eval ::struct::graph {}





|



<
<







1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
# graph.tcl --
#
#	Implementation of a graph data structure for Tcl.
#
# Copyright (c) 2000-2005,2019 by Andreas Kupries
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.



# @mdgen EXCLUDE: graph_c.tcl

package require Tcl 8.4

namespace eval ::struct::graph {}

173
174
175
176
177
178
179
180
## Ready

namespace eval ::struct {
    # Export the constructor command.
    namespace export graph
}

package provide struct::graph 2.4.1







|
171
172
173
174
175
176
177
178
## Ready

namespace eval ::struct {
    # Export the constructor command.
    namespace export graph
}

package provide struct::graph 2.4.3

Changes to modules/struct/graph.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- tcl -*-
# graph.test:  tests for the graph structure.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
# Copyright (c) 2017-2017 Andreas Kupries
# All rights reserved.
#
# RCS: @(#) $Id: graph.test,v 1.27 2007/04/12 03:01:54 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]









|

<
<







1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
# -*- tcl -*-
# graph.test:  tests for the graph structure.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
# Copyright (c) 2017,2019 Andreas Kupries
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

Changes to modules/struct/graph/filter.c.

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
    static const int mode [] = {
	NA_ADJ,   NA_EMBEDDING, -1,     NA_IN,
	NA_INNER, -1,           NA_OUT, -1
    };

    int             ac = oc;
    Tcl_Obj* const* av = ov;
    int             r;

    na->mode   = NA_NONE;
    na->nc     = 0;
    na->nv     = NALLOC (oc, Tcl_Obj*);
    na->key    = NULL;
    na->value  = NULL;
    na->filter = NULL;

    oc -= 2; /* Skip 'graph arcs' */
    ov += 2;


    while (oc) {
	if ('-' == Tcl_GetString (ov[0])[0]) {
	    if (Tcl_GetIndexFromObj (interp, ov [0], restr,
				     "restriction", 0, &r) != TCL_OK) {

		goto abort;
	    }
	    switch (r) {
	    case R_ADJ:
	    case R_EMB:
	    case R_IN:
	    case R_INNER:
	    case R_OUT:
		if (na->mode != NA_NONE) {
		    Tcl_SetObjResult (interp,
		      Tcl_NewStringObj ("invalid restriction: illegal multiple use of \"-in\"|\"-out\"|\"-adj\"|\"-inner\"|\"-embedding\"", -1));
		    goto abort;
		}
		na->mode = mode [r];

		break;
	    case R_CMD:
		if (oc < 2) goto wrongargs;
		if (na->filter) {
		    Tcl_SetObjResult (interp,
		      Tcl_NewStringObj ("invalid restriction: illegal multiple use of \"-filter\"", -1));
		    goto abort;
		}
		na->filter = ov [1];
		oc --;
		ov ++;

		break;
	    case R_KEY:
		if (oc < 2) goto wrongargs;
		if (na->key) {
		    Tcl_SetObjResult (interp,
		      Tcl_NewStringObj ("invalid restriction: illegal multiple use of \"-key\"", -1));
		    goto abort;
		}
		na->key = ov [1];
		oc --;
		ov ++;

		break;
	    case R_VAL:
		if (oc < 2) goto wrongargs;
		if (na->value) {
		    Tcl_SetObjResult (interp,
		      Tcl_NewStringObj ("invalid restriction: illegal multiple use of \"-value\"", -1));
		    goto abort;
		}
		na->value = ov [1];
		oc --;
		ov ++;

		break;
	    }
	    oc --;
	    ov ++;
	} else {

	    /* Save non-options for the list of nodes */
	    ASSERT_BOUNDS (na->nc, ac);
	    na->nv [na->nc] = ov[0];
	    na->nc ++;
	    oc --;
	    ov ++;
	}







|











>




>














>











>











>











>





>







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
    static const int mode [] = {
	NA_ADJ,   NA_EMBEDDING, -1,     NA_IN,
	NA_INNER, -1,           NA_OUT, -1
    };

    int             ac = oc;
    Tcl_Obj* const* av = ov;
    int             r, seenodes;

    na->mode   = NA_NONE;
    na->nc     = 0;
    na->nv     = NALLOC (oc, Tcl_Obj*);
    na->key    = NULL;
    na->value  = NULL;
    na->filter = NULL;

    oc -= 2; /* Skip 'graph arcs' */
    ov += 2;

    seenodes = 0;
    while (oc) {
	if ('-' == Tcl_GetString (ov[0])[0]) {
	    if (Tcl_GetIndexFromObj (interp, ov [0], restr,
				     "restriction", 0, &r) != TCL_OK) {
		if (seenodes) goto addnode;
		goto abort;
	    }
	    switch (r) {
	    case R_ADJ:
	    case R_EMB:
	    case R_IN:
	    case R_INNER:
	    case R_OUT:
		if (na->mode != NA_NONE) {
		    Tcl_SetObjResult (interp,
		      Tcl_NewStringObj ("invalid restriction: illegal multiple use of \"-in\"|\"-out\"|\"-adj\"|\"-inner\"|\"-embedding\"", -1));
		    goto abort;
		}
		na->mode = mode [r];
		seenodes = 1;
		break;
	    case R_CMD:
		if (oc < 2) goto wrongargs;
		if (na->filter) {
		    Tcl_SetObjResult (interp,
		      Tcl_NewStringObj ("invalid restriction: illegal multiple use of \"-filter\"", -1));
		    goto abort;
		}
		na->filter = ov [1];
		oc --;
		ov ++;
		seenodes = 0;
		break;
	    case R_KEY:
		if (oc < 2) goto wrongargs;
		if (na->key) {
		    Tcl_SetObjResult (interp,
		      Tcl_NewStringObj ("invalid restriction: illegal multiple use of \"-key\"", -1));
		    goto abort;
		}
		na->key = ov [1];
		oc --;
		ov ++;
		seenodes = 0;
		break;
	    case R_VAL:
		if (oc < 2) goto wrongargs;
		if (na->value) {
		    Tcl_SetObjResult (interp,
		      Tcl_NewStringObj ("invalid restriction: illegal multiple use of \"-value\"", -1));
		    goto abort;
		}
		na->value = ov [1];
		oc --;
		ov ++;
		seenodes = 0;
		break;
	    }
	    oc --;
	    ov ++;
	} else {
	addnode:
	    /* Save non-options for the list of nodes */
	    ASSERT_BOUNDS (na->nc, ac);
	    na->nv [na->nc] = ov[0];
	    na->nc ++;
	    oc --;
	    ov ++;
	}

Changes to modules/struct/graph/methods.c.

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
gm_arc_DELETE (G* g, Tcl_Interp* interp, int objc, Tcl_Obj* const* objv)
{
    /* Syntax: graph arc  delete ARC ARC...
     *	       [0]   [1]  [2]    [3] [4+]
     */

    GA* a;
    int i;


    if (objc < 4) {
	Tcl_WrongNumArgs (interp, 3, objv, "arc arc...");
	return TCL_ERROR;
    }


    for (i=3; i<objc; i++) {
	a = ga_get_arc (g, objv[i], interp, objv[0]);







	FAIL (a);

    }


    for (i=3; i<objc; i++) {
	a = ga_get_arc (g, objv[i], interp, objv[0]);
	ga_delete (a);
    }
    return TCL_OK;
}







|
>






>


>
>
>
>
>
>
>

>

>







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
gm_arc_DELETE (G* g, Tcl_Interp* interp, int objc, Tcl_Obj* const* objv)
{
    /* Syntax: graph arc  delete ARC ARC...
     *	       [0]   [1]  [2]    [3] [4+]
     */

    GA* a;
    int i, new;
    Tcl_HashTable seen;

    if (objc < 4) {
	Tcl_WrongNumArgs (interp, 3, objv, "arc arc...");
	return TCL_ERROR;
    }

    Tcl_InitHashTable (&seen, TCL_STRING_KEYS);
    for (i=3; i<objc; i++) {
	a = ga_get_arc (g, objv[i], interp, objv[0]);
	if (a && (Tcl_FindHashEntry (&seen, Tcl_GetString (objv[i])) != NULL)) {
	    ga_err_missing (interp, objv[i], objv[0]);
	    a = NULL;
	}
	if (a == NULL) {
	    Tcl_DeleteHashTable (&seen);
	}
	FAIL (a);
	Tcl_CreateHashEntry (&seen, Tcl_GetString (objv[i]), &new);
    }
    Tcl_DeleteHashTable (&seen);

    for (i=3; i<objc; i++) {
	a = ga_get_arc (g, objv[i], interp, objv[0]);
	ga_delete (a);
    }
    return TCL_OK;
}
1812
1813
1814
1815
1816
1817
1818
1819
1820

1821
1822
1823
1824
1825
1826

1827
1828







1829

1830

1831
1832
1833
1834
1835
1836
1837
int
gm_node_DELETE (G* g, Tcl_Interp* interp, int objc, Tcl_Obj* const* objv)
{
    /* Syntax: graph node delete NODE NODE...
     *	       [0]   [1]  [2]    [3]  [4+]
     */

    int i;
    GN* n;


    if (objc < 4) {
	Tcl_WrongNumArgs (interp, 3, objv, "node node...");
	return TCL_ERROR;
    }


    for (i=3; i< objc; i++) {
	n = gn_get_node (g, objv [i], interp, objv [0]);







	FAIL (n);

    }


    for (i=3; i< objc; i++) {
	n = gn_get_node (g, objv [i], interp, objv [0]);
	gn_delete (n);
    }
    return TCL_OK;
}







|

>






>


>
>
>
>
>
>
>

>

>







1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
int
gm_node_DELETE (G* g, Tcl_Interp* interp, int objc, Tcl_Obj* const* objv)
{
    /* Syntax: graph node delete NODE NODE...
     *	       [0]   [1]  [2]    [3]  [4+]
     */

    int i, new;
    GN* n;
    Tcl_HashTable seen;

    if (objc < 4) {
	Tcl_WrongNumArgs (interp, 3, objv, "node node...");
	return TCL_ERROR;
    }

    Tcl_InitHashTable (&seen, TCL_STRING_KEYS);
    for (i=3; i< objc; i++) {
	n = gn_get_node (g, objv [i], interp, objv [0]);
	if (n && (Tcl_FindHashEntry (&seen, Tcl_GetString (objv[i])) != NULL)) {
	    gn_err_missing (interp, objv[i], objv[0]);
	    n = NULL;
	}
	if (n == NULL) {
	    Tcl_DeleteHashTable (&seen);
	}
	FAIL (n);
	Tcl_CreateHashEntry (&seen, Tcl_GetString (objv[i]), &new);
    }
    Tcl_DeleteHashTable (&seen);

    for (i=3; i< objc; i++) {
	n = gn_get_node (g, objv [i], interp, objv [0]);
	gn_delete (n);
    }
    return TCL_OK;
}
1977
1978
1979
1980
1981
1982
1983
1984
1985

1986
1987
1988
1989

1990
1991

1992
1993

1994

1995
1996
1997
1998
1999
2000
2001

    if (objc < 3) {
	Tcl_WrongNumArgs (interp, 3, objv, "?node...?");
	return TCL_ERROR;
    }

    if (objc >= 4) {
	int       lc, i;
	Tcl_Obj** lv;


	/* Explicit node names, must not exist */

	for (i=3; i<objc; i++) {

	    if (gn_get_node (g, objv [i], NULL, NULL)) {
		gn_err_duplicate (interp, objv[i], objv[0]);

		return TCL_ERROR;
	    }

	}


	/* No matching nodes found. Create nodes with specified name, then
	 * insert them
	 */

	lc = objc-3;
	lv = NALLOC (lc, Tcl_Obj*);







|

>


|

>
|

>


>

>







1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028

    if (objc < 3) {
	Tcl_WrongNumArgs (interp, 3, objv, "?node...?");
	return TCL_ERROR;
    }

    if (objc >= 4) {
	int       lc, i, new;
	Tcl_Obj** lv;
	Tcl_HashTable seen;

	/* Explicit node names, must not exist */
	Tcl_InitHashTable (&seen, TCL_STRING_KEYS);
	for (i=3; i<objc; i++) {
	    if ((Tcl_FindHashEntry (&seen, Tcl_GetString (objv[i])) != NULL) ||
		gn_get_node (g, objv [i], NULL, NULL)) {
		gn_err_duplicate (interp, objv[i], objv[0]);
		Tcl_DeleteHashTable (&seen);
		return TCL_ERROR;
	    }
	    Tcl_CreateHashEntry (&seen, Tcl_GetString (objv[i]), &new);
	}
	Tcl_DeleteHashTable (&seen);

	/* No matching nodes found. Create nodes with specified name, then
	 * insert them
	 */

	lc = objc-3;
	lv = NALLOC (lc, Tcl_Obj*);

Changes to modules/struct/graph/tests/arc/delete.test.

27
28
29
30
31
32
33










34
35
36
37
38
39
40
# -------------------------------------------------------------------------
# Logical arguments checks and failures

test graph-${impl}-${setimpl}-arc-delete-2.0 {arc delete, missing arc} {
    SETUP
    catch {mygraph arc delete arc0} msg
    mygraph destroy










    set msg
} [MissingArc $MY arc0]

# -------------------------------------------------------------------------
# Ok arguments, single, multiple deletion.

test graph-${impl}-${setimpl}-arc-delete-3.0 {arc delete} {







>
>
>
>
>
>
>
>
>
>







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# -------------------------------------------------------------------------
# Logical arguments checks and failures

test graph-${impl}-${setimpl}-arc-delete-2.0 {arc delete, missing arc} {
    SETUP
    catch {mygraph arc delete arc0} msg
    mygraph destroy
    set msg
} [MissingArc $MY arc0]

test graph-${impl}-${setimpl}-arc-delete-2.1 {arc delete, missing arc} {
    SETUP
    mygraph node insert node0 node1
    mygraph arc  insert node0 node1 arc0

    catch {mygraph arc delete arc0 arc0} msg
    mygraph destroy
    set msg
} [MissingArc $MY arc0]

# -------------------------------------------------------------------------
# Ok arguments, single, multiple deletion.

test graph-${impl}-${setimpl}-arc-delete-3.0 {arc delete} {

Changes to modules/struct/graph/tests/arcs.test.

229
230
231
232
233
234
235

236
237
238
239
240
241
242
243
244
245
246
247
248
249
	catch {mygraph arcs $switch} msg
	mygraph destroy
	set msg
    } "wrong # args: should be \"$MY arcs ?-key key? ?-value value? ?-filter cmd? ?-in|-out|-adj|-inner|-embedding node node...?\"" ; # {}

    incr n
}


# -------------------------------------------------------------------------
# Logical arguments checks and failures

set n 0
foreach switch {-in -out -adj -inner -embedding} {

    test graph-${impl}-${setimpl}-arcs-ioaie-2.$n "arcs, $switch, missing node" {
	SETUP
	catch {mygraph arcs $switch x} msg
	mygraph destroy
	set msg
    } [MissingNode $MY x] ; # {}








>






<







229
230
231
232
233
234
235
236
237
238
239
240
241
242

243
244
245
246
247
248
249
	catch {mygraph arcs $switch} msg
	mygraph destroy
	set msg
    } "wrong # args: should be \"$MY arcs ?-key key? ?-value value? ?-filter cmd? ?-in|-out|-adj|-inner|-embedding node node...?\"" ; # {}

    incr n
}
unset n

# -------------------------------------------------------------------------
# Logical arguments checks and failures

set n 0
foreach switch {-in -out -adj -inner -embedding} {

    test graph-${impl}-${setimpl}-arcs-ioaie-2.$n "arcs, $switch, missing node" {
	SETUP
	catch {mygraph arcs $switch x} msg
	mygraph destroy
	set msg
    } [MissingNode $MY x] ; # {}

257
258
259
260
261
262
263

264
265
266
267
268
269
270
	    mygraph destroy
	    set msg
	} {invalid restriction: illegal multiple use of "-in"|"-out"|"-adj"|"-inner"|"-embedding"} ; # {}

	incr n
    }
}


# -------------------------------------------------------------------------
# Ok arguments.

set n 0
foreach {switch nodes expected} {
    -in        {1 2 3} {A B C D E F}    -in        {4 5 6} {}







>







257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
	    mygraph destroy
	    set msg
	} {invalid restriction: illegal multiple use of "-in"|"-out"|"-adj"|"-inner"|"-embedding"} ; # {}

	incr n
    }
}
unset n

# -------------------------------------------------------------------------
# Ok arguments.

set n 0
foreach {switch nodes expected} {
    -in        {1 2 3} {A B C D E F}    -in        {4 5 6} {}
307
308
309
310
311
312
313

314
315
316
317
318
319
320
321
322
323
324
325
326
	set result [lsort [eval [linsert $nodes 0 mygraph arcs $switch]]]
	mygraph destroy
	set result
    } $expected ; # {}

    incr n
}


test graph-${impl}-${setimpl}-arcs-adj-1.0 {arcs -adj, border case C code failure} -setup {
    struct::graph mygraph
    mygraph node insert E
    mygraph node insert F
    mygraph arc  insert E F E_F
} -body {
    mygraph arcs -adj E
} -cleanup {
    mygraph destroy
} -result {E_F}

# ---------------------------------------------------







>













308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
	set result [lsort [eval [linsert $nodes 0 mygraph arcs $switch]]]
	mygraph destroy
	set result
    } $expected ; # {}

    incr n
}
unset n

test graph-${impl}-${setimpl}-arcs-adj-1.0 {arcs -adj, border case C code failure} -setup {
    struct::graph mygraph
    mygraph node insert E
    mygraph node insert F
    mygraph arc  insert E F E_F
} -body {
    mygraph arcs -adj E
} -cleanup {
    mygraph destroy
} -result {E_F}

# ---------------------------------------------------

Changes to modules/struct/graph/tests/node/delete.test.

27
28
29
30
31
32
33








34
35
36
37
38
39
40
# -------------------------------------------------------------------------
# Logical arguments checks and failures

test graph-${impl}-${setimpl}-node-delete-2.0 {node delete, missing node} {
    SETUP
    catch {mygraph node delete node0} msg
    mygraph destroy








    set msg
} [MissingNode $MY node0]

# -------------------------------------------------------------------------
# Ok arguments, single, multiple deletion.

test graph-${impl}-${setimpl}-node-delete-3.0 {node delete, single} {







>
>
>
>
>
>
>
>







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# -------------------------------------------------------------------------
# Logical arguments checks and failures

test graph-${impl}-${setimpl}-node-delete-2.0 {node delete, missing node} {
    SETUP
    catch {mygraph node delete node0} msg
    mygraph destroy
    set msg
} [MissingNode $MY node0]

test graph-${impl}-${setimpl}-node-delete-2.1 {node delete, missing node} {
    SETUP
    mygraph node insert node0
    catch {mygraph node delete node0 node0} msg
    mygraph destroy
    set msg
} [MissingNode $MY node0]

# -------------------------------------------------------------------------
# Ok arguments, single, multiple deletion.

test graph-${impl}-${setimpl}-node-delete-3.0 {node delete, single} {

Changes to modules/struct/graph/tests/node/insert.test.

16
17
18
19
20
21
22







23
24
25
26
27
28
29
# Logical arguments checks and failures

test graph-${impl}-${setimpl}-node-insert-2.0 {node insert, duplicate node} {
    SETUP
    mygraph node insert node0
    catch {mygraph node insert node0} msg
    mygraph destroy







    set msg
} [ExistingNode $MY node0]

# -------------------------------------------------------------------------
# Ok arguments. None, single, multiple, defaults

test graph-${impl}-${setimpl}-node-insert-3.0 {node insert, defaults} {







>
>
>
>
>
>
>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# Logical arguments checks and failures

test graph-${impl}-${setimpl}-node-insert-2.0 {node insert, duplicate node} {
    SETUP
    mygraph node insert node0
    catch {mygraph node insert node0} msg
    mygraph destroy
    set msg
} [ExistingNode $MY node0]

test graph-${impl}-${setimpl}-node-insert-2.1 {node insert, duplicate nodes} {
    SETUP
    catch {mygraph node insert node0 node0} msg
    mygraph destroy
    set msg
} [ExistingNode $MY node0]

# -------------------------------------------------------------------------
# Ok arguments. None, single, multiple, defaults

test graph-${impl}-${setimpl}-node-insert-3.0 {node insert, defaults} {

Changes to modules/struct/graph/tests/nodes.test.

11
12
13
14
15
16
17





18
19
20
21
22
23
24
# (3)     graph nodes -in       NODE...
#         graph nodes -out      NODE...
#         graph nodes -adj      NODE...
#         graph nodes -inner    NODE...
#         graph nodes -embedded NODE...

# We can use one in each group (1,2,3)






# -------------------------------------------------------------------------
# Wrong # args: Missing, Too many

# Cannot have missing arguments (zero is fine),
# except when switches are in use. That however
# is tested with the switches. Ditto for too many







>
>
>
>
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# (3)     graph nodes -in       NODE...
#         graph nodes -out      NODE...
#         graph nodes -adj      NODE...
#         graph nodes -inner    NODE...
#         graph nodes -embedded NODE...

# We can use one in each group (1,2,3)

# Note: node names may have a leading dash ('-').

# Heuristics: Unknown options after (3) are considered node names
# until we reach a valid option.

# -------------------------------------------------------------------------
# Wrong # args: Missing, Too many

# Cannot have missing arguments (zero is fine),
# except when switches are in use. That however
# is tested with the switches. Ditto for too many
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
}

# -------------------------------------------------------------------------
# Ok arguments.

set n 0
foreach {switch nodes expected} {
    -in        {1 2 3} {1 2 3 4 5 6}    -in        {4 5 6} {}
    -out       {1 2 3} {1 2 3}          -out       {4 5 6} {1 2 3}
    -adj       {1 2 3} {1 2 3 4 5 6}    -adj       {4 5 6} {1 2 3}
    -inner     {1 2 3} {1 2 3}          -inner     {4 5 6} {}
    -embedding {1 2 3} {4 5 6}          -embedding {4 5 6} {1 2 3}
    -in        {1 2}   {1 3 4 5}        -in        {4 5}   {}
    -out       {1 2}   {2 3}            -out       {4 5}   {1 2}
    -adj       {1 2}   {1 2 3 4 5}      -adj       {4 5}   {1 2}
    -inner     {1 2}   {1 2}            -inner     {4 5}   {}
    -embedding {1 2}   {3 4 5}          -embedding {4 5}   {1 2}
    -in        {1}     {3 4}            -in        {4}     {}
    -out       {1}     {2}              -out       {4}     {1}
    -adj       {1}     {2 3 4}          -adj       {4}     {1}
    -inner     {1}     {}               -inner     {4}     {}
    -embedding {1}     {2 3 4}          -embedding {4}     {1}
    -in        {1 4}   {3 4}            -in        {4 2}   {1 5}
    -out       {1 4}   {1 2}            -out       {4 2}   {1 3}
    -adj       {1 4}   {1 2 3 4}        -adj       {4 2}   {1 3 5}
    -inner     {1 4}   {1 4}            -inner     {4 2}   {}
    -embedding {1 4}   {2 3}            -embedding {4 2}   {1 3 5}





} {


    test graph-${impl}-${setimpl}-nodes-ioaie-3.$n "nodes, $switch" {
	SETUP










	mygraph node insert 1 2 3 4 5 6
	mygraph arc  insert 4 1 A
	mygraph arc  insert 5 2 B
	mygraph arc  insert 6 3 C
	mygraph arc  insert 3 1 D
	mygraph arc  insert 1 2 E
	mygraph arc  insert 2 3 F


	set result [lsort [eval [linsert $nodes 0 mygraph nodes $switch]]]
	mygraph destroy

	set result
    } $expected ; # {}

    incr n
}


# ---------------------------------------------------
# Test with many parallel arcs, beyond the number of nodes, i.e. lots
# of duplicates sources and destinations, to check that the dup
# removal works correctly. See bug [SF 1923685].

set n 0
foreach {switch nodes expected} {
    -in        2       1
    -out       2       3
    -adj       2       {1 3}
    -inner     {1 2 3} {1 2 3}
    -embedding 2       {1 3}
} {


    test graph-${impl}-${setimpl}-nodes-parallel-ioaie-bug1923685-4.$n "nodes, $switch, parallel arcs, bug 1923685" {
	SETUP

	mygraph node insert 1 2 3 4
	mygraph arc  insert 1 2 A ; mygraph arc  insert 2 3 A.
	mygraph arc  insert 1 2 B ; mygraph arc  insert 2 3 B.
	mygraph arc  insert 1 2 C ; mygraph arc  insert 2 3 C.
	mygraph arc  insert 1 2 D ; mygraph arc  insert 2 3 D.
	mygraph arc  insert 1 2 E ; mygraph arc  insert 2 3 E.
	mygraph arc  insert 1 2 F ; mygraph arc  insert 2 3 F.
	mygraph arc  insert 1 2 G ; mygraph arc  insert 2 3 G.
	mygraph arc  insert 1 2 H ; mygraph arc  insert 2 3 H.

	set result [lsort [eval [linsert $nodes 0 mygraph nodes $switch]]]
	mygraph destroy

	set result
    } $expected ; # {}

    incr n
}


# ---------------------------------------------------







|

|

|
|

|

|





|

|

|
>
>
>
>
>

>
>
|

>
>
>
>
>
>
>
>
>
|
|






>



>





>



|










>
>















>





>


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
}

# -------------------------------------------------------------------------
# Ok arguments.

set n 0
foreach {switch nodes expected} {
    -in        {1 2 3} {-1 1 2 3 4 5 6} -in        {4 5 6} {}
    -out       {1 2 3} {1 2 3}          -out       {4 5 6} {1 2 3}
    -adj       {1 2 3} {-1 1 2 3 4 5 6} -adj       {4 5 6} {1 2 3}
    -inner     {1 2 3} {1 2 3}          -inner     {4 5 6} {}
    -embedding {1 2 3} {-1 4 5 6}       -embedding {4 5 6} {1 2 3}
    -in        {1 2}   {-1 1 3 4 5}     -in        {4 5}   {}
    -out       {1 2}   {2 3}            -out       {4 5}   {1 2}
    -adj       {1 2}   {-1 1 2 3 4 5}   -adj       {4 5}   {1 2}
    -inner     {1 2}   {1 2}            -inner     {4 5}   {}
    -embedding {1 2}   {-1 3 4 5}       -embedding {4 5}   {1 2}
    -in        {1}     {3 4}            -in        {4}     {}
    -out       {1}     {2}              -out       {4}     {1}
    -adj       {1}     {2 3 4}          -adj       {4}     {1}
    -inner     {1}     {}               -inner     {4}     {}
    -embedding {1}     {2 3 4}          -embedding {4}     {1}
    -in        {1 4}   {3 4}            -in        {4 2}   {-1 1 5}
    -out       {1 4}   {1 2}            -out       {4 2}   {1 3}
    -adj       {1 4}   {1 2 3 4}        -adj       {4 2}   {-1 1 3 5}
    -inner     {1 4}   {1 4}            -inner     {4 2}   {}
    -embedding {1 4}   {2 3}            -embedding {4 2}   {-1 1 3 5}
    -in        {1 -1}  {3 4}
    -out       {1 -1}  2
    -adj       {1 -1}  {2 3 4}
    -inner     {1 -1}  {}
    -embedding {1 -1}  {2 3 4}
} {
    lappend expected $switch $nodes

    test graph-${impl}-${setimpl}-nodes-ioaie-3.$n "nodes, $switch ($nodes)" {
	SETUP
	# Nodes (digits -1,1-6) and arcs (letters A-G), no direction
	#        4
	#        |A
	#        1     -1
	#      D/ \   /G
	#      /   \E/
	#     3 --- 2
	#   C/  F    \B
	#   6         5
	
	mygraph node insert 1 2 3 4 5 6 -1
	mygraph arc  insert 4 1 A
	mygraph arc  insert 5 2 B
	mygraph arc  insert 6 3 C
	mygraph arc  insert 3 1 D
	mygraph arc  insert 1 2 E
	mygraph arc  insert 2 3 F
	mygraph arc  insert -1 2 G

	set result [lsort [eval [linsert $nodes 0 mygraph nodes $switch]]]
	mygraph destroy
	lappend result $switch $nodes
	set result
    } $expected ; # {}

    incr n
}
unset n

# ---------------------------------------------------
# Test with many parallel arcs, beyond the number of nodes, i.e. lots
# of duplicated sources and destinations, to check that the dup
# removal works correctly. See bug [SF 1923685].

set n 0
foreach {switch nodes expected} {
    -in        2       1
    -out       2       3
    -adj       2       {1 3}
    -inner     {1 2 3} {1 2 3}
    -embedding 2       {1 3}
} {
    lappend expected $switch $nodes

    test graph-${impl}-${setimpl}-nodes-parallel-ioaie-bug1923685-4.$n "nodes, $switch, parallel arcs, bug 1923685" {
	SETUP

	mygraph node insert 1 2 3 4
	mygraph arc  insert 1 2 A ; mygraph arc  insert 2 3 A.
	mygraph arc  insert 1 2 B ; mygraph arc  insert 2 3 B.
	mygraph arc  insert 1 2 C ; mygraph arc  insert 2 3 C.
	mygraph arc  insert 1 2 D ; mygraph arc  insert 2 3 D.
	mygraph arc  insert 1 2 E ; mygraph arc  insert 2 3 E.
	mygraph arc  insert 1 2 F ; mygraph arc  insert 2 3 F.
	mygraph arc  insert 1 2 G ; mygraph arc  insert 2 3 G.
	mygraph arc  insert 1 2 H ; mygraph arc  insert 2 3 H.

	set result [lsort [eval [linsert $nodes 0 mygraph nodes $switch]]]
	mygraph destroy
	lappend result $switch $nodes
	set result
    } $expected ; # {}

    incr n
}
unset n

# ---------------------------------------------------

Changes to modules/struct/graph1.man.

367
368
369
370
371
372
373
374
375
node appended. For a pre-order walk, all nodes are [const enter]ed, for a
post-order all nodes are left. In a both-order walk the first visit of
a node [const enter]s it, the second visit [const leave]s it.

[list_end]

[vset CATEGORY {struct :: graph}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

367
368
369
370
371
372
373
374
375
node appended. For a pre-order walk, all nodes are [const enter]ed, for a
post-order all nodes are left. In a both-order walk the first visit of
a node [const enter]s it, the second visit [const leave]s it.

[list_end]

[vset CATEGORY {struct :: graph}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/struct/graph_c.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# graphc.tcl --
#
#       Implementation of a graph data structure for Tcl.
#       This code based on critcl, API compatible to the PTI [x].
#       [x] Pure Tcl Implementation.
#
# Copyright (c) 2006 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: graph_c.tcl,v 1.3 2008/03/25 07:15:34 andreas_kupries Exp $

package require critcl
# @sak notprovided struct_graphc
package provide struct_graphc 2.1
package require Tcl 8.2

namespace eval ::struct {
    # Supporting code for the main command.

    catch {
	#critcl::cheaders -g






|



<
<



|







1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
18
19
20
21
# graphc.tcl --
#
#       Implementation of a graph data structure for Tcl.
#       This code based on critcl, API compatible to the PTI [x].
#       [x] Pure Tcl Implementation.
#
# Copyright (c) 2006,2019 Andreas Kupries <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.



package require critcl
# @sak notprovided struct_graphc
package provide struct_graphc 2.4.3
package require Tcl 8.2

namespace eval ::struct {
    # Supporting code for the main command.

    catch {
	#critcl::cheaders -g

Changes to modules/struct/graph_tcl.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# graph_tcl.tcl --
#
#	Implementation of a graph data structure for Tcl.
#
# Copyright (c) 2000-2009 by Andreas Kupries <[email protected]>
# Copyright (c) 2008      by Alejandro Paz <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: graph_tcl.tcl,v 1.5 2009/11/26 04:42:16 andreas_kupries Exp $

package require Tcl 8.4
package require struct::list
package require struct::set

namespace eval ::struct::graph {
    # Data storage in the graph module




|
|



<
<







1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
# graph_tcl.tcl --
#
#	Implementation of a graph data structure for Tcl.
#
# Copyright (c) 2000-2009,2019 by Andreas Kupries <[email protected]>
# Copyright (c) 2008           by Alejandro Paz <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.



package require Tcl 8.4
package require struct::list
package require struct::set

namespace eval ::struct::graph {
    # Data storage in the graph module
316
317
318
319
320
321
322


323






324
325
326
327
328
329
330
#	None.

proc ::struct::graph::__arc_delete {name args} {
    if {![llength $args]} {
	return {wrong # args: should be "::struct::graph::__arc_delete name arc arc..."}
    }



    foreach arc $args {CheckMissingArc $name $arc}







    variable ${name}::inArcs
    variable ${name}::outArcs
    variable ${name}::arcNodes
    variable ${name}::arcAttr
    variable ${name}::arcWeight








>
>
|
>
>
>
>
>
>







314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
#	None.

proc ::struct::graph::__arc_delete {name args} {
    if {![llength $args]} {
	return {wrong # args: should be "::struct::graph::__arc_delete name arc arc..."}
    }

    # seen is used to catch duplicate arcs in the args
    array set seen {}
    foreach arc $args {
	if {[info exists seen($arc)]} {
	    return -code error "arc \"$arc\" does not exist in graph \"$name\""
	}
	CheckMissingArc $name $arc
	set seen($arc) .
    }

    variable ${name}::inArcs
    variable ${name}::outArcs
    variable ${name}::arcNodes
    variable ${name}::arcAttr
    variable ${name}::arcWeight

1676
1677
1678
1679
1680
1681
1682


1683






1684
1685
1686
1687
1688
1689
1690
# Results:
#	None.

proc ::struct::graph::__node_delete {name args} {
    if {![llength $args]} {
	return {wrong # args: should be "::struct::graph::__node_delete name node node..."}
    }


    foreach node $args {CheckMissingNode $name $node}







    variable ${name}::inArcs
    variable ${name}::outArcs
    variable ${name}::nodeAttr

    foreach node $args {
	# Remove all the arcs connected to this node







>
>
|
>
>
>
>
>
>







1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
# Results:
#	None.

proc ::struct::graph::__node_delete {name args} {
    if {![llength $args]} {
	return {wrong # args: should be "::struct::graph::__node_delete name node node..."}
    }
    # seen is used to catch duplicate nodes in the args
    array set seen {}
    foreach node $args {
	if {[info exists seen($node)]} {
	    return -code error "node \"$node\" does not exist in graph \"$name\""
	}
	CheckMissingNode $name $node
	set seen($node) .
    }

    variable ${name}::inArcs
    variable ${name}::outArcs
    variable ${name}::nodeAttr

    foreach node $args {
	# Remove all the arcs connected to this node
1843
1844
1845
1846
1847
1848
1849


1850






1851
1852
1853
1854
1855
1856
1857
#	node		The name of the new node.

proc ::struct::graph::__node_insert {name args} {
    if {[llength $args] == 0} {
	# No node name was given; generate a unique one
	set args [list [__generateUniqueNodeName $name]]
    } else {


	foreach node $args {CheckDuplicateNode $name $node}






    }
    
    variable ${name}::inArcs
    variable ${name}::outArcs

    foreach node $args {
	# Set up the new node







>
>
|
>
>
>
>
>
>







1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
#	node		The name of the new node.

proc ::struct::graph::__node_insert {name args} {
    if {[llength $args] == 0} {
	# No node name was given; generate a unique one
	set args [list [__generateUniqueNodeName $name]]
    } else {
	# seen is used to catch duplicate nodes in the args
	array set seen {}
	foreach node $args {
	    if {[info exists seen($node)]} {
		return -code error "node \"$node\" already exists in graph \"$name\""
	    }
	    CheckDuplicateNode $name $node
	    set seen($node) .
	}
    }
    
    variable ${name}::inArcs
    variable ${name}::outArcs

    foreach node $args {
	# Set up the new node
2997
2998
2999
3000
3001
3002
3003

3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020

3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032

3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044

3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056

3057
3058



3059
3060

3061
3062
3063
3064
3065
3066
3067
    upvar 1 value      value      ; set value      {}
    upvar 1 haveFilter haveFilter ; set haveFilter 0
    upvar 1 fcmd       fcmd       ; set fcmd       {}
    upvar 1 cond       cond       ; set cond       "none"
    upvar 1 condNodes  condNodes  ; set condNodes  {}

    set wa_usage "wrong # args: should be \"$name $what ?-key key? ?-value value? ?-filter cmd? ?-in|-out|-adj|-inner|-embedding node node...?\""


    for {set i 0} {$i < [llength $arguments]} {incr i} {
	set arg [lindex $arguments $i]
	switch -glob -- $arg {
	    -in -
	    -out -
	    -adj -
	    -inner -
	    -embedding {
		if {$haveCond} {
		    return -code error "invalid restriction:\
			    illegal multiple use of\
			    \"-in\"|\"-out\"|\"-adj\"|\"-inner\"|\"-embedding\""
		}

		set haveCond 1
		set cond [string range $arg 1 end]

	    }
	    -key {
		if {($i + 1) == [llength $arguments]} {
		    return -code error $wa_usage
		}
		if {$haveKey} {
		    return -code error {invalid restriction: illegal multiple use of "-key"}
		}

		incr i
		set key [lindex $arguments $i]
		set haveKey 1

	    }
	    -value {
		if {($i + 1) == [llength $arguments]} {
		    return -code error $wa_usage
		}
		if {$haveValue} {
		    return -code error {invalid restriction: illegal multiple use of "-value"}
		}

		incr i
		set value [lindex $arguments $i]
		set haveValue 1

	    }
	    -filter {
		if {($i + 1) == [llength $arguments]} {
		    return -code error $wa_usage
		}
		if {$haveFilter} {
		    return -code error {invalid restriction: illegal multiple use of "-filter"}
		}

		incr i
		set fcmd [lindex $arguments $i]
		set haveFilter 1

	    }
	    -* {



		return -code error "bad restriction \"$arg\": must be -adj, -embedding,\
			-filter, -in, -inner, -key, -out, or -value"

	    }
	    default {
		lappend condNodes $arg
	    }
	}
    }








>
|
















>












>












>












>


>
>
>
|

>







3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
    upvar 1 value      value      ; set value      {}
    upvar 1 haveFilter haveFilter ; set haveFilter 0
    upvar 1 fcmd       fcmd       ; set fcmd       {}
    upvar 1 cond       cond       ; set cond       "none"
    upvar 1 condNodes  condNodes  ; set condNodes  {}

    set wa_usage "wrong # args: should be \"$name $what ?-key key? ?-value value? ?-filter cmd? ?-in|-out|-adj|-inner|-embedding node node...?\""
    set seenodes 0
    
    for {set i 0} {$i < [llength $arguments]} {incr i} {
	set arg [lindex $arguments $i]
	switch -glob -- $arg {
	    -in -
	    -out -
	    -adj -
	    -inner -
	    -embedding {
		if {$haveCond} {
		    return -code error "invalid restriction:\
			    illegal multiple use of\
			    \"-in\"|\"-out\"|\"-adj\"|\"-inner\"|\"-embedding\""
		}

		set haveCond 1
		set cond [string range $arg 1 end]
		set seenodes 1
	    }
	    -key {
		if {($i + 1) == [llength $arguments]} {
		    return -code error $wa_usage
		}
		if {$haveKey} {
		    return -code error {invalid restriction: illegal multiple use of "-key"}
		}

		incr i
		set key [lindex $arguments $i]
		set haveKey 1
		set seenodes 0
	    }
	    -value {
		if {($i + 1) == [llength $arguments]} {
		    return -code error $wa_usage
		}
		if {$haveValue} {
		    return -code error {invalid restriction: illegal multiple use of "-value"}
		}

		incr i
		set value [lindex $arguments $i]
		set haveValue 1
		set seenodes 0
	    }
	    -filter {
		if {($i + 1) == [llength $arguments]} {
		    return -code error $wa_usage
		}
		if {$haveFilter} {
		    return -code error {invalid restriction: illegal multiple use of "-filter"}
		}

		incr i
		set fcmd [lindex $arguments $i]
		set haveFilter 1
		set seenodes 0
	    }
	    -* {
		if {$seenodes} {
		    lappend condNodes $arg
		} else {
		    return -code error "bad restriction \"$arg\": must be -adj, -embedding,\
			-filter, -in, -inner, -key, -out, or -value"
		}
	    }
	    default {
		lappend condNodes $arg
	    }
	}
    }

Changes to modules/struct/graphops.man.

1311
1312
1313
1314
1315
1316
1317
1318
1319
[enum] [uri http://www.csc.kth.se/~viggo/wwwcompendium/node128.html {K-Center problem}]
[enum] [uri http://en.wikipedia.org/wiki/Breadth-first_search {BFS}]
[enum] [uri http://en.wikipedia.org/wiki/Degree-constrained_spanning_tree {Minimum Degree Spanning Tree}]
[enum] [uri http://en.wikipedia.org/wiki/Approximation_algorithm {Approximation algorithm}]
[list_end]

[vset CATEGORY {struct :: graph}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

1311
1312
1313
1314
1315
1316
1317
1318
1319
[enum] [uri http://www.csc.kth.se/~viggo/wwwcompendium/node128.html {K-Center problem}]
[enum] [uri http://en.wikipedia.org/wiki/Breadth-first_search {BFS}]
[enum] [uri http://en.wikipedia.org/wiki/Degree-constrained_spanning_tree {Minimum Degree Spanning Tree}]
[enum] [uri http://en.wikipedia.org/wiki/Approximation_algorithm {Approximation algorithm}]
[list_end]

[vset CATEGORY {struct :: graph}]
[include ../common-text/feedback.inc]
[manpage_end]

Added modules/struct/map.tcl.

















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# map.tcl --
# Copyright (c) 2009-2019 Andreas Kupries <[email protected]>
#
# Object wrapper around array/dict. Useful as key/value store in
# larger systems.
#
# Examples:
# - configuration mgmt in doctools v2 import/export managers
# - pt import/export managers
#
# Each object manages a key/value map.

# ### ### ### ######### ######### #########
## Requisites

package require Tcl 8.4
package require snit

# ### ### ### ######### ######### #########
## API

# ATTENTION:
##
# From an API point of view the code below is equivalent to the much
# shorter `snit::type struct::map { ... }`.
#
# Then why the more complex form ?
#
# When snit compiles the class to Tcl code, and later on when methods
# are executed it will happen in the `struct` namespace. The moment
# this package is used together with `struct::set` all unqualified
# `set` statements will go bonkers, eiter in snit, or, here, in method
# `set`, because they get resolved to the `struct::set` dispatcher
# instead of `::set`. Moving the implementation a level deeper makes
# the `struct::map` namespace the context, with no conflict.

# Future / TODO: Convert all the OO stuff here over to TclOO, as much
# as possible (snit configure/cget support is currently still better,
# ditto hierarchical methods).

namespace eval ::struct {}

proc ::struct::map {args} {
    uplevel 1 [linsert $args 0 struct::map::I]
}

snit::type ::struct::map::I {

    # ### ### ### ######### ######### #########
    ## Options :: None

    # ### ### ### ######### ######### #########
    ## Creating, destruction

    # Default constructor.
    # Default destructor.

    # ### ### ### ######### ######### #########
    ## Public methods. Reading and writing the map.

    method names {} {
	return [array names mymap]
    }

    method get {} {
	return [array get mymap]
    }

    method set {name {value {}}} {
	# 7 instead of 3 in the condition below, because of the 4
	# implicit arguments snit is providing to each method.
	if {[llength [info level 0]] == 7} {
	    ::set mymap($name) $value
	} elseif {![info exists mymap($name)]} {
	    return -code error "can't read \"$name\": no such variable"
	}
	return $mymap($name)
    }

    method unset {args} {
	if {![llength $args]} { lappend args * }
	foreach pattern $args {
	    array unset mymap $pattern
	}
	return
    }

    # ### ### ### ######### ######### #########
    ## Internal methods :: None.

    # ### ### ### ######### ######### #########
    ## State :: Map data, Tcl array

    variable mymap -array {}

    ##
    # ### ### ### ######### ######### #########
}

# ### ### ### ######### ######### #########
## Ready

package provide struct::map 1
return

Added modules/struct/map.test.































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# -*- tcl -*-
# map.test:  Testsuite for package struct::map
#
# Copyright (c) 2019 by Andreas Kupries <[email protected]>
# All rights reserved.

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.4
testsNeedTcltest 2.0

support {
    use       snit/snit.tcl   snit
}
testing {
    useLocal map.tcl struct::map
}

# ---------------------------------------------------------------------
# [] constructor
# [] destructor
# [] get
# [] names
# [] set
# [] unset

#----------------------------------------------------------------------
## Constructor, destructor

test struct-map-1.0 {constructor, wrong args, too many} -body {
    struct::map M X
} -returnCodes error -result {Error in constructor: wrong # args: should be "::struct::map::I::Snit_constructor type selfns win self"}

test struct-map-1.1 {instance, bogus method} -setup {
    struct::map M
} -cleanup {
    M destroy
} -body {
    M bogus
} -returnCodes error -result {"::M bogus" is not defined}

#----------------------------------------------------------------------
## get

test struct-map-2.0 {get, wrong args, too many} -setup {
    struct::map M
} -cleanup {
    M destroy
} -body {
    M get X
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodget type selfns win self"}

test struct-map-2.1 {get, base state, none} -setup {
    struct::map M
} -cleanup {
    M destroy
} -body {
    M get
} -result {}

#----------------------------------------------------------------------
## names

test struct-map-3.0 {names, wrong args, too many} -setup {
    struct::map M
} -cleanup {
    M destroy
} -body {
    M names X
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodnames type selfns win self"}

test struct-map-3.1 {names, base state, none} -setup {
    struct::map M
} -cleanup {
    M destroy
} -body {
    M names
} -result {}

#----------------------------------------------------------------------
## set

test struct-map-4.0 {set, wrong args, not enough} -setup {
    struct::map M
} -cleanup {
    M destroy
} -body {
    M set
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

test struct-map-4.1 {set, wrong args, too many} -setup {
    struct::map M
} -cleanup {
    M destroy
} -body {
    M set K V X
} -returnCodes error -result {wrong # args: should be "::struct::map::I::Snit_methodset type selfns win self name ?value?"}

test struct-map-4.2 {set, state change, result} -setup {
    struct::map M
} -cleanup {
    M destroy
} -body {
    list [M names] [M get] [M set K V] [M names] [M get]
} -result {{} {} V K {K V}}

#----------------------------------------------------------------------
## unset

test struct-map-5.2 {unset, known key, state change, result} -setup {
    struct::map M
    M set K V
} -cleanup {
    M destroy
} -body {
    list [M names] [M get] [M unset K] [M names] [M get]
} -result {K {K V} {} {} {}}

test struct-map-5.3 {unset, missing key, no state change, result} -setup {
    struct::map M
    M set K V
} -cleanup {
    M destroy
} -body {
    list [M names] [M get] [M unset K'] [M names] [M get]
} -result {K {K V} {} K {K V}}

test struct-map-5.4 {unset, no pattern, clear, result} -setup {
    struct::map M
    M set K V
} -cleanup {
    M destroy
} -body {
    list [M names] [M get] [M unset] [M names] [M get]
} -result {K {K V} {} {} {}}

#----------------------------------------------------------------------
testsuiteCleanup
return

Changes to modules/struct/matrix.man.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

[comment {-*- tcl -*-}]
[manpage_begin struct::matrix n 2.0.3]
[keywords matrix]
[copyright {2002-2013 Andreas Kupries <[email protected]>}]
[moddesc   {Tcl Data Structures}]
[titledesc {Create and manipulate matrix objects}]
[category  {Data structures}]
[require Tcl 8.2]
[require struct::matrix [opt 2.0.3]]
[description]
[para]

A matrix is a rectangular collection of cells, i.e. organized in rows
and columns. Each cell contains exactly one value of arbitrary
form. The cells in the matrix are addressed by pairs of integer
numbers, with the first (left) number in the pair specifying the
>

|

|




|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[vset VERSION 2.0.4]
[comment {-*- tcl -*-}]
[manpage_begin struct::matrix n [vset VERSION]]
[keywords matrix]
[copyright {2002-2013,2019 Andreas Kupries <[email protected]>}]
[moddesc   {Tcl Data Structures}]
[titledesc {Create and manipulate matrix objects}]
[category  {Data structures}]
[require Tcl 8.2]
[require struct::matrix [opt [vset VERSION]]]
[description]
[para]

A matrix is a rectangular collection of cells, i.e. organized in rows
and columns. Each cell contains exactly one value of arbitrary
form. The cells in the matrix are addressed by pairs of integer
numbers, with the first (left) number in the pair specifying the
531
532
533
534
535
536
537
538
539
    +---+-------------------+-------+-------+--------+
    %
    % # alternate way of doing the above
    % r printmatrix m
}]

[vset CATEGORY {struct :: matrix}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

532
533
534
535
536
537
538
539
540
    +---+-------------------+-------+-------+--------+
    %
    % # alternate way of doing the above
    % r printmatrix m
}]

[vset CATEGORY {struct :: matrix}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/struct/matrix.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# matrix.tcl --
#
#	Implementation of a matrix data structure for Tcl.
#
# Copyright (c) 2001-2013 by Andreas Kupries <[email protected]>
#
# Heapsort code Copyright (c) 2003 by Edwin A. Suominen <[email protected]>,
# based on concepts in "Introduction to Algorithms" by Thomas H. Cormen et al.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: matrix.tcl,v 1.23 2008/02/20 00:39:39 andreas_kupries Exp $

package require Tcl 8.2

namespace eval ::struct {}

namespace eval ::struct::matrix {
    # Data storage in the matrix module




|






<
<







1
2
3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18
# matrix.tcl --
#
#	Implementation of a matrix data structure for Tcl.
#
# Copyright (c) 2001-2013,2019 by Andreas Kupries <[email protected]>
#
# Heapsort code Copyright (c) 2003 by Edwin A. Suominen <[email protected]>,
# based on concepts in "Introduction to Algorithms" by Thomas H. Cormen et al.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.



package require Tcl 8.2

namespace eval ::struct {}

namespace eval ::struct::matrix {
    # Data storage in the matrix module
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
# Results:
#	None.

proc ::struct::matrix::__format_2chan {name {report {}} {chan stdout}} {
    if {$report == {}} {
	# Use an internal hardwired simple report to format the matrix.
	# We delegate this to the string formatter and print its result.
	puts -nonewline [__format_2string $name]
    } else {
	$report printmatrix2channel $name $chan
    }
    return
}

# ::struct::matrix::__get_cell --







|







1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
# Results:
#	None.

proc ::struct::matrix::__format_2chan {name {report {}} {chan stdout}} {
    if {$report == {}} {
	# Use an internal hardwired simple report to format the matrix.
	# We delegate this to the string formatter and print its result.
	puts -nonewline $chan [__format_2string $name]
    } else {
	$report printmatrix2channel $name $chan
    }
    return
}

# ::struct::matrix::__get_cell --
2785
2786
2787
2788
2789
2790
2791
2792
## Ready

namespace eval ::struct {
    # Get 'matrix::matrix' into the general structure namespace.
    namespace import -force matrix::matrix
    namespace export matrix
}
package provide struct::matrix 2.0.3







|
2783
2784
2785
2786
2787
2788
2789
2790
## Ready

namespace eval ::struct {
    # Get 'matrix::matrix' into the general structure namespace.
    namespace import -force matrix::matrix
    namespace export matrix
}
package provide struct::matrix 2.0.4

Changes to modules/struct/matrix.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22












23
24
25
26
27
28
29
# -*- tcl -*-
# matrix.test:  tests for the matrix structure.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2001 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: matrix.test,v 1.21 2006/10/09 21:41:42 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.2
testsNeedTcltest 1.0


support {












    useLocalFile matrix.testsupport
}
testing {
    useLocal matrix.tcl struct::matrix
}

# -------------------------------------------------------------------------







|

<
<







|
|
>


>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# -*- tcl -*-
# matrix.test:  tests for the matrix structure.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2001, 2019 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2.0
testsNeed        TclOO 1

support {
    # memchan allows proper testing of `format 2chan` method.
    # Note, somebody may have imported these already.
    if {![llength [info commands ::tcl::chan::core]]} {
	use virtchannel_core/core.tcl tcl::chan::core
    }
    if {![llength [info commands ::tcl::chan::events]]} {
	use virtchannel_core/events.tcl  tcl::chan::events
    }
    if {![llength [info commands ::tcl::chan::memchan]]} {
	use virtchannel_base/memchan.tcl tcl::chan::memchan
    }

    useLocalFile matrix.testsupport
}
testing {
    useLocal matrix.tcl struct::matrix
}

# -------------------------------------------------------------------------
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
test matrix-5.0 {format error} {
    matrix mymatrix
    catch {mymatrix format} msg
    mymatrix destroy
    set msg
} {wrong # args: should be "::mymatrix format option ?arg arg ...?"}

test matrix-5.1 {formatting} {
    matrix mymatrix
    mymatrix add column
    mymatrix add row {1}
    mymatrix add column {2}
    mymatrix add row {3 4}
    mymatrix add column {5 6}
    mymatrix add row {7 8 9}







|







619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
test matrix-5.0 {format error} {
    matrix mymatrix
    catch {mymatrix format} msg
    mymatrix destroy
    set msg
} {wrong # args: should be "::mymatrix format option ?arg arg ...?"}

test matrix-5.1 {formatting, 2 string, by report} {
    matrix mymatrix
    mymatrix add column
    mymatrix add row {1}
    mymatrix add column {2}
    mymatrix add row {3 4}
    mymatrix add column {5 6}
    mymatrix add row {7 8 9}
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
    mymatrix add column {5 6}
    mymatrix add row [list 7 8 "9\nb"]
    set result [mymatrix format 2string]
    mymatrix destroy
    set result
} "1  2 5\n3a 4 6\n7  8 9\n     b"









if {![catch {package require memchan}]} {



    # We have memory channels and can therefore test










    # 'format2channel-via' too.















    test matrix-5.4 {formatting} {
	matrix mymatrix
	mymatrix add column
	mymatrix add row {1}
	mymatrix add column {2}
	mymatrix add row {3 4}
	mymatrix add column {5 6}
	mymatrix add row {7 8 9}

	set chan [memchan]
	mymatrix format 2chan tclformat $chan
	mymatrix destroy

	seek $chan 0
	set result [read $chan]
	close $chan
	set result
    } "# mymatrix 3 x 3
matrix mymatrix
mymatrix add rows    3
mymatrix add columns 3
mymatrix set rect 0 0 {{1 2 5} {3 4 6} {7 8 9}}"
}

test matrix-6.0 {set/get error} {
    matrix mymatrix
    catch {mymatrix set} msga
    catch {mymatrix get} msgb
    mymatrix destroy
    list $msga $msgb







>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
|
|
|
|
|
|
|

|
|
|

|
|
|
|
|
|
<
<
|
<







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
    mymatrix add column {5 6}
    mymatrix add row [list 7 8 "9\nb"]
    set result [mymatrix format 2string]
    mymatrix destroy
    set result
} "1  2 5\n3a 4 6\n7  8 9\n     b"

test matrix-5.4 {formatting 2 channel, by report} {
    matrix mymatrix
    mymatrix add column
    mymatrix add row {1}
    mymatrix add column {2}
    mymatrix add row {3 4}
    mymatrix add column {5 6}
    mymatrix add row {7 8 9}

    set chan [tcl::chan::memchan]
    mymatrix format 2chan tclformat $chan
    mymatrix destroy

    seek $chan 0
    set result [read $chan]
    close $chan
    set result
} "# ::mymatrix 3 x 3
matrix ::mymatrix
::mymatrix add rows    3
::mymatrix add columns 3
::mymatrix set rect 0 0 {{1 2 5} {3 4 6} {7 8 9}}
"

test matrix-5.5 {formatting, 2 string, no report} {
    matrix mymatrix
    mymatrix add column
    mymatrix add row {1}
    mymatrix add column {2}
    mymatrix add row {3 4}
    mymatrix add column {5 6}
    mymatrix add row {7 8 9}
    set result [mymatrix format 2string]
    mymatrix destroy
    set result
} "1 2 5
3 4 6
7 8 9"

test matrix-5.6 {formatting 2 channel, no report} {
    matrix mymatrix
    mymatrix add column
    mymatrix add row {1}
    mymatrix add column {2}
    mymatrix add row {3 4}
    mymatrix add column {5 6}
    mymatrix add row {7 8 9}

    set chan [tcl::chan::memchan]
    mymatrix format 2chan {} $chan
    mymatrix destroy

    seek $chan 0
    set result [read $chan]
    close $chan
    set result
} "1 2 5
3 4 6


7 8 9"


test matrix-6.0 {set/get error} {
    matrix mymatrix
    catch {mymatrix set} msga
    catch {mymatrix get} msgb
    mymatrix destroy
    list $msga $msgb

Changes to modules/struct/matrix1.man.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

[comment {-*- tcl -*-}]
[manpage_begin {struct::matrix_v1} n 1.2.1]
[keywords matrix]
[copyright {2002 Andreas Kupries <[email protected]>}]
[moddesc   {Tcl Data Structures}]
[titledesc {Create and manipulate matrix objects}]
[category  {Data structures}]
[require Tcl 8.2]
[require struct::matrix [opt 1.2.1]]
[description]
[para]

The [cmd ::struct::matrix] command creates a new matrix object with an
associated global Tcl command whose name is [arg matrixName].  This
command may be used to invoke various operations on the matrix.  It has
the following general form:
>

|

|




|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[vset VERSION 1.2.2]
[comment {-*- tcl -*-}]
[manpage_begin {struct::matrix_v1} n [vset VERSION]]
[keywords matrix]
[copyright {2002,2019 Andreas Kupries <[email protected]>}]
[moddesc   {Tcl Data Structures}]
[titledesc {Create and manipulate matrix objects}]
[category  {Data structures}]
[require Tcl 8.2]
[require struct::matrix [opt [vset VERSION]]]
[description]
[para]

The [cmd ::struct::matrix] command creates a new matrix object with an
associated global Tcl command whose name is [arg matrixName].  This
command may be used to invoke various operations on the matrix.  It has
the following general form:
373
374
375
376
377
378
379
380
381
    +---+-------------------+-------+-------+--------+
    %
    % # alternate way of doing the above
    % r printmatrix m
}]

[vset CATEGORY {struct :: matrix}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

374
375
376
377
378
379
380
381
382
    +---+-------------------+-------+-------+--------+
    %
    % # alternate way of doing the above
    % r printmatrix m
}]

[vset CATEGORY {struct :: matrix}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/struct/matrix1.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# matrix.tcl --
#
#	Implementation of a matrix data structure for Tcl.
#
# Copyright (c) 2001 by Andreas Kupries <[email protected]>
#
# Heapsort code Copyright (c) 2003 by Edwin A. Suominen <[email protected]>,
# based on concepts in "Introduction to Algorithms" by Thomas H. Cormen et al.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# 
# RCS: @(#) $Id: matrix1.tcl,v 1.3 2005/09/28 04:51:24 andreas_kupries Exp $

package require Tcl 8.2

namespace eval ::struct {}

namespace eval ::struct::matrix {
    # Data storage in the matrix module




|






<
<







1
2
3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18
# matrix.tcl --
#
#	Implementation of a matrix data structure for Tcl.
#
# Copyright (c) 2001,2019 by Andreas Kupries <[email protected]>
#
# Heapsort code Copyright (c) 2003 by Edwin A. Suominen <[email protected]>,
# based on concepts in "Introduction to Algorithms" by Thomas H. Cormen et al.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.



package require Tcl 8.2

namespace eval ::struct {}

namespace eval ::struct::matrix {
    # Data storage in the matrix module
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
# Results:
#	None.

proc ::struct::matrix::__format_2chan {name {report {}} {chan stdout}} {
    if {$report == {}} {
	# Use an internal hardwired simple report to format the matrix.
	# We delegate this to the string formatter and print its result.
	puts -nonewline [__format_2string $name]
    } else {
	$report printmatrix2channel $name $chan
    }
    return
}

# ::struct::matrix::__get_cell --







|







1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
# Results:
#	None.

proc ::struct::matrix::__format_2chan {name {report {}} {chan stdout}} {
    if {$report == {}} {
	# Use an internal hardwired simple report to format the matrix.
	# We delegate this to the string formatter and print its result.
	puts -nonewline $chan [__format_2string $name]
    } else {
	$report printmatrix2channel $name $chan
    }
    return
}

# ::struct::matrix::__get_cell --
2280
2281
2282
2283
2284
2285
2286
2287
## Ready

namespace eval ::struct {
    # Get 'matrix::matrix' into the general structure namespace.
    namespace import -force matrix::matrix
    namespace export matrix
}
package provide struct::matrix 1.2.1







|
2278
2279
2280
2281
2282
2283
2284
2285
## Ready

namespace eval ::struct {
    # Get 'matrix::matrix' into the general structure namespace.
    namespace import -force matrix::matrix
    namespace export matrix
}
package provide struct::matrix 1.2.2

Changes to modules/struct/matrix1.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22












23
24
25
26
27
28
29
# -*- tcl -*-
# matrix.test:  tests for the matrix structure.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2001 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# RCS: @(#) $Id: matrix1.test,v 1.8 2006/10/09 21:41:42 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.2
testsNeedTcltest 1.0


support {












    useLocalFile matrix.testsupport
}
testing {
    useLocal matrix1.tcl struct::matrix
}

# -------------------------------------------------------------------------









<
<







|
|
>


>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# -*- tcl -*-
# matrix.test:  tests for the matrix structure.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2001 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2.0
testsNeed        TclOO 1

support {
    # memchan allows proper testing of `format 2chan` method.
    # Note, matrix.test may have imported these already.
    if {![llength [info commands ::tcl::chan::core]]} {
	use virtchannel_core/core.tcl tcl::chan::core
    }
    if {![llength [info commands ::tcl::chan::events]]} {
	use virtchannel_core/events.tcl  tcl::chan::events
    }
    if {![llength [info commands ::tcl::chan::memchan]]} {
	use virtchannel_base/memchan.tcl tcl::chan::memchan
    }

    useLocalFile matrix.testsupport
}
testing {
    useLocal matrix1.tcl struct::matrix
}

# -------------------------------------------------------------------------
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
    mymatrix add column {5 6}
    mymatrix add row [list 7 8 "9\nb"]
    set result [mymatrix format 2string]
    mymatrix destroy
    set result
} "1  2 5\n3a 4 6\n7  8 9\n     b"

if {![catch {package require memchan}]} {
    # We have memory channels and can therefore test
    # 'format2channel-via' too.

    test matrix1-5.4 {formatting} {
	matrix mymatrix
	mymatrix add column
	mymatrix add row {1}
	mymatrix add column {2}
	mymatrix add row {3 4}
	mymatrix add column {5 6}
	mymatrix add row {7 8 9}

	set chan [memchan]
	mymatrix format 2chan tclformat $chan
	mymatrix destroy

	seek $chan 0
	set result [read $chan]
	close $chan
	set result
    } "# mymatrix 3 x 3
matrix mymatrix
mymatrix add rows    3
mymatrix add columns 3
mymatrix set rect 0 0 {{1 2 5} {3 4 6} {7 8 9}}"

}




































test matrix1-6.0 {set/get error} {
    matrix mymatrix
    catch {mymatrix set} msga
    catch {mymatrix get} msgb
    mymatrix destroy
    list $msga $msgb







<
<
<
<
|
|
|
|
|
|
|
|

|
|
|

|
|
|
|
|
|
|
|
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    mymatrix add column {5 6}
    mymatrix add row [list 7 8 "9\nb"]
    set result [mymatrix format 2string]
    mymatrix destroy
    set result
} "1  2 5\n3a 4 6\n7  8 9\n     b"





test matrix1-5.4 {formatting} {
    matrix mymatrix
    mymatrix add column
    mymatrix add row {1}
    mymatrix add column {2}
    mymatrix add row {3 4}
    mymatrix add column {5 6}
    mymatrix add row {7 8 9}

    set chan [tcl::chan::memchan]
    mymatrix format 2chan tclformat $chan
    mymatrix destroy

    seek $chan 0
    set result [read $chan]
    close $chan
    set result
} "# ::mymatrix 3 x 3
matrix ::mymatrix
::mymatrix add rows    3
::mymatrix add columns 3
::mymatrix set rect 0 0 {{1 2 5} {3 4 6} {7 8 9}}
"

test matrix-5.5 {formatting, 2 string, no report} {
    matrix mymatrix
    mymatrix add column
    mymatrix add row {1}
    mymatrix add column {2}
    mymatrix add row {3 4}
    mymatrix add column {5 6}
    mymatrix add row {7 8 9}
    set result [mymatrix format 2string]
    mymatrix destroy
    set result
} "1 2 5
3 4 6
7 8 9"

test matrix-5.6 {formatting 2 channel, no report} {
    matrix mymatrix
    mymatrix add column
    mymatrix add row {1}
    mymatrix add column {2}
    mymatrix add row {3 4}
    mymatrix add column {5 6}
    mymatrix add row {7 8 9}

    set chan [tcl::chan::memchan]
    mymatrix format 2chan {} $chan
    mymatrix destroy

    seek $chan 0
    set result [read $chan]
    close $chan
    set result
} "1 2 5
3 4 6
7 8 9"

test matrix1-6.0 {set/get error} {
    matrix mymatrix
    catch {mymatrix set} msga
    catch {mymatrix get} msgb
    mymatrix destroy
    list $msga $msgb

Changes to modules/struct/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded struct            2.1   [list source [file join $dir struct.tcl]]
package ifneeded struct            1.4   [list source [file join $dir struct1.tcl]]

package ifneeded struct::queue     1.4.5 [list source [file join $dir queue.tcl]]
package ifneeded struct::stack     1.5.3 [list source [file join $dir stack.tcl]]
package ifneeded struct::tree      2.1.2 [list source [file join $dir tree.tcl]]
package ifneeded struct::matrix    2.0.3 [list source [file join $dir matrix.tcl]]
package ifneeded struct::pool      1.2.3 [list source [file join $dir pool.tcl]]
package ifneeded struct::record    1.2.1 [list source [file join $dir record.tcl]]
package ifneeded struct::set       2.2.3 [list source [file join $dir sets.tcl]]
package ifneeded struct::prioqueue 1.4   [list source [file join $dir prioqueue.tcl]]
package ifneeded struct::skiplist  1.3   [list source [file join $dir skiplist.tcl]]

package ifneeded struct::graph     1.2.1 [list source [file join $dir graph1.tcl]]
package ifneeded struct::tree      1.2.2 [list source [file join $dir tree1.tcl]]
package ifneeded struct::matrix    1.2.1 [list source [file join $dir matrix1.tcl]]

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded struct::list      1.8.4  [list source [file join $dir list.tcl]]
package ifneeded struct::graph     2.4.1  [list source [file join $dir graph.tcl]]


if {![package vsatisfies [package provide Tcl] 8.5]} {return}

if {![package vsatisfies [package provide Tcl] 8.6]} {return}
package ifneeded struct::disjointset 1.1 [list source [file join $dir disjointset.tcl]]
package ifneeded struct::graph::op 0.11.3 [list source [file join $dir graphops.tcl]]







|

|






|



|
>






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
if {![package vsatisfies [package provide Tcl] 8.2]} {return}
package ifneeded struct            2.1   [list source [file join $dir struct.tcl]]
package ifneeded struct            1.4   [list source [file join $dir struct1.tcl]]

package ifneeded struct::queue     1.4.5 [list source [file join $dir queue.tcl]]
package ifneeded struct::stack     1.5.3 [list source [file join $dir stack.tcl]]
package ifneeded struct::tree      2.1.2 [list source [file join $dir tree.tcl]]
package ifneeded struct::matrix    2.0.4 [list source [file join $dir matrix.tcl]]
package ifneeded struct::pool      1.2.3 [list source [file join $dir pool.tcl]]
package ifneeded struct::record    1.2.2 [list source [file join $dir record.tcl]]
package ifneeded struct::set       2.2.3 [list source [file join $dir sets.tcl]]
package ifneeded struct::prioqueue 1.4   [list source [file join $dir prioqueue.tcl]]
package ifneeded struct::skiplist  1.3   [list source [file join $dir skiplist.tcl]]

package ifneeded struct::graph     1.2.1 [list source [file join $dir graph1.tcl]]
package ifneeded struct::tree      1.2.2 [list source [file join $dir tree1.tcl]]
package ifneeded struct::matrix    1.2.2 [list source [file join $dir matrix1.tcl]]

if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded struct::list      1.8.4  [list source [file join $dir list.tcl]]
package ifneeded struct::graph     2.4.3  [list source [file join $dir graph.tcl]]
package ifneeded struct::map       1      [list source [file join $dir map.tcl]]

if {![package vsatisfies [package provide Tcl] 8.5]} {return}

if {![package vsatisfies [package provide Tcl] 8.6]} {return}
package ifneeded struct::disjointset 1.1 [list source [file join $dir disjointset.tcl]]
package ifneeded struct::graph::op 0.11.3 [list source [file join $dir graphops.tcl]]

Changes to modules/struct/pool.man.

435
436
437
438
439
440
441
442
443
         # all connections are currently occupied
         # store the client request in a queue for later processing,
         # or return a 'Server busy' message to the client.
     }
}]

[vset CATEGORY {struct :: pool}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

435
436
437
438
439
440
441
442
443
         # all connections are currently occupied
         # store the client request in a queue for later processing,
         # or return a 'Server busy' message to the client.
     }
}]

[vset CATEGORY {struct :: pool}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/struct/prioqueue.man.

103
104
105
106
107
108
109
110
111
[call [arg prioqueueName] [cmd size]]

Return the number of items in the prioqueue.

[list_end]

[vset CATEGORY {struct :: prioqueue}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

103
104
105
106
107
108
109
110
111
[call [arg prioqueueName] [cmd size]]

Return the number of items in the prioqueue.

[list_end]

[vset CATEGORY {struct :: prioqueue}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/struct/queue.man.

88
89
90
91
92
93
94
95
96
[call [arg queueName] [cmd size]]

Return the number of items in the queue.

[list_end]

[vset CATEGORY {struct :: queue}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

88
89
90
91
92
93
94
95
96
[call [arg queueName] [cmd size]]

Return the number of items in the queue.

[list_end]

[vset CATEGORY {struct :: queue}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/struct/record.man.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15

16
17
18
19
20
21

22
23
24
25
26
27

28
29
30
31

32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
[comment {-*- tcl -*-}]

[manpage_begin struct::record n 1.2.1]
[keywords {data structures}]
[keywords record]
[keywords struct]
[copyright {2002, Brett Schwarz <[email protected]>}]
[moddesc   {Tcl Data Structures}]
[titledesc {Define and create records (similar to 'C' structures)}]
[category  {Data structures}]
[require Tcl 8.2]
[require struct::record [opt 1.2.1]]
[description]

The [cmd ::struct::record] package provides a mechanism to group variables together
as one data structure, similar to a 'C' structure. The members of a

record can be variables or other records. However, a record can not contain circular
record, i.e. records that contain the same record as a
member.

[para]
This package was structured so that it is very similar to how Tk objects work. Each record

definition creates a record object that encompasses that definition. Subsequently, that
record object can create instances of that record. These instances can then
be manipulated with the [method cget] and [method configure] methods.

[para]
The package only contains one top level command, but several sub commands (see below). It also obeys the namespace in which the record was define, hence the objects returned are fully qualified.


[list_begin definitions]

[call [cmd {record define}] [arg recordName] [arg recordMembers] [opt [arg "instanceName1 instanceName2 ..."]]]


Defines a record. [arg recordName] is the name of the record, and is also
used as an object command. This object command is used to create instances of the
record definition. [arg recordMembers] are the members of
the record that make up the record definition. These are variables
and other record. If optional [arg instanceName] args are given, then an instance

is generated after the definition is created for each [arg instanceName].

[call [cmd {record show}] [arg record]]

Returns a list of records that have been defined.

[call [cmd {record show}] [arg instances] [arg recordName]]

Returns the instances that have been instantiated by
[arg recordName].

[call [cmd {record show}] [arg members] [arg recordName]]

Returns the members that are defined for
record [arg recordName]. It returns the same format as how the
records were defined.

[call [cmd {record show}] [arg values] [arg instanceName]]

Returns a list of values that are set for the instance
[arg instanceName]. The output is a list of key/value pairs. If there
are nested records, then the values of the nested records will
itself be a list.

[call [cmd {record exists}] [arg record] [arg recordName]]

Tests for the existence of a [arg record] with the
name [arg recordName].

[call [cmd {record exists}] [arg instance] [arg instanceName]]

Tests for the existence of a [arg instance] with the
name [arg instanceName].

[call [cmd {record delete}] [arg record] [arg recordName]]

Deletes [arg recordName], and all instances of [arg recordName]. It will return
an error if the record does not exist.

[call [cmd {record delete}] [arg instance] [arg instanceName]]

Deletes [arg instance] with the name of [arg instanceName]. It
will return an error if the instance does not exist.


[list_end]
[para]

[section {RECORD MEMBERS}]

Record members can either be variables, or other records, However, the
same record can not be nested witin itself (circular). To define a
nested record, you need to specify the [const record] keyword, along
the with name of the record, and the name of the instance of that
nested record. For example, it would look like this:


[para]
[example_begin]
# this is the nested record
record define mynestedrecord {
    nest1
    nest2
}

# This is the main record
record define myrecord {
    mem1
    mem2
    {record mynestedrecord mem3}
}

[example_end]

You can also assign default or initial values to the members of a record,
by enclosing the member entry in braces:

[para]
[example_begin]

record define myrecord {
    mem1
    {mem2 5}
}

[example_end]

All instances created from this record definition, will initially have 5 as

the value for [arg mem2]. If no default is given, then the value will be the empty string.

[para]
[emph {Getting Values}]
[para]

To get a value of a member, there are several ways to do this.

[list_begin enumerated]


[enum]
To get a member value, then use the instance built-in [method cget] method:

[para]


    [arg instanceName] [method cget] -mem1


[enum]
To get multiple member values, you can specify them all in one command:
[para]
    [arg instanceName] [method cget] -mem1 -mem2

[enum]

To get a list of the key/value of all of the members, there are 3 ways:
[para]
    - [arg instanceName] [method cget]
[para]
	- [arg instanceName] [method configure]
[para]
	- [arg instanceName]

[enum]

To get a value of a nested member, then use the dot notation:
[para]
    [arg instanceName] [method cget] -mem3.nest1

[list_end]

[para]
[emph {Setting Values}]
[para]

To set a value of a member, there are several ways to do this.

[list_begin enumerated]


[enum]
To set a member value, then use the instance built-in [method configure] method:


[para]


    [arg instanceName] [method configure] -mem1 val1




[enum]
To set multiple member values, you can specify them all in one command:
[para]
    [arg instanceName] [method configure] -mem1 va1 -mem2 val2

[enum]
To set a value of a nested member, then use the dot notation:
[para]
    [arg instanceName] [method configure] -mem3.nest1 value


[list_end]

[para]
[emph {Alias access}]
[para]

In the original implementation, access was done by using dot notation similar to how 'C' structures are accessed. However,

there was a concensus to make the interface more Tcl like, which made sense. However, the original alias access still


exists. It might prove to be helpful to some.

[para]
Basically, for every member of every instance, an alias is created. This alias is used to get and set values for that

member. An example will illustrate the point, using the above defined records:

[para]
[example_begin]
# Create an instance first
% myrecord inst1
::inst1

% # To get a member of an instance, just use the
% # alias (it behaves like a Tcl command):
% inst1.mem1
%
% # To set a member via the alias, just include
% # a value (optionally the equal sign - syntactic sugar)
% inst1.mem1 = 5
5

% inst1.mem1
5

% # For nested records, just continue with the
% # dot notation (note no equal sign)
% inst1.mem3.nest1 10
10

% inst1.mem3.nest1
10

% # just the instance by itself gives all
% # member/values pairs for that instance
% inst1
-mem1 5 -mem2 {} -mem3 {-nest1 10 -nest2 {}}

% # and to get all members within the nested record
% inst1.mem3
-nest1 10 -nest2 {}
%

[example_end]

[section {RECORD COMMAND}]

The following subcommands and corresponding arguments are available to any
record command:

[list_begin definitions]


[call [arg recordName] [method [arg instanceName|#auto]] [opt [arg "-member1 value1 -member2 value2 ..."]]]

Using the [arg recordName] object command that was created from the record definition,
instances of the record definition can be created. Once a instance is


created, then it inherits the members of the record definition, very


similar to how objects work. During instance generation, an object command for the instance
is created as well, using [arg instanceName]. This object command is used

to access the data members of the instance. During the instantiation, values for



that instance can be given, [emph but] all values must be given, and be given

in key/value pairs. Nested records, need to be in list format.

[para]
Optionally, [arg #auto] can be used in place of [arg instanceName]. When #auto is used,

then a instance name will automatically be generated, of the form recordName<integer>, where

<integer> is a unique integer (starting at 0) that is generated.

[list_end]
[para]

[section {INSTANCE COMMAND}]

The following subcommands and corresponding arguments are available to
any record instance command:

[list_begin definitions]

[call [arg instanceName] [method cget] [opt [arg "-member1 -member2 ..."]]]

Each instance has the sub command [method cget] associated with it. This
is very similar to how Tk widget's cget command works. It queries
the values of the member for that particular instance. If
no arguments are given, then a key/value list is returned.

[call [arg instanceName] [method configure] [opt [arg "-member1 value1 -member2 value2 ..."]]]


Each instance has the sub command [method configure] associated with it. This
is very similar to how Tk widget's configure command works. It sets
the values of the particular member for that particular instance. If
no arguments are given, then a key/value list is returned.

[list_end]

[section EXAMPLES]

Two examples are provided to give an good illustration on how to use
this package.

[para]
[emph {Example 1}]
[para]

Probably the most obvious example would be to hold contact information,
such as addresses, phone numbers, comments, etc. Since a person can have
multiple phone numbers, multiple email addresses, etc, we will use nested
records to define these. So, the first thing we do is define the nested
records:

[para]
[example {

##
##  This is an interactive example, to see what is
##  returned by each command as well.
##

% namespace import ::struct::record::*

% # define a nested record. Notice that country has default 'USA'.
% record define locations {
    street

>
|








|


|
|
>
|
|
<

<
|
>
|
|
|

|
|
>



|
>

|
|
|
|
|
>
|












|
|
<




















|
|



|
|
>


<







|
>

<
|












<


|
|



<




<


|
>
|

<
|
<



|

>
|
|
>
|
>
>
|
>

|
<
<
|

<
>
|
|
|
<
|
<
|

<
>
|
|
<



<
|
<



|

>
|
|
>
>
|
>
>
|
>
>
>
|
<
|
<
<

<
<
<
|
>



<
|
<

|
>
|
>
>
|

|
|
>
|



|


>
|
|

|
|
|


>


>
|
|


>


>
|
|


>



<





|
|



>
|

|
|
>
>
|
>
>
|
|
>
|
>
>
>
|
>
|

|
|
>
|
>
|













|
|
|
|

|
>

|
|
|
|





|


<
|
<

|
|
|
|
|

|
<


|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
[comment {-*- tcl -*-}]
[vset VERSION 1.2.2]
[manpage_begin struct::record n [vset VERSION]]
[keywords {data structures}]
[keywords record]
[keywords struct]
[copyright {2002, Brett Schwarz <[email protected]>}]
[moddesc   {Tcl Data Structures}]
[titledesc {Define and create records (similar to 'C' structures)}]
[category  {Data structures}]
[require Tcl 8.2]
[require struct::record [opt [vset VERSION]]]
[description]

The [cmd ::struct::record] package provides a mechanism to group
variables together as one data structure, similar to a [term C]
structure. The members of a record can be variables or other
records. However, a record can not contain circular records,
i.e. records that contain the same record as a member.



[para] This package was structured so that it is very similar to how
Tk objects work. Each record definition creates a record object that
encompasses that definition. Subsequently, that record object can
create instances of that record. These instances can then be
manipulated with the [method cget] and [method configure] methods.

[para] The package only contains one top level command, but several
sub commands (see below). It also obeys the namespace in which the
record was defined, hence the objects returned are fully qualified.

[list_begin definitions]

[call [cmd {record define}] [arg recordName] [arg recordMembers] \
     [opt [arg "instanceName1 instanceName2 ..."]]]

Defines a record. [arg recordName] is the name of the record, and is
also used as an object command. This object command is used to create
instances of the record definition. The [arg recordMembers] are the
members of the record that make up the record definition. These are
variables and other records. If optional [arg instanceName] args are
specified, then an instance is generated after the definition is
created for each [arg instanceName].

[call [cmd {record show}] [arg record]]

Returns a list of records that have been defined.

[call [cmd {record show}] [arg instances] [arg recordName]]

Returns the instances that have been instantiated by
[arg recordName].

[call [cmd {record show}] [arg members] [arg recordName]]

Returns the members that are defined for record [arg recordName].
It returns the same format as how the records were defined.


[call [cmd {record show}] [arg values] [arg instanceName]]

Returns a list of values that are set for the instance
[arg instanceName]. The output is a list of key/value pairs. If there
are nested records, then the values of the nested records will
itself be a list.

[call [cmd {record exists}] [arg record] [arg recordName]]

Tests for the existence of a [arg record] with the
name [arg recordName].

[call [cmd {record exists}] [arg instance] [arg instanceName]]

Tests for the existence of a [arg instance] with the
name [arg instanceName].

[call [cmd {record delete}] [arg record] [arg recordName]]

Deletes [arg recordName], and all instances of [arg recordName].
It will return an error if the record does not exist.

[call [cmd {record delete}] [arg instance] [arg instanceName]]

Deletes [arg instance] with the name of [arg instanceName]. It will
return an error if the instance does not exist. Note that this
recursively deletes any nested instances as well.

[list_end]


[section {RECORD MEMBERS}]

Record members can either be variables, or other records, However, the
same record can not be nested witin itself (circular). To define a
nested record, you need to specify the [const record] keyword, along
the with name of the record, and the name of the instance of that
nested record (within the container). For example, it would look like
this:


[para][example_begin]
# this is the nested record
record define mynestedrecord {
    nest1
    nest2
}

# This is the main record
record define myrecord {
    mem1
    mem2
    {record mynestedrecord mem3}
}

[example_end]

You can also assign default or initial values to the members of a
record, by enclosing the member entry in braces:

[para]
[example_begin]

record define myrecord {
    mem1
    {mem2 5}
}

[example_end]

All instances created from this record definition will initially have
[const 5] as the value for member [arg mem2]. If no default is given,
then the value will be the empty string.


[subsection {Getting Values}]


To get a value of a member, there are several ways to do this.

[list_begin definitions]

[call [arg instanceName] [method cget] -[arg member]]

In this form the built-in [method cget] instance method returns the
value of the specified [arg member]. Note the leading dash.

[para] To reach a nested member use [term {dot notation}]:
[example_begin]
[arg instanceName] [method cget] -mem3.nest1
[example_end]




[call [arg instanceName] [method cget] -[arg member1] -[arg member2]]


In this form the built-in [method cget] instance method returns a list
containing the values of both specified members, in the order of specification.

[call [arg instanceName] [method cget]]

[call [arg instanceName] [method configure]]

[call [arg instanceName]]


These forms are all equivalent. They return a dictionary of all
members and the associated values.



[list_end]


[subsection {Setting Values}]


To set a value of a member, there are several ways to do this.

[list_begin definitions]

[call [arg instanceName] [method configure] -[arg member] [arg value]]

In this form the built-in [method configure] instance method sets the
specified [arg member] to the given [arg value]. Note the leading
dash.

[para] To reach a nested member use [term {dot notation}]:
[example_begin]
[arg instanceName] [method configure] -mem3.nest1 value
[example_end]

[call [arg instanceName] [method configure] \
     -[arg member1] [arg value1] \

     -[arg member2] [arg value2]]






In this form the built-in [method configure] instance method sets all
specified members to the associated values.

[list_end]


[subsection {Alias access}]


In the original implementation, access was done by using dot notation
similar to how [term C] structures are accessed. However, there was a
concensus to make the interface more Tcl like, which made sense.

However, the original alias access still exists. It might prove to be
helpful to some.

[para] Basically, for every member of every instance, an alias is
created. This alias is used to get and set values for that member.

An example will illustrate the point, using the above defined records:

[para]
[example_begin]
% # Create an instance first
% myrecord inst1
::inst1

% # To get a member of an instance, just use the alias. It behaves
% # like a Tcl command:
% inst1.mem1

% # To set a member via the alias, just include a value. And optionally
% # the equal sign - syntactic sugar.
% inst1.mem1 = 5
5

% inst1.mem1
5

% # For nested records, just continue with the dot notation.
% # note, no equal sign.
% inst1.mem3.nest1 10
10

% inst1.mem3.nest1
10

% # just the instance by itself gives all member/values pairs for that
% # instance
% inst1
-mem1 5 -mem2 {} -mem3 {-nest1 10 -nest2 {}}

% # and to get all members within the nested record
% inst1.mem3
-nest1 10 -nest2 {}


[example_end]

[section {RECORD COMMAND}]

The following subcommands and corresponding arguments are available to
any record command:

[list_begin definitions]

[call [arg recordName] [arg instanceName]|[const #auto] \
     [opt [arg "-member1 value1 -member2 value2 ..."]]]

Using the [arg recordName] object command that was created from the
record definition, instances of the record definition can be
created.

Once an instance is created, it inherits the members of the record
definition, very similar to how objects work.

During instance generation, an object command for the instance is
created as well, using [arg instanceName].

[para] This object command is used to access the data members of the
instance.

During the instantiation, while values for that instance may be given,
when done, [strong all] values must be given, and be given as
key/value pairs, like for method [method configure]. Nested records
have to be in list format.

[para] Optionally, [const #auto] can be used in place of
[arg instanceName]. When [const #auto] is used, the instance name will
be automatically generated, and of the form

[const recordName[var N]], where [var N] is a unique integer (starting
at 0) that is generated.

[list_end]
[para]

[section {INSTANCE COMMAND}]

The following subcommands and corresponding arguments are available to
any record instance command:

[list_begin definitions]

[call [arg instanceName] [method cget] [opt [arg "-member1 -member2 ..."]]]

Each instance has the method [method cget]. This is very similar to
how Tk widget's [method cget] command works. It queries the values of
the members for that particular instance. If no arguments are given,
then a dictionary is returned.

[call [arg instanceName] [method configure] \
     [opt [arg "-member1 value1 -member2 value2 ..."]]]

Each instance has the method [method configure]. This is very similar
to how Tk widget's [method configure] command works. It sets the
values of the particular members for that particular instance. If no
arguments are given, then a dictionary list is returned.

[list_end]

[section EXAMPLES]

Two examples are provided to give a good illustration on how to use
this package.


[subsection {Example 1 - Contact Information}]


Probably the most obvious example would be to hold contact
information, such as addresses, phone numbers, comments, etc. Since a
person can have multiple phone numbers, multiple email addresses, etc,
we will use nested records to define these. So, the first thing we do
is define the nested records:

[para][example {


##
##  This is an interactive example, to see what is returned by
##  each command as well.
##

% namespace import ::struct::record::*

% # define a nested record. Notice that country has default 'USA'.
% record define locations {
    street
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
% record show members contacts2
first middle last {record locations home} {record locations work}
% record show members contacts
first middle last {record locations home} {record locations work}
%
}]

[para]
[emph {Example 1}]
[para]

This next example just illustrates a simple linked list
[para]
[example {

% # define a very simple record for linked list
% record define llist {
    value
    next
}
::llist
% llist lstart
::lstart
% lstart config -value 1 -next [llist #auto]
% [lstart cget -next] config -value 2 -next [llist #auto]
% [[lstart cget -next] cget -next] config -value 3 -next "end"
% set next lstart
lstart
% while 1 {
lappend values [$next cget -value]
set next [$next cget -next]
if {[string match "end" $next]} {break}
}
% puts "$values"
1 2 3
% # cleanup linked list
% # We could just use delete record llist also
% foreach I [record show instances llist] {
record delete instance $I
}
% record show instances llist
%

}]

[para]

[vset CATEGORY {struct :: record}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







<
|
<


|
|
<

|



|
|

|
|




|
|
|




|
|
|

|

<


<
<

|

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
% record show members contacts2
first middle last {record locations home} {record locations work}
% record show members contacts
first middle last {record locations home} {record locations work}
%
}]


[subsection {Example 2 - Linked List}]


This next example just illustrates a simple linked list

[para][example {

% # define a very simple record for linked list
% record define linkedlist {
    value
    next
}
::linkedlist
% linkedlist lstart
::lstart
% lstart config -value 1 -next [linkedlist #auto]
% [lstart cget -next] config -value 2 -next [linkedlist #auto]
% [[lstart cget -next] cget -next] config -value 3 -next "end"
% set next lstart
lstart
% while 1 {
    lappend values [$next cget -value]
    set next [$next cget -next]
    if {[string match "end" $next]} break
}
% puts "$values"
1 2 3
% # cleanup linked list
% # We could just use delete record linkedlist also
% foreach I [record show instances linkedlist] {
    record delete instance $I
}
% record show instances linkedlist
%

}]



[vset CATEGORY {struct :: record}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/struct/record.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#============================================================
# ::struct::record --
#
#    Implements a container data structure similar to a 'C' 
#    structure. It hides the ugly details about keeping the
#    data organized by using a combination of arrays, lists
#    and namespaces.
#   
#    Each record definition is kept in a master array 
#    (_recorddefn) under the ::struct::record namespace. Each
#    instance of a record is kept within a separate namespace
#    for each record definition. Hence, instances of
#    the same record definition are managed under the
#    same namespace. This avoids possible collisions, and
#    also limits one big global array mechanism.
#
# Copyright (c) 2002 by Brett Schwarz
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# This code may be distributed under the same terms as Tcl.
#
# $Id: record.tcl,v 1.10 2004/09/29 20:56:18 andreas_kupries Exp $
#
#============================================================
#
####  FIX ERROR MESSAGES SO THEY MAKE SENSE (Wrong args)

namespace eval ::struct {}

namespace eval ::struct::record {

    ##
    ##  array of lists that holds the 
    ##  definition (variables) for each 
    ##  record
    ##
    ##  _recorddefn(some_record) var1 var2 var3 ...
    ##
    variable _recorddefn

    ##
    ##  holds the count for each record
    ##  in cases where the instance is
    ##  automatically generated
    ##
    ##  _count(some_record) 0
    ##

    ## This is not a count, but an id generator. Its value has to
    ## increase monotonicaly.

    variable _count

    ##
    ##  array that holds the defining record's
    ##  name for each instances
    ##
    ##  _defn(some_instances) name_of_defining_record
    ##
    variable  _defn
    array set _defn {}

    ##
    ##  This holds the defaults for a record definition.
    ##  If no default is given for a member of a record,
    ##  then the value is assigned to the empty string
    ##
    variable _defaults

    ##
    ##  These are the possible sub commands
    ##
    variable commands
    set commands [list define delete exists show]

    ##
    ##  This keeps track of the level that we are in
    ##  when handling nested records. This is kind of
    ##  a hack, and probably can be handled better
    ##
    set _level 0

    namespace export record
}

#------------------------------------------------------------



|



|
|














<
<









|
<







|
<











|
<







|
|
|










|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23


24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#============================================================
# ::struct::record --
#
#    Implements a container data structure similar to a 'C'
#    structure. It hides the ugly details about keeping the
#    data organized by using a combination of arrays, lists
#    and namespaces.
#
#    Each record definition is kept in a master array
#    (_recorddefn) under the ::struct::record namespace. Each
#    instance of a record is kept within a separate namespace
#    for each record definition. Hence, instances of
#    the same record definition are managed under the
#    same namespace. This avoids possible collisions, and
#    also limits one big global array mechanism.
#
# Copyright (c) 2002 by Brett Schwarz
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# This code may be distributed under the same terms as Tcl.
#


#============================================================
#
####  FIX ERROR MESSAGES SO THEY MAKE SENSE (Wrong args)

namespace eval ::struct {}

namespace eval ::struct::record {

    ##
    ##  array of lists that holds the definition (variables) for each

    ##  record
    ##
    ##  _recorddefn(some_record) var1 var2 var3 ...
    ##
    variable _recorddefn

    ##
    ##  holds the count for each record in cases where the instance is

    ##  automatically generated
    ##
    ##  _count(some_record) 0
    ##

    ## This is not a count, but an id generator. Its value has to
    ## increase monotonicaly.

    variable _count

    ##
    ##  array that holds the defining record's name for each instances

    ##
    ##  _defn(some_instances) name_of_defining_record
    ##
    variable  _defn
    array set _defn {}

    ##
    ##  This holds the defaults for a record definition.  If no
    ##  default is given for a member of a record, then the value is
    ##  assigned to the empty string
    ##
    variable _defaults

    ##
    ##  These are the possible sub commands
    ##
    variable commands
    set commands [list define delete exists show]

    ##
    ##  This keeps track of the level that we are in when handling
    ##  nested records. This is kind of a hack, and probably can be
    ##  handled better
    ##
    set _level 0

    namespace export record
}

#------------------------------------------------------------
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
#
# Results:
#   Returns the name of the definition during successful
#   creation.
#------------------------------------------------------------
#
proc ::struct::record::Define {defn_ vars_ args} {

    variable _recorddefn
    variable _count
    variable _defaults



    set defn_ [Qualify $defn_]

    if {[info exists _recorddefn($defn_)]} {
        error "Record definition $defn_ already exists"
    }

    if {[lsearch [info commands] $defn_] >= 0} {
        error "Structure definition name can not be a Tcl command name"
    }

    set _defaults($defn_)   [list]
    set _recorddefn($defn_) [list]


    ##
    ##  Loop through the members of the record
    ##  definition
    ##
    foreach V $vars_ {

        set len [llength $V]
        set D ""

        ##

        ##  2 --> there is a default value
        ##        assigned to the member
        ##
        ##  3 --> there is a nested record
        ##        definition given as a member
        ##
        if {$len == 2} {

            set D [lindex $V 1]
            set V [lindex $V 0]

        } elseif {$len == 3} {




            if {![string match "record" "[lindex $V 0]"]} {

                Delete record $defn_
                error "$V is a Bad member for record definition
                definition creation aborted."
            }

            set new [lindex $V 1]

            set new [Qualify $new]

            ##
            ##  Right now, there can not be circular records
            ##  so, we abort the creation
            ##
            if {[string match "$defn_" "$new"]} {

                Delete record $defn_
                error "Can not have circular records. Structure was not created."
            }

            ##
            ##  Will take care of the nested record later
            ##  We just join by :: because this is how it
            ##  use to be declared, so the parsing code
            ##  is already there.
            ##
            set V [join [lrange $V 1 2] "::"]
        }



        lappend _recorddefn($defn_) $V
        lappend _defaults($defn_)   $D
    }
    

    uplevel #0 [list interp alias {} $defn_ {} ::struct::record::Create $defn_]



    set _count($defn_) 0


    namespace eval ::struct::record${defn_} {
        variable values
        variable instances


        set instances [list]
    }



    ##
    ##    If there were args given (instances), then
    ##    create them now
    ##
    foreach A $args {

        uplevel 1 [list ::struct::record::Create $defn_ $A]
    }


    return $defn_

}; # end proc ::struct::record::Define


#------------------------------------------------------------
# ::struct::record::Create --
#
#    Creates an instance of a record definition
#
# Arguments:
#    defn_    the name of the record definition
#    inst_    the name of the instances to create
#    args     values to set to the record's members
#
# Results:
#   Returns the name of the instance for a successful creation
#------------------------------------------------------------
#
proc ::struct::record::Create {defn_ inst_ args} {

    variable _recorddefn
    variable _count
    variable _defn
    variable _defaults
    variable _level



    set inst_ [Qualify "$inst_"]

    ##
    ##    test to see if the record
    ##    definition has been defined yet
    ##
    if {![info exists _recorddefn($defn_)]} {
        error "Structure $defn_ does not exist"
    }


    ##
    ##    if there was no argument given,
    ##    then assume that the record
    ##    variable is automatically
    ##    generated
    ##







<



>
>














<





<



<
>
|
|
<
<
<
<
<





>
>
>


<

|
<



<

|





>












>
>




|
|
|
>
>



>



>



>
>






<



>




















<





>
>










<







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
#
# Results:
#   Returns the name of the definition during successful
#   creation.
#------------------------------------------------------------
#
proc ::struct::record::Define {defn_ vars_ args} {

    variable _recorddefn
    variable _count
    variable _defaults

    # puts .([info level 0])...

    set defn_ [Qualify $defn_]

    if {[info exists _recorddefn($defn_)]} {
        error "Record definition $defn_ already exists"
    }

    if {[lsearch [info commands] $defn_] >= 0} {
        error "Structure definition name can not be a Tcl command name"
    }

    set _defaults($defn_)   [list]
    set _recorddefn($defn_) [list]


    ##
    ##  Loop through the members of the record
    ##  definition
    ##
    foreach V $vars_ {

        set len [llength $V]
        set D ""


        if {$len == 2} {
	    ##  2 --> there is a default value
	    ##        assigned to the member






            set D [lindex $V 1]
            set V [lindex $V 0]

        } elseif {$len == 3} {
	    ##  3 --> there is a nested record
	    ##        definition given as a member
	    ##  V = ('record' record-name field-name)

            if {![string match "record" "[lindex $V 0]"]} {

                Delete record $defn_
                error "$V is a Bad member for record definition. Definition creation aborted."

            }

            set new [lindex $V 1]

            set new [Qualify $new]
	    # puts .\tchild=$new
            ##
            ##  Right now, there can not be circular records
            ##  so, we abort the creation
            ##
            if {[string match "$defn_" "$new"]} {
		# puts .\tabort
                Delete record $defn_
                error "Can not have circular records. Structure was not created."
            }

            ##
            ##  Will take care of the nested record later
            ##  We just join by :: because this is how it
            ##  use to be declared, so the parsing code
            ##  is already there.
            ##
            set V [join [lrange $V 1 2] "::"]
        }

	# puts .\tfield($V)=default($D)

        lappend _recorddefn($defn_) $V
        lappend _defaults($defn_)   $D
    }

    # Create class command as alias to instance creator.
    uplevel #0 [list interp alias \
		    {} $defn_ \
		    {} ::struct::record::Create $defn_]

    set _count($defn_) 0

    # Create class namespace. This will hold all the instance information.
    namespace eval ::struct::record${defn_} {
        variable values
        variable instances
	variable record

        set instances [list]
    }

    set ::struct::record${defn_}::record $defn_

    ##
    ##    If there were args given (instances), then
    ##    create them now
    ##
    foreach A $args {

        uplevel 1 [list ::struct::record::Create $defn_ $A]
    }

    # puts .=>${defn_}
    return $defn_

}; # end proc ::struct::record::Define


#------------------------------------------------------------
# ::struct::record::Create --
#
#    Creates an instance of a record definition
#
# Arguments:
#    defn_    the name of the record definition
#    inst_    the name of the instances to create
#    args     values to set to the record's members
#
# Results:
#   Returns the name of the instance for a successful creation
#------------------------------------------------------------
#
proc ::struct::record::Create {defn_ inst_ args} {

    variable _recorddefn
    variable _count
    variable _defn
    variable _defaults
    variable _level

    # puts .([info level 0])...

    set inst_ [Qualify "$inst_"]

    ##
    ##    test to see if the record
    ##    definition has been defined yet
    ##
    if {![info exists _recorddefn($defn_)]} {
        error "Structure $defn_ does not exist"
    }


    ##
    ##    if there was no argument given,
    ##    then assume that the record
    ##    variable is automatically
    ##    generated
    ##
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
        incr _count($defn_) -1
        error "Instances $inst_ already exists"
    }

    set _defn($inst_) $defn_

    ##
    ##    Initialize record variables to
    ##    defaults
    ##


    uplevel #0 [list interp alias {} ${inst_} {} ::struct::record::Cmd $inst_]









    set cnt 0
    foreach V $_recorddefn($defn_) D $_defaults($defn_) {



        set [Ns $inst_]values($inst_,$V) $D

        ##
        ##  Test to see if there is a nested record
        ##
        if {[regexp -- {([\w]*)::([\w]*)} $V m def inst]} {

            if {$_level == 0} {
                set _level 2
            }

            ##
            ##  This is to guard against if the creation
            ##  had failed, that there isn't any
            ##  lingering variables/alias around
            ##
            set def [Qualify $def $_level]

            if {![info exists _recorddefn($def)]} {

                Delete inst "$inst_"

                return
            }

            ##
            ##    evaluate the nested record. If there
            ##    were values for the variables passed
            ##    in, then we assume that the value for
            ##    this nested record is a list 
            ##    corresponding the the nested list's
            ##    variables, and so we pass that to
            ##    the nested record's instantiation.
            ##    We then get rid of those args for later
            ##    processing.
            ##
            set cnt_plus [expr {$cnt + 1}]
            set mem [lindex $args $cnt]
            if {![string match "" "$mem"]} {
                 if {![string match "-$inst" "$mem"]} {
                    Delete inst "$inst_"
                    error "$inst is not a member of $defn_"
                }
            }
            incr _level
            set narg [lindex $args $cnt_plus]


            eval [linsert $narg 0 Create $def ${inst_}.${inst}]

            set args [lreplace $args $cnt $cnt_plus]

            incr _level -1
        } else {


            uplevel #0 [list interp alias {} ${inst_}.$V {} ::struct::record::Access $defn_ $inst_ $V]


            incr cnt 2
        }

    }; # end foreach variable


    lappend [Ns $inst_]instances $inst_


    foreach {k v} $args {

        Access $defn_ $inst_ [string trimleft "$k" -] $v

    }; # end foreach arg {}

    if {$_level == 2} {
	set _level 0
    }


    return $inst_

}; # end proc ::struct::record::Create


#------------------------------------------------------------
# ::struct::record::Access --







|
<


>

>
>
>
>
>
>
>
>




>
>
|




|






|
<
|




<

<




|
<
|
|
<
|
|
|
<




|






>
>

>




|
>
|
>
>


<


>
|

>

<

<






>







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
        incr _count($defn_) -1
        error "Instances $inst_ already exists"
    }

    set _defn($inst_) $defn_

    ##
    ##    Initialize record variables to defaults

    ##

    # Create instance command as alias of instance dispatcher.
    uplevel #0 [list interp alias {} ${inst_} {} ::struct::record::Cmd $inst_]

    # Locate manager namespace, i.e. class namespace for new instance
    set nsi [Ns $inst_]
    # puts .\tnsi=$nsi

    # Import the state of the manager namespace
    upvar 0 ${nsi}values    __values
    upvar 0 ${nsi}instances __instances

    set cnt 0
    foreach V $_recorddefn($defn_) D $_defaults($defn_) {

	# puts .\tfield($V)=default($D)

	set __values($inst_,$V) $D

        ##
        ##  Test to see if there is a nested record
        ##
        if {[regexp -- {([\w]*)::([\w]*)} $V -> def inst]} {

            if {$_level == 0} {
                set _level 2
            }

            ##
            ##  This is to guard against if the creation had failed,

            ##  that there isn't any lingering variables/alias around
            ##
            set def [Qualify $def $_level]

            if {![info exists _recorddefn($def)]} {

                Delete inst "$inst_"

                return
            }

            ##
            ##    evaluate the nested record. If there were values for

            ##    the variables passed in, then we assume that the
            ##    value for this nested record is a list corresponding

            ##    the the nested list's variables, and so we pass that
            ##    to the nested record's instantiation.  We then get
            ##    rid of those args for later processing.

            ##
            set cnt_plus [expr {$cnt + 1}]
            set mem [lindex $args $cnt]
            if {![string match "" "$mem"]} {
		if {![string match "-$inst" "$mem"]} {
                    Delete inst "$inst_"
                    error "$inst is not a member of $defn_"
                }
            }
            incr _level
            set narg [lindex $args $cnt_plus]

	    # Create instance of the nested record.
            eval [linsert $narg 0 Create $def ${inst_}.${inst}]

            set args [lreplace $args $cnt $cnt_plus]

            incr _level -1
        } else {
	    # Regular field, not a nested record. Create alias for
	    # field access.
            uplevel #0 [list interp alias \
			    {} ${inst_}.$V \
			    {} ::struct::record::Access $defn_ $inst_ $V]
            incr cnt 2
        }

    }; # end foreach variable

    # Remember new instance.
    lappend __instances $inst_

    # Apply field values handed to the instance constructor.
    foreach {k v} $args {

        Access $defn_ $inst_ [string trimleft "$k" -] $v

    }; # end foreach arg {}

    if {$_level == 2} {
	set _level 0
    }

    # puts .=>${inst_}
    return $inst_

}; # end proc ::struct::record::Create


#------------------------------------------------------------
# ::struct::record::Access --
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

    variable _recorddefn
    variable _defn

    set i [lsearch $_recorddefn($defn_) $var_]

    if {$i < 0} {
         error "$var_ does not exist in record $defn_"
    }

    if {![info exists _defn($inst_)]} {

         error "$inst_ does not exist"
    }

    if {[set idx [lsearch $args "="]] >= 0} {
        set args [lreplace $args $idx $idx]
    } 







    ##
    ##    If a value was given, then set it
    ##
    if {[llength $args] != 0} {

        set val_ [lindex $args 0]

        set [Ns $inst_]values($inst_,$var_) $val_
    }

    return [set [Ns $inst_]values($inst_,$var_)]
     
}; # end proc ::struct::record::Access


#------------------------------------------------------------
# ::struct::record::Cmd --
#
#    Used to process the set/get requests.







|




|




|
>
>
>
>
>
>








|


|
|







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

    variable _recorddefn
    variable _defn

    set i [lsearch $_recorddefn($defn_) $var_]

    if {$i < 0} {
	error "$var_ does not exist in record $defn_"
    }

    if {![info exists _defn($inst_)]} {

	error "$inst_ does not exist"
    }

    if {[set idx [lsearch $args "="]] >= 0} {
        set args [lreplace $args $idx $idx]
    }

    set nsi [Ns $inst_]
    # puts .\tnsi=$nsi

    # Import the state of the manager namespace
    upvar 0 ${nsi}values    __values

    ##
    ##    If a value was given, then set it
    ##
    if {[llength $args] != 0} {

        set val_ [lindex $args 0]

        set __values($inst_,$var_) $val_
    }

    return $__values($inst_,$var_)

}; # end proc ::struct::record::Access


#------------------------------------------------------------
# ::struct::record::Cmd --
#
#    Used to process the set/get requests.
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
    set len [llength $args]
    if {$len <= 1} {return [Show values "$inst_"]}

    set cmd [lindex $args 0]

    if {[string match "cget" "$cmd"]} {

            set cnt 0
            foreach k [lrange $args 1 end] {
                if {[catch {set r [${inst_}.[string trimleft ${k} -]]} err]} {
                    error "Bad option \"$k\""
                }

                lappend result $r
                incr cnt
            }
            if {$cnt == 1} {set result [lindex $result 0]}
            return $result

    } elseif {[string match "config*" "$cmd"]} {

            set L [lrange $args 1 end]
            foreach {k v} $L {
                 ${inst_}.[string trimleft ${k} -] $v
            }

    } else {
            error "Wrong argument.
            must be \"object cget|configure args\""
    }

    return [list]

}; # end proc ::struct::record::Cmd








|
|
|
|
|

|
|
|
|
|



|
|
|
|


|







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
    set len [llength $args]
    if {$len <= 1} {return [Show values "$inst_"]}

    set cmd [lindex $args 0]

    if {[string match "cget" "$cmd"]} {

	set cnt 0
	foreach k [lrange $args 1 end] {
	    if {[catch {set r [${inst_}.[string trimleft ${k} -]]} err]} {
		error "Bad option \"$k\""
	    }

	    lappend result $r
	    incr cnt
	}
	if {$cnt == 1} {set result [lindex $result 0]}
	return $result

    } elseif {[string match "config*" "$cmd"]} {

	set L [lrange $args 1 end]
	foreach {k v} $L {
	    ${inst_}.[string trimleft ${k} -] $v
	}

    } else {
	error "Wrong argument.
            must be \"object cget|configure args\""
    }

    return [list]

}; # end proc ::struct::record::Cmd

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
#    if what_ = instance, then return a list of instances
#               with record definition of record_
#    if what_ = values, then it will return the values
#               for a particular instance
#------------------------------------------------------------
#
proc ::struct::record::Show {what_ {record_ ""}} {

    variable _recorddefn
    variable _defn
    variable _defaults



    ##
    ## We just prepend :: to the record_ argument
    ##
    if {![string match "::*" "$record_"]} {set record_ "::$record_"}

    if {[string match "record*" "$what_"]} {


        return [lsort [array names _recorddefn]]


    } elseif {[string match "mem*" "$what_"]} {


       if {[string match "" "$record_"] || ![info exists _recorddefn($record_)]} {
           error "Bad arguments while accessing members. Bad record name"
       }

       set res [list]
       set cnt 0
       foreach m $_recorddefn($record_) {
           set def [lindex $_defaults($record_) $cnt]
           if {[regexp -- {([\w]+)::([\w]+)} $m m d i]} {
               lappend res [list record $d $i]
           } elseif {![string match "" "$def"]} {
               lappend res [list $m $def]
           } else {
               lappend res $m
           }

           incr cnt
       }

       return $res


    } elseif {[string match "inst*" "$what_"]} {


        if {![info exists ::struct::record${record_}::instances]} {
            return [list]
        }


        return [lsort [set ::struct::record${record_}::instances]]








    } elseif {[string match "val*" "$what_"]} {


           set ns $_defn($record_)




           if {[string match "" "$record_"] || ([lsearch [set [Ns $record_]instances] $record_] < 0)} {


               error "Wrong arguments to values. Bad instance name"
           }

           set ret [list]
           foreach k $_recorddefn($ns) {

              set v [set [Ns $record_]values($record_,$k)]

              if {[regexp -- {([\w]*)::([\w]*)} $k m def inst]} {
                  set v [::struct::record::Show values ${record_}.${inst}]
              }

              lappend ret -[namespace tail $k] $v
           }
           return $ret

    }


    return [list]

}; # end proc ::struct::record::Show


#------------------------------------------------------------
# ::struct::record::Delete --







<



>
>




|


>
>

>
>
|
>

|
|
|

|
|
|
|
|
|
|
|
|
|
|

|
|

|
|
>
|
>

|
|
|
>
>
|

>
>
>
>
>
>
>
|
>

|
>
>
>

|
>

|
|

|
|
<
|

|
|
|

|
|
|



>







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
#    if what_ = instance, then return a list of instances
#               with record definition of record_
#    if what_ = values, then it will return the values
#               for a particular instance
#------------------------------------------------------------
#
proc ::struct::record::Show {what_ {record_ ""}} {

    variable _recorddefn
    variable _defn
    variable _defaults

    set record_ [Qualify $record_]

    ##
    ## We just prepend :: to the record_ argument
    ##
    #if {![string match "::*" "$record_"]} {set record_ "::$record_"}

    if {[string match "record*" "$what_"]} {
	# Show record

        return [lsort [array names _recorddefn]]
    }

    if {[string match "mem*" "$what_"]} {
	# Show members

	if {[string match "" "$record_"] || ![info exists _recorddefn($record_)]} {
	    error "Bad arguments while accessing members. Bad record name"
	}

	set res [list]
	set cnt 0
	foreach m $_recorddefn($record_) {
	    set def [lindex $_defaults($record_) $cnt]
	    if {[regexp -- {([\w]+)::([\w]+)} $m m d i]} {
		lappend res [list record $d $i]
	    } elseif {![string match "" "$def"]} {
		lappend res [list $m $def]
	    } else {
		lappend res $m
	    }

	    incr cnt
	}

	return $res
    }

    if {[string match "inst*" "$what_"]} {
	# Show instances

	if {![namespace exists ::struct::record${record_}]} {
	    return [list]
	}

	# Import the state of the manager namespace
	upvar 0 ::struct::record${record_}::instances __instances

        if {![info exists __instances]} {
            return [list]
        }
        return [lsort $__instances]

    }

    if {[string match "val*" "$what_"]} {
	# Show values

	set nsi [Ns $record_]
	upvar 0 ${nsi}::instances __instances
	upvar 0 ${nsi}::values    __values
	upvar 0 ${nsi}::record    __record

	if {[string match "" "$record_"] ||
	    ([lsearch $__instances $record_] < 0)} {

	    error "Wrong arguments to values. Bad instance name"
	}

	set ret [list]
	foreach k $_recorddefn($__record) {

	    set v $__values($record_,$k)

	    if {[regexp -- {([\w]*)::([\w]*)} $k m def inst]} {
		set v [::struct::record::Show values ${record_}.${inst}]
	    }

	    lappend ret -[namespace tail $k] $v
	}
	return $ret

    }

    # Bogus submethod
    return [list]

}; # end proc ::struct::record::Show


#------------------------------------------------------------
# ::struct::record::Delete --
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

#
# Returns:
#    none
#
#------------------------------------------------------------
#
proc ::struct::record::Delete {sub_ item_} {

    variable _recorddefn
    variable _defn
    variable _count
    variable _defaults

    ##
    ## We just semi-blindly prepend :: to the record_ argument
    ##
    if {![string match "::*" "$item_"]} {set item_ "::$item_"}

    switch -- $sub_ {

        instance -
        instances -
        inst    {



            if {[Exists instance $item_]} {
        


		set ns $_defn($item_)

                foreach A [info commands ${item_}.*] {


		    Delete inst $A


                }




        

                catch {
                    foreach {k v} [array get [Ns $item_]values $item_,*] {

                        






                        unset [Ns $item_]values($k)

                    }
                    set i [lsearch [set [Ns $item_]instances] $item_]
                    set [Ns $item_]instances [lreplace [set [Ns $item_]instances] $i $i]
                    unset _defn($item_)
                }

		# Auto-generated id numbers increase monotonically.
		# Reverting here causes the next auto to fail, claiming
		# that the instance exists.
                # incr _count($ns) -1
        
            } else {
                #error "$item_ is not a instance"
            }
        }
        record  -
        records   {


            ##
            ##  Delete the instances for this
            ##  record
            ##

            foreach I [Show instance "$item_"] {


                catch {Delete instance "$I"}

            }

            catch {
                unset _recorddefn($item_)
                unset _defaults($item_)
                unset _count($item_)
                namespace delete ::struct::record${item_}
            }

            
        }
        default   {
            error "Wrong arguments to delete"
        }

    }; # end switch



    catch { uplevel #0 [list interp alias {} $item_ {}]}


    return

}; # end proc ::struct::record::Delete


#------------------------------------------------------------
# ::struct::record::Exists --
#
#    Tests whether a record definition or record
#    instance exists.
#
# Arguments:
#    sub_    what to test. Either 'instance' or 'record'
#    item_   the specific record instance or definition
#            that needs to be tested.
#    
# Tests to see if a particular instance exists
#
#------------------------------------------------------------
#
proc ::struct::record::Exists {sub_ item_} {





    switch -glob -- $sub_ {
        inst*    {
    
            if {([lsearch ::[Ns $item_]instances $item_] >=0) || [llength [info commands ::${item_}.*]]} {
                return 1
            } else {
                return 0
            }
        }
        record  {
    
            set item_ "::$item_"
            if {[info exists _recorddefn($item_)] || [llength [info commands ${item_}]]} {
                return 1
            } else {
                return 0
            }
        }
        default  {
            error "Wrong arguments. Must be exists record|instance target"
        }
    }; # end switch

}; # end proc ::struct::record::Exists


#------------------------------------------------------------
# ::struct::record::Qualify --
#
#    Contructs the qualified name of the calling scope. This
#    defaults to 2 levels since there is an extra proc call in
#    between.
#
# Arguments:
#    item_   the command that needs to be qualified
#    level_  how many levels to go up (default = 2)
#    
# Results:
#    the item_ passed in fully qualified
#
#------------------------------------------------------------
#
proc ::struct::record::Qualify {item_ {level_ 2}} {

    if {![string match "::*" "$item_"]} {
        set ns [uplevel $level_ [list namespace current]]

        if {![string match "::" "$ns"]} {
            append ns "::"
        }
     
        set item_ "$ns${item_}"
    }

    return "$item_"

}; # end proc ::struct::record::Qualify

# ### ### ### ######### ######### #########
## Ready

namespace eval ::struct {
    # Get 'record::record' into the general structure namespace.
    namespace import -force record::record
    namespace export record
}

package provide struct::record 1.2.1








<





|
|
<
|


<



|
>


|
>
>
|
>
|
>
>
|
>
>
|
>
>
>
>
|
>
|
|
>
|
>
>
>
>
>
>
|
>
|
|
<
|
|





|






|
<




>

>
>
|
>








<
<







>
>


>















|






>

>
>

|
|
<
|
<
<
|
<
|
|
<
|
<
<
<
<



















|






<






|















>
|
>
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
#
# Returns:
#    none
#
#------------------------------------------------------------
#
proc ::struct::record::Delete {sub_ item_} {

    variable _recorddefn
    variable _defn
    variable _count
    variable _defaults

    # puts .([info level 0])...


    set item_ [Qualify $item_]

    switch -- $sub_ {

        instance -
        instances -
        inst    {
	    # puts .instance
	    # puts .is-instance=[Exists instance $item_]

            if {[Exists instance $item_]} {

		# Locate manager namespace, i.e. class namespace for
		# instance to remove
		set nsi [Ns $item_]
		# puts .\tnsi=$nsi

		# Import the state of the manager namespace
		upvar 0 ${nsi}values    __values
		upvar 0 ${nsi}instances __instances
		upvar 0 ${nsi}record    __record
		# puts .\trecord=$__record

		# Remove instance from state
		set i [lsearch $__instances $item_]
		set __instances [lreplace $__instances $i $i]
		unset _defn($item_)

		# Process instance fields.

		foreach V $_recorddefn($__record) {
		    # puts .\tfield($V)=/clear

		    if {[regexp -- {([\w]*)::([\w]*)} $V m def inst]} {
			# Nested record detected.
			# Determine associated instance and delete recursively.
			Delete inst ${item_}.${inst}
		    } else {
			# Delete field accessor alias
			# puts .de-alias\t($item_.$V)
			uplevel #0 [list interp alias {} ${item_}.$V {}]
		    }


		    unset __values($item_,$V)
		}

		# Auto-generated id numbers increase monotonically.
		# Reverting here causes the next auto to fail, claiming
		# that the instance exists.
                # incr _count($ns) -1

            } else {
                #error "$item_ is not a instance"
            }
        }
        record  -
        records   {
	    # puts .record

            ##
            ##  Delete the instances for this
            ##  record
            ##
	    # puts .get-instances
            foreach I [Show instance "$item_"] {
                catch {
		    # puts .di/$I
		    Delete instance "$I"
		}
            }

            catch {
                unset _recorddefn($item_)
                unset _defaults($item_)
                unset _count($item_)
                namespace delete ::struct::record${item_}
            }


        }
        default   {
            error "Wrong arguments to delete"
        }

    }; # end switch

    # Remove alias associated with instance or record (class)
    # puts .de-alias\t($item_)
    catch { uplevel #0 [list interp alias {} $item_ {}]}

    # puts ./
    return

}; # end proc ::struct::record::Delete


#------------------------------------------------------------
# ::struct::record::Exists --
#
#    Tests whether a record definition or record
#    instance exists.
#
# Arguments:
#    sub_    what to test. Either 'instance' or 'record'
#    item_   the specific record instance or definition
#            that needs to be tested.
#
# Tests to see if a particular instance exists
#
#------------------------------------------------------------
#
proc ::struct::record::Exists {sub_ item_} {

    # puts .([info level 0])...

    set item_ [Qualify $item_]

    switch -glob -- $sub_ {
        inst* {
	    variable _defn

            return [info exists _defn($item_)]


        }

        record {
	    variable _recorddefn

            return [info exists _recorddefn($item_)]




        }
        default  {
            error "Wrong arguments. Must be exists record|instance target"
        }
    }; # end switch

}; # end proc ::struct::record::Exists


#------------------------------------------------------------
# ::struct::record::Qualify --
#
#    Contructs the qualified name of the calling scope. This
#    defaults to 2 levels since there is an extra proc call in
#    between.
#
# Arguments:
#    item_   the command that needs to be qualified
#    level_  how many levels to go up (default = 2)
#
# Results:
#    the item_ passed in fully qualified
#
#------------------------------------------------------------
#
proc ::struct::record::Qualify {item_ {level_ 2}} {

    if {![string match "::*" "$item_"]} {
        set ns [uplevel $level_ [list namespace current]]

        if {![string match "::" "$ns"]} {
            append ns "::"
        }

        set item_ "$ns${item_}"
    }

    return "$item_"

}; # end proc ::struct::record::Qualify

# ### ### ### ######### ######### #########
## Ready

namespace eval ::struct {
    # Get 'record::record' into the general structure namespace.
    namespace import -force record::record
    namespace export record
}

package provide struct::record 1.2.2
return

Changes to modules/struct/record.test.

23
24
25
26
27
28
29


30
31
32
33
34
35
36
}

# -------------------------------------------------------------------------

namespace import struct::record

#----------------------------------------------------------------------



test record-0.1 {record define} {
    record define phones {home work cell}
} ::phones

test record-0.2 {record define - multi line} {
    record define contact {







>
>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
}

# -------------------------------------------------------------------------

namespace import struct::record

#----------------------------------------------------------------------
## __Attention__, currently the later tests depend on actions
## performed here in the early tests (new records, instances, etc.).

test record-0.1 {record define} {
    record define phones {home work cell}
} ::phones

test record-0.2 {record define - multi line} {
    record define contact {
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87


88
89
90
91
92
93
94
	record define circular {
	    one
	    {record circular cir}
	} cir(1)
    } err
    set err
} "Can not have circular records. Structure was not created."


test record-0.6 {single instance} {
    contact cont(1)
} ::cont(1)

test record-0.7 {auto instance} {
    contact #auto
} ::contact0

test record-0.8 {instance of double nested record} {
    set res [mycontact #auto]
    lappend res [record show values $res]
    set res
} {::mycontact0 {-age {} -sex {} -cont {-first {} -middle {} -last {} -phlist {-home {} -work {} -cell {}}}}}

test record-0.9 {setting a instance var via alias} {
    cont(1).first Brett
} Brett



test record-1.0 {setting a nested instance var via alias} {
    cont(1).phlist.cell 425-555-1212
} 425-555-1212

test record-1.1 {setting a double nested instance var via alias} {
    mycontact0.cont.phlist.cell 206-555-1212







>


















>
>







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
	record define circular {
	    one
	    {record circular cir}
	} cir(1)
    } err
    set err
} "Can not have circular records. Structure was not created."


test record-0.6 {single instance} {
    contact cont(1)
} ::cont(1)

test record-0.7 {auto instance} {
    contact #auto
} ::contact0

test record-0.8 {instance of double nested record} {
    set res [mycontact #auto]
    lappend res [record show values $res]
    set res
} {::mycontact0 {-age {} -sex {} -cont {-first {} -middle {} -last {} -phlist {-home {} -work {} -cell {}}}}}

test record-0.9 {setting a instance var via alias} {
    cont(1).first Brett
} Brett

#----------------------------------------------------------------------

test record-1.0 {setting a nested instance var via alias} {
    cont(1).phlist.cell 425-555-1212
} 425-555-1212

test record-1.1 {setting a double nested instance var via alias} {
    mycontact0.cont.phlist.cell 206-555-1212
122
123
124
125
126
127
128


129
130
131
132
133
134
135
    loc(1) config -street somestreet -city somecity -state somestate -country somecountry
} ""

test record-1.9 {setting nested vars via config} {
    cont(1) config -phlist.home 425-555-1212
} ""



test record-2.0 {test value of nested member} {
    cont(1) cget -phlist.home
} 425-555-1212

test record-2.1 {config with no values} {
    loc(1) config
} [list -street somestreet -city somecity -state somestate -country somecountry]







>
>







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
    loc(1) config -street somestreet -city somecity -state somestate -country somecountry
} ""

test record-1.9 {setting nested vars via config} {
    cont(1) config -phlist.home 425-555-1212
} ""

#----------------------------------------------------------------------

test record-2.0 {test value of nested member} {
    cont(1) cget -phlist.home
} 425-555-1212

test record-2.1 {config with no values} {
    loc(1) config
} [list -street somestreet -city somecity -state somestate -country somecountry]
161
162
163
164
165
166
167


168
169
170
171
172
173
174
test record-2.8 {copy one instance to another during creation} {
    eval contact cont(3) [cont(1)]
} ::cont(3)

test record-2.9 {get the above values via alias} {
    cont(2).phlist.home
} 425-555-1212



test record-3.0 {copy one definition to another definition} {
    record define new_contact [record show members contact]
} ::new_contact

test record-3.1 {show defined records} {
    record show records







>
>







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
test record-2.8 {copy one instance to another during creation} {
    eval contact cont(3) [cont(1)]
} ::cont(3)

test record-2.9 {get the above values via alias} {
    cont(2).phlist.home
} 425-555-1212

#----------------------------------------------------------------------

test record-3.0 {copy one definition to another definition} {
    record define new_contact [record show members contact]
} ::new_contact

test record-3.1 {show defined records} {
    record show records
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
    record delete instance loc(2)
} ""

test record-3.9 {delete a nested instance} {
    record delete instance cont(2)
} ""



test record-4.0 {delete a record} {
    record delete record location
} ""

test record-4.1 {test existence of an instance that was deleted} {
    record exists instance loc(1)
} 0

test record-4.2 {show existence of an instance} {
    record exists instance cont(1)
} 1

test record-4.3 {show non-existent instance} {
    record exists instance junk
} 0

test record-4.4 {show existence of record} {
    record exists record contact
} 1






















##
##    NAMESPACE TESTS
##

test record-5.0 {record define} {
    namespace eval myns {







>
>




















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    record delete instance loc(2)
} ""

test record-3.9 {delete a nested instance} {
    record delete instance cont(2)
} ""

#----------------------------------------------------------------------

test record-4.0 {delete a record} {
    record delete record location
} ""

test record-4.1 {test existence of an instance that was deleted} {
    record exists instance loc(1)
} 0

test record-4.2 {show existence of an instance} {
    record exists instance cont(1)
} 1

test record-4.3 {show non-existent instance} {
    record exists instance junk
} 0

test record-4.4 {show existence of record} {
    record exists record contact
} 1

test record-4.5-tkt-baa334cfef {deletion of nested record through container} {
    record define details {date place}
    record define person {fullname {record details birth}}
    person js
    js.fullname "John Smith"
    js.birth.date "31 Jul 1935"
    js.birth.place London

    record delete instance js
    set r [list [record show instances person] \
	       [record show instances details]]

    record delete record details
    record delete record person

    set r
} {{} {}}
unset r

#----------------------------------------------------------------------

##
##    NAMESPACE TESTS
##

test record-5.0 {record define} {
    namespace eval myns {
294
295
296
297
298
299
300


301
302
303
304
305
306
307
    myns::cont(1) config -middle Allen -last Schwarz
} ""

test record-5.9 {get a value via cget} {
    myns::cont(1) cget -first -middle -last
} [list Brett Allen Schwarz]



test record-6.0 {record default value} {
    myns::loc(1) cget -country
} USA

test record-6.1 {setting values via config} {
    myns::loc(1) config -street somestreet -city somecity -state somestate -country somecountry
} ""







>
>







325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
    myns::cont(1) config -middle Allen -last Schwarz
} ""

test record-5.9 {get a value via cget} {
    myns::cont(1) cget -first -middle -last
} [list Brett Allen Schwarz]

#----------------------------------------------------------------------

test record-6.0 {record default value} {
    myns::loc(1) cget -country
} USA

test record-6.1 {setting values via config} {
    myns::loc(1) config -street somestreet -city somecity -state somestate -country somecountry
} ""
335
336
337
338
339
340
341


342
343
344
345
346
347
348
	location loc(2) -street street2 -city city2 -state state2 -country country2
    }
} ::myns::loc(2)

test record-6.9 {get the above value via alias} {
    myns::loc(2).street
} street2



test record-7.0 {set values during instantiation - nested record} {
    namespace eval myns {
	contact cont(2) -first John -middle Q -last Doe -phlist [list home 425-555-1212 work 425-555-1222 cell 425-555-1111]
    }
} ::myns::cont(2)








>
>







368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
	location loc(2) -street street2 -city city2 -state state2 -country country2
    }
} ::myns::loc(2)

test record-6.9 {get the above value via alias} {
    myns::loc(2).street
} street2

#----------------------------------------------------------------------

test record-7.0 {set values during instantiation - nested record} {
    namespace eval myns {
	contact cont(2) -first John -middle Q -last Doe -phlist [list home 425-555-1212 work 425-555-1222 cell 425-555-1111]
    }
} ::myns::cont(2)

380
381
382
383
384
385
386


387
388
389
390
391
392
393
} [list ::myns::loc(1) ::myns::loc(2) ::myns::loc(5)]


test record-7.9 {delete an instance} {
    record delete instance myns::loc(2)
} ""



test record-8.0 {delete a nested instance} {
    record delete instance myns::cont(2)
} ""

test record-8.1 {delete a record} {
    record delete record myns::location
} ""







>
>







415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
} [list ::myns::loc(1) ::myns::loc(2) ::myns::loc(5)]


test record-7.9 {delete an instance} {
    record delete instance myns::loc(2)
} ""

#----------------------------------------------------------------------

test record-8.0 {delete a nested instance} {
    record delete instance myns::cont(2)
} ""

test record-8.1 {delete a record} {
    record delete record myns::location
} ""
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
    record exists instance myns::junk
} 0

test record-8.5 {show existence of record} {
    record exists record myns::contact
} 1


# Auto instances and deletion.

test record-9.0 {auto instance & deletion} {
    set res {}
    lappend res [contact #auto]
    lappend res [contact #auto]

    record delete instance [lindex $res end]

    lappend res [contact #auto]

} {::contact1 ::contact2 ::contact3}



test record-10.0 {nesting records more than one level} {
    set jmod aMacro

    record define fitParams {
	amp
	unmod







|












>
>







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
    record exists instance myns::junk
} 0

test record-8.5 {show existence of record} {
    record exists record myns::contact
} 1

#----------------------------------------------------------------------
# Auto instances and deletion.

test record-9.0 {auto instance & deletion} {
    set res {}
    lappend res [contact #auto]
    lappend res [contact #auto]

    record delete instance [lindex $res end]

    lappend res [contact #auto]

} {::contact1 ::contact2 ::contact3}

#----------------------------------------------------------------------

test record-10.0 {nesting records more than one level} {
    set jmod aMacro

    record define fitParams {
	amp
	unmod
461
462
463
464
465
466
467




    $fitXYInputData.confidence 0.9

    set res [record show values $fitXYInputData]

    record delete instance $fitXYInputData
    set res
} {-silent true -verbose true -macro aMacro -confidence 0.9 -input {-reps 30 -sdev 0.1 -seed 12345 -params {-amp {} -unmod {} -jcoup {} -t2star {}} -data {-delays {} -values {}}}}











>
>
>
>
500
501
502
503
504
505
506
507
508
509
510
    $fitXYInputData.confidence 0.9

    set res [record show values $fitXYInputData]

    record delete instance $fitXYInputData
    set res
} {-silent true -verbose true -macro aMacro -confidence 0.9 -input {-reps 30 -sdev 0.1 -seed 12345 -params {-amp {} -unmod {} -jcoup {} -t2star {}} -data {-delays {} -values {}}}}

#----------------------------------------------------------------------
testsuiteCleanup
return

Changes to modules/struct/skiplist.man.

78
79
80
81
82
83
84
85
86
Walk the skiplist from the first node to the last. At each node, the
command [arg cmd] will be evaluated with the key and value of the
current node appended.

[list_end]

[vset CATEGORY {struct :: skiplist}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

78
79
80
81
82
83
84
85
86
Walk the skiplist from the first node to the last. At each node, the
command [arg cmd] will be evaluated with the key and value of the
current node appended.

[list_end]

[vset CATEGORY {struct :: skiplist}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/struct/stack.man.

100
101
102
103
104
105
106
107
108
[call [arg stackName] [method size]]

Return the number of items on the stack.

[list_end]

[vset CATEGORY {struct :: stack}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

100
101
102
103
104
105
106
107
108
[call [arg stackName] [method size]]

Return the number of items on the stack.

[list_end]

[vset CATEGORY {struct :: stack}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/struct/struct_list.man.

822
823
824
825
826
827
828
829
830
Donald E. Knuth, "Fascicle 2b of 'The Art of Computer Programming'
volume 4". Available on the Web at the author's personal site:
[uri http://www-cs-faculty.stanford.edu/~knuth/fasc2b.ps.gz].

[list_end]

[vset CATEGORY {struct :: list}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

822
823
824
825
826
827
828
829
830
Donald E. Knuth, "Fascicle 2b of 'The Art of Computer Programming'
volume 4". Available on the Web at the author's personal site:
[uri http://www-cs-faculty.stanford.edu/~knuth/fasc2b.ps.gz].

[list_end]

[vset CATEGORY {struct :: list}]
[include ../common-text/feedback.inc]
[manpage_end]

Added modules/struct/struct_map.man.























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
[comment {-*- text -*- doctools manpage}]
[vset VERSION 1]
[manpage_begin struct::map n [vset VERSION]]
[titledesc {Manage key/value maps}]
[require struct::map [opt [vset VERSION]]]
[description]

Provides a snit class whose instances manage a key/value map.
In other words, an object wrapper around Tcl arrays.

[section API]

The main command provides construction of maps:

[list_begin definitions]

[call [cmd ::struct::map] [arg mapName]]

Creates a new, empty map with an associated global Tcl command whose
name is [arg mapName].

It may be used to invoke various operations on the map.

It has the following general form:

[list_begin definitions]
[call [cmd mapName] [method method] [opt [arg "arg arg ..."]]]
[method method] and [arg arg]uments determine the exact behavior of
the command.
[list_end][comment --instance-command--]

If [arg mapName] is specified as [const %AUTO%] a unique name will be
generated by the package itself.

The result of the command is the fully-qualified name of the instance
command. 

[list_end][comment --class-command--]

[para]

The following commands are possible for map objects:

[list_begin definitions]

[call [arg mapName] [method get]]

Returns the entire map as a Tcl dictionary.

[call [arg mapName] [method names]]

Returns the list of all keys known to the map, in arbitrary order.

[call [arg mapName] [method set] [arg name] [opt [arg value]]]

Sets key [arg name] to the specified [arg value], if the value specified.

Returns the value for the key.

Throws an error if the key is not known.

[call [arg mapName] [method unset] [opt [arg pattern]...]]

Removes all keys matching at least one of the glob [arg pattern]s from
the map.

If no pattern is specified all keys are removed.
In other words, the default pattern is [const *].

The result of the command is the empty string.

[list_end]

[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/struct/struct_set.man.

128
129
130
131
132
133
134
135
136
([const false]).

[list_end]

[section REFERENCES]

[vset CATEGORY {struct :: set}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

128
129
130
131
132
133
134
135
136
([const false]).

[list_end]

[section REFERENCES]

[vset CATEGORY {struct :: set}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/struct/struct_tree.man.

784
785
786
787
788
789
790
791
792
    mytree insert 0    end 3   ; # Now create node 3 as child of node 0
    mytree insert 0    end     ; # Create another child of 0, with a
    #                              generated name. The name is returned
    #                              as the result of the command.
}]

[vset CATEGORY {struct :: tree}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

784
785
786
787
788
789
790
791
792
    mytree insert 0    end 3   ; # Now create node 3 as child of node 0
    mytree insert 0    end     ; # Create another child of 0, with a
    #                              generated name. The name is returned
    #                              as the result of the command.
}]

[vset CATEGORY {struct :: tree}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/struct/struct_tree1.man.

284
285
286
287
288
289
290
291
292
[const enter] for the first evaluation, and [const leave] for the
second.

[list_end]
[list_end]

[vset CATEGORY {struct :: tree}]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

284
285
286
287
288
289
290
291
292
[const enter] for the first evaluation, and [const leave] for the
second.

[list_end]
[list_end]

[vset CATEGORY {struct :: tree}]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/tar/tar.man.

161
162
163
164
165
166
167
168
169
% ::tar::contents new.tar
file3
}]

[list_end]

[vset CATEGORY tar]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

161
162
163
164
165
166
167
168
169
% ::tar::contents new.tar
file3
}]

[list_end]

[vset CATEGORY tar]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/term/ansi_cattr.man.

75
76
77
78
79
80
81
82
83
[call [cmd ::term::ansi::code::attr::norevers]]    Reverse off.
[call [cmd ::term::ansi::code::attr::nohidden]]    Hidden off.
[call [cmd ::term::ansi::code::attr::nostrike]]    Strike-through off.
[call [cmd ::term::ansi::code::attr::reset]]       Reset all attributes to their default values.
[list_end]

[vset CATEGORY term]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

75
76
77
78
79
80
81
82
83
[call [cmd ::term::ansi::code::attr::norevers]]    Reverse off.
[call [cmd ::term::ansi::code::attr::nohidden]]    Hidden off.
[call [cmd ::term::ansi::code::attr::nostrike]]    Strike-through off.
[call [cmd ::term::ansi::code::attr::reset]]       Reset all attributes to their default values.
[list_end]

[vset CATEGORY term]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/term/ansi_cctrl.man.

191
192
193
194
195
196
197
198
199
[call [cmd ::term::ansi::code::ctrl::showat] [arg row] [arg col] [arg text]]

Format the block of text for display at the specified location.

[list_end]

[vset CATEGORY term]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

191
192
193
194
195
196
197
198
199
[call [cmd ::term::ansi::code::ctrl::showat] [arg row] [arg col] [arg text]]

Format the block of text for display at the specified location.

[list_end]

[vset CATEGORY term]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/term/ansi_cmacros.man.

58
59
60
61
62
63
64
65
66
the right margin, after normalizing internal tabs, and then put into a
frame made of box-graphics. The result is returned as the result of
the command.

[list_end]

[vset CATEGORY term]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

58
59
60
61
62
63
64
65
66
the right margin, after normalizing internal tabs, and then put into a
frame made of box-graphics. The result is returned as the result of
the command.

[list_end]

[vset CATEGORY term]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/term/ansi_code.man.

38
39
40
41
42
43
44
45
46

This command defines a procedure [arg name] which returns the control
sequence [arg code].

[list_end]

[vset CATEGORY term]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

38
39
40
41
42
43
44
45
46

This command defines a procedure [arg name] which returns the control
sequence [arg code].

[list_end]

[vset CATEGORY term]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/term/ansi_ctrlu.man.

71
72
73
74
75
76
77
78
79

This command queries the terminal connected to the standard input for
the number of rows (aka lines) available for display.

[list_end]

[vset CATEGORY term]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

71
72
73
74
75
76
77
78
79

This command queries the terminal connected to the standard input for
the number of rows (aka lines) available for display.

[list_end]

[vset CATEGORY term]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/term/ansi_send.man.

258
259
260
261
262
263
264
265
266
[call [cmd ::term::ansi::send::showat] [arg row] [arg col] [arg text]]

Show the block of text at the specified location.

[list_end]

[vset CATEGORY term]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

258
259
260
261
262
263
264
265
266
[call [cmd ::term::ansi::send::showat] [arg row] [arg col] [arg text]]

Show the block of text at the specified location.

[list_end]

[vset CATEGORY term]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/term/imenu.man.

147
148
149
150
151
152
153
154
155
[def Enter/Return]

The interaction with the object is terminated.

[list_end]

[vset CATEGORY term]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

147
148
149
150
151
152
153
154
155
[def Enter/Return]

The interaction with the object is terminated.

[list_end]

[vset CATEGORY term]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/term/ipager.man.

146
147
148
149
150
151
152
153
154
[def Enter/Return]

The interaction with the object is terminated.

[list_end]

[vset CATEGORY term]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

146
147
148
149
150
151
152
153
154
[def Enter/Return]

The interaction with the object is terminated.

[list_end]

[vset CATEGORY term]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/term/receive.man.

69
70
71
72
73
74
75
76
77
[para]

If not specified [arg chan] defaults to [const stdin].

[list_end]

[vset CATEGORY term]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

69
70
71
72
73
74
75
76
77
[para]

If not specified [arg chan] defaults to [const stdin].

[list_end]

[vset CATEGORY term]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/term/term.man.

12
13
14
15
16
17
18
19
20

It is planned to have this package provide highlevel general terminal control
commands, in the vein of ncurses or similar packages. Currently nothing has
been implemented however. I.e. this package is empty. It can be loaded, yet
provides nothing.

[vset CATEGORY term]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

12
13
14
15
16
17
18
19
20

It is planned to have this package provide highlevel general terminal control
commands, in the vein of ncurses or similar packages. Currently nothing has
been implemented however. I.e. this package is empty. It can be loaded, yet
provides nothing.

[vset CATEGORY term]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/term/term_bind.man.

116
117
118
119
120
121
122
123
124

[para]

In other words, the set of recognized strings has to form a
[term {prefix code}].

[vset CATEGORY term]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

116
117
118
119
120
121
122
123
124

[para]

In other words, the set of recognized strings has to form a
[term {prefix code}].

[vset CATEGORY term]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/term/term_send.man.

28
29
30
31
32
33
34
35
36

This convenience command is like [cmd ::term::send::wrch], except that the
destination channel is fixed to [emph stdout].

[list_end]

[vset CATEGORY term]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

28
29
30
31
32
33
34
35
36

This convenience command is like [cmd ::term::send::wrch], except that the
destination channel is fixed to [emph stdout].

[list_end]

[vset CATEGORY term]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/textutil/adjust.man.

200
201
202
203
204
205
206
207
208

Together with [cmd ::textutil::adjust::adjust] it is possible to
create properly wrapped paragraphs with arbitrary indentations.

[list_end]

[vset CATEGORY textutil]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

200
201
202
203
204
205
206
207
208

Together with [cmd ::textutil::adjust::adjust] it is possible to
create properly wrapped paragraphs with arbitrary indentations.

[list_end]

[vset CATEGORY textutil]
[include ../common-text/feedback.inc]
[manpage_end]

Added modules/textutil/build/EastAsianWidth.txt.







































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
# EastAsianWidth-11.0.0.txt
# Date: 2018-05-14, 09:41:59 GMT [KW, LI]
# © 2018 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see http://www.unicode.org/terms_of_use.html
#
# Unicode Character Database
# For documentation, see http://www.unicode.org/reports/tr44/
#
# East_Asian_Width Property
#
# This file is an informative contributory data file in the
# Unicode Character Database.
#
# The format is two fields separated by a semicolon.
# Field 0: Unicode code point value or range of code point values
# Field 1: East_Asian_Width property, consisting of one of the following values:
#         "A", "F", "H", "N", "Na", "W"
#  - All code points, assigned or unassigned, that are not listed
#      explicitly are given the value "N".
#  - The unassigned code points in the following blocks default to "W":
#         CJK Unified Ideographs Extension A: U+3400..U+4DBF
#         CJK Unified Ideographs:             U+4E00..U+9FFF
#         CJK Compatibility Ideographs:       U+F900..U+FAFF
#  - All undesignated code points in Planes 2 and 3, whether inside or
#      outside of allocated blocks, default to "W":
#         Plane 2:                            U+20000..U+2FFFD
#         Plane 3:                            U+30000..U+3FFFD
#
# Character ranges are specified as for other property files in the
# Unicode Character Database.
#
# For legacy reasons, there are no spaces before or after the semicolon
# which separates the two fields. The comments following the number sign
# "#" list the General_Category property value or the L& alias of the
# derived value LC, the Unicode character name or names, and, in lines
# with ranges of code points, the code point count in square brackets.
#
# For more information, see UAX #11: East Asian Width,
# at http://www.unicode.org/reports/tr11/
#
# @missing: 0000..10FFFF; N
0000..001F;N     # Cc    [32] <control-0000>..<control-001F>
0020;Na          # Zs         SPACE
0021..0023;Na    # Po     [3] EXCLAMATION MARK..NUMBER SIGN
0024;Na          # Sc         DOLLAR SIGN
0025..0027;Na    # Po     [3] PERCENT SIGN..APOSTROPHE
0028;Na          # Ps         LEFT PARENTHESIS
0029;Na          # Pe         RIGHT PARENTHESIS
002A;Na          # Po         ASTERISK
002B;Na          # Sm         PLUS SIGN
002C;Na          # Po         COMMA
002D;Na          # Pd         HYPHEN-MINUS
002E..002F;Na    # Po     [2] FULL STOP..SOLIDUS
0030..0039;Na    # Nd    [10] DIGIT ZERO..DIGIT NINE
003A..003B;Na    # Po     [2] COLON..SEMICOLON
003C..003E;Na    # Sm     [3] LESS-THAN SIGN..GREATER-THAN SIGN
003F..0040;Na    # Po     [2] QUESTION MARK..COMMERCIAL AT
0041..005A;Na    # Lu    [26] LATIN CAPITAL LETTER A..LATIN CAPITAL LETTER Z
005B;Na          # Ps         LEFT SQUARE BRACKET
005C;Na          # Po         REVERSE SOLIDUS
005D;Na          # Pe         RIGHT SQUARE BRACKET
005E;Na          # Sk         CIRCUMFLEX ACCENT
005F;Na          # Pc         LOW LINE
0060;Na          # Sk         GRAVE ACCENT
0061..007A;Na    # Ll    [26] LATIN SMALL LETTER A..LATIN SMALL LETTER Z
007B;Na          # Ps         LEFT CURLY BRACKET
007C;Na          # Sm         VERTICAL LINE
007D;Na          # Pe         RIGHT CURLY BRACKET
007E;Na          # Sm         TILDE
007F;N           # Cc         <control-007F>
0080..009F;N     # Cc    [32] <control-0080>..<control-009F>
00A0;N           # Zs         NO-BREAK SPACE
00A1;A           # Po         INVERTED EXCLAMATION MARK
00A2..00A3;Na    # Sc     [2] CENT SIGN..POUND SIGN
00A4;A           # Sc         CURRENCY SIGN
00A5;Na          # Sc         YEN SIGN
00A6;Na          # So         BROKEN BAR
00A7;A           # Po         SECTION SIGN
00A8;A           # Sk         DIAERESIS
00A9;N           # So         COPYRIGHT SIGN
00AA;A           # Lo         FEMININE ORDINAL INDICATOR
00AB;N           # Pi         LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
00AC;Na          # Sm         NOT SIGN
00AD;A           # Cf         SOFT HYPHEN
00AE;A           # So         REGISTERED SIGN
00AF;Na          # Sk         MACRON
00B0;A           # So         DEGREE SIGN
00B1;A           # Sm         PLUS-MINUS SIGN
00B2..00B3;A     # No     [2] SUPERSCRIPT TWO..SUPERSCRIPT THREE
00B4;A           # Sk         ACUTE ACCENT
00B5;N           # Ll         MICRO SIGN
00B6..00B7;A     # Po     [2] PILCROW SIGN..MIDDLE DOT
00B8;A           # Sk         CEDILLA
00B9;A           # No         SUPERSCRIPT ONE
00BA;A           # Lo         MASCULINE ORDINAL INDICATOR
00BB;N           # Pf         RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
00BC..00BE;A     # No     [3] VULGAR FRACTION ONE QUARTER..VULGAR FRACTION THREE QUARTERS
00BF;A           # Po         INVERTED QUESTION MARK
00C0..00C5;N     # Lu     [6] LATIN CAPITAL LETTER A WITH GRAVE..LATIN CAPITAL LETTER A WITH RING ABOVE
00C6;A           # Lu         LATIN CAPITAL LETTER AE
00C7..00CF;N     # Lu     [9] LATIN CAPITAL LETTER C WITH CEDILLA..LATIN CAPITAL LETTER I WITH DIAERESIS
00D0;A           # Lu         LATIN CAPITAL LETTER ETH
00D1..00D6;N     # Lu     [6] LATIN CAPITAL LETTER N WITH TILDE..LATIN CAPITAL LETTER O WITH DIAERESIS
00D7;A           # Sm         MULTIPLICATION SIGN
00D8;A           # Lu         LATIN CAPITAL LETTER O WITH STROKE
00D9..00DD;N     # Lu     [5] LATIN CAPITAL LETTER U WITH GRAVE..LATIN CAPITAL LETTER Y WITH ACUTE
00DE..00E1;A     # L&     [4] LATIN CAPITAL LETTER THORN..LATIN SMALL LETTER A WITH ACUTE
00E2..00E5;N     # Ll     [4] LATIN SMALL LETTER A WITH CIRCUMFLEX..LATIN SMALL LETTER A WITH RING ABOVE
00E6;A           # Ll         LATIN SMALL LETTER AE
00E7;N           # Ll         LATIN SMALL LETTER C WITH CEDILLA
00E8..00EA;A     # Ll     [3] LATIN SMALL LETTER E WITH GRAVE..LATIN SMALL LETTER E WITH CIRCUMFLEX
00EB;N           # Ll         LATIN SMALL LETTER E WITH DIAERESIS
00EC..00ED;A     # Ll     [2] LATIN SMALL LETTER I WITH GRAVE..LATIN SMALL LETTER I WITH ACUTE
00EE..00EF;N     # Ll     [2] LATIN SMALL LETTER I WITH CIRCUMFLEX..LATIN SMALL LETTER I WITH DIAERESIS
00F0;A           # Ll         LATIN SMALL LETTER ETH
00F1;N           # Ll         LATIN SMALL LETTER N WITH TILDE
00F2..00F3;A     # Ll     [2] LATIN SMALL LETTER O WITH GRAVE..LATIN SMALL LETTER O WITH ACUTE
00F4..00F6;N     # Ll     [3] LATIN SMALL LETTER O WITH CIRCUMFLEX..LATIN SMALL LETTER O WITH DIAERESIS
00F7;A           # Sm         DIVISION SIGN
00F8..00FA;A     # Ll     [3] LATIN SMALL LETTER O WITH STROKE..LATIN SMALL LETTER U WITH ACUTE
00FB;N           # Ll         LATIN SMALL LETTER U WITH CIRCUMFLEX
00FC;A           # Ll         LATIN SMALL LETTER U WITH DIAERESIS
00FD;N           # Ll         LATIN SMALL LETTER Y WITH ACUTE
00FE;A           # Ll         LATIN SMALL LETTER THORN
00FF;N           # Ll         LATIN SMALL LETTER Y WITH DIAERESIS
0100;N           # Lu         LATIN CAPITAL LETTER A WITH MACRON
0101;A           # Ll         LATIN SMALL LETTER A WITH MACRON
0102..0110;N     # L&    [15] LATIN CAPITAL LETTER A WITH BREVE..LATIN CAPITAL LETTER D WITH STROKE
0111;A           # Ll         LATIN SMALL LETTER D WITH STROKE
0112;N           # Lu         LATIN CAPITAL LETTER E WITH MACRON
0113;A           # Ll         LATIN SMALL LETTER E WITH MACRON
0114..011A;N     # L&     [7] LATIN CAPITAL LETTER E WITH BREVE..LATIN CAPITAL LETTER E WITH CARON
011B;A           # Ll         LATIN SMALL LETTER E WITH CARON
011C..0125;N     # L&    [10] LATIN CAPITAL LETTER G WITH CIRCUMFLEX..LATIN SMALL LETTER H WITH CIRCUMFLEX
0126..0127;A     # L&     [2] LATIN CAPITAL LETTER H WITH STROKE..LATIN SMALL LETTER H WITH STROKE
0128..012A;N     # L&     [3] LATIN CAPITAL LETTER I WITH TILDE..LATIN CAPITAL LETTER I WITH MACRON
012B;A           # Ll         LATIN SMALL LETTER I WITH MACRON
012C..0130;N     # L&     [5] LATIN CAPITAL LETTER I WITH BREVE..LATIN CAPITAL LETTER I WITH DOT ABOVE
0131..0133;A     # L&     [3] LATIN SMALL LETTER DOTLESS I..LATIN SMALL LIGATURE IJ
0134..0137;N     # L&     [4] LATIN CAPITAL LETTER J WITH CIRCUMFLEX..LATIN SMALL LETTER K WITH CEDILLA
0138;A           # Ll         LATIN SMALL LETTER KRA
0139..013E;N     # L&     [6] LATIN CAPITAL LETTER L WITH ACUTE..LATIN SMALL LETTER L WITH CARON
013F..0142;A     # L&     [4] LATIN CAPITAL LETTER L WITH MIDDLE DOT..LATIN SMALL LETTER L WITH STROKE
0143;N           # Lu         LATIN CAPITAL LETTER N WITH ACUTE
0144;A           # Ll         LATIN SMALL LETTER N WITH ACUTE
0145..0147;N     # L&     [3] LATIN CAPITAL LETTER N WITH CEDILLA..LATIN CAPITAL LETTER N WITH CARON
0148..014B;A     # L&     [4] LATIN SMALL LETTER N WITH CARON..LATIN SMALL LETTER ENG
014C;N           # Lu         LATIN CAPITAL LETTER O WITH MACRON
014D;A           # Ll         LATIN SMALL LETTER O WITH MACRON
014E..0151;N     # L&     [4] LATIN CAPITAL LETTER O WITH BREVE..LATIN SMALL LETTER O WITH DOUBLE ACUTE
0152..0153;A     # L&     [2] LATIN CAPITAL LIGATURE OE..LATIN SMALL LIGATURE OE
0154..0165;N     # L&    [18] LATIN CAPITAL LETTER R WITH ACUTE..LATIN SMALL LETTER T WITH CARON
0166..0167;A     # L&     [2] LATIN CAPITAL LETTER T WITH STROKE..LATIN SMALL LETTER T WITH STROKE
0168..016A;N     # L&     [3] LATIN CAPITAL LETTER U WITH TILDE..LATIN CAPITAL LETTER U WITH MACRON
016B;A           # Ll         LATIN SMALL LETTER U WITH MACRON
016C..017F;N     # L&    [20] LATIN CAPITAL LETTER U WITH BREVE..LATIN SMALL LETTER LONG S
0180..01BA;N     # L&    [59] LATIN SMALL LETTER B WITH STROKE..LATIN SMALL LETTER EZH WITH TAIL
01BB;N           # Lo         LATIN LETTER TWO WITH STROKE
01BC..01BF;N     # L&     [4] LATIN CAPITAL LETTER TONE FIVE..LATIN LETTER WYNN
01C0..01C3;N     # Lo     [4] LATIN LETTER DENTAL CLICK..LATIN LETTER RETROFLEX CLICK
01C4..01CD;N     # L&    [10] LATIN CAPITAL LETTER DZ WITH CARON..LATIN CAPITAL LETTER A WITH CARON
01CE;A           # Ll         LATIN SMALL LETTER A WITH CARON
01CF;N           # Lu         LATIN CAPITAL LETTER I WITH CARON
01D0;A           # Ll         LATIN SMALL LETTER I WITH CARON
01D1;N           # Lu         LATIN CAPITAL LETTER O WITH CARON
01D2;A           # Ll         LATIN SMALL LETTER O WITH CARON
01D3;N           # Lu         LATIN CAPITAL LETTER U WITH CARON
01D4;A           # Ll         LATIN SMALL LETTER U WITH CARON
01D5;N           # Lu         LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON
01D6;A           # Ll         LATIN SMALL LETTER U WITH DIAERESIS AND MACRON
01D7;N           # Lu         LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE
01D8;A           # Ll         LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE
01D9;N           # Lu         LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON
01DA;A           # Ll         LATIN SMALL LETTER U WITH DIAERESIS AND CARON
01DB;N           # Lu         LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE
01DC;A           # Ll         LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE
01DD..024F;N     # L&   [115] LATIN SMALL LETTER TURNED E..LATIN SMALL LETTER Y WITH STROKE
0250;N           # Ll         LATIN SMALL LETTER TURNED A
0251;A           # Ll         LATIN SMALL LETTER ALPHA
0252..0260;N     # Ll    [15] LATIN SMALL LETTER TURNED ALPHA..LATIN SMALL LETTER G WITH HOOK
0261;A           # Ll         LATIN SMALL LETTER SCRIPT G
0262..0293;N     # Ll    [50] LATIN LETTER SMALL CAPITAL G..LATIN SMALL LETTER EZH WITH CURL
0294;N           # Lo         LATIN LETTER GLOTTAL STOP
0295..02AF;N     # Ll    [27] LATIN LETTER PHARYNGEAL VOICED FRICATIVE..LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL
02B0..02C1;N     # Lm    [18] MODIFIER LETTER SMALL H..MODIFIER LETTER REVERSED GLOTTAL STOP
02C2..02C3;N     # Sk     [2] MODIFIER LETTER LEFT ARROWHEAD..MODIFIER LETTER RIGHT ARROWHEAD
02C4;A           # Sk         MODIFIER LETTER UP ARROWHEAD
02C5;N           # Sk         MODIFIER LETTER DOWN ARROWHEAD
02C6;N           # Lm         MODIFIER LETTER CIRCUMFLEX ACCENT
02C7;A           # Lm         CARON
02C8;N           # Lm         MODIFIER LETTER VERTICAL LINE
02C9..02CB;A     # Lm     [3] MODIFIER LETTER MACRON..MODIFIER LETTER GRAVE ACCENT
02CC;N           # Lm         MODIFIER LETTER LOW VERTICAL LINE
02CD;A           # Lm         MODIFIER LETTER LOW MACRON
02CE..02CF;N     # Lm     [2] MODIFIER LETTER LOW GRAVE ACCENT..MODIFIER LETTER LOW ACUTE ACCENT
02D0;A           # Lm         MODIFIER LETTER TRIANGULAR COLON
02D1;N           # Lm         MODIFIER LETTER HALF TRIANGULAR COLON
02D2..02D7;N     # Sk     [6] MODIFIER LETTER CENTRED RIGHT HALF RING..MODIFIER LETTER MINUS SIGN
02D8..02DB;A     # Sk     [4] BREVE..OGONEK
02DC;N           # Sk         SMALL TILDE
02DD;A           # Sk         DOUBLE ACUTE ACCENT
02DE;N           # Sk         MODIFIER LETTER RHOTIC HOOK
02DF;A           # Sk         MODIFIER LETTER CROSS ACCENT
02E0..02E4;N     # Lm     [5] MODIFIER LETTER SMALL GAMMA..MODIFIER LETTER SMALL REVERSED GLOTTAL STOP
02E5..02EB;N     # Sk     [7] MODIFIER LETTER EXTRA-HIGH TONE BAR..MODIFIER LETTER YANG DEPARTING TONE MARK
02EC;N           # Lm         MODIFIER LETTER VOICING
02ED;N           # Sk         MODIFIER LETTER UNASPIRATED
02EE;N           # Lm         MODIFIER LETTER DOUBLE APOSTROPHE
02EF..02FF;N     # Sk    [17] MODIFIER LETTER LOW DOWN ARROWHEAD..MODIFIER LETTER LOW LEFT ARROW
0300..036F;A     # Mn   [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X
0370..0373;N     # L&     [4] GREEK CAPITAL LETTER HETA..GREEK SMALL LETTER ARCHAIC SAMPI
0374;N           # Lm         GREEK NUMERAL SIGN
0375;N           # Sk         GREEK LOWER NUMERAL SIGN
0376..0377;N     # L&     [2] GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA..GREEK SMALL LETTER PAMPHYLIAN DIGAMMA
037A;N           # Lm         GREEK YPOGEGRAMMENI
037B..037D;N     # Ll     [3] GREEK SMALL REVERSED LUNATE SIGMA SYMBOL..GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL
037E;N           # Po         GREEK QUESTION MARK
037F;N           # Lu         GREEK CAPITAL LETTER YOT
0384..0385;N     # Sk     [2] GREEK TONOS..GREEK DIALYTIKA TONOS
0386;N           # Lu         GREEK CAPITAL LETTER ALPHA WITH TONOS
0387;N           # Po         GREEK ANO TELEIA
0388..038A;N     # Lu     [3] GREEK CAPITAL LETTER EPSILON WITH TONOS..GREEK CAPITAL LETTER IOTA WITH TONOS
038C;N           # Lu         GREEK CAPITAL LETTER OMICRON WITH TONOS
038E..0390;N     # L&     [3] GREEK CAPITAL LETTER UPSILON WITH TONOS..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
0391..03A1;A     # Lu    [17] GREEK CAPITAL LETTER ALPHA..GREEK CAPITAL LETTER RHO
03A3..03A9;A     # Lu     [7] GREEK CAPITAL LETTER SIGMA..GREEK CAPITAL LETTER OMEGA
03AA..03B0;N     # L&     [7] GREEK CAPITAL LETTER IOTA WITH DIALYTIKA..GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
03B1..03C1;A     # Ll    [17] GREEK SMALL LETTER ALPHA..GREEK SMALL LETTER RHO
03C2;N           # Ll         GREEK SMALL LETTER FINAL SIGMA
03C3..03C9;A     # Ll     [7] GREEK SMALL LETTER SIGMA..GREEK SMALL LETTER OMEGA
03CA..03F5;N     # L&    [44] GREEK SMALL LETTER IOTA WITH DIALYTIKA..GREEK LUNATE EPSILON SYMBOL
03F6;N           # Sm         GREEK REVERSED LUNATE EPSILON SYMBOL
03F7..03FF;N     # L&     [9] GREEK CAPITAL LETTER SHO..GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL
0400;N           # Lu         CYRILLIC CAPITAL LETTER IE WITH GRAVE
0401;A           # Lu         CYRILLIC CAPITAL LETTER IO
0402..040F;N     # Lu    [14] CYRILLIC CAPITAL LETTER DJE..CYRILLIC CAPITAL LETTER DZHE
0410..044F;A     # L&    [64] CYRILLIC CAPITAL LETTER A..CYRILLIC SMALL LETTER YA
0450;N           # Ll         CYRILLIC SMALL LETTER IE WITH GRAVE
0451;A           # Ll         CYRILLIC SMALL LETTER IO
0452..0481;N     # L&    [48] CYRILLIC SMALL LETTER DJE..CYRILLIC SMALL LETTER KOPPA
0482;N           # So         CYRILLIC THOUSANDS SIGN
0483..0487;N     # Mn     [5] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE
0488..0489;N     # Me     [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN
048A..04FF;N     # L&   [118] CYRILLIC CAPITAL LETTER SHORT I WITH TAIL..CYRILLIC SMALL LETTER HA WITH STROKE
0500..052F;N     # L&    [48] CYRILLIC CAPITAL LETTER KOMI DE..CYRILLIC SMALL LETTER EL WITH DESCENDER
0531..0556;N     # Lu    [38] ARMENIAN CAPITAL LETTER AYB..ARMENIAN CAPITAL LETTER FEH
0559;N           # Lm         ARMENIAN MODIFIER LETTER LEFT HALF RING
055A..055F;N     # Po     [6] ARMENIAN APOSTROPHE..ARMENIAN ABBREVIATION MARK
0560..0588;N     # Ll    [41] ARMENIAN SMALL LETTER TURNED AYB..ARMENIAN SMALL LETTER YI WITH STROKE
0589;N           # Po         ARMENIAN FULL STOP
058A;N           # Pd         ARMENIAN HYPHEN
058D..058E;N     # So     [2] RIGHT-FACING ARMENIAN ETERNITY SIGN..LEFT-FACING ARMENIAN ETERNITY SIGN
058F;N           # Sc         ARMENIAN DRAM SIGN
0591..05BD;N     # Mn    [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG
05BE;N           # Pd         HEBREW PUNCTUATION MAQAF
05BF;N           # Mn         HEBREW POINT RAFE
05C0;N           # Po         HEBREW PUNCTUATION PASEQ
05C1..05C2;N     # Mn     [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT
05C3;N           # Po         HEBREW PUNCTUATION SOF PASUQ
05C4..05C5;N     # Mn     [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT
05C6;N           # Po         HEBREW PUNCTUATION NUN HAFUKHA
05C7;N           # Mn         HEBREW POINT QAMATS QATAN
05D0..05EA;N     # Lo    [27] HEBREW LETTER ALEF..HEBREW LETTER TAV
05EF..05F2;N     # Lo     [4] HEBREW YOD TRIANGLE..HEBREW LIGATURE YIDDISH DOUBLE YOD
05F3..05F4;N     # Po     [2] HEBREW PUNCTUATION GERESH..HEBREW PUNCTUATION GERSHAYIM
0600..0605;N     # Cf     [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE
0606..0608;N     # Sm     [3] ARABIC-INDIC CUBE ROOT..ARABIC RAY
0609..060A;N     # Po     [2] ARABIC-INDIC PER MILLE SIGN..ARABIC-INDIC PER TEN THOUSAND SIGN
060B;N           # Sc         AFGHANI SIGN
060C..060D;N     # Po     [2] ARABIC COMMA..ARABIC DATE SEPARATOR
060E..060F;N     # So     [2] ARABIC POETIC VERSE SIGN..ARABIC SIGN MISRA
0610..061A;N     # Mn    [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA
061B;N           # Po         ARABIC SEMICOLON
061C;N           # Cf         ARABIC LETTER MARK
061E..061F;N     # Po     [2] ARABIC TRIPLE DOT PUNCTUATION MARK..ARABIC QUESTION MARK
0620..063F;N     # Lo    [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
0640;N           # Lm         ARABIC TATWEEL
0641..064A;N     # Lo    [10] ARABIC LETTER FEH..ARABIC LETTER YEH
064B..065F;N     # Mn    [21] ARABIC FATHATAN..ARABIC WAVY HAMZA BELOW
0660..0669;N     # Nd    [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE
066A..066D;N     # Po     [4] ARABIC PERCENT SIGN..ARABIC FIVE POINTED STAR
066E..066F;N     # Lo     [2] ARABIC LETTER DOTLESS BEH..ARABIC LETTER DOTLESS QAF
0670;N           # Mn         ARABIC LETTER SUPERSCRIPT ALEF
0671..06D3;N     # Lo    [99] ARABIC LETTER ALEF WASLA..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE
06D4;N           # Po         ARABIC FULL STOP
06D5;N           # Lo         ARABIC LETTER AE
06D6..06DC;N     # Mn     [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN
06DD;N           # Cf         ARABIC END OF AYAH
06DE;N           # So         ARABIC START OF RUB EL HIZB
06DF..06E4;N     # Mn     [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA
06E5..06E6;N     # Lm     [2] ARABIC SMALL WAW..ARABIC SMALL YEH
06E7..06E8;N     # Mn     [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON
06E9;N           # So         ARABIC PLACE OF SAJDAH
06EA..06ED;N     # Mn     [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM
06EE..06EF;N     # Lo     [2] ARABIC LETTER DAL WITH INVERTED V..ARABIC LETTER REH WITH INVERTED V
06F0..06F9;N     # Nd    [10] EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE
06FA..06FC;N     # Lo     [3] ARABIC LETTER SHEEN WITH DOT BELOW..ARABIC LETTER GHAIN WITH DOT BELOW
06FD..06FE;N     # So     [2] ARABIC SIGN SINDHI AMPERSAND..ARABIC SIGN SINDHI POSTPOSITION MEN
06FF;N           # Lo         ARABIC LETTER HEH WITH INVERTED V
0700..070D;N     # Po    [14] SYRIAC END OF PARAGRAPH..SYRIAC HARKLEAN ASTERISCUS
070F;N           # Cf         SYRIAC ABBREVIATION MARK
0710;N           # Lo         SYRIAC LETTER ALAPH
0711;N           # Mn         SYRIAC LETTER SUPERSCRIPT ALAPH
0712..072F;N     # Lo    [30] SYRIAC LETTER BETH..SYRIAC LETTER PERSIAN DHALATH
0730..074A;N     # Mn    [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH
074D..074F;N     # Lo     [3] SYRIAC LETTER SOGDIAN ZHAIN..SYRIAC LETTER SOGDIAN FE
0750..077F;N     # Lo    [48] ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW..ARABIC LETTER KAF WITH TWO DOTS ABOVE
0780..07A5;N     # Lo    [38] THAANA LETTER HAA..THAANA LETTER WAAVU
07A6..07B0;N     # Mn    [11] THAANA ABAFILI..THAANA SUKUN
07B1;N           # Lo         THAANA LETTER NAA
07C0..07C9;N     # Nd    [10] NKO DIGIT ZERO..NKO DIGIT NINE
07CA..07EA;N     # Lo    [33] NKO LETTER A..NKO LETTER JONA RA
07EB..07F3;N     # Mn     [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE
07F4..07F5;N     # Lm     [2] NKO HIGH TONE APOSTROPHE..NKO LOW TONE APOSTROPHE
07F6;N           # So         NKO SYMBOL OO DENNEN
07F7..07F9;N     # Po     [3] NKO SYMBOL GBAKURUNEN..NKO EXCLAMATION MARK
07FA;N           # Lm         NKO LAJANYALAN
07FD;N           # Mn         NKO DANTAYALAN
07FE..07FF;N     # Sc     [2] NKO DOROME SIGN..NKO TAMAN SIGN
0800..0815;N     # Lo    [22] SAMARITAN LETTER ALAF..SAMARITAN LETTER TAAF
0816..0819;N     # Mn     [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH
081A;N           # Lm         SAMARITAN MODIFIER LETTER EPENTHETIC YUT
081B..0823;N     # Mn     [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A
0824;N           # Lm         SAMARITAN MODIFIER LETTER SHORT A
0825..0827;N     # Mn     [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U
0828;N           # Lm         SAMARITAN MODIFIER LETTER I
0829..082D;N     # Mn     [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA
0830..083E;N     # Po    [15] SAMARITAN PUNCTUATION NEQUDAA..SAMARITAN PUNCTUATION ANNAAU
0840..0858;N     # Lo    [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN
0859..085B;N     # Mn     [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK
085E;N           # Po         MANDAIC PUNCTUATION
0860..086A;N     # Lo    [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA
08A0..08B4;N     # Lo    [21] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER KAF WITH DOT BELOW
08B6..08BD;N     # Lo     [8] ARABIC LETTER BEH WITH SMALL MEEM ABOVE..ARABIC LETTER AFRICAN NOON
08D3..08E1;N     # Mn    [15] ARABIC SMALL LOW WAW..ARABIC SMALL HIGH SIGN SAFHA
08E2;N           # Cf         ARABIC DISPUTED END OF AYAH
08E3..08FF;N     # Mn    [29] ARABIC TURNED DAMMA BELOW..ARABIC MARK SIDEWAYS NOON GHUNNA
0900..0902;N     # Mn     [3] DEVANAGARI SIGN INVERTED CANDRABINDU..DEVANAGARI SIGN ANUSVARA
0903;N           # Mc         DEVANAGARI SIGN VISARGA
0904..0939;N     # Lo    [54] DEVANAGARI LETTER SHORT A..DEVANAGARI LETTER HA
093A;N           # Mn         DEVANAGARI VOWEL SIGN OE
093B;N           # Mc         DEVANAGARI VOWEL SIGN OOE
093C;N           # Mn         DEVANAGARI SIGN NUKTA
093D;N           # Lo         DEVANAGARI SIGN AVAGRAHA
093E..0940;N     # Mc     [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II
0941..0948;N     # Mn     [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI
0949..094C;N     # Mc     [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU
094D;N           # Mn         DEVANAGARI SIGN VIRAMA
094E..094F;N     # Mc     [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW
0950;N           # Lo         DEVANAGARI OM
0951..0957;N     # Mn     [7] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI VOWEL SIGN UUE
0958..0961;N     # Lo    [10] DEVANAGARI LETTER QA..DEVANAGARI LETTER VOCALIC LL
0962..0963;N     # Mn     [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL
0964..0965;N     # Po     [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA
0966..096F;N     # Nd    [10] DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE
0970;N           # Po         DEVANAGARI ABBREVIATION SIGN
0971;N           # Lm         DEVANAGARI SIGN HIGH SPACING DOT
0972..097F;N     # Lo    [14] DEVANAGARI LETTER CANDRA A..DEVANAGARI LETTER BBA
0980;N           # Lo         BENGALI ANJI
0981;N           # Mn         BENGALI SIGN CANDRABINDU
0982..0983;N     # Mc     [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA
0985..098C;N     # Lo     [8] BENGALI LETTER A..BENGALI LETTER VOCALIC L
098F..0990;N     # Lo     [2] BENGALI LETTER E..BENGALI LETTER AI
0993..09A8;N     # Lo    [22] BENGALI LETTER O..BENGALI LETTER NA
09AA..09B0;N     # Lo     [7] BENGALI LETTER PA..BENGALI LETTER RA
09B2;N           # Lo         BENGALI LETTER LA
09B6..09B9;N     # Lo     [4] BENGALI LETTER SHA..BENGALI LETTER HA
09BC;N           # Mn         BENGALI SIGN NUKTA
09BD;N           # Lo         BENGALI SIGN AVAGRAHA
09BE..09C0;N     # Mc     [3] BENGALI VOWEL SIGN AA..BENGALI VOWEL SIGN II
09C1..09C4;N     # Mn     [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR
09C7..09C8;N     # Mc     [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI
09CB..09CC;N     # Mc     [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU
09CD;N           # Mn         BENGALI SIGN VIRAMA
09CE;N           # Lo         BENGALI LETTER KHANDA TA
09D7;N           # Mc         BENGALI AU LENGTH MARK
09DC..09DD;N     # Lo     [2] BENGALI LETTER RRA..BENGALI LETTER RHA
09DF..09E1;N     # Lo     [3] BENGALI LETTER YYA..BENGALI LETTER VOCALIC LL
09E2..09E3;N     # Mn     [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL
09E6..09EF;N     # Nd    [10] BENGALI DIGIT ZERO..BENGALI DIGIT NINE
09F0..09F1;N     # Lo     [2] BENGALI LETTER RA WITH MIDDLE DIAGONAL..BENGALI LETTER RA WITH LOWER DIAGONAL
09F2..09F3;N     # Sc     [2] BENGALI RUPEE MARK..BENGALI RUPEE SIGN
09F4..09F9;N     # No     [6] BENGALI CURRENCY NUMERATOR ONE..BENGALI CURRENCY DENOMINATOR SIXTEEN
09FA;N           # So         BENGALI ISSHAR
09FB;N           # Sc         BENGALI GANDA MARK
09FC;N           # Lo         BENGALI LETTER VEDIC ANUSVARA
09FD;N           # Po         BENGALI ABBREVIATION SIGN
09FE;N           # Mn         BENGALI SANDHI MARK
0A01..0A02;N     # Mn     [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI
0A03;N           # Mc         GURMUKHI SIGN VISARGA
0A05..0A0A;N     # Lo     [6] GURMUKHI LETTER A..GURMUKHI LETTER UU
0A0F..0A10;N     # Lo     [2] GURMUKHI LETTER EE..GURMUKHI LETTER AI
0A13..0A28;N     # Lo    [22] GURMUKHI LETTER OO..GURMUKHI LETTER NA
0A2A..0A30;N     # Lo     [7] GURMUKHI LETTER PA..GURMUKHI LETTER RA
0A32..0A33;N     # Lo     [2] GURMUKHI LETTER LA..GURMUKHI LETTER LLA
0A35..0A36;N     # Lo     [2] GURMUKHI LETTER VA..GURMUKHI LETTER SHA
0A38..0A39;N     # Lo     [2] GURMUKHI LETTER SA..GURMUKHI LETTER HA
0A3C;N           # Mn         GURMUKHI SIGN NUKTA
0A3E..0A40;N     # Mc     [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II
0A41..0A42;N     # Mn     [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU
0A47..0A48;N     # Mn     [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI
0A4B..0A4D;N     # Mn     [3] GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA
0A51;N           # Mn         GURMUKHI SIGN UDAAT
0A59..0A5C;N     # Lo     [4] GURMUKHI LETTER KHHA..GURMUKHI LETTER RRA
0A5E;N           # Lo         GURMUKHI LETTER FA
0A66..0A6F;N     # Nd    [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGIT NINE
0A70..0A71;N     # Mn     [2] GURMUKHI TIPPI..GURMUKHI ADDAK
0A72..0A74;N     # Lo     [3] GURMUKHI IRI..GURMUKHI EK ONKAR
0A75;N           # Mn         GURMUKHI SIGN YAKASH
0A76;N           # Po         GURMUKHI ABBREVIATION SIGN
0A81..0A82;N     # Mn     [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA
0A83;N           # Mc         GUJARATI SIGN VISARGA
0A85..0A8D;N     # Lo     [9] GUJARATI LETTER A..GUJARATI VOWEL CANDRA E
0A8F..0A91;N     # Lo     [3] GUJARATI LETTER E..GUJARATI VOWEL CANDRA O
0A93..0AA8;N     # Lo    [22] GUJARATI LETTER O..GUJARATI LETTER NA
0AAA..0AB0;N     # Lo     [7] GUJARATI LETTER PA..GUJARATI LETTER RA
0AB2..0AB3;N     # Lo     [2] GUJARATI LETTER LA..GUJARATI LETTER LLA
0AB5..0AB9;N     # Lo     [5] GUJARATI LETTER VA..GUJARATI LETTER HA
0ABC;N           # Mn         GUJARATI SIGN NUKTA
0ABD;N           # Lo         GUJARATI SIGN AVAGRAHA
0ABE..0AC0;N     # Mc     [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II
0AC1..0AC5;N     # Mn     [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E
0AC7..0AC8;N     # Mn     [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI
0AC9;N           # Mc         GUJARATI VOWEL SIGN CANDRA O
0ACB..0ACC;N     # Mc     [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU
0ACD;N           # Mn         GUJARATI SIGN VIRAMA
0AD0;N           # Lo         GUJARATI OM
0AE0..0AE1;N     # Lo     [2] GUJARATI LETTER VOCALIC RR..GUJARATI LETTER VOCALIC LL
0AE2..0AE3;N     # Mn     [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL
0AE6..0AEF;N     # Nd    [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE
0AF0;N           # Po         GUJARATI ABBREVIATION SIGN
0AF1;N           # Sc         GUJARATI RUPEE SIGN
0AF9;N           # Lo         GUJARATI LETTER ZHA
0AFA..0AFF;N     # Mn     [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE
0B01;N           # Mn         ORIYA SIGN CANDRABINDU
0B02..0B03;N     # Mc     [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA
0B05..0B0C;N     # Lo     [8] ORIYA LETTER A..ORIYA LETTER VOCALIC L
0B0F..0B10;N     # Lo     [2] ORIYA LETTER E..ORIYA LETTER AI
0B13..0B28;N     # Lo    [22] ORIYA LETTER O..ORIYA LETTER NA
0B2A..0B30;N     # Lo     [7] ORIYA LETTER PA..ORIYA LETTER RA
0B32..0B33;N     # Lo     [2] ORIYA LETTER LA..ORIYA LETTER LLA
0B35..0B39;N     # Lo     [5] ORIYA LETTER VA..ORIYA LETTER HA
0B3C;N           # Mn         ORIYA SIGN NUKTA
0B3D;N           # Lo         ORIYA SIGN AVAGRAHA
0B3E;N           # Mc         ORIYA VOWEL SIGN AA
0B3F;N           # Mn         ORIYA VOWEL SIGN I
0B40;N           # Mc         ORIYA VOWEL SIGN II
0B41..0B44;N     # Mn     [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR
0B47..0B48;N     # Mc     [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI
0B4B..0B4C;N     # Mc     [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU
0B4D;N           # Mn         ORIYA SIGN VIRAMA
0B56;N           # Mn         ORIYA AI LENGTH MARK
0B57;N           # Mc         ORIYA AU LENGTH MARK
0B5C..0B5D;N     # Lo     [2] ORIYA LETTER RRA..ORIYA LETTER RHA
0B5F..0B61;N     # Lo     [3] ORIYA LETTER YYA..ORIYA LETTER VOCALIC LL
0B62..0B63;N     # Mn     [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL
0B66..0B6F;N     # Nd    [10] ORIYA DIGIT ZERO..ORIYA DIGIT NINE
0B70;N           # So         ORIYA ISSHAR
0B71;N           # Lo         ORIYA LETTER WA
0B72..0B77;N     # No     [6] ORIYA FRACTION ONE QUARTER..ORIYA FRACTION THREE SIXTEENTHS
0B82;N           # Mn         TAMIL SIGN ANUSVARA
0B83;N           # Lo         TAMIL SIGN VISARGA
0B85..0B8A;N     # Lo     [6] TAMIL LETTER A..TAMIL LETTER UU
0B8E..0B90;N     # Lo     [3] TAMIL LETTER E..TAMIL LETTER AI
0B92..0B95;N     # Lo     [4] TAMIL LETTER O..TAMIL LETTER KA
0B99..0B9A;N     # Lo     [2] TAMIL LETTER NGA..TAMIL LETTER CA
0B9C;N           # Lo         TAMIL LETTER JA
0B9E..0B9F;N     # Lo     [2] TAMIL LETTER NYA..TAMIL LETTER TTA
0BA3..0BA4;N     # Lo     [2] TAMIL LETTER NNA..TAMIL LETTER TA
0BA8..0BAA;N     # Lo     [3] TAMIL LETTER NA..TAMIL LETTER PA
0BAE..0BB9;N     # Lo    [12] TAMIL LETTER MA..TAMIL LETTER HA
0BBE..0BBF;N     # Mc     [2] TAMIL VOWEL SIGN AA..TAMIL VOWEL SIGN I
0BC0;N           # Mn         TAMIL VOWEL SIGN II
0BC1..0BC2;N     # Mc     [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU
0BC6..0BC8;N     # Mc     [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI
0BCA..0BCC;N     # Mc     [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU
0BCD;N           # Mn         TAMIL SIGN VIRAMA
0BD0;N           # Lo         TAMIL OM
0BD7;N           # Mc         TAMIL AU LENGTH MARK
0BE6..0BEF;N     # Nd    [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE
0BF0..0BF2;N     # No     [3] TAMIL NUMBER TEN..TAMIL NUMBER ONE THOUSAND
0BF3..0BF8;N     # So     [6] TAMIL DAY SIGN..TAMIL AS ABOVE SIGN
0BF9;N           # Sc         TAMIL RUPEE SIGN
0BFA;N           # So         TAMIL NUMBER SIGN
0C00;N           # Mn         TELUGU SIGN COMBINING CANDRABINDU ABOVE
0C01..0C03;N     # Mc     [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA
0C04;N           # Mn         TELUGU SIGN COMBINING ANUSVARA ABOVE
0C05..0C0C;N     # Lo     [8] TELUGU LETTER A..TELUGU LETTER VOCALIC L
0C0E..0C10;N     # Lo     [3] TELUGU LETTER E..TELUGU LETTER AI
0C12..0C28;N     # Lo    [23] TELUGU LETTER O..TELUGU LETTER NA
0C2A..0C39;N     # Lo    [16] TELUGU LETTER PA..TELUGU LETTER HA
0C3D;N           # Lo         TELUGU SIGN AVAGRAHA
0C3E..0C40;N     # Mn     [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II
0C41..0C44;N     # Mc     [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR
0C46..0C48;N     # Mn     [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI
0C4A..0C4D;N     # Mn     [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA
0C55..0C56;N     # Mn     [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK
0C58..0C5A;N     # Lo     [3] TELUGU LETTER TSA..TELUGU LETTER RRRA
0C60..0C61;N     # Lo     [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL
0C62..0C63;N     # Mn     [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL
0C66..0C6F;N     # Nd    [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE
0C78..0C7E;N     # No     [7] TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR..TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR
0C7F;N           # So         TELUGU SIGN TUUMU
0C80;N           # Lo         KANNADA SIGN SPACING CANDRABINDU
0C81;N           # Mn         KANNADA SIGN CANDRABINDU
0C82..0C83;N     # Mc     [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA
0C84;N           # Po         KANNADA SIGN SIDDHAM
0C85..0C8C;N     # Lo     [8] KANNADA LETTER A..KANNADA LETTER VOCALIC L
0C8E..0C90;N     # Lo     [3] KANNADA LETTER E..KANNADA LETTER AI
0C92..0CA8;N     # Lo    [23] KANNADA LETTER O..KANNADA LETTER NA
0CAA..0CB3;N     # Lo    [10] KANNADA LETTER PA..KANNADA LETTER LLA
0CB5..0CB9;N     # Lo     [5] KANNADA LETTER VA..KANNADA LETTER HA
0CBC;N           # Mn         KANNADA SIGN NUKTA
0CBD;N           # Lo         KANNADA SIGN AVAGRAHA
0CBE;N           # Mc         KANNADA VOWEL SIGN AA
0CBF;N           # Mn         KANNADA VOWEL SIGN I
0CC0..0CC4;N     # Mc     [5] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN VOCALIC RR
0CC6;N           # Mn         KANNADA VOWEL SIGN E
0CC7..0CC8;N     # Mc     [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI
0CCA..0CCB;N     # Mc     [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO
0CCC..0CCD;N     # Mn     [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA
0CD5..0CD6;N     # Mc     [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK
0CDE;N           # Lo         KANNADA LETTER FA
0CE0..0CE1;N     # Lo     [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL
0CE2..0CE3;N     # Mn     [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL
0CE6..0CEF;N     # Nd    [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE
0CF1..0CF2;N     # Lo     [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA
0D00..0D01;N     # Mn     [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU
0D02..0D03;N     # Mc     [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA
0D05..0D0C;N     # Lo     [8] MALAYALAM LETTER A..MALAYALAM LETTER VOCALIC L
0D0E..0D10;N     # Lo     [3] MALAYALAM LETTER E..MALAYALAM LETTER AI
0D12..0D3A;N     # Lo    [41] MALAYALAM LETTER O..MALAYALAM LETTER TTTA
0D3B..0D3C;N     # Mn     [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA
0D3D;N           # Lo         MALAYALAM SIGN AVAGRAHA
0D3E..0D40;N     # Mc     [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II
0D41..0D44;N     # Mn     [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR
0D46..0D48;N     # Mc     [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI
0D4A..0D4C;N     # Mc     [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU
0D4D;N           # Mn         MALAYALAM SIGN VIRAMA
0D4E;N           # Lo         MALAYALAM LETTER DOT REPH
0D4F;N           # So         MALAYALAM SIGN PARA
0D54..0D56;N     # Lo     [3] MALAYALAM LETTER CHILLU M..MALAYALAM LETTER CHILLU LLL
0D57;N           # Mc         MALAYALAM AU LENGTH MARK
0D58..0D5E;N     # No     [7] MALAYALAM FRACTION ONE ONE-HUNDRED-AND-SIXTIETH..MALAYALAM FRACTION ONE FIFTH
0D5F..0D61;N     # Lo     [3] MALAYALAM LETTER ARCHAIC II..MALAYALAM LETTER VOCALIC LL
0D62..0D63;N     # Mn     [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL
0D66..0D6F;N     # Nd    [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE
0D70..0D78;N     # No     [9] MALAYALAM NUMBER TEN..MALAYALAM FRACTION THREE SIXTEENTHS
0D79;N           # So         MALAYALAM DATE MARK
0D7A..0D7F;N     # Lo     [6] MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K
0D82..0D83;N     # Mc     [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA
0D85..0D96;N     # Lo    [18] SINHALA LETTER AYANNA..SINHALA LETTER AUYANNA
0D9A..0DB1;N     # Lo    [24] SINHALA LETTER ALPAPRAANA KAYANNA..SINHALA LETTER DANTAJA NAYANNA
0DB3..0DBB;N     # Lo     [9] SINHALA LETTER SANYAKA DAYANNA..SINHALA LETTER RAYANNA
0DBD;N           # Lo         SINHALA LETTER DANTAJA LAYANNA
0DC0..0DC6;N     # Lo     [7] SINHALA LETTER VAYANNA..SINHALA LETTER FAYANNA
0DCA;N           # Mn         SINHALA SIGN AL-LAKUNA
0DCF..0DD1;N     # Mc     [3] SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA
0DD2..0DD4;N     # Mn     [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA
0DD6;N           # Mn         SINHALA VOWEL SIGN DIGA PAA-PILLA
0DD8..0DDF;N     # Mc     [8] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN GAYANUKITTA
0DE6..0DEF;N     # Nd    [10] SINHALA LITH DIGIT ZERO..SINHALA LITH DIGIT NINE
0DF2..0DF3;N     # Mc     [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA
0DF4;N           # Po         SINHALA PUNCTUATION KUNDDALIYA
0E01..0E30;N     # Lo    [48] THAI CHARACTER KO KAI..THAI CHARACTER SARA A
0E31;N           # Mn         THAI CHARACTER MAI HAN-AKAT
0E32..0E33;N     # Lo     [2] THAI CHARACTER SARA AA..THAI CHARACTER SARA AM
0E34..0E3A;N     # Mn     [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU
0E3F;N           # Sc         THAI CURRENCY SYMBOL BAHT
0E40..0E45;N     # Lo     [6] THAI CHARACTER SARA E..THAI CHARACTER LAKKHANGYAO
0E46;N           # Lm         THAI CHARACTER MAIYAMOK
0E47..0E4E;N     # Mn     [8] THAI CHARACTER MAITAIKHU..THAI CHARACTER YAMAKKAN
0E4F;N           # Po         THAI CHARACTER FONGMAN
0E50..0E59;N     # Nd    [10] THAI DIGIT ZERO..THAI DIGIT NINE
0E5A..0E5B;N     # Po     [2] THAI CHARACTER ANGKHANKHU..THAI CHARACTER KHOMUT
0E81..0E82;N     # Lo     [2] LAO LETTER KO..LAO LETTER KHO SUNG
0E84;N           # Lo         LAO LETTER KHO TAM
0E87..0E88;N     # Lo     [2] LAO LETTER NGO..LAO LETTER CO
0E8A;N           # Lo         LAO LETTER SO TAM
0E8D;N           # Lo         LAO LETTER NYO
0E94..0E97;N     # Lo     [4] LAO LETTER DO..LAO LETTER THO TAM
0E99..0E9F;N     # Lo     [7] LAO LETTER NO..LAO LETTER FO SUNG
0EA1..0EA3;N     # Lo     [3] LAO LETTER MO..LAO LETTER LO LING
0EA5;N           # Lo         LAO LETTER LO LOOT
0EA7;N           # Lo         LAO LETTER WO
0EAA..0EAB;N     # Lo     [2] LAO LETTER SO SUNG..LAO LETTER HO SUNG
0EAD..0EB0;N     # Lo     [4] LAO LETTER O..LAO VOWEL SIGN A
0EB1;N           # Mn         LAO VOWEL SIGN MAI KAN
0EB2..0EB3;N     # Lo     [2] LAO VOWEL SIGN AA..LAO VOWEL SIGN AM
0EB4..0EB9;N     # Mn     [6] LAO VOWEL SIGN I..LAO VOWEL SIGN UU
0EBB..0EBC;N     # Mn     [2] LAO VOWEL SIGN MAI KON..LAO SEMIVOWEL SIGN LO
0EBD;N           # Lo         LAO SEMIVOWEL SIGN NYO
0EC0..0EC4;N     # Lo     [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI
0EC6;N           # Lm         LAO KO LA
0EC8..0ECD;N     # Mn     [6] LAO TONE MAI EK..LAO NIGGAHITA
0ED0..0ED9;N     # Nd    [10] LAO DIGIT ZERO..LAO DIGIT NINE
0EDC..0EDF;N     # Lo     [4] LAO HO NO..LAO LETTER KHMU NYO
0F00;N           # Lo         TIBETAN SYLLABLE OM
0F01..0F03;N     # So     [3] TIBETAN MARK GTER YIG MGO TRUNCATED A..TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA
0F04..0F12;N     # Po    [15] TIBETAN MARK INITIAL YIG MGO MDUN MA..TIBETAN MARK RGYA GRAM SHAD
0F13;N           # So         TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN
0F14;N           # Po         TIBETAN MARK GTER TSHEG
0F15..0F17;N     # So     [3] TIBETAN LOGOTYPE SIGN CHAD RTAGS..TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS
0F18..0F19;N     # Mn     [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS
0F1A..0F1F;N     # So     [6] TIBETAN SIGN RDEL DKAR GCIG..TIBETAN SIGN RDEL DKAR RDEL NAG
0F20..0F29;N     # Nd    [10] TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE
0F2A..0F33;N     # No    [10] TIBETAN DIGIT HALF ONE..TIBETAN DIGIT HALF ZERO
0F34;N           # So         TIBETAN MARK BSDUS RTAGS
0F35;N           # Mn         TIBETAN MARK NGAS BZUNG NYI ZLA
0F36;N           # So         TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN
0F37;N           # Mn         TIBETAN MARK NGAS BZUNG SGOR RTAGS
0F38;N           # So         TIBETAN MARK CHE MGO
0F39;N           # Mn         TIBETAN MARK TSA -PHRU
0F3A;N           # Ps         TIBETAN MARK GUG RTAGS GYON
0F3B;N           # Pe         TIBETAN MARK GUG RTAGS GYAS
0F3C;N           # Ps         TIBETAN MARK ANG KHANG GYON
0F3D;N           # Pe         TIBETAN MARK ANG KHANG GYAS
0F3E..0F3F;N     # Mc     [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES
0F40..0F47;N     # Lo     [8] TIBETAN LETTER KA..TIBETAN LETTER JA
0F49..0F6C;N     # Lo    [36] TIBETAN LETTER NYA..TIBETAN LETTER RRA
0F71..0F7E;N     # Mn    [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO
0F7F;N           # Mc         TIBETAN SIGN RNAM BCAD
0F80..0F84;N     # Mn     [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA
0F85;N           # Po         TIBETAN MARK PALUTA
0F86..0F87;N     # Mn     [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS
0F88..0F8C;N     # Lo     [5] TIBETAN SIGN LCE TSA CAN..TIBETAN SIGN INVERTED MCHU CAN
0F8D..0F97;N     # Mn    [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA
0F99..0FBC;N     # Mn    [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA
0FBE..0FC5;N     # So     [8] TIBETAN KU RU KHA..TIBETAN SYMBOL RDO RJE
0FC6;N           # Mn         TIBETAN SYMBOL PADMA GDAN
0FC7..0FCC;N     # So     [6] TIBETAN SYMBOL RDO RJE RGYA GRAM..TIBETAN SYMBOL NOR BU BZHI -KHYIL
0FCE..0FCF;N     # So     [2] TIBETAN SIGN RDEL NAG RDEL DKAR..TIBETAN SIGN RDEL NAG GSUM
0FD0..0FD4;N     # Po     [5] TIBETAN MARK BSKA- SHOG GI MGO RGYAN..TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA
0FD5..0FD8;N     # So     [4] RIGHT-FACING SVASTI SIGN..LEFT-FACING SVASTI SIGN WITH DOTS
0FD9..0FDA;N     # Po     [2] TIBETAN MARK LEADING MCHAN RTAGS..TIBETAN MARK TRAILING MCHAN RTAGS
1000..102A;N     # Lo    [43] MYANMAR LETTER KA..MYANMAR LETTER AU
102B..102C;N     # Mc     [2] MYANMAR VOWEL SIGN TALL AA..MYANMAR VOWEL SIGN AA
102D..1030;N     # Mn     [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU
1031;N           # Mc         MYANMAR VOWEL SIGN E
1032..1037;N     # Mn     [6] MYANMAR VOWEL SIGN AI..MYANMAR SIGN DOT BELOW
1038;N           # Mc         MYANMAR SIGN VISARGA
1039..103A;N     # Mn     [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT
103B..103C;N     # Mc     [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA
103D..103E;N     # Mn     [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA
103F;N           # Lo         MYANMAR LETTER GREAT SA
1040..1049;N     # Nd    [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE
104A..104F;N     # Po     [6] MYANMAR SIGN LITTLE SECTION..MYANMAR SYMBOL GENITIVE
1050..1055;N     # Lo     [6] MYANMAR LETTER SHA..MYANMAR LETTER VOCALIC LL
1056..1057;N     # Mc     [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR
1058..1059;N     # Mn     [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL
105A..105D;N     # Lo     [4] MYANMAR LETTER MON NGA..MYANMAR LETTER MON BBE
105E..1060;N     # Mn     [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA
1061;N           # Lo         MYANMAR LETTER SGAW KAREN SHA
1062..1064;N     # Mc     [3] MYANMAR VOWEL SIGN SGAW KAREN EU..MYANMAR TONE MARK SGAW KAREN KE PHO
1065..1066;N     # Lo     [2] MYANMAR LETTER WESTERN PWO KAREN THA..MYANMAR LETTER WESTERN PWO KAREN PWA
1067..106D;N     # Mc     [7] MYANMAR VOWEL SIGN WESTERN PWO KAREN EU..MYANMAR SIGN WESTERN PWO KAREN TONE-5
106E..1070;N     # Lo     [3] MYANMAR LETTER EASTERN PWO KAREN NNA..MYANMAR LETTER EASTERN PWO KAREN GHWA
1071..1074;N     # Mn     [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE
1075..1081;N     # Lo    [13] MYANMAR LETTER SHAN KA..MYANMAR LETTER SHAN HA
1082;N           # Mn         MYANMAR CONSONANT SIGN SHAN MEDIAL WA
1083..1084;N     # Mc     [2] MYANMAR VOWEL SIGN SHAN AA..MYANMAR VOWEL SIGN SHAN E
1085..1086;N     # Mn     [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y
1087..108C;N     # Mc     [6] MYANMAR SIGN SHAN TONE-2..MYANMAR SIGN SHAN COUNCIL TONE-3
108D;N           # Mn         MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE
108E;N           # Lo         MYANMAR LETTER RUMAI PALAUNG FA
108F;N           # Mc         MYANMAR SIGN RUMAI PALAUNG TONE-5
1090..1099;N     # Nd    [10] MYANMAR SHAN DIGIT ZERO..MYANMAR SHAN DIGIT NINE
109A..109C;N     # Mc     [3] MYANMAR SIGN KHAMTI TONE-1..MYANMAR VOWEL SIGN AITON A
109D;N           # Mn         MYANMAR VOWEL SIGN AITON AI
109E..109F;N     # So     [2] MYANMAR SYMBOL SHAN ONE..MYANMAR SYMBOL SHAN EXCLAMATION
10A0..10C5;N     # Lu    [38] GEORGIAN CAPITAL LETTER AN..GEORGIAN CAPITAL LETTER HOE
10C7;N           # Lu         GEORGIAN CAPITAL LETTER YN
10CD;N           # Lu         GEORGIAN CAPITAL LETTER AEN
10D0..10FA;N     # Ll    [43] GEORGIAN LETTER AN..GEORGIAN LETTER AIN
10FB;N           # Po         GEORGIAN PARAGRAPH SEPARATOR
10FC;N           # Lm         MODIFIER LETTER GEORGIAN NAR
10FD..10FF;N     # Ll     [3] GEORGIAN LETTER AEN..GEORGIAN LETTER LABIAL SIGN
1100..115F;W     # Lo    [96] HANGUL CHOSEONG KIYEOK..HANGUL CHOSEONG FILLER
1160..11FF;N     # Lo   [160] HANGUL JUNGSEONG FILLER..HANGUL JONGSEONG SSANGNIEUN
1200..1248;N     # Lo    [73] ETHIOPIC SYLLABLE HA..ETHIOPIC SYLLABLE QWA
124A..124D;N     # Lo     [4] ETHIOPIC SYLLABLE QWI..ETHIOPIC SYLLABLE QWE
1250..1256;N     # Lo     [7] ETHIOPIC SYLLABLE QHA..ETHIOPIC SYLLABLE QHO
1258;N           # Lo         ETHIOPIC SYLLABLE QHWA
125A..125D;N     # Lo     [4] ETHIOPIC SYLLABLE QHWI..ETHIOPIC SYLLABLE QHWE
1260..1288;N     # Lo    [41] ETHIOPIC SYLLABLE BA..ETHIOPIC SYLLABLE XWA
128A..128D;N     # Lo     [4] ETHIOPIC SYLLABLE XWI..ETHIOPIC SYLLABLE XWE
1290..12B0;N     # Lo    [33] ETHIOPIC SYLLABLE NA..ETHIOPIC SYLLABLE KWA
12B2..12B5;N     # Lo     [4] ETHIOPIC SYLLABLE KWI..ETHIOPIC SYLLABLE KWE
12B8..12BE;N     # Lo     [7] ETHIOPIC SYLLABLE KXA..ETHIOPIC SYLLABLE KXO
12C0;N           # Lo         ETHIOPIC SYLLABLE KXWA
12C2..12C5;N     # Lo     [4] ETHIOPIC SYLLABLE KXWI..ETHIOPIC SYLLABLE KXWE
12C8..12D6;N     # Lo    [15] ETHIOPIC SYLLABLE WA..ETHIOPIC SYLLABLE PHARYNGEAL O
12D8..1310;N     # Lo    [57] ETHIOPIC SYLLABLE ZA..ETHIOPIC SYLLABLE GWA
1312..1315;N     # Lo     [4] ETHIOPIC SYLLABLE GWI..ETHIOPIC SYLLABLE GWE
1318..135A;N     # Lo    [67] ETHIOPIC SYLLABLE GGA..ETHIOPIC SYLLABLE FYA
135D..135F;N     # Mn     [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK
1360..1368;N     # Po     [9] ETHIOPIC SECTION MARK..ETHIOPIC PARAGRAPH SEPARATOR
1369..137C;N     # No    [20] ETHIOPIC DIGIT ONE..ETHIOPIC NUMBER TEN THOUSAND
1380..138F;N     # Lo    [16] ETHIOPIC SYLLABLE SEBATBEIT MWA..ETHIOPIC SYLLABLE PWE
1390..1399;N     # So    [10] ETHIOPIC TONAL MARK YIZET..ETHIOPIC TONAL MARK KURT
13A0..13F5;N     # Lu    [86] CHEROKEE LETTER A..CHEROKEE LETTER MV
13F8..13FD;N     # Ll     [6] CHEROKEE SMALL LETTER YE..CHEROKEE SMALL LETTER MV
1400;N           # Pd         CANADIAN SYLLABICS HYPHEN
1401..166C;N     # Lo   [620] CANADIAN SYLLABICS E..CANADIAN SYLLABICS CARRIER TTSA
166D..166E;N     # Po     [2] CANADIAN SYLLABICS CHI SIGN..CANADIAN SYLLABICS FULL STOP
166F..167F;N     # Lo    [17] CANADIAN SYLLABICS QAI..CANADIAN SYLLABICS BLACKFOOT W
1680;N           # Zs         OGHAM SPACE MARK
1681..169A;N     # Lo    [26] OGHAM LETTER BEITH..OGHAM LETTER PEITH
169B;N           # Ps         OGHAM FEATHER MARK
169C;N           # Pe         OGHAM REVERSED FEATHER MARK
16A0..16EA;N     # Lo    [75] RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X
16EB..16ED;N     # Po     [3] RUNIC SINGLE PUNCTUATION..RUNIC CROSS PUNCTUATION
16EE..16F0;N     # Nl     [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHOR SYMBOL
16F1..16F8;N     # Lo     [8] RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC
1700..170C;N     # Lo    [13] TAGALOG LETTER A..TAGALOG LETTER YA
170E..1711;N     # Lo     [4] TAGALOG LETTER LA..TAGALOG LETTER HA
1712..1714;N     # Mn     [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA
1720..1731;N     # Lo    [18] HANUNOO LETTER A..HANUNOO LETTER HA
1732..1734;N     # Mn     [3] HANUNOO VOWEL SIGN I..HANUNOO SIGN PAMUDPOD
1735..1736;N     # Po     [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION
1740..1751;N     # Lo    [18] BUHID LETTER A..BUHID LETTER HA
1752..1753;N     # Mn     [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U
1760..176C;N     # Lo    [13] TAGBANWA LETTER A..TAGBANWA LETTER YA
176E..1770;N     # Lo     [3] TAGBANWA LETTER LA..TAGBANWA LETTER SA
1772..1773;N     # Mn     [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U
1780..17B3;N     # Lo    [52] KHMER LETTER KA..KHMER INDEPENDENT VOWEL QAU
17B4..17B5;N     # Mn     [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
17B6;N           # Mc         KHMER VOWEL SIGN AA
17B7..17BD;N     # Mn     [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA
17BE..17C5;N     # Mc     [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU
17C6;N           # Mn         KHMER SIGN NIKAHIT
17C7..17C8;N     # Mc     [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU
17C9..17D3;N     # Mn    [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT
17D4..17D6;N     # Po     [3] KHMER SIGN KHAN..KHMER SIGN CAMNUC PII KUUH
17D7;N           # Lm         KHMER SIGN LEK TOO
17D8..17DA;N     # Po     [3] KHMER SIGN BEYYAL..KHMER SIGN KOOMUUT
17DB;N           # Sc         KHMER CURRENCY SYMBOL RIEL
17DC;N           # Lo         KHMER SIGN AVAKRAHASANYA
17DD;N           # Mn         KHMER SIGN ATTHACAN
17E0..17E9;N     # Nd    [10] KHMER DIGIT ZERO..KHMER DIGIT NINE
17F0..17F9;N     # No    [10] KHMER SYMBOL LEK ATTAK SON..KHMER SYMBOL LEK ATTAK PRAM-BUON
1800..1805;N     # Po     [6] MONGOLIAN BIRGA..MONGOLIAN FOUR DOTS
1806;N           # Pd         MONGOLIAN TODO SOFT HYPHEN
1807..180A;N     # Po     [4] MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER..MONGOLIAN NIRUGU
180B..180D;N     # Mn     [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
180E;N           # Cf         MONGOLIAN VOWEL SEPARATOR
1810..1819;N     # Nd    [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE
1820..1842;N     # Lo    [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI
1843;N           # Lm         MONGOLIAN LETTER TODO LONG VOWEL SIGN
1844..1878;N     # Lo    [53] MONGOLIAN LETTER TODO E..MONGOLIAN LETTER CHA WITH TWO DOTS
1880..1884;N     # Lo     [5] MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER ALI GALI INVERTED UBADAMA
1885..1886;N     # Mn     [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA
1887..18A8;N     # Lo    [34] MONGOLIAN LETTER ALI GALI A..MONGOLIAN LETTER MANCHU ALI GALI BHA
18A9;N           # Mn         MONGOLIAN LETTER ALI GALI DAGALGA
18AA;N           # Lo         MONGOLIAN LETTER MANCHU ALI GALI LHA
18B0..18F5;N     # Lo    [70] CANADIAN SYLLABICS OY..CANADIAN SYLLABICS CARRIER DENTAL S
1900..191E;N     # Lo    [31] LIMBU VOWEL-CARRIER LETTER..LIMBU LETTER TRA
1920..1922;N     # Mn     [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U
1923..1926;N     # Mc     [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU
1927..1928;N     # Mn     [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O
1929..192B;N     # Mc     [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA
1930..1931;N     # Mc     [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA
1932;N           # Mn         LIMBU SMALL LETTER ANUSVARA
1933..1938;N     # Mc     [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA
1939..193B;N     # Mn     [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I
1940;N           # So         LIMBU SIGN LOO
1944..1945;N     # Po     [2] LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK
1946..194F;N     # Nd    [10] LIMBU DIGIT ZERO..LIMBU DIGIT NINE
1950..196D;N     # Lo    [30] TAI LE LETTER KA..TAI LE LETTER AI
1970..1974;N     # Lo     [5] TAI LE LETTER TONE-2..TAI LE LETTER TONE-6
1980..19AB;N     # Lo    [44] NEW TAI LUE LETTER HIGH QA..NEW TAI LUE LETTER LOW SUA
19B0..19C9;N     # Lo    [26] NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE TONE MARK-2
19D0..19D9;N     # Nd    [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE
19DA;N           # No         NEW TAI LUE THAM DIGIT ONE
19DE..19DF;N     # So     [2] NEW TAI LUE SIGN LAE..NEW TAI LUE SIGN LAEV
19E0..19FF;N     # So    [32] KHMER SYMBOL PATHAMASAT..KHMER SYMBOL DAP-PRAM ROC
1A00..1A16;N     # Lo    [23] BUGINESE LETTER KA..BUGINESE LETTER HA
1A17..1A18;N     # Mn     [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U
1A19..1A1A;N     # Mc     [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O
1A1B;N           # Mn         BUGINESE VOWEL SIGN AE
1A1E..1A1F;N     # Po     [2] BUGINESE PALLAWA..BUGINESE END OF SECTION
1A20..1A54;N     # Lo    [53] TAI THAM LETTER HIGH KA..TAI THAM LETTER GREAT SA
1A55;N           # Mc         TAI THAM CONSONANT SIGN MEDIAL RA
1A56;N           # Mn         TAI THAM CONSONANT SIGN MEDIAL LA
1A57;N           # Mc         TAI THAM CONSONANT SIGN LA TANG LAI
1A58..1A5E;N     # Mn     [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA
1A60;N           # Mn         TAI THAM SIGN SAKOT
1A61;N           # Mc         TAI THAM VOWEL SIGN A
1A62;N           # Mn         TAI THAM VOWEL SIGN MAI SAT
1A63..1A64;N     # Mc     [2] TAI THAM VOWEL SIGN AA..TAI THAM VOWEL SIGN TALL AA
1A65..1A6C;N     # Mn     [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW
1A6D..1A72;N     # Mc     [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI
1A73..1A7C;N     # Mn    [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN
1A7F;N           # Mn         TAI THAM COMBINING CRYPTOGRAMMIC DOT
1A80..1A89;N     # Nd    [10] TAI THAM HORA DIGIT ZERO..TAI THAM HORA DIGIT NINE
1A90..1A99;N     # Nd    [10] TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGIT NINE
1AA0..1AA6;N     # Po     [7] TAI THAM SIGN WIANG..TAI THAM SIGN REVERSED ROTATED RANA
1AA7;N           # Lm         TAI THAM SIGN MAI YAMOK
1AA8..1AAD;N     # Po     [6] TAI THAM SIGN KAAN..TAI THAM SIGN CAANG
1AB0..1ABD;N     # Mn    [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW
1ABE;N           # Me         COMBINING PARENTHESES OVERLAY
1B00..1B03;N     # Mn     [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG
1B04;N           # Mc         BALINESE SIGN BISAH
1B05..1B33;N     # Lo    [47] BALINESE LETTER AKARA..BALINESE LETTER HA
1B34;N           # Mn         BALINESE SIGN REREKAN
1B35;N           # Mc         BALINESE VOWEL SIGN TEDUNG
1B36..1B3A;N     # Mn     [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA
1B3B;N           # Mc         BALINESE VOWEL SIGN RA REPA TEDUNG
1B3C;N           # Mn         BALINESE VOWEL SIGN LA LENGA
1B3D..1B41;N     # Mc     [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG
1B42;N           # Mn         BALINESE VOWEL SIGN PEPET
1B43..1B44;N     # Mc     [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG
1B45..1B4B;N     # Lo     [7] BALINESE LETTER KAF SASAK..BALINESE LETTER ASYURA SASAK
1B50..1B59;N     # Nd    [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE
1B5A..1B60;N     # Po     [7] BALINESE PANTI..BALINESE PAMENENG
1B61..1B6A;N     # So    [10] BALINESE MUSICAL SYMBOL DONG..BALINESE MUSICAL SYMBOL DANG GEDE
1B6B..1B73;N     # Mn     [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG
1B74..1B7C;N     # So     [9] BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG..BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING
1B80..1B81;N     # Mn     [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR
1B82;N           # Mc         SUNDANESE SIGN PANGWISAD
1B83..1BA0;N     # Lo    [30] SUNDANESE LETTER A..SUNDANESE LETTER HA
1BA1;N           # Mc         SUNDANESE CONSONANT SIGN PAMINGKAL
1BA2..1BA5;N     # Mn     [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU
1BA6..1BA7;N     # Mc     [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG
1BA8..1BA9;N     # Mn     [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG
1BAA;N           # Mc         SUNDANESE SIGN PAMAAEH
1BAB..1BAD;N     # Mn     [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA
1BAE..1BAF;N     # Lo     [2] SUNDANESE LETTER KHA..SUNDANESE LETTER SYA
1BB0..1BB9;N     # Nd    [10] SUNDANESE DIGIT ZERO..SUNDANESE DIGIT NINE
1BBA..1BBF;N     # Lo     [6] SUNDANESE AVAGRAHA..SUNDANESE LETTER FINAL M
1BC0..1BE5;N     # Lo    [38] BATAK LETTER A..BATAK LETTER U
1BE6;N           # Mn         BATAK SIGN TOMPI
1BE7;N           # Mc         BATAK VOWEL SIGN E
1BE8..1BE9;N     # Mn     [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE
1BEA..1BEC;N     # Mc     [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O
1BED;N           # Mn         BATAK VOWEL SIGN KARO O
1BEE;N           # Mc         BATAK VOWEL SIGN U
1BEF..1BF1;N     # Mn     [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H
1BF2..1BF3;N     # Mc     [2] BATAK PANGOLAT..BATAK PANONGONAN
1BFC..1BFF;N     # Po     [4] BATAK SYMBOL BINDU NA METEK..BATAK SYMBOL BINDU PANGOLAT
1C00..1C23;N     # Lo    [36] LEPCHA LETTER KA..LEPCHA LETTER A
1C24..1C2B;N     # Mc     [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU
1C2C..1C33;N     # Mn     [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T
1C34..1C35;N     # Mc     [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG
1C36..1C37;N     # Mn     [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA
1C3B..1C3F;N     # Po     [5] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION TSHOOK
1C40..1C49;N     # Nd    [10] LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE
1C4D..1C4F;N     # Lo     [3] LEPCHA LETTER TTA..LEPCHA LETTER DDA
1C50..1C59;N     # Nd    [10] OL CHIKI DIGIT ZERO..OL CHIKI DIGIT NINE
1C5A..1C77;N     # Lo    [30] OL CHIKI LETTER LA..OL CHIKI LETTER OH
1C78..1C7D;N     # Lm     [6] OL CHIKI MU TTUDDAG..OL CHIKI AHAD
1C7E..1C7F;N     # Po     [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD
1C80..1C88;N     # Ll     [9] CYRILLIC SMALL LETTER ROUNDED VE..CYRILLIC SMALL LETTER UNBLENDED UK
1C90..1CBA;N     # Lu    [43] GEORGIAN MTAVRULI CAPITAL LETTER AN..GEORGIAN MTAVRULI CAPITAL LETTER AIN
1CBD..1CBF;N     # Lu     [3] GEORGIAN MTAVRULI CAPITAL LETTER AEN..GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN
1CC0..1CC7;N     # Po     [8] SUNDANESE PUNCTUATION BINDU SURYA..SUNDANESE PUNCTUATION BINDU BA SATANGA
1CD0..1CD2;N     # Mn     [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA
1CD3;N           # Po         VEDIC SIGN NIHSHVASA
1CD4..1CE0;N     # Mn    [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA
1CE1;N           # Mc         VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA
1CE2..1CE8;N     # Mn     [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL
1CE9..1CEC;N     # Lo     [4] VEDIC SIGN ANUSVARA ANTARGOMUKHA..VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL
1CED;N           # Mn         VEDIC SIGN TIRYAK
1CEE..1CF1;N     # Lo     [4] VEDIC SIGN HEXIFORM LONG ANUSVARA..VEDIC SIGN ANUSVARA UBHAYATO MUKHA
1CF2..1CF3;N     # Mc     [2] VEDIC SIGN ARDHAVISARGA..VEDIC SIGN ROTATED ARDHAVISARGA
1CF4;N           # Mn         VEDIC TONE CANDRA ABOVE
1CF5..1CF6;N     # Lo     [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN UPADHMANIYA
1CF7;N           # Mc         VEDIC SIGN ATIKRAMA
1CF8..1CF9;N     # Mn     [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE
1D00..1D2B;N     # Ll    [44] LATIN LETTER SMALL CAPITAL A..CYRILLIC LETTER SMALL CAPITAL EL
1D2C..1D6A;N     # Lm    [63] MODIFIER LETTER CAPITAL A..GREEK SUBSCRIPT SMALL LETTER CHI
1D6B..1D77;N     # Ll    [13] LATIN SMALL LETTER UE..LATIN SMALL LETTER TURNED G
1D78;N           # Lm         MODIFIER LETTER CYRILLIC EN
1D79..1D7F;N     # Ll     [7] LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER UPSILON WITH STROKE
1D80..1D9A;N     # Ll    [27] LATIN SMALL LETTER B WITH PALATAL HOOK..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK
1D9B..1DBF;N     # Lm    [37] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA
1DC0..1DF9;N     # Mn    [58] COMBINING DOTTED GRAVE ACCENT..COMBINING WIDE INVERTED BRIDGE BELOW
1DFB..1DFF;N     # Mn     [5] COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
1E00..1EFF;N     # L&   [256] LATIN CAPITAL LETTER A WITH RING BELOW..LATIN SMALL LETTER Y WITH LOOP
1F00..1F15;N     # L&    [22] GREEK SMALL LETTER ALPHA WITH PSILI..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA
1F18..1F1D;N     # Lu     [6] GREEK CAPITAL LETTER EPSILON WITH PSILI..GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA
1F20..1F45;N     # L&    [38] GREEK SMALL LETTER ETA WITH PSILI..GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA
1F48..1F4D;N     # Lu     [6] GREEK CAPITAL LETTER OMICRON WITH PSILI..GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA
1F50..1F57;N     # Ll     [8] GREEK SMALL LETTER UPSILON WITH PSILI..GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI
1F59;N           # Lu         GREEK CAPITAL LETTER UPSILON WITH DASIA
1F5B;N           # Lu         GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA
1F5D;N           # Lu         GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA
1F5F..1F7D;N     # L&    [31] GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI..GREEK SMALL LETTER OMEGA WITH OXIA
1F80..1FB4;N     # L&    [53] GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI..GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI
1FB6..1FBC;N     # L&     [7] GREEK SMALL LETTER ALPHA WITH PERISPOMENI..GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI
1FBD;N           # Sk         GREEK KORONIS
1FBE;N           # Ll         GREEK PROSGEGRAMMENI
1FBF..1FC1;N     # Sk     [3] GREEK PSILI..GREEK DIALYTIKA AND PERISPOMENI
1FC2..1FC4;N     # Ll     [3] GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI
1FC6..1FCC;N     # L&     [7] GREEK SMALL LETTER ETA WITH PERISPOMENI..GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI
1FCD..1FCF;N     # Sk     [3] GREEK PSILI AND VARIA..GREEK PSILI AND PERISPOMENI
1FD0..1FD3;N     # Ll     [4] GREEK SMALL LETTER IOTA WITH VRACHY..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA
1FD6..1FDB;N     # L&     [6] GREEK SMALL LETTER IOTA WITH PERISPOMENI..GREEK CAPITAL LETTER IOTA WITH OXIA
1FDD..1FDF;N     # Sk     [3] GREEK DASIA AND VARIA..GREEK DASIA AND PERISPOMENI
1FE0..1FEC;N     # L&    [13] GREEK SMALL LETTER UPSILON WITH VRACHY..GREEK CAPITAL LETTER RHO WITH DASIA
1FED..1FEF;N     # Sk     [3] GREEK DIALYTIKA AND VARIA..GREEK VARIA
1FF2..1FF4;N     # Ll     [3] GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI
1FF6..1FFC;N     # L&     [7] GREEK SMALL LETTER OMEGA WITH PERISPOMENI..GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
1FFD..1FFE;N     # Sk     [2] GREEK OXIA..GREEK DASIA
2000..200A;N     # Zs    [11] EN QUAD..HAIR SPACE
200B..200F;N     # Cf     [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
2010;A           # Pd         HYPHEN
2011..2012;N     # Pd     [2] NON-BREAKING HYPHEN..FIGURE DASH
2013..2015;A     # Pd     [3] EN DASH..HORIZONTAL BAR
2016;A           # Po         DOUBLE VERTICAL LINE
2017;N           # Po         DOUBLE LOW LINE
2018;A           # Pi         LEFT SINGLE QUOTATION MARK
2019;A           # Pf         RIGHT SINGLE QUOTATION MARK
201A;N           # Ps         SINGLE LOW-9 QUOTATION MARK
201B;N           # Pi         SINGLE HIGH-REVERSED-9 QUOTATION MARK
201C;A           # Pi         LEFT DOUBLE QUOTATION MARK
201D;A           # Pf         RIGHT DOUBLE QUOTATION MARK
201E;N           # Ps         DOUBLE LOW-9 QUOTATION MARK
201F;N           # Pi         DOUBLE HIGH-REVERSED-9 QUOTATION MARK
2020..2022;A     # Po     [3] DAGGER..BULLET
2023;N           # Po         TRIANGULAR BULLET
2024..2027;A     # Po     [4] ONE DOT LEADER..HYPHENATION POINT
2028;N           # Zl         LINE SEPARATOR
2029;N           # Zp         PARAGRAPH SEPARATOR
202A..202E;N     # Cf     [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
202F;N           # Zs         NARROW NO-BREAK SPACE
2030;A           # Po         PER MILLE SIGN
2031;N           # Po         PER TEN THOUSAND SIGN
2032..2033;A     # Po     [2] PRIME..DOUBLE PRIME
2034;N           # Po         TRIPLE PRIME
2035;A           # Po         REVERSED PRIME
2036..2038;N     # Po     [3] REVERSED DOUBLE PRIME..CARET
2039;N           # Pi         SINGLE LEFT-POINTING ANGLE QUOTATION MARK
203A;N           # Pf         SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
203B;A           # Po         REFERENCE MARK
203C..203D;N     # Po     [2] DOUBLE EXCLAMATION MARK..INTERROBANG
203E;A           # Po         OVERLINE
203F..2040;N     # Pc     [2] UNDERTIE..CHARACTER TIE
2041..2043;N     # Po     [3] CARET INSERTION POINT..HYPHEN BULLET
2044;N           # Sm         FRACTION SLASH
2045;N           # Ps         LEFT SQUARE BRACKET WITH QUILL
2046;N           # Pe         RIGHT SQUARE BRACKET WITH QUILL
2047..2051;N     # Po    [11] DOUBLE QUESTION MARK..TWO ASTERISKS ALIGNED VERTICALLY
2052;N           # Sm         COMMERCIAL MINUS SIGN
2053;N           # Po         SWUNG DASH
2054;N           # Pc         INVERTED UNDERTIE
2055..205E;N     # Po    [10] FLOWER PUNCTUATION MARK..VERTICAL FOUR DOTS
205F;N           # Zs         MEDIUM MATHEMATICAL SPACE
2060..2064;N     # Cf     [5] WORD JOINER..INVISIBLE PLUS
2066..206F;N     # Cf    [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
2070;N           # No         SUPERSCRIPT ZERO
2071;N           # Lm         SUPERSCRIPT LATIN SMALL LETTER I
2074;A           # No         SUPERSCRIPT FOUR
2075..2079;N     # No     [5] SUPERSCRIPT FIVE..SUPERSCRIPT NINE
207A..207C;N     # Sm     [3] SUPERSCRIPT PLUS SIGN..SUPERSCRIPT EQUALS SIGN
207D;N           # Ps         SUPERSCRIPT LEFT PARENTHESIS
207E;N           # Pe         SUPERSCRIPT RIGHT PARENTHESIS
207F;A           # Lm         SUPERSCRIPT LATIN SMALL LETTER N
2080;N           # No         SUBSCRIPT ZERO
2081..2084;A     # No     [4] SUBSCRIPT ONE..SUBSCRIPT FOUR
2085..2089;N     # No     [5] SUBSCRIPT FIVE..SUBSCRIPT NINE
208A..208C;N     # Sm     [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN
208D;N           # Ps         SUBSCRIPT LEFT PARENTHESIS
208E;N           # Pe         SUBSCRIPT RIGHT PARENTHESIS
2090..209C;N     # Lm    [13] LATIN SUBSCRIPT SMALL LETTER A..LATIN SUBSCRIPT SMALL LETTER T
20A0..20A8;N     # Sc     [9] EURO-CURRENCY SIGN..RUPEE SIGN
20A9;H           # Sc         WON SIGN
20AA..20AB;N     # Sc     [2] NEW SHEQEL SIGN..DONG SIGN
20AC;A           # Sc         EURO SIGN
20AD..20BF;N     # Sc    [19] KIP SIGN..BITCOIN SIGN
20D0..20DC;N     # Mn    [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE
20DD..20E0;N     # Me     [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH
20E1;N           # Mn         COMBINING LEFT RIGHT ARROW ABOVE
20E2..20E4;N     # Me     [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE
20E5..20F0;N     # Mn    [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE
2100..2101;N     # So     [2] ACCOUNT OF..ADDRESSED TO THE SUBJECT
2102;N           # Lu         DOUBLE-STRUCK CAPITAL C
2103;A           # So         DEGREE CELSIUS
2104;N           # So         CENTRE LINE SYMBOL
2105;A           # So         CARE OF
2106;N           # So         CADA UNA
2107;N           # Lu         EULER CONSTANT
2108;N           # So         SCRUPLE
2109;A           # So         DEGREE FAHRENHEIT
210A..2112;N     # L&     [9] SCRIPT SMALL G..SCRIPT CAPITAL L
2113;A           # Ll         SCRIPT SMALL L
2114;N           # So         L B BAR SYMBOL
2115;N           # Lu         DOUBLE-STRUCK CAPITAL N
2116;A           # So         NUMERO SIGN
2117;N           # So         SOUND RECORDING COPYRIGHT
2118;N           # Sm         SCRIPT CAPITAL P
2119..211D;N     # Lu     [5] DOUBLE-STRUCK CAPITAL P..DOUBLE-STRUCK CAPITAL R
211E..2120;N     # So     [3] PRESCRIPTION TAKE..SERVICE MARK
2121..2122;A     # So     [2] TELEPHONE SIGN..TRADE MARK SIGN
2123;N           # So         VERSICLE
2124;N           # Lu         DOUBLE-STRUCK CAPITAL Z
2125;N           # So         OUNCE SIGN
2126;A           # Lu         OHM SIGN
2127;N           # So         INVERTED OHM SIGN
2128;N           # Lu         BLACK-LETTER CAPITAL Z
2129;N           # So         TURNED GREEK SMALL LETTER IOTA
212A;N           # Lu         KELVIN SIGN
212B;A           # Lu         ANGSTROM SIGN
212C..212D;N     # Lu     [2] SCRIPT CAPITAL B..BLACK-LETTER CAPITAL C
212E;N           # So         ESTIMATED SYMBOL
212F..2134;N     # L&     [6] SCRIPT SMALL E..SCRIPT SMALL O
2135..2138;N     # Lo     [4] ALEF SYMBOL..DALET SYMBOL
2139;N           # Ll         INFORMATION SOURCE
213A..213B;N     # So     [2] ROTATED CAPITAL Q..FACSIMILE SIGN
213C..213F;N     # L&     [4] DOUBLE-STRUCK SMALL PI..DOUBLE-STRUCK CAPITAL PI
2140..2144;N     # Sm     [5] DOUBLE-STRUCK N-ARY SUMMATION..TURNED SANS-SERIF CAPITAL Y
2145..2149;N     # L&     [5] DOUBLE-STRUCK ITALIC CAPITAL D..DOUBLE-STRUCK ITALIC SMALL J
214A;N           # So         PROPERTY LINE
214B;N           # Sm         TURNED AMPERSAND
214C..214D;N     # So     [2] PER SIGN..AKTIESELSKAB
214E;N           # Ll         TURNED SMALL F
214F;N           # So         SYMBOL FOR SAMARITAN SOURCE
2150..2152;N     # No     [3] VULGAR FRACTION ONE SEVENTH..VULGAR FRACTION ONE TENTH
2153..2154;A     # No     [2] VULGAR FRACTION ONE THIRD..VULGAR FRACTION TWO THIRDS
2155..215A;N     # No     [6] VULGAR FRACTION ONE FIFTH..VULGAR FRACTION FIVE SIXTHS
215B..215E;A     # No     [4] VULGAR FRACTION ONE EIGHTH..VULGAR FRACTION SEVEN EIGHTHS
215F;N           # No         FRACTION NUMERATOR ONE
2160..216B;A     # Nl    [12] ROMAN NUMERAL ONE..ROMAN NUMERAL TWELVE
216C..216F;N     # Nl     [4] ROMAN NUMERAL FIFTY..ROMAN NUMERAL ONE THOUSAND
2170..2179;A     # Nl    [10] SMALL ROMAN NUMERAL ONE..SMALL ROMAN NUMERAL TEN
217A..2182;N     # Nl     [9] SMALL ROMAN NUMERAL ELEVEN..ROMAN NUMERAL TEN THOUSAND
2183..2184;N     # L&     [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C
2185..2188;N     # Nl     [4] ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND
2189;A           # No         VULGAR FRACTION ZERO THIRDS
218A..218B;N     # So     [2] TURNED DIGIT TWO..TURNED DIGIT THREE
2190..2194;A     # Sm     [5] LEFTWARDS ARROW..LEFT RIGHT ARROW
2195..2199;A     # So     [5] UP DOWN ARROW..SOUTH WEST ARROW
219A..219B;N     # Sm     [2] LEFTWARDS ARROW WITH STROKE..RIGHTWARDS ARROW WITH STROKE
219C..219F;N     # So     [4] LEFTWARDS WAVE ARROW..UPWARDS TWO HEADED ARROW
21A0;N           # Sm         RIGHTWARDS TWO HEADED ARROW
21A1..21A2;N     # So     [2] DOWNWARDS TWO HEADED ARROW..LEFTWARDS ARROW WITH TAIL
21A3;N           # Sm         RIGHTWARDS ARROW WITH TAIL
21A4..21A5;N     # So     [2] LEFTWARDS ARROW FROM BAR..UPWARDS ARROW FROM BAR
21A6;N           # Sm         RIGHTWARDS ARROW FROM BAR
21A7..21AD;N     # So     [7] DOWNWARDS ARROW FROM BAR..LEFT RIGHT WAVE ARROW
21AE;N           # Sm         LEFT RIGHT ARROW WITH STROKE
21AF..21B7;N     # So     [9] DOWNWARDS ZIGZAG ARROW..CLOCKWISE TOP SEMICIRCLE ARROW
21B8..21B9;A     # So     [2] NORTH WEST ARROW TO LONG BAR..LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR
21BA..21CD;N     # So    [20] ANTICLOCKWISE OPEN CIRCLE ARROW..LEFTWARDS DOUBLE ARROW WITH STROKE
21CE..21CF;N     # Sm     [2] LEFT RIGHT DOUBLE ARROW WITH STROKE..RIGHTWARDS DOUBLE ARROW WITH STROKE
21D0..21D1;N     # So     [2] LEFTWARDS DOUBLE ARROW..UPWARDS DOUBLE ARROW
21D2;A           # Sm         RIGHTWARDS DOUBLE ARROW
21D3;N           # So         DOWNWARDS DOUBLE ARROW
21D4;A           # Sm         LEFT RIGHT DOUBLE ARROW
21D5..21E6;N     # So    [18] UP DOWN DOUBLE ARROW..LEFTWARDS WHITE ARROW
21E7;A           # So         UPWARDS WHITE ARROW
21E8..21F3;N     # So    [12] RIGHTWARDS WHITE ARROW..UP DOWN WHITE ARROW
21F4..21FF;N     # Sm    [12] RIGHT ARROW WITH SMALL CIRCLE..LEFT RIGHT OPEN-HEADED ARROW
2200;A           # Sm         FOR ALL
2201;N           # Sm         COMPLEMENT
2202..2203;A     # Sm     [2] PARTIAL DIFFERENTIAL..THERE EXISTS
2204..2206;N     # Sm     [3] THERE DOES NOT EXIST..INCREMENT
2207..2208;A     # Sm     [2] NABLA..ELEMENT OF
2209..220A;N     # Sm     [2] NOT AN ELEMENT OF..SMALL ELEMENT OF
220B;A           # Sm         CONTAINS AS MEMBER
220C..220E;N     # Sm     [3] DOES NOT CONTAIN AS MEMBER..END OF PROOF
220F;A           # Sm         N-ARY PRODUCT
2210;N           # Sm         N-ARY COPRODUCT
2211;A           # Sm         N-ARY SUMMATION
2212..2214;N     # Sm     [3] MINUS SIGN..DOT PLUS
2215;A           # Sm         DIVISION SLASH
2216..2219;N     # Sm     [4] SET MINUS..BULLET OPERATOR
221A;A           # Sm         SQUARE ROOT
221B..221C;N     # Sm     [2] CUBE ROOT..FOURTH ROOT
221D..2220;A     # Sm     [4] PROPORTIONAL TO..ANGLE
2221..2222;N     # Sm     [2] MEASURED ANGLE..SPHERICAL ANGLE
2223;A           # Sm         DIVIDES
2224;N           # Sm         DOES NOT DIVIDE
2225;A           # Sm         PARALLEL TO
2226;N           # Sm         NOT PARALLEL TO
2227..222C;A     # Sm     [6] LOGICAL AND..DOUBLE INTEGRAL
222D;N           # Sm         TRIPLE INTEGRAL
222E;A           # Sm         CONTOUR INTEGRAL
222F..2233;N     # Sm     [5] SURFACE INTEGRAL..ANTICLOCKWISE CONTOUR INTEGRAL
2234..2237;A     # Sm     [4] THEREFORE..PROPORTION
2238..223B;N     # Sm     [4] DOT MINUS..HOMOTHETIC
223C..223D;A     # Sm     [2] TILDE OPERATOR..REVERSED TILDE
223E..2247;N     # Sm    [10] INVERTED LAZY S..NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO
2248;A           # Sm         ALMOST EQUAL TO
2249..224B;N     # Sm     [3] NOT ALMOST EQUAL TO..TRIPLE TILDE
224C;A           # Sm         ALL EQUAL TO
224D..2251;N     # Sm     [5] EQUIVALENT TO..GEOMETRICALLY EQUAL TO
2252;A           # Sm         APPROXIMATELY EQUAL TO OR THE IMAGE OF
2253..225F;N     # Sm    [13] IMAGE OF OR APPROXIMATELY EQUAL TO..QUESTIONED EQUAL TO
2260..2261;A     # Sm     [2] NOT EQUAL TO..IDENTICAL TO
2262..2263;N     # Sm     [2] NOT IDENTICAL TO..STRICTLY EQUIVALENT TO
2264..2267;A     # Sm     [4] LESS-THAN OR EQUAL TO..GREATER-THAN OVER EQUAL TO
2268..2269;N     # Sm     [2] LESS-THAN BUT NOT EQUAL TO..GREATER-THAN BUT NOT EQUAL TO
226A..226B;A     # Sm     [2] MUCH LESS-THAN..MUCH GREATER-THAN
226C..226D;N     # Sm     [2] BETWEEN..NOT EQUIVALENT TO
226E..226F;A     # Sm     [2] NOT LESS-THAN..NOT GREATER-THAN
2270..2281;N     # Sm    [18] NEITHER LESS-THAN NOR EQUAL TO..DOES NOT SUCCEED
2282..2283;A     # Sm     [2] SUBSET OF..SUPERSET OF
2284..2285;N     # Sm     [2] NOT A SUBSET OF..NOT A SUPERSET OF
2286..2287;A     # Sm     [2] SUBSET OF OR EQUAL TO..SUPERSET OF OR EQUAL TO
2288..2294;N     # Sm    [13] NEITHER A SUBSET OF NOR EQUAL TO..SQUARE CUP
2295;A           # Sm         CIRCLED PLUS
2296..2298;N     # Sm     [3] CIRCLED MINUS..CIRCLED DIVISION SLASH
2299;A           # Sm         CIRCLED DOT OPERATOR
229A..22A4;N     # Sm    [11] CIRCLED RING OPERATOR..DOWN TACK
22A5;A           # Sm         UP TACK
22A6..22BE;N     # Sm    [25] ASSERTION..RIGHT ANGLE WITH ARC
22BF;A           # Sm         RIGHT TRIANGLE
22C0..22FF;N     # Sm    [64] N-ARY LOGICAL AND..Z NOTATION BAG MEMBERSHIP
2300..2307;N     # So     [8] DIAMETER SIGN..WAVY LINE
2308;N           # Ps         LEFT CEILING
2309;N           # Pe         RIGHT CEILING
230A;N           # Ps         LEFT FLOOR
230B;N           # Pe         RIGHT FLOOR
230C..2311;N     # So     [6] BOTTOM RIGHT CROP..SQUARE LOZENGE
2312;A           # So         ARC
2313..2319;N     # So     [7] SEGMENT..TURNED NOT SIGN
231A..231B;W     # So     [2] WATCH..HOURGLASS
231C..231F;N     # So     [4] TOP LEFT CORNER..BOTTOM RIGHT CORNER
2320..2321;N     # Sm     [2] TOP HALF INTEGRAL..BOTTOM HALF INTEGRAL
2322..2328;N     # So     [7] FROWN..KEYBOARD
2329;W           # Ps         LEFT-POINTING ANGLE BRACKET
232A;W           # Pe         RIGHT-POINTING ANGLE BRACKET
232B..237B;N     # So    [81] ERASE TO THE LEFT..NOT CHECK MARK
237C;N           # Sm         RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW
237D..239A;N     # So    [30] SHOULDERED OPEN BOX..CLEAR SCREEN SYMBOL
239B..23B3;N     # Sm    [25] LEFT PARENTHESIS UPPER HOOK..SUMMATION BOTTOM
23B4..23DB;N     # So    [40] TOP SQUARE BRACKET..FUSE
23DC..23E1;N     # Sm     [6] TOP PARENTHESIS..BOTTOM TORTOISE SHELL BRACKET
23E2..23E8;N     # So     [7] WHITE TRAPEZIUM..DECIMAL EXPONENT SYMBOL
23E9..23EC;W     # So     [4] BLACK RIGHT-POINTING DOUBLE TRIANGLE..BLACK DOWN-POINTING DOUBLE TRIANGLE
23ED..23EF;N     # So     [3] BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR..BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR
23F0;W           # So         ALARM CLOCK
23F1..23F2;N     # So     [2] STOPWATCH..TIMER CLOCK
23F3;W           # So         HOURGLASS WITH FLOWING SAND
23F4..23FF;N     # So    [12] BLACK MEDIUM LEFT-POINTING TRIANGLE..OBSERVER EYE SYMBOL
2400..2426;N     # So    [39] SYMBOL FOR NULL..SYMBOL FOR SUBSTITUTE FORM TWO
2440..244A;N     # So    [11] OCR HOOK..OCR DOUBLE BACKSLASH
2460..249B;A     # No    [60] CIRCLED DIGIT ONE..NUMBER TWENTY FULL STOP
249C..24E9;A     # So    [78] PARENTHESIZED LATIN SMALL LETTER A..CIRCLED LATIN SMALL LETTER Z
24EA;N           # No         CIRCLED DIGIT ZERO
24EB..24FF;A     # No    [21] NEGATIVE CIRCLED NUMBER ELEVEN..NEGATIVE CIRCLED DIGIT ZERO
2500..254B;A     # So    [76] BOX DRAWINGS LIGHT HORIZONTAL..BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL
254C..254F;N     # So     [4] BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL..BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL
2550..2573;A     # So    [36] BOX DRAWINGS DOUBLE HORIZONTAL..BOX DRAWINGS LIGHT DIAGONAL CROSS
2574..257F;N     # So    [12] BOX DRAWINGS LIGHT LEFT..BOX DRAWINGS HEAVY UP AND LIGHT DOWN
2580..258F;A     # So    [16] UPPER HALF BLOCK..LEFT ONE EIGHTH BLOCK
2590..2591;N     # So     [2] RIGHT HALF BLOCK..LIGHT SHADE
2592..2595;A     # So     [4] MEDIUM SHADE..RIGHT ONE EIGHTH BLOCK
2596..259F;N     # So    [10] QUADRANT LOWER LEFT..QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
25A0..25A1;A     # So     [2] BLACK SQUARE..WHITE SQUARE
25A2;N           # So         WHITE SQUARE WITH ROUNDED CORNERS
25A3..25A9;A     # So     [7] WHITE SQUARE CONTAINING BLACK SMALL SQUARE..SQUARE WITH DIAGONAL CROSSHATCH FILL
25AA..25B1;N     # So     [8] BLACK SMALL SQUARE..WHITE PARALLELOGRAM
25B2..25B3;A     # So     [2] BLACK UP-POINTING TRIANGLE..WHITE UP-POINTING TRIANGLE
25B4..25B5;N     # So     [2] BLACK UP-POINTING SMALL TRIANGLE..WHITE UP-POINTING SMALL TRIANGLE
25B6;A           # So         BLACK RIGHT-POINTING TRIANGLE
25B7;A           # Sm         WHITE RIGHT-POINTING TRIANGLE
25B8..25BB;N     # So     [4] BLACK RIGHT-POINTING SMALL TRIANGLE..WHITE RIGHT-POINTING POINTER
25BC..25BD;A     # So     [2] BLACK DOWN-POINTING TRIANGLE..WHITE DOWN-POINTING TRIANGLE
25BE..25BF;N     # So     [2] BLACK DOWN-POINTING SMALL TRIANGLE..WHITE DOWN-POINTING SMALL TRIANGLE
25C0;A           # So         BLACK LEFT-POINTING TRIANGLE
25C1;A           # Sm         WHITE LEFT-POINTING TRIANGLE
25C2..25C5;N     # So     [4] BLACK LEFT-POINTING SMALL TRIANGLE..WHITE LEFT-POINTING POINTER
25C6..25C8;A     # So     [3] BLACK DIAMOND..WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND
25C9..25CA;N     # So     [2] FISHEYE..LOZENGE
25CB;A           # So         WHITE CIRCLE
25CC..25CD;N     # So     [2] DOTTED CIRCLE..CIRCLE WITH VERTICAL FILL
25CE..25D1;A     # So     [4] BULLSEYE..CIRCLE WITH RIGHT HALF BLACK
25D2..25E1;N     # So    [16] CIRCLE WITH LOWER HALF BLACK..LOWER HALF CIRCLE
25E2..25E5;A     # So     [4] BLACK LOWER RIGHT TRIANGLE..BLACK UPPER RIGHT TRIANGLE
25E6..25EE;N     # So     [9] WHITE BULLET..UP-POINTING TRIANGLE WITH RIGHT HALF BLACK
25EF;A           # So         LARGE CIRCLE
25F0..25F7;N     # So     [8] WHITE SQUARE WITH UPPER LEFT QUADRANT..WHITE CIRCLE WITH UPPER RIGHT QUADRANT
25F8..25FC;N     # Sm     [5] UPPER LEFT TRIANGLE..BLACK MEDIUM SQUARE
25FD..25FE;W     # Sm     [2] WHITE MEDIUM SMALL SQUARE..BLACK MEDIUM SMALL SQUARE
25FF;N           # Sm         LOWER RIGHT TRIANGLE
2600..2604;N     # So     [5] BLACK SUN WITH RAYS..COMET
2605..2606;A     # So     [2] BLACK STAR..WHITE STAR
2607..2608;N     # So     [2] LIGHTNING..THUNDERSTORM
2609;A           # So         SUN
260A..260D;N     # So     [4] ASCENDING NODE..OPPOSITION
260E..260F;A     # So     [2] BLACK TELEPHONE..WHITE TELEPHONE
2610..2613;N     # So     [4] BALLOT BOX..SALTIRE
2614..2615;W     # So     [2] UMBRELLA WITH RAIN DROPS..HOT BEVERAGE
2616..261B;N     # So     [6] WHITE SHOGI PIECE..BLACK RIGHT POINTING INDEX
261C;A           # So         WHITE LEFT POINTING INDEX
261D;N           # So         WHITE UP POINTING INDEX
261E;A           # So         WHITE RIGHT POINTING INDEX
261F..263F;N     # So    [33] WHITE DOWN POINTING INDEX..MERCURY
2640;A           # So         FEMALE SIGN
2641;N           # So         EARTH
2642;A           # So         MALE SIGN
2643..2647;N     # So     [5] JUPITER..PLUTO
2648..2653;W     # So    [12] ARIES..PISCES
2654..265F;N     # So    [12] WHITE CHESS KING..BLACK CHESS PAWN
2660..2661;A     # So     [2] BLACK SPADE SUIT..WHITE HEART SUIT
2662;N           # So         WHITE DIAMOND SUIT
2663..2665;A     # So     [3] BLACK CLUB SUIT..BLACK HEART SUIT
2666;N           # So         BLACK DIAMOND SUIT
2667..266A;A     # So     [4] WHITE CLUB SUIT..EIGHTH NOTE
266B;N           # So         BEAMED EIGHTH NOTES
266C..266D;A     # So     [2] BEAMED SIXTEENTH NOTES..MUSIC FLAT SIGN
266E;N           # So         MUSIC NATURAL SIGN
266F;A           # Sm         MUSIC SHARP SIGN
2670..267E;N     # So    [15] WEST SYRIAC CROSS..PERMANENT PAPER SIGN
267F;W           # So         WHEELCHAIR SYMBOL
2680..2692;N     # So    [19] DIE FACE-1..HAMMER AND PICK
2693;W           # So         ANCHOR
2694..269D;N     # So    [10] CROSSED SWORDS..OUTLINED WHITE STAR
269E..269F;A     # So     [2] THREE LINES CONVERGING RIGHT..THREE LINES CONVERGING LEFT
26A0;N           # So         WARNING SIGN
26A1;W           # So         HIGH VOLTAGE SIGN
26A2..26A9;N     # So     [8] DOUBLED FEMALE SIGN..HORIZONTAL MALE WITH STROKE SIGN
26AA..26AB;W     # So     [2] MEDIUM WHITE CIRCLE..MEDIUM BLACK CIRCLE
26AC..26BC;N     # So    [17] MEDIUM SMALL WHITE CIRCLE..SESQUIQUADRATE
26BD..26BE;W     # So     [2] SOCCER BALL..BASEBALL
26BF;A           # So         SQUARED KEY
26C0..26C3;N     # So     [4] WHITE DRAUGHTS MAN..BLACK DRAUGHTS KING
26C4..26C5;W     # So     [2] SNOWMAN WITHOUT SNOW..SUN BEHIND CLOUD
26C6..26CD;A     # So     [8] RAIN..DISABLED CAR
26CE;W           # So         OPHIUCHUS
26CF..26D3;A     # So     [5] PICK..CHAINS
26D4;W           # So         NO ENTRY
26D5..26E1;A     # So    [13] ALTERNATE ONE-WAY LEFT WAY TRAFFIC..RESTRICTED LEFT ENTRY-2
26E2;N           # So         ASTRONOMICAL SYMBOL FOR URANUS
26E3;A           # So         HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE
26E4..26E7;N     # So     [4] PENTAGRAM..INVERTED PENTAGRAM
26E8..26E9;A     # So     [2] BLACK CROSS ON SHIELD..SHINTO SHRINE
26EA;W           # So         CHURCH
26EB..26F1;A     # So     [7] CASTLE..UMBRELLA ON GROUND
26F2..26F3;W     # So     [2] FOUNTAIN..FLAG IN HOLE
26F4;A           # So         FERRY
26F5;W           # So         SAILBOAT
26F6..26F9;A     # So     [4] SQUARE FOUR CORNERS..PERSON WITH BALL
26FA;W           # So         TENT
26FB..26FC;A     # So     [2] JAPANESE BANK SYMBOL..HEADSTONE GRAVEYARD SYMBOL
26FD;W           # So         FUEL PUMP
26FE..26FF;A     # So     [2] CUP ON BLACK SQUARE..WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE
2700..2704;N     # So     [5] BLACK SAFETY SCISSORS..WHITE SCISSORS
2705;W           # So         WHITE HEAVY CHECK MARK
2706..2709;N     # So     [4] TELEPHONE LOCATION SIGN..ENVELOPE
270A..270B;W     # So     [2] RAISED FIST..RAISED HAND
270C..2727;N     # So    [28] VICTORY HAND..WHITE FOUR POINTED STAR
2728;W           # So         SPARKLES
2729..273C;N     # So    [20] STRESS OUTLINED WHITE STAR..OPEN CENTRE TEARDROP-SPOKED ASTERISK
273D;A           # So         HEAVY TEARDROP-SPOKED ASTERISK
273E..274B;N     # So    [14] SIX PETALLED BLACK AND WHITE FLORETTE..HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK
274C;W           # So         CROSS MARK
274D;N           # So         SHADOWED WHITE CIRCLE
274E;W           # So         NEGATIVE SQUARED CROSS MARK
274F..2752;N     # So     [4] LOWER RIGHT DROP-SHADOWED WHITE SQUARE..UPPER RIGHT SHADOWED WHITE SQUARE
2753..2755;W     # So     [3] BLACK QUESTION MARK ORNAMENT..WHITE EXCLAMATION MARK ORNAMENT
2756;N           # So         BLACK DIAMOND MINUS WHITE X
2757;W           # So         HEAVY EXCLAMATION MARK SYMBOL
2758..2767;N     # So    [16] LIGHT VERTICAL BAR..ROTATED FLORAL HEART BULLET
2768;N           # Ps         MEDIUM LEFT PARENTHESIS ORNAMENT
2769;N           # Pe         MEDIUM RIGHT PARENTHESIS ORNAMENT
276A;N           # Ps         MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT
276B;N           # Pe         MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT
276C;N           # Ps         MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT
276D;N           # Pe         MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT
276E;N           # Ps         HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT
276F;N           # Pe         HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT
2770;N           # Ps         HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT
2771;N           # Pe         HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT
2772;N           # Ps         LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT
2773;N           # Pe         LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT
2774;N           # Ps         MEDIUM LEFT CURLY BRACKET ORNAMENT
2775;N           # Pe         MEDIUM RIGHT CURLY BRACKET ORNAMENT
2776..277F;A     # No    [10] DINGBAT NEGATIVE CIRCLED DIGIT ONE..DINGBAT NEGATIVE CIRCLED NUMBER TEN
2780..2793;N     # No    [20] DINGBAT CIRCLED SANS-SERIF DIGIT ONE..DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN
2794;N           # So         HEAVY WIDE-HEADED RIGHTWARDS ARROW
2795..2797;W     # So     [3] HEAVY PLUS SIGN..HEAVY DIVISION SIGN
2798..27AF;N     # So    [24] HEAVY SOUTH EAST ARROW..NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
27B0;W           # So         CURLY LOOP
27B1..27BE;N     # So    [14] NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW..OPEN-OUTLINED RIGHTWARDS ARROW
27BF;W           # So         DOUBLE CURLY LOOP
27C0..27C4;N     # Sm     [5] THREE DIMENSIONAL ANGLE..OPEN SUPERSET
27C5;N           # Ps         LEFT S-SHAPED BAG DELIMITER
27C6;N           # Pe         RIGHT S-SHAPED BAG DELIMITER
27C7..27E5;N     # Sm    [31] OR WITH DOT INSIDE..WHITE SQUARE WITH RIGHTWARDS TICK
27E6;Na          # Ps         MATHEMATICAL LEFT WHITE SQUARE BRACKET
27E7;Na          # Pe         MATHEMATICAL RIGHT WHITE SQUARE BRACKET
27E8;Na          # Ps         MATHEMATICAL LEFT ANGLE BRACKET
27E9;Na          # Pe         MATHEMATICAL RIGHT ANGLE BRACKET
27EA;Na          # Ps         MATHEMATICAL LEFT DOUBLE ANGLE BRACKET
27EB;Na          # Pe         MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
27EC;Na          # Ps         MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET
27ED;Na          # Pe         MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET
27EE;N           # Ps         MATHEMATICAL LEFT FLATTENED PARENTHESIS
27EF;N           # Pe         MATHEMATICAL RIGHT FLATTENED PARENTHESIS
27F0..27FF;N     # Sm    [16] UPWARDS QUADRUPLE ARROW..LONG RIGHTWARDS SQUIGGLE ARROW
2800..28FF;N     # So   [256] BRAILLE PATTERN BLANK..BRAILLE PATTERN DOTS-12345678
2900..297F;N     # Sm   [128] RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE..DOWN FISH TAIL
2980..2982;N     # Sm     [3] TRIPLE VERTICAL BAR DELIMITER..Z NOTATION TYPE COLON
2983;N           # Ps         LEFT WHITE CURLY BRACKET
2984;N           # Pe         RIGHT WHITE CURLY BRACKET
2985;Na          # Ps         LEFT WHITE PARENTHESIS
2986;Na          # Pe         RIGHT WHITE PARENTHESIS
2987;N           # Ps         Z NOTATION LEFT IMAGE BRACKET
2988;N           # Pe         Z NOTATION RIGHT IMAGE BRACKET
2989;N           # Ps         Z NOTATION LEFT BINDING BRACKET
298A;N           # Pe         Z NOTATION RIGHT BINDING BRACKET
298B;N           # Ps         LEFT SQUARE BRACKET WITH UNDERBAR
298C;N           # Pe         RIGHT SQUARE BRACKET WITH UNDERBAR
298D;N           # Ps         LEFT SQUARE BRACKET WITH TICK IN TOP CORNER
298E;N           # Pe         RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
298F;N           # Ps         LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
2990;N           # Pe         RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER
2991;N           # Ps         LEFT ANGLE BRACKET WITH DOT
2992;N           # Pe         RIGHT ANGLE BRACKET WITH DOT
2993;N           # Ps         LEFT ARC LESS-THAN BRACKET
2994;N           # Pe         RIGHT ARC GREATER-THAN BRACKET
2995;N           # Ps         DOUBLE LEFT ARC GREATER-THAN BRACKET
2996;N           # Pe         DOUBLE RIGHT ARC LESS-THAN BRACKET
2997;N           # Ps         LEFT BLACK TORTOISE SHELL BRACKET
2998;N           # Pe         RIGHT BLACK TORTOISE SHELL BRACKET
2999..29D7;N     # Sm    [63] DOTTED FENCE..BLACK HOURGLASS
29D8;N           # Ps         LEFT WIGGLY FENCE
29D9;N           # Pe         RIGHT WIGGLY FENCE
29DA;N           # Ps         LEFT DOUBLE WIGGLY FENCE
29DB;N           # Pe         RIGHT DOUBLE WIGGLY FENCE
29DC..29FB;N     # Sm    [32] INCOMPLETE INFINITY..TRIPLE PLUS
29FC;N           # Ps         LEFT-POINTING CURVED ANGLE BRACKET
29FD;N           # Pe         RIGHT-POINTING CURVED ANGLE BRACKET
29FE..29FF;N     # Sm     [2] TINY..MINY
2A00..2AFF;N     # Sm   [256] N-ARY CIRCLED DOT OPERATOR..N-ARY WHITE VERTICAL BAR
2B00..2B1A;N     # So    [27] NORTH EAST WHITE ARROW..DOTTED SQUARE
2B1B..2B1C;W     # So     [2] BLACK LARGE SQUARE..WHITE LARGE SQUARE
2B1D..2B2F;N     # So    [19] BLACK VERY SMALL SQUARE..WHITE VERTICAL ELLIPSE
2B30..2B44;N     # Sm    [21] LEFT ARROW WITH SMALL CIRCLE..RIGHTWARDS ARROW THROUGH SUPERSET
2B45..2B46;N     # So     [2] LEFTWARDS QUADRUPLE ARROW..RIGHTWARDS QUADRUPLE ARROW
2B47..2B4C;N     # Sm     [6] REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW..RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR
2B4D..2B4F;N     # So     [3] DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW..SHORT BACKSLANTED SOUTH ARROW
2B50;W           # So         WHITE MEDIUM STAR
2B51..2B54;N     # So     [4] BLACK SMALL STAR..WHITE RIGHT-POINTING PENTAGON
2B55;W           # So         HEAVY LARGE CIRCLE
2B56..2B59;A     # So     [4] HEAVY OVAL WITH OVAL INSIDE..HEAVY CIRCLED SALTIRE
2B5A..2B73;N     # So    [26] SLANTED NORTH ARROW WITH HOOKED HEAD..DOWNWARDS TRIANGLE-HEADED ARROW TO BAR
2B76..2B95;N     # So    [32] NORTH WEST TRIANGLE-HEADED ARROW TO BAR..RIGHTWARDS BLACK ARROW
2B98..2BC8;N     # So    [49] THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD..BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED
2BCA..2BFE;N     # So    [53] TOP HALF BLACK CIRCLE..REVERSED RIGHT ANGLE
2C00..2C2E;N     # Lu    [47] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE
2C30..2C5E;N     # Ll    [47] GLAGOLITIC SMALL LETTER AZU..GLAGOLITIC SMALL LETTER LATINATE MYSLITE
2C60..2C7B;N     # L&    [28] LATIN CAPITAL LETTER L WITH DOUBLE BAR..LATIN LETTER SMALL CAPITAL TURNED E
2C7C..2C7D;N     # Lm     [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V
2C7E..2C7F;N     # Lu     [2] LATIN CAPITAL LETTER S WITH SWASH TAIL..LATIN CAPITAL LETTER Z WITH SWASH TAIL
2C80..2CE4;N     # L&   [101] COPTIC CAPITAL LETTER ALFA..COPTIC SYMBOL KAI
2CE5..2CEA;N     # So     [6] COPTIC SYMBOL MI RO..COPTIC SYMBOL SHIMA SIMA
2CEB..2CEE;N     # L&     [4] COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI..COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA
2CEF..2CF1;N     # Mn     [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS
2CF2..2CF3;N     # L&     [2] COPTIC CAPITAL LETTER BOHAIRIC KHEI..COPTIC SMALL LETTER BOHAIRIC KHEI
2CF9..2CFC;N     # Po     [4] COPTIC OLD NUBIAN FULL STOP..COPTIC OLD NUBIAN VERSE DIVIDER
2CFD;N           # No         COPTIC FRACTION ONE HALF
2CFE..2CFF;N     # Po     [2] COPTIC FULL STOP..COPTIC MORPHOLOGICAL DIVIDER
2D00..2D25;N     # Ll    [38] GEORGIAN SMALL LETTER AN..GEORGIAN SMALL LETTER HOE
2D27;N           # Ll         GEORGIAN SMALL LETTER YN
2D2D;N           # Ll         GEORGIAN SMALL LETTER AEN
2D30..2D67;N     # Lo    [56] TIFINAGH LETTER YA..TIFINAGH LETTER YO
2D6F;N           # Lm         TIFINAGH MODIFIER LETTER LABIALIZATION MARK
2D70;N           # Po         TIFINAGH SEPARATOR MARK
2D7F;N           # Mn         TIFINAGH CONSONANT JOINER
2D80..2D96;N     # Lo    [23] ETHIOPIC SYLLABLE LOA..ETHIOPIC SYLLABLE GGWE
2DA0..2DA6;N     # Lo     [7] ETHIOPIC SYLLABLE SSA..ETHIOPIC SYLLABLE SSO
2DA8..2DAE;N     # Lo     [7] ETHIOPIC SYLLABLE CCA..ETHIOPIC SYLLABLE CCO
2DB0..2DB6;N     # Lo     [7] ETHIOPIC SYLLABLE ZZA..ETHIOPIC SYLLABLE ZZO
2DB8..2DBE;N     # Lo     [7] ETHIOPIC SYLLABLE CCHA..ETHIOPIC SYLLABLE CCHO
2DC0..2DC6;N     # Lo     [7] ETHIOPIC SYLLABLE QYA..ETHIOPIC SYLLABLE QYO
2DC8..2DCE;N     # Lo     [7] ETHIOPIC SYLLABLE KYA..ETHIOPIC SYLLABLE KYO
2DD0..2DD6;N     # Lo     [7] ETHIOPIC SYLLABLE XYA..ETHIOPIC SYLLABLE XYO
2DD8..2DDE;N     # Lo     [7] ETHIOPIC SYLLABLE GYA..ETHIOPIC SYLLABLE GYO
2DE0..2DFF;N     # Mn    [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS
2E00..2E01;N     # Po     [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER
2E02;N           # Pi         LEFT SUBSTITUTION BRACKET
2E03;N           # Pf         RIGHT SUBSTITUTION BRACKET
2E04;N           # Pi         LEFT DOTTED SUBSTITUTION BRACKET
2E05;N           # Pf         RIGHT DOTTED SUBSTITUTION BRACKET
2E06..2E08;N     # Po     [3] RAISED INTERPOLATION MARKER..DOTTED TRANSPOSITION MARKER
2E09;N           # Pi         LEFT TRANSPOSITION BRACKET
2E0A;N           # Pf         RIGHT TRANSPOSITION BRACKET
2E0B;N           # Po         RAISED SQUARE
2E0C;N           # Pi         LEFT RAISED OMISSION BRACKET
2E0D;N           # Pf         RIGHT RAISED OMISSION BRACKET
2E0E..2E16;N     # Po     [9] EDITORIAL CORONIS..DOTTED RIGHT-POINTING ANGLE
2E17;N           # Pd         DOUBLE OBLIQUE HYPHEN
2E18..2E19;N     # Po     [2] INVERTED INTERROBANG..PALM BRANCH
2E1A;N           # Pd         HYPHEN WITH DIAERESIS
2E1B;N           # Po         TILDE WITH RING ABOVE
2E1C;N           # Pi         LEFT LOW PARAPHRASE BRACKET
2E1D;N           # Pf         RIGHT LOW PARAPHRASE BRACKET
2E1E..2E1F;N     # Po     [2] TILDE WITH DOT ABOVE..TILDE WITH DOT BELOW
2E20;N           # Pi         LEFT VERTICAL BAR WITH QUILL
2E21;N           # Pf         RIGHT VERTICAL BAR WITH QUILL
2E22;N           # Ps         TOP LEFT HALF BRACKET
2E23;N           # Pe         TOP RIGHT HALF BRACKET
2E24;N           # Ps         BOTTOM LEFT HALF BRACKET
2E25;N           # Pe         BOTTOM RIGHT HALF BRACKET
2E26;N           # Ps         LEFT SIDEWAYS U BRACKET
2E27;N           # Pe         RIGHT SIDEWAYS U BRACKET
2E28;N           # Ps         LEFT DOUBLE PARENTHESIS
2E29;N           # Pe         RIGHT DOUBLE PARENTHESIS
2E2A..2E2E;N     # Po     [5] TWO DOTS OVER ONE DOT PUNCTUATION..REVERSED QUESTION MARK
2E2F;N           # Lm         VERTICAL TILDE
2E30..2E39;N     # Po    [10] RING POINT..TOP HALF SECTION SIGN
2E3A..2E3B;N     # Pd     [2] TWO-EM DASH..THREE-EM DASH
2E3C..2E3F;N     # Po     [4] STENOGRAPHIC FULL STOP..CAPITULUM
2E40;N           # Pd         DOUBLE HYPHEN
2E41;N           # Po         REVERSED COMMA
2E42;N           # Ps         DOUBLE LOW-REVERSED-9 QUOTATION MARK
2E43..2E4E;N     # Po    [12] DASH WITH LEFT UPTURN..PUNCTUS ELEVATUS MARK
2E80..2E99;W     # So    [26] CJK RADICAL REPEAT..CJK RADICAL RAP
2E9B..2EF3;W     # So    [89] CJK RADICAL CHOKE..CJK RADICAL C-SIMPLIFIED TURTLE
2F00..2FD5;W     # So   [214] KANGXI RADICAL ONE..KANGXI RADICAL FLUTE
2FF0..2FFB;W     # So    [12] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID
3000;F           # Zs         IDEOGRAPHIC SPACE
3001..3003;W     # Po     [3] IDEOGRAPHIC COMMA..DITTO MARK
3004;W           # So         JAPANESE INDUSTRIAL STANDARD SYMBOL
3005;W           # Lm         IDEOGRAPHIC ITERATION MARK
3006;W           # Lo         IDEOGRAPHIC CLOSING MARK
3007;W           # Nl         IDEOGRAPHIC NUMBER ZERO
3008;W           # Ps         LEFT ANGLE BRACKET
3009;W           # Pe         RIGHT ANGLE BRACKET
300A;W           # Ps         LEFT DOUBLE ANGLE BRACKET
300B;W           # Pe         RIGHT DOUBLE ANGLE BRACKET
300C;W           # Ps         LEFT CORNER BRACKET
300D;W           # Pe         RIGHT CORNER BRACKET
300E;W           # Ps         LEFT WHITE CORNER BRACKET
300F;W           # Pe         RIGHT WHITE CORNER BRACKET
3010;W           # Ps         LEFT BLACK LENTICULAR BRACKET
3011;W           # Pe         RIGHT BLACK LENTICULAR BRACKET
3012..3013;W     # So     [2] POSTAL MARK..GETA MARK
3014;W           # Ps         LEFT TORTOISE SHELL BRACKET
3015;W           # Pe         RIGHT TORTOISE SHELL BRACKET
3016;W           # Ps         LEFT WHITE LENTICULAR BRACKET
3017;W           # Pe         RIGHT WHITE LENTICULAR BRACKET
3018;W           # Ps         LEFT WHITE TORTOISE SHELL BRACKET
3019;W           # Pe         RIGHT WHITE TORTOISE SHELL BRACKET
301A;W           # Ps         LEFT WHITE SQUARE BRACKET
301B;W           # Pe         RIGHT WHITE SQUARE BRACKET
301C;W           # Pd         WAVE DASH
301D;W           # Ps         REVERSED DOUBLE PRIME QUOTATION MARK
301E..301F;W     # Pe     [2] DOUBLE PRIME QUOTATION MARK..LOW DOUBLE PRIME QUOTATION MARK
3020;W           # So         POSTAL MARK FACE
3021..3029;W     # Nl     [9] HANGZHOU NUMERAL ONE..HANGZHOU NUMERAL NINE
302A..302D;W     # Mn     [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK
302E..302F;W     # Mc     [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK
3030;W           # Pd         WAVY DASH
3031..3035;W     # Lm     [5] VERTICAL KANA REPEAT MARK..VERTICAL KANA REPEAT MARK LOWER HALF
3036..3037;W     # So     [2] CIRCLED POSTAL MARK..IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL
3038..303A;W     # Nl     [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY
303B;W           # Lm         VERTICAL IDEOGRAPHIC ITERATION MARK
303C;W           # Lo         MASU MARK
303D;W           # Po         PART ALTERNATION MARK
303E;W           # So         IDEOGRAPHIC VARIATION INDICATOR
303F;N           # So         IDEOGRAPHIC HALF FILL SPACE
3041..3096;W     # Lo    [86] HIRAGANA LETTER SMALL A..HIRAGANA LETTER SMALL KE
3099..309A;W     # Mn     [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
309B..309C;W     # Sk     [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
309D..309E;W     # Lm     [2] HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK
309F;W           # Lo         HIRAGANA DIGRAPH YORI
30A0;W           # Pd         KATAKANA-HIRAGANA DOUBLE HYPHEN
30A1..30FA;W     # Lo    [90] KATAKANA LETTER SMALL A..KATAKANA LETTER VO
30FB;W           # Po         KATAKANA MIDDLE DOT
30FC..30FE;W     # Lm     [3] KATAKANA-HIRAGANA PROLONGED SOUND MARK..KATAKANA VOICED ITERATION MARK
30FF;W           # Lo         KATAKANA DIGRAPH KOTO
3105..312F;W     # Lo    [43] BOPOMOFO LETTER B..BOPOMOFO LETTER NN
3131..318E;W     # Lo    [94] HANGUL LETTER KIYEOK..HANGUL LETTER ARAEAE
3190..3191;W     # So     [2] IDEOGRAPHIC ANNOTATION LINKING MARK..IDEOGRAPHIC ANNOTATION REVERSE MARK
3192..3195;W     # No     [4] IDEOGRAPHIC ANNOTATION ONE MARK..IDEOGRAPHIC ANNOTATION FOUR MARK
3196..319F;W     # So    [10] IDEOGRAPHIC ANNOTATION TOP MARK..IDEOGRAPHIC ANNOTATION MAN MARK
31A0..31BA;W     # Lo    [27] BOPOMOFO LETTER BU..BOPOMOFO LETTER ZY
31C0..31E3;W     # So    [36] CJK STROKE T..CJK STROKE Q
31F0..31FF;W     # Lo    [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO
3200..321E;W     # So    [31] PARENTHESIZED HANGUL KIYEOK..PARENTHESIZED KOREAN CHARACTER O HU
3220..3229;W     # No    [10] PARENTHESIZED IDEOGRAPH ONE..PARENTHESIZED IDEOGRAPH TEN
322A..3247;W     # So    [30] PARENTHESIZED IDEOGRAPH MOON..CIRCLED IDEOGRAPH KOTO
3248..324F;A     # No     [8] CIRCLED NUMBER TEN ON BLACK SQUARE..CIRCLED NUMBER EIGHTY ON BLACK SQUARE
3250;W           # So         PARTNERSHIP SIGN
3251..325F;W     # No    [15] CIRCLED NUMBER TWENTY ONE..CIRCLED NUMBER THIRTY FIVE
3260..327F;W     # So    [32] CIRCLED HANGUL KIYEOK..KOREAN STANDARD SYMBOL
3280..3289;W     # No    [10] CIRCLED IDEOGRAPH ONE..CIRCLED IDEOGRAPH TEN
328A..32B0;W     # So    [39] CIRCLED IDEOGRAPH MOON..CIRCLED IDEOGRAPH NIGHT
32B1..32BF;W     # No    [15] CIRCLED NUMBER THIRTY SIX..CIRCLED NUMBER FIFTY
32C0..32FE;W     # So    [63] IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY..CIRCLED KATAKANA WO
3300..33FF;W     # So   [256] SQUARE APAATO..SQUARE GAL
3400..4DB5;W     # Lo  [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5
4DB6..4DBF;W     # Cn    [10] <reserved-4DB6>..<reserved-4DBF>
4DC0..4DFF;N     # So    [64] HEXAGRAM FOR THE CREATIVE HEAVEN..HEXAGRAM FOR BEFORE COMPLETION
4E00..9FEF;W     # Lo [20976] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FEF
9FF0..9FFF;W     # Cn    [16] <reserved-9FF0>..<reserved-9FFF>
A000..A014;W     # Lo    [21] YI SYLLABLE IT..YI SYLLABLE E
A015;W           # Lm         YI SYLLABLE WU
A016..A48C;W     # Lo  [1143] YI SYLLABLE BIT..YI SYLLABLE YYR
A490..A4C6;W     # So    [55] YI RADICAL QOT..YI RADICAL KE
A4D0..A4F7;N     # Lo    [40] LISU LETTER BA..LISU LETTER OE
A4F8..A4FD;N     # Lm     [6] LISU LETTER TONE MYA TI..LISU LETTER TONE MYA JEU
A4FE..A4FF;N     # Po     [2] LISU PUNCTUATION COMMA..LISU PUNCTUATION FULL STOP
A500..A60B;N     # Lo   [268] VAI SYLLABLE EE..VAI SYLLABLE NG
A60C;N           # Lm         VAI SYLLABLE LENGTHENER
A60D..A60F;N     # Po     [3] VAI COMMA..VAI QUESTION MARK
A610..A61F;N     # Lo    [16] VAI SYLLABLE NDOLE FA..VAI SYMBOL JONG
A620..A629;N     # Nd    [10] VAI DIGIT ZERO..VAI DIGIT NINE
A62A..A62B;N     # Lo     [2] VAI SYLLABLE NDOLE MA..VAI SYLLABLE NDOLE DO
A640..A66D;N     # L&    [46] CYRILLIC CAPITAL LETTER ZEMLYA..CYRILLIC SMALL LETTER DOUBLE MONOCULAR O
A66E;N           # Lo         CYRILLIC LETTER MULTIOCULAR O
A66F;N           # Mn         COMBINING CYRILLIC VZMET
A670..A672;N     # Me     [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN
A673;N           # Po         SLAVONIC ASTERISK
A674..A67D;N     # Mn    [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK
A67E;N           # Po         CYRILLIC KAVYKA
A67F;N           # Lm         CYRILLIC PAYEROK
A680..A69B;N     # L&    [28] CYRILLIC CAPITAL LETTER DWE..CYRILLIC SMALL LETTER CROSSED O
A69C..A69D;N     # Lm     [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER LETTER CYRILLIC SOFT SIGN
A69E..A69F;N     # Mn     [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E
A6A0..A6E5;N     # Lo    [70] BAMUM LETTER A..BAMUM LETTER KI
A6E6..A6EF;N     # Nl    [10] BAMUM LETTER MO..BAMUM LETTER KOGHOM
A6F0..A6F1;N     # Mn     [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS
A6F2..A6F7;N     # Po     [6] BAMUM NJAEMLI..BAMUM QUESTION MARK
A700..A716;N     # Sk    [23] MODIFIER LETTER CHINESE TONE YIN PING..MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR
A717..A71F;N     # Lm     [9] MODIFIER LETTER DOT VERTICAL BAR..MODIFIER LETTER LOW INVERTED EXCLAMATION MARK
A720..A721;N     # Sk     [2] MODIFIER LETTER STRESS AND HIGH TONE..MODIFIER LETTER STRESS AND LOW TONE
A722..A76F;N     # L&    [78] LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF..LATIN SMALL LETTER CON
A770;N           # Lm         MODIFIER LETTER US
A771..A787;N     # L&    [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER INSULAR T
A788;N           # Lm         MODIFIER LETTER LOW CIRCUMFLEX ACCENT
A789..A78A;N     # Sk     [2] MODIFIER LETTER COLON..MODIFIER LETTER SHORT EQUALS SIGN
A78B..A78E;N     # L&     [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT
A78F;N           # Lo         LATIN LETTER SINOLOGICAL DOT
A790..A7B9;N     # L&    [42] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER U WITH STROKE
A7F7;N           # Lo         LATIN EPIGRAPHIC LETTER SIDEWAYS I
A7F8..A7F9;N     # Lm     [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE
A7FA;N           # Ll         LATIN LETTER SMALL CAPITAL TURNED M
A7FB..A7FF;N     # Lo     [5] LATIN EPIGRAPHIC LETTER REVERSED F..LATIN EPIGRAPHIC LETTER ARCHAIC M
A800..A801;N     # Lo     [2] SYLOTI NAGRI LETTER A..SYLOTI NAGRI LETTER I
A802;N           # Mn         SYLOTI NAGRI SIGN DVISVARA
A803..A805;N     # Lo     [3] SYLOTI NAGRI LETTER U..SYLOTI NAGRI LETTER O
A806;N           # Mn         SYLOTI NAGRI SIGN HASANTA
A807..A80A;N     # Lo     [4] SYLOTI NAGRI LETTER KO..SYLOTI NAGRI LETTER GHO
A80B;N           # Mn         SYLOTI NAGRI SIGN ANUSVARA
A80C..A822;N     # Lo    [23] SYLOTI NAGRI LETTER CO..SYLOTI NAGRI LETTER HO
A823..A824;N     # Mc     [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I
A825..A826;N     # Mn     [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E
A827;N           # Mc         SYLOTI NAGRI VOWEL SIGN OO
A828..A82B;N     # So     [4] SYLOTI NAGRI POETRY MARK-1..SYLOTI NAGRI POETRY MARK-4
A830..A835;N     # No     [6] NORTH INDIC FRACTION ONE QUARTER..NORTH INDIC FRACTION THREE SIXTEENTHS
A836..A837;N     # So     [2] NORTH INDIC QUARTER MARK..NORTH INDIC PLACEHOLDER MARK
A838;N           # Sc         NORTH INDIC RUPEE MARK
A839;N           # So         NORTH INDIC QUANTITY MARK
A840..A873;N     # Lo    [52] PHAGS-PA LETTER KA..PHAGS-PA LETTER CANDRABINDU
A874..A877;N     # Po     [4] PHAGS-PA SINGLE HEAD MARK..PHAGS-PA MARK DOUBLE SHAD
A880..A881;N     # Mc     [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA
A882..A8B3;N     # Lo    [50] SAURASHTRA LETTER A..SAURASHTRA LETTER LLA
A8B4..A8C3;N     # Mc    [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU
A8C4..A8C5;N     # Mn     [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU
A8CE..A8CF;N     # Po     [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA
A8D0..A8D9;N     # Nd    [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE
A8E0..A8F1;N     # Mn    [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA
A8F2..A8F7;N     # Lo     [6] DEVANAGARI SIGN SPACING CANDRABINDU..DEVANAGARI SIGN CANDRABINDU AVAGRAHA
A8F8..A8FA;N     # Po     [3] DEVANAGARI SIGN PUSHPIKA..DEVANAGARI CARET
A8FB;N           # Lo         DEVANAGARI HEADSTROKE
A8FC;N           # Po         DEVANAGARI SIGN SIDDHAM
A8FD..A8FE;N     # Lo     [2] DEVANAGARI JAIN OM..DEVANAGARI LETTER AY
A8FF;N           # Mn         DEVANAGARI VOWEL SIGN AY
A900..A909;N     # Nd    [10] KAYAH LI DIGIT ZERO..KAYAH LI DIGIT NINE
A90A..A925;N     # Lo    [28] KAYAH LI LETTER KA..KAYAH LI LETTER OO
A926..A92D;N     # Mn     [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU
A92E..A92F;N     # Po     [2] KAYAH LI SIGN CWI..KAYAH LI SIGN SHYA
A930..A946;N     # Lo    [23] REJANG LETTER KA..REJANG LETTER A
A947..A951;N     # Mn    [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R
A952..A953;N     # Mc     [2] REJANG CONSONANT SIGN H..REJANG VIRAMA
A95F;N           # Po         REJANG SECTION MARK
A960..A97C;W     # Lo    [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH
A980..A982;N     # Mn     [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR
A983;N           # Mc         JAVANESE SIGN WIGNYAN
A984..A9B2;N     # Lo    [47] JAVANESE LETTER A..JAVANESE LETTER HA
A9B3;N           # Mn         JAVANESE SIGN CECAK TELU
A9B4..A9B5;N     # Mc     [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG
A9B6..A9B9;N     # Mn     [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT
A9BA..A9BB;N     # Mc     [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE
A9BC;N           # Mn         JAVANESE VOWEL SIGN PEPET
A9BD..A9C0;N     # Mc     [4] JAVANESE CONSONANT SIGN KERET..JAVANESE PANGKON
A9C1..A9CD;N     # Po    [13] JAVANESE LEFT RERENGGAN..JAVANESE TURNED PADA PISELEH
A9CF;N           # Lm         JAVANESE PANGRANGKEP
A9D0..A9D9;N     # Nd    [10] JAVANESE DIGIT ZERO..JAVANESE DIGIT NINE
A9DE..A9DF;N     # Po     [2] JAVANESE PADA TIRTA TUMETES..JAVANESE PADA ISEN-ISEN
A9E0..A9E4;N     # Lo     [5] MYANMAR LETTER SHAN GHA..MYANMAR LETTER SHAN BHA
A9E5;N           # Mn         MYANMAR SIGN SHAN SAW
A9E6;N           # Lm         MYANMAR MODIFIER LETTER SHAN REDUPLICATION
A9E7..A9EF;N     # Lo     [9] MYANMAR LETTER TAI LAING NYA..MYANMAR LETTER TAI LAING NNA
A9F0..A9F9;N     # Nd    [10] MYANMAR TAI LAING DIGIT ZERO..MYANMAR TAI LAING DIGIT NINE
A9FA..A9FE;N     # Lo     [5] MYANMAR LETTER TAI LAING LLA..MYANMAR LETTER TAI LAING BHA
AA00..AA28;N     # Lo    [41] CHAM LETTER A..CHAM LETTER HA
AA29..AA2E;N     # Mn     [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE
AA2F..AA30;N     # Mc     [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI
AA31..AA32;N     # Mn     [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE
AA33..AA34;N     # Mc     [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA
AA35..AA36;N     # Mn     [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA
AA40..AA42;N     # Lo     [3] CHAM LETTER FINAL K..CHAM LETTER FINAL NG
AA43;N           # Mn         CHAM CONSONANT SIGN FINAL NG
AA44..AA4B;N     # Lo     [8] CHAM LETTER FINAL CH..CHAM LETTER FINAL SS
AA4C;N           # Mn         CHAM CONSONANT SIGN FINAL M
AA4D;N           # Mc         CHAM CONSONANT SIGN FINAL H
AA50..AA59;N     # Nd    [10] CHAM DIGIT ZERO..CHAM DIGIT NINE
AA5C..AA5F;N     # Po     [4] CHAM PUNCTUATION SPIRAL..CHAM PUNCTUATION TRIPLE DANDA
AA60..AA6F;N     # Lo    [16] MYANMAR LETTER KHAMTI GA..MYANMAR LETTER KHAMTI FA
AA70;N           # Lm         MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION
AA71..AA76;N     # Lo     [6] MYANMAR LETTER KHAMTI XA..MYANMAR LOGOGRAM KHAMTI HM
AA77..AA79;N     # So     [3] MYANMAR SYMBOL AITON EXCLAMATION..MYANMAR SYMBOL AITON TWO
AA7A;N           # Lo         MYANMAR LETTER AITON RA
AA7B;N           # Mc         MYANMAR SIGN PAO KAREN TONE
AA7C;N           # Mn         MYANMAR SIGN TAI LAING TONE-2
AA7D;N           # Mc         MYANMAR SIGN TAI LAING TONE-5
AA7E..AA7F;N     # Lo     [2] MYANMAR LETTER SHWE PALAUNG CHA..MYANMAR LETTER SHWE PALAUNG SHA
AA80..AAAF;N     # Lo    [48] TAI VIET LETTER LOW KO..TAI VIET LETTER HIGH O
AAB0;N           # Mn         TAI VIET MAI KANG
AAB1;N           # Lo         TAI VIET VOWEL AA
AAB2..AAB4;N     # Mn     [3] TAI VIET VOWEL I..TAI VIET VOWEL U
AAB5..AAB6;N     # Lo     [2] TAI VIET VOWEL E..TAI VIET VOWEL O
AAB7..AAB8;N     # Mn     [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA
AAB9..AABD;N     # Lo     [5] TAI VIET VOWEL UEA..TAI VIET VOWEL AN
AABE..AABF;N     # Mn     [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK
AAC0;N           # Lo         TAI VIET TONE MAI NUENG
AAC1;N           # Mn         TAI VIET TONE MAI THO
AAC2;N           # Lo         TAI VIET TONE MAI SONG
AADB..AADC;N     # Lo     [2] TAI VIET SYMBOL KON..TAI VIET SYMBOL NUENG
AADD;N           # Lm         TAI VIET SYMBOL SAM
AADE..AADF;N     # Po     [2] TAI VIET SYMBOL HO HOI..TAI VIET SYMBOL KOI KOI
AAE0..AAEA;N     # Lo    [11] MEETEI MAYEK LETTER E..MEETEI MAYEK LETTER SSA
AAEB;N           # Mc         MEETEI MAYEK VOWEL SIGN II
AAEC..AAED;N     # Mn     [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI
AAEE..AAEF;N     # Mc     [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU
AAF0..AAF1;N     # Po     [2] MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM
AAF2;N           # Lo         MEETEI MAYEK ANJI
AAF3..AAF4;N     # Lm     [2] MEETEI MAYEK SYLLABLE REPETITION MARK..MEETEI MAYEK WORD REPETITION MARK
AAF5;N           # Mc         MEETEI MAYEK VOWEL SIGN VISARGA
AAF6;N           # Mn         MEETEI MAYEK VIRAMA
AB01..AB06;N     # Lo     [6] ETHIOPIC SYLLABLE TTHU..ETHIOPIC SYLLABLE TTHO
AB09..AB0E;N     # Lo     [6] ETHIOPIC SYLLABLE DDHU..ETHIOPIC SYLLABLE DDHO
AB11..AB16;N     # Lo     [6] ETHIOPIC SYLLABLE DZU..ETHIOPIC SYLLABLE DZO
AB20..AB26;N     # Lo     [7] ETHIOPIC SYLLABLE CCHHA..ETHIOPIC SYLLABLE CCHHO
AB28..AB2E;N     # Lo     [7] ETHIOPIC SYLLABLE BBA..ETHIOPIC SYLLABLE BBO
AB30..AB5A;N     # Ll    [43] LATIN SMALL LETTER BARRED ALPHA..LATIN SMALL LETTER Y WITH SHORT RIGHT LEG
AB5B;N           # Sk         MODIFIER BREVE WITH INVERTED BREVE
AB5C..AB5F;N     # Lm     [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK
AB60..AB65;N     # Ll     [6] LATIN SMALL LETTER SAKHA YAT..GREEK LETTER SMALL CAPITAL OMEGA
AB70..ABBF;N     # Ll    [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA
ABC0..ABE2;N     # Lo    [35] MEETEI MAYEK LETTER KOK..MEETEI MAYEK LETTER I LONSUM
ABE3..ABE4;N     # Mc     [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP
ABE5;N           # Mn         MEETEI MAYEK VOWEL SIGN ANAP
ABE6..ABE7;N     # Mc     [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP
ABE8;N           # Mn         MEETEI MAYEK VOWEL SIGN UNAP
ABE9..ABEA;N     # Mc     [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG
ABEB;N           # Po         MEETEI MAYEK CHEIKHEI
ABEC;N           # Mc         MEETEI MAYEK LUM IYEK
ABED;N           # Mn         MEETEI MAYEK APUN IYEK
ABF0..ABF9;N     # Nd    [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DIGIT NINE
AC00..D7A3;W     # Lo [11172] HANGUL SYLLABLE GA..HANGUL SYLLABLE HIH
D7B0..D7C6;N     # Lo    [23] HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E
D7CB..D7FB;N     # Lo    [49] HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH
D800..DB7F;N     # Cs   [896] <surrogate-D800>..<surrogate-DB7F>
DB80..DBFF;N     # Cs   [128] <surrogate-DB80>..<surrogate-DBFF>
DC00..DFFF;N     # Cs  [1024] <surrogate-DC00>..<surrogate-DFFF>
E000..F8FF;A     # Co  [6400] <private-use-E000>..<private-use-F8FF>
F900..FA6D;W     # Lo   [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D
FA6E..FA6F;W     # Cn     [2] <reserved-FA6E>..<reserved-FA6F>
FA70..FAD9;W     # Lo   [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9
FADA..FAFF;W     # Cn    [38] <reserved-FADA>..<reserved-FAFF>
FB00..FB06;N     # Ll     [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST
FB13..FB17;N     # Ll     [5] ARMENIAN SMALL LIGATURE MEN NOW..ARMENIAN SMALL LIGATURE MEN XEH
FB1D;N           # Lo         HEBREW LETTER YOD WITH HIRIQ
FB1E;N           # Mn         HEBREW POINT JUDEO-SPANISH VARIKA
FB1F..FB28;N     # Lo    [10] HEBREW LIGATURE YIDDISH YOD YOD PATAH..HEBREW LETTER WIDE TAV
FB29;N           # Sm         HEBREW LETTER ALTERNATIVE PLUS SIGN
FB2A..FB36;N     # Lo    [13] HEBREW LETTER SHIN WITH SHIN DOT..HEBREW LETTER ZAYIN WITH DAGESH
FB38..FB3C;N     # Lo     [5] HEBREW LETTER TET WITH DAGESH..HEBREW LETTER LAMED WITH DAGESH
FB3E;N           # Lo         HEBREW LETTER MEM WITH DAGESH
FB40..FB41;N     # Lo     [2] HEBREW LETTER NUN WITH DAGESH..HEBREW LETTER SAMEKH WITH DAGESH
FB43..FB44;N     # Lo     [2] HEBREW LETTER FINAL PE WITH DAGESH..HEBREW LETTER PE WITH DAGESH
FB46..FB4F;N     # Lo    [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW LIGATURE ALEF LAMED
FB50..FBB1;N     # Lo    [98] ARABIC LETTER ALEF WASLA ISOLATED FORM..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM
FBB2..FBC1;N     # Sk    [16] ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL SMALL TAH BELOW
FBD3..FD3D;N     # Lo   [363] ARABIC LETTER NG ISOLATED FORM..ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM
FD3E;N           # Pe         ORNATE LEFT PARENTHESIS
FD3F;N           # Ps         ORNATE RIGHT PARENTHESIS
FD50..FD8F;N     # Lo    [64] ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM..ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM
FD92..FDC7;N     # Lo    [54] ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM..ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM
FDF0..FDFB;N     # Lo    [12] ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM..ARABIC LIGATURE JALLAJALALOUHOU
FDFC;N           # Sc         RIAL SIGN
FDFD;N           # So         ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM
FE00..FE0F;A     # Mn    [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
FE10..FE16;W     # Po     [7] PRESENTATION FORM FOR VERTICAL COMMA..PRESENTATION FORM FOR VERTICAL QUESTION MARK
FE17;W           # Ps         PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET
FE18;W           # Pe         PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET
FE19;W           # Po         PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS
FE20..FE2F;N     # Mn    [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF
FE30;W           # Po         PRESENTATION FORM FOR VERTICAL TWO DOT LEADER
FE31..FE32;W     # Pd     [2] PRESENTATION FORM FOR VERTICAL EM DASH..PRESENTATION FORM FOR VERTICAL EN DASH
FE33..FE34;W     # Pc     [2] PRESENTATION FORM FOR VERTICAL LOW LINE..PRESENTATION FORM FOR VERTICAL WAVY LOW LINE
FE35;W           # Ps         PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS
FE36;W           # Pe         PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS
FE37;W           # Ps         PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET
FE38;W           # Pe         PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET
FE39;W           # Ps         PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET
FE3A;W           # Pe         PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET
FE3B;W           # Ps         PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET
FE3C;W           # Pe         PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET
FE3D;W           # Ps         PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET
FE3E;W           # Pe         PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET
FE3F;W           # Ps         PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET
FE40;W           # Pe         PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET
FE41;W           # Ps         PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET
FE42;W           # Pe         PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET
FE43;W           # Ps         PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET
FE44;W           # Pe         PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET
FE45..FE46;W     # Po     [2] SESAME DOT..WHITE SESAME DOT
FE47;W           # Ps         PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET
FE48;W           # Pe         PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET
FE49..FE4C;W     # Po     [4] DASHED OVERLINE..DOUBLE WAVY OVERLINE
FE4D..FE4F;W     # Pc     [3] DASHED LOW LINE..WAVY LOW LINE
FE50..FE52;W     # Po     [3] SMALL COMMA..SMALL FULL STOP
FE54..FE57;W     # Po     [4] SMALL SEMICOLON..SMALL EXCLAMATION MARK
FE58;W           # Pd         SMALL EM DASH
FE59;W           # Ps         SMALL LEFT PARENTHESIS
FE5A;W           # Pe         SMALL RIGHT PARENTHESIS
FE5B;W           # Ps         SMALL LEFT CURLY BRACKET
FE5C;W           # Pe         SMALL RIGHT CURLY BRACKET
FE5D;W           # Ps         SMALL LEFT TORTOISE SHELL BRACKET
FE5E;W           # Pe         SMALL RIGHT TORTOISE SHELL BRACKET
FE5F..FE61;W     # Po     [3] SMALL NUMBER SIGN..SMALL ASTERISK
FE62;W           # Sm         SMALL PLUS SIGN
FE63;W           # Pd         SMALL HYPHEN-MINUS
FE64..FE66;W     # Sm     [3] SMALL LESS-THAN SIGN..SMALL EQUALS SIGN
FE68;W           # Po         SMALL REVERSE SOLIDUS
FE69;W           # Sc         SMALL DOLLAR SIGN
FE6A..FE6B;W     # Po     [2] SMALL PERCENT SIGN..SMALL COMMERCIAL AT
FE70..FE74;N     # Lo     [5] ARABIC FATHATAN ISOLATED FORM..ARABIC KASRATAN ISOLATED FORM
FE76..FEFC;N     # Lo   [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF FINAL FORM
FEFF;N           # Cf         ZERO WIDTH NO-BREAK SPACE
FF01..FF03;F     # Po     [3] FULLWIDTH EXCLAMATION MARK..FULLWIDTH NUMBER SIGN
FF04;F           # Sc         FULLWIDTH DOLLAR SIGN
FF05..FF07;F     # Po     [3] FULLWIDTH PERCENT SIGN..FULLWIDTH APOSTROPHE
FF08;F           # Ps         FULLWIDTH LEFT PARENTHESIS
FF09;F           # Pe         FULLWIDTH RIGHT PARENTHESIS
FF0A;F           # Po         FULLWIDTH ASTERISK
FF0B;F           # Sm         FULLWIDTH PLUS SIGN
FF0C;F           # Po         FULLWIDTH COMMA
FF0D;F           # Pd         FULLWIDTH HYPHEN-MINUS
FF0E..FF0F;F     # Po     [2] FULLWIDTH FULL STOP..FULLWIDTH SOLIDUS
FF10..FF19;F     # Nd    [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE
FF1A..FF1B;F     # Po     [2] FULLWIDTH COLON..FULLWIDTH SEMICOLON
FF1C..FF1E;F     # Sm     [3] FULLWIDTH LESS-THAN SIGN..FULLWIDTH GREATER-THAN SIGN
FF1F..FF20;F     # Po     [2] FULLWIDTH QUESTION MARK..FULLWIDTH COMMERCIAL AT
FF21..FF3A;F     # Lu    [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z
FF3B;F           # Ps         FULLWIDTH LEFT SQUARE BRACKET
FF3C;F           # Po         FULLWIDTH REVERSE SOLIDUS
FF3D;F           # Pe         FULLWIDTH RIGHT SQUARE BRACKET
FF3E;F           # Sk         FULLWIDTH CIRCUMFLEX ACCENT
FF3F;F           # Pc         FULLWIDTH LOW LINE
FF40;F           # Sk         FULLWIDTH GRAVE ACCENT
FF41..FF5A;F     # Ll    [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z
FF5B;F           # Ps         FULLWIDTH LEFT CURLY BRACKET
FF5C;F           # Sm         FULLWIDTH VERTICAL LINE
FF5D;F           # Pe         FULLWIDTH RIGHT CURLY BRACKET
FF5E;F           # Sm         FULLWIDTH TILDE
FF5F;F           # Ps         FULLWIDTH LEFT WHITE PARENTHESIS
FF60;F           # Pe         FULLWIDTH RIGHT WHITE PARENTHESIS
FF61;H           # Po         HALFWIDTH IDEOGRAPHIC FULL STOP
FF62;H           # Ps         HALFWIDTH LEFT CORNER BRACKET
FF63;H           # Pe         HALFWIDTH RIGHT CORNER BRACKET
FF64..FF65;H     # Po     [2] HALFWIDTH IDEOGRAPHIC COMMA..HALFWIDTH KATAKANA MIDDLE DOT
FF66..FF6F;H     # Lo    [10] HALFWIDTH KATAKANA LETTER WO..HALFWIDTH KATAKANA LETTER SMALL TU
FF70;H           # Lm         HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
FF71..FF9D;H     # Lo    [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAKANA LETTER N
FF9E..FF9F;H     # Lm     [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
FFA0..FFBE;H     # Lo    [31] HALFWIDTH HANGUL FILLER..HALFWIDTH HANGUL LETTER HIEUH
FFC2..FFC7;H     # Lo     [6] HALFWIDTH HANGUL LETTER A..HALFWIDTH HANGUL LETTER E
FFCA..FFCF;H     # Lo     [6] HALFWIDTH HANGUL LETTER YEO..HALFWIDTH HANGUL LETTER OE
FFD2..FFD7;H     # Lo     [6] HALFWIDTH HANGUL LETTER YO..HALFWIDTH HANGUL LETTER YU
FFDA..FFDC;H     # Lo     [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL LETTER I
FFE0..FFE1;F     # Sc     [2] FULLWIDTH CENT SIGN..FULLWIDTH POUND SIGN
FFE2;F           # Sm         FULLWIDTH NOT SIGN
FFE3;F           # Sk         FULLWIDTH MACRON
FFE4;F           # So         FULLWIDTH BROKEN BAR
FFE5..FFE6;F     # Sc     [2] FULLWIDTH YEN SIGN..FULLWIDTH WON SIGN
FFE8;H           # So         HALFWIDTH FORMS LIGHT VERTICAL
FFE9..FFEC;H     # Sm     [4] HALFWIDTH LEFTWARDS ARROW..HALFWIDTH DOWNWARDS ARROW
FFED..FFEE;H     # So     [2] HALFWIDTH BLACK SQUARE..HALFWIDTH WHITE CIRCLE
FFF9..FFFB;N     # Cf     [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR
FFFC;N           # So         OBJECT REPLACEMENT CHARACTER
FFFD;A           # So         REPLACEMENT CHARACTER
10000..1000B;N   # Lo    [12] LINEAR B SYLLABLE B008 A..LINEAR B SYLLABLE B046 JE
1000D..10026;N   # Lo    [26] LINEAR B SYLLABLE B036 JO..LINEAR B SYLLABLE B032 QO
10028..1003A;N   # Lo    [19] LINEAR B SYLLABLE B060 RA..LINEAR B SYLLABLE B042 WO
1003C..1003D;N   # Lo     [2] LINEAR B SYLLABLE B017 ZA..LINEAR B SYLLABLE B074 ZE
1003F..1004D;N   # Lo    [15] LINEAR B SYLLABLE B020 ZO..LINEAR B SYLLABLE B091 TWO
10050..1005D;N   # Lo    [14] LINEAR B SYMBOL B018..LINEAR B SYMBOL B089
10080..100FA;N   # Lo   [123] LINEAR B IDEOGRAM B100 MAN..LINEAR B IDEOGRAM VESSEL B305
10100..10102;N   # Po     [3] AEGEAN WORD SEPARATOR LINE..AEGEAN CHECK MARK
10107..10133;N   # No    [45] AEGEAN NUMBER ONE..AEGEAN NUMBER NINETY THOUSAND
10137..1013F;N   # So     [9] AEGEAN WEIGHT BASE UNIT..AEGEAN MEASURE THIRD SUBUNIT
10140..10174;N   # Nl    [53] GREEK ACROPHONIC ATTIC ONE QUARTER..GREEK ACROPHONIC STRATIAN FIFTY MNAS
10175..10178;N   # No     [4] GREEK ONE HALF SIGN..GREEK THREE QUARTERS SIGN
10179..10189;N   # So    [17] GREEK YEAR SIGN..GREEK TRYBLION BASE SIGN
1018A..1018B;N   # No     [2] GREEK ZERO SIGN..GREEK ONE QUARTER SIGN
1018C..1018E;N   # So     [3] GREEK SINUSOID SIGN..NOMISMA SIGN
10190..1019B;N   # So    [12] ROMAN SEXTANS SIGN..ROMAN CENTURIAL SIGN
101A0;N          # So         GREEK SYMBOL TAU RHO
101D0..101FC;N   # So    [45] PHAISTOS DISC SIGN PEDESTRIAN..PHAISTOS DISC SIGN WAVY BAND
101FD;N          # Mn         PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE
10280..1029C;N   # Lo    [29] LYCIAN LETTER A..LYCIAN LETTER X
102A0..102D0;N   # Lo    [49] CARIAN LETTER A..CARIAN LETTER UUU3
102E0;N          # Mn         COPTIC EPACT THOUSANDS MARK
102E1..102FB;N   # No    [27] COPTIC EPACT DIGIT ONE..COPTIC EPACT NUMBER NINE HUNDRED
10300..1031F;N   # Lo    [32] OLD ITALIC LETTER A..OLD ITALIC LETTER ESS
10320..10323;N   # No     [4] OLD ITALIC NUMERAL ONE..OLD ITALIC NUMERAL FIFTY
1032D..1032F;N   # Lo     [3] OLD ITALIC LETTER YE..OLD ITALIC LETTER SOUTHERN TSE
10330..10340;N   # Lo    [17] GOTHIC LETTER AHSA..GOTHIC LETTER PAIRTHRA
10341;N          # Nl         GOTHIC LETTER NINETY
10342..10349;N   # Lo     [8] GOTHIC LETTER RAIDA..GOTHIC LETTER OTHAL
1034A;N          # Nl         GOTHIC LETTER NINE HUNDRED
10350..10375;N   # Lo    [38] OLD PERMIC LETTER AN..OLD PERMIC LETTER IA
10376..1037A;N   # Mn     [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII
10380..1039D;N   # Lo    [30] UGARITIC LETTER ALPA..UGARITIC LETTER SSU
1039F;N          # Po         UGARITIC WORD DIVIDER
103A0..103C3;N   # Lo    [36] OLD PERSIAN SIGN A..OLD PERSIAN SIGN HA
103C8..103CF;N   # Lo     [8] OLD PERSIAN SIGN AURAMAZDAA..OLD PERSIAN SIGN BUUMISH
103D0;N          # Po         OLD PERSIAN WORD DIVIDER
103D1..103D5;N   # Nl     [5] OLD PERSIAN NUMBER ONE..OLD PERSIAN NUMBER HUNDRED
10400..1044F;N   # L&    [80] DESERET CAPITAL LETTER LONG I..DESERET SMALL LETTER EW
10450..1047F;N   # Lo    [48] SHAVIAN LETTER PEEP..SHAVIAN LETTER YEW
10480..1049D;N   # Lo    [30] OSMANYA LETTER ALEF..OSMANYA LETTER OO
104A0..104A9;N   # Nd    [10] OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE
104B0..104D3;N   # Lu    [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA
104D8..104FB;N   # Ll    [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA
10500..10527;N   # Lo    [40] ELBASAN LETTER A..ELBASAN LETTER KHE
10530..10563;N   # Lo    [52] CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW
1056F;N          # Po         CAUCASIAN ALBANIAN CITATION MARK
10600..10736;N   # Lo   [311] LINEAR A SIGN AB001..LINEAR A SIGN A664
10740..10755;N   # Lo    [22] LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE
10760..10767;N   # Lo     [8] LINEAR A SIGN A800..LINEAR A SIGN A807
10800..10805;N   # Lo     [6] CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA
10808;N          # Lo         CYPRIOT SYLLABLE JO
1080A..10835;N   # Lo    [44] CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO
10837..10838;N   # Lo     [2] CYPRIOT SYLLABLE XA..CYPRIOT SYLLABLE XE
1083C;N          # Lo         CYPRIOT SYLLABLE ZA
1083F;N          # Lo         CYPRIOT SYLLABLE ZO
10840..10855;N   # Lo    [22] IMPERIAL ARAMAIC LETTER ALEPH..IMPERIAL ARAMAIC LETTER TAW
10857;N          # Po         IMPERIAL ARAMAIC SECTION SIGN
10858..1085F;N   # No     [8] IMPERIAL ARAMAIC NUMBER ONE..IMPERIAL ARAMAIC NUMBER TEN THOUSAND
10860..10876;N   # Lo    [23] PALMYRENE LETTER ALEPH..PALMYRENE LETTER TAW
10877..10878;N   # So     [2] PALMYRENE LEFT-POINTING FLEURON..PALMYRENE RIGHT-POINTING FLEURON
10879..1087F;N   # No     [7] PALMYRENE NUMBER ONE..PALMYRENE NUMBER TWENTY
10880..1089E;N   # Lo    [31] NABATAEAN LETTER FINAL ALEPH..NABATAEAN LETTER TAW
108A7..108AF;N   # No     [9] NABATAEAN NUMBER ONE..NABATAEAN NUMBER ONE HUNDRED
108E0..108F2;N   # Lo    [19] HATRAN LETTER ALEPH..HATRAN LETTER QOPH
108F4..108F5;N   # Lo     [2] HATRAN LETTER SHIN..HATRAN LETTER TAW
108FB..108FF;N   # No     [5] HATRAN NUMBER ONE..HATRAN NUMBER ONE HUNDRED
10900..10915;N   # Lo    [22] PHOENICIAN LETTER ALF..PHOENICIAN LETTER TAU
10916..1091B;N   # No     [6] PHOENICIAN NUMBER ONE..PHOENICIAN NUMBER THREE
1091F;N          # Po         PHOENICIAN WORD SEPARATOR
10920..10939;N   # Lo    [26] LYDIAN LETTER A..LYDIAN LETTER C
1093F;N          # Po         LYDIAN TRIANGULAR MARK
10980..1099F;N   # Lo    [32] MEROITIC HIEROGLYPHIC LETTER A..MEROITIC HIEROGLYPHIC SYMBOL VIDJ-2
109A0..109B7;N   # Lo    [24] MEROITIC CURSIVE LETTER A..MEROITIC CURSIVE LETTER DA
109BC..109BD;N   # No     [2] MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS..MEROITIC CURSIVE FRACTION ONE HALF
109BE..109BF;N   # Lo     [2] MEROITIC CURSIVE LOGOGRAM RMT..MEROITIC CURSIVE LOGOGRAM IMN
109C0..109CF;N   # No    [16] MEROITIC CURSIVE NUMBER ONE..MEROITIC CURSIVE NUMBER SEVENTY
109D2..109FF;N   # No    [46] MEROITIC CURSIVE NUMBER ONE HUNDRED..MEROITIC CURSIVE FRACTION TEN TWELFTHS
10A00;N          # Lo         KHAROSHTHI LETTER A
10A01..10A03;N   # Mn     [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R
10A05..10A06;N   # Mn     [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O
10A0C..10A0F;N   # Mn     [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA
10A10..10A13;N   # Lo     [4] KHAROSHTHI LETTER KA..KHAROSHTHI LETTER GHA
10A15..10A17;N   # Lo     [3] KHAROSHTHI LETTER CA..KHAROSHTHI LETTER JA
10A19..10A35;N   # Lo    [29] KHAROSHTHI LETTER NYA..KHAROSHTHI LETTER VHA
10A38..10A3A;N   # Mn     [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW
10A3F;N          # Mn         KHAROSHTHI VIRAMA
10A40..10A48;N   # No     [9] KHAROSHTHI DIGIT ONE..KHAROSHTHI FRACTION ONE HALF
10A50..10A58;N   # Po     [9] KHAROSHTHI PUNCTUATION DOT..KHAROSHTHI PUNCTUATION LINES
10A60..10A7C;N   # Lo    [29] OLD SOUTH ARABIAN LETTER HE..OLD SOUTH ARABIAN LETTER THETH
10A7D..10A7E;N   # No     [2] OLD SOUTH ARABIAN NUMBER ONE..OLD SOUTH ARABIAN NUMBER FIFTY
10A7F;N          # Po         OLD SOUTH ARABIAN NUMERIC INDICATOR
10A80..10A9C;N   # Lo    [29] OLD NORTH ARABIAN LETTER HEH..OLD NORTH ARABIAN LETTER ZAH
10A9D..10A9F;N   # No     [3] OLD NORTH ARABIAN NUMBER ONE..OLD NORTH ARABIAN NUMBER TWENTY
10AC0..10AC7;N   # Lo     [8] MANICHAEAN LETTER ALEPH..MANICHAEAN LETTER WAW
10AC8;N          # So         MANICHAEAN SIGN UD
10AC9..10AE4;N   # Lo    [28] MANICHAEAN LETTER ZAYIN..MANICHAEAN LETTER TAW
10AE5..10AE6;N   # Mn     [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW
10AEB..10AEF;N   # No     [5] MANICHAEAN NUMBER ONE..MANICHAEAN NUMBER ONE HUNDRED
10AF0..10AF6;N   # Po     [7] MANICHAEAN PUNCTUATION STAR..MANICHAEAN PUNCTUATION LINE FILLER
10B00..10B35;N   # Lo    [54] AVESTAN LETTER A..AVESTAN LETTER HE
10B39..10B3F;N   # Po     [7] AVESTAN ABBREVIATION MARK..LARGE ONE RING OVER TWO RINGS PUNCTUATION
10B40..10B55;N   # Lo    [22] INSCRIPTIONAL PARTHIAN LETTER ALEPH..INSCRIPTIONAL PARTHIAN LETTER TAW
10B58..10B5F;N   # No     [8] INSCRIPTIONAL PARTHIAN NUMBER ONE..INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND
10B60..10B72;N   # Lo    [19] INSCRIPTIONAL PAHLAVI LETTER ALEPH..INSCRIPTIONAL PAHLAVI LETTER TAW
10B78..10B7F;N   # No     [8] INSCRIPTIONAL PAHLAVI NUMBER ONE..INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND
10B80..10B91;N   # Lo    [18] PSALTER PAHLAVI LETTER ALEPH..PSALTER PAHLAVI LETTER TAW
10B99..10B9C;N   # Po     [4] PSALTER PAHLAVI SECTION MARK..PSALTER PAHLAVI FOUR DOTS WITH DOT
10BA9..10BAF;N   # No     [7] PSALTER PAHLAVI NUMBER ONE..PSALTER PAHLAVI NUMBER ONE HUNDRED
10C00..10C48;N   # Lo    [73] OLD TURKIC LETTER ORKHON A..OLD TURKIC LETTER ORKHON BASH
10C80..10CB2;N   # Lu    [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US
10CC0..10CF2;N   # Ll    [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US
10CFA..10CFF;N   # No     [6] OLD HUNGARIAN NUMBER ONE..OLD HUNGARIAN NUMBER ONE THOUSAND
10D00..10D23;N   # Lo    [36] HANIFI ROHINGYA LETTER A..HANIFI ROHINGYA MARK NA KHONNA
10D24..10D27;N   # Mn     [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI
10D30..10D39;N   # Nd    [10] HANIFI ROHINGYA DIGIT ZERO..HANIFI ROHINGYA DIGIT NINE
10E60..10E7E;N   # No    [31] RUMI DIGIT ONE..RUMI FRACTION TWO THIRDS
10F00..10F1C;N   # Lo    [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL
10F1D..10F26;N   # No    [10] OLD SOGDIAN NUMBER ONE..OLD SOGDIAN FRACTION ONE HALF
10F27;N          # Lo         OLD SOGDIAN LIGATURE AYIN-DALETH
10F30..10F45;N   # Lo    [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN
10F46..10F50;N   # Mn    [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW
10F51..10F54;N   # No     [4] SOGDIAN NUMBER ONE..SOGDIAN NUMBER ONE HUNDRED
10F55..10F59;N   # Po     [5] SOGDIAN PUNCTUATION TWO VERTICAL BARS..SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT
11000;N          # Mc         BRAHMI SIGN CANDRABINDU
11001;N          # Mn         BRAHMI SIGN ANUSVARA
11002;N          # Mc         BRAHMI SIGN VISARGA
11003..11037;N   # Lo    [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI LETTER OLD TAMIL NNNA
11038..11046;N   # Mn    [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA
11047..1104D;N   # Po     [7] BRAHMI DANDA..BRAHMI PUNCTUATION LOTUS
11052..11065;N   # No    [20] BRAHMI NUMBER ONE..BRAHMI NUMBER ONE THOUSAND
11066..1106F;N   # Nd    [10] BRAHMI DIGIT ZERO..BRAHMI DIGIT NINE
1107F;N          # Mn         BRAHMI NUMBER JOINER
11080..11081;N   # Mn     [2] KAITHI SIGN CANDRABINDU..KAITHI SIGN ANUSVARA
11082;N          # Mc         KAITHI SIGN VISARGA
11083..110AF;N   # Lo    [45] KAITHI LETTER A..KAITHI LETTER HA
110B0..110B2;N   # Mc     [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II
110B3..110B6;N   # Mn     [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI
110B7..110B8;N   # Mc     [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU
110B9..110BA;N   # Mn     [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA
110BB..110BC;N   # Po     [2] KAITHI ABBREVIATION SIGN..KAITHI ENUMERATION SIGN
110BD;N          # Cf         KAITHI NUMBER SIGN
110BE..110C1;N   # Po     [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA
110CD;N          # Cf         KAITHI NUMBER SIGN ABOVE
110D0..110E8;N   # Lo    [25] SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE
110F0..110F9;N   # Nd    [10] SORA SOMPENG DIGIT ZERO..SORA SOMPENG DIGIT NINE
11100..11102;N   # Mn     [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA
11103..11126;N   # Lo    [36] CHAKMA LETTER AA..CHAKMA LETTER HAA
11127..1112B;N   # Mn     [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU
1112C;N          # Mc         CHAKMA VOWEL SIGN E
1112D..11134;N   # Mn     [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA
11136..1113F;N   # Nd    [10] CHAKMA DIGIT ZERO..CHAKMA DIGIT NINE
11140..11143;N   # Po     [4] CHAKMA SECTION MARK..CHAKMA QUESTION MARK
11144;N          # Lo         CHAKMA LETTER LHAA
11145..11146;N   # Mc     [2] CHAKMA VOWEL SIGN AA..CHAKMA VOWEL SIGN EI
11150..11172;N   # Lo    [35] MAHAJANI LETTER A..MAHAJANI LETTER RRA
11173;N          # Mn         MAHAJANI SIGN NUKTA
11174..11175;N   # Po     [2] MAHAJANI ABBREVIATION SIGN..MAHAJANI SECTION MARK
11176;N          # Lo         MAHAJANI LIGATURE SHRI
11180..11181;N   # Mn     [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA
11182;N          # Mc         SHARADA SIGN VISARGA
11183..111B2;N   # Lo    [48] SHARADA LETTER A..SHARADA LETTER HA
111B3..111B5;N   # Mc     [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II
111B6..111BE;N   # Mn     [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O
111BF..111C0;N   # Mc     [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA
111C1..111C4;N   # Lo     [4] SHARADA SIGN AVAGRAHA..SHARADA OM
111C5..111C8;N   # Po     [4] SHARADA DANDA..SHARADA SEPARATOR
111C9..111CC;N   # Mn     [4] SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK
111CD;N          # Po         SHARADA SUTRA MARK
111D0..111D9;N   # Nd    [10] SHARADA DIGIT ZERO..SHARADA DIGIT NINE
111DA;N          # Lo         SHARADA EKAM
111DB;N          # Po         SHARADA SIGN SIDDHAM
111DC;N          # Lo         SHARADA HEADSTROKE
111DD..111DF;N   # Po     [3] SHARADA CONTINUATION SIGN..SHARADA SECTION MARK-2
111E1..111F4;N   # No    [20] SINHALA ARCHAIC DIGIT ONE..SINHALA ARCHAIC NUMBER ONE THOUSAND
11200..11211;N   # Lo    [18] KHOJKI LETTER A..KHOJKI LETTER JJA
11213..1122B;N   # Lo    [25] KHOJKI LETTER NYA..KHOJKI LETTER LLA
1122C..1122E;N   # Mc     [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II
1122F..11231;N   # Mn     [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI
11232..11233;N   # Mc     [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU
11234;N          # Mn         KHOJKI SIGN ANUSVARA
11235;N          # Mc         KHOJKI SIGN VIRAMA
11236..11237;N   # Mn     [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA
11238..1123D;N   # Po     [6] KHOJKI DANDA..KHOJKI ABBREVIATION SIGN
1123E;N          # Mn         KHOJKI SIGN SUKUN
11280..11286;N   # Lo     [7] MULTANI LETTER A..MULTANI LETTER GA
11288;N          # Lo         MULTANI LETTER GHA
1128A..1128D;N   # Lo     [4] MULTANI LETTER CA..MULTANI LETTER JJA
1128F..1129D;N   # Lo    [15] MULTANI LETTER NYA..MULTANI LETTER BA
1129F..112A8;N   # Lo    [10] MULTANI LETTER BHA..MULTANI LETTER RHA
112A9;N          # Po         MULTANI SECTION MARK
112B0..112DE;N   # Lo    [47] KHUDAWADI LETTER A..KHUDAWADI LETTER HA
112DF;N          # Mn         KHUDAWADI SIGN ANUSVARA
112E0..112E2;N   # Mc     [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II
112E3..112EA;N   # Mn     [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA
112F0..112F9;N   # Nd    [10] KHUDAWADI DIGIT ZERO..KHUDAWADI DIGIT NINE
11300..11301;N   # Mn     [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU
11302..11303;N   # Mc     [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA
11305..1130C;N   # Lo     [8] GRANTHA LETTER A..GRANTHA LETTER VOCALIC L
1130F..11310;N   # Lo     [2] GRANTHA LETTER EE..GRANTHA LETTER AI
11313..11328;N   # Lo    [22] GRANTHA LETTER OO..GRANTHA LETTER NA
1132A..11330;N   # Lo     [7] GRANTHA LETTER PA..GRANTHA LETTER RA
11332..11333;N   # Lo     [2] GRANTHA LETTER LA..GRANTHA LETTER LLA
11335..11339;N   # Lo     [5] GRANTHA LETTER VA..GRANTHA LETTER HA
1133B..1133C;N   # Mn     [2] COMBINING BINDU BELOW..GRANTHA SIGN NUKTA
1133D;N          # Lo         GRANTHA SIGN AVAGRAHA
1133E..1133F;N   # Mc     [2] GRANTHA VOWEL SIGN AA..GRANTHA VOWEL SIGN I
11340;N          # Mn         GRANTHA VOWEL SIGN II
11341..11344;N   # Mc     [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR
11347..11348;N   # Mc     [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI
1134B..1134D;N   # Mc     [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA
11350;N          # Lo         GRANTHA OM
11357;N          # Mc         GRANTHA AU LENGTH MARK
1135D..11361;N   # Lo     [5] GRANTHA SIGN PLUTA..GRANTHA LETTER VOCALIC LL
11362..11363;N   # Mc     [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL
11366..1136C;N   # Mn     [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX
11370..11374;N   # Mn     [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA
11400..11434;N   # Lo    [53] NEWA LETTER A..NEWA LETTER HA
11435..11437;N   # Mc     [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II
11438..1143F;N   # Mn     [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI
11440..11441;N   # Mc     [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU
11442..11444;N   # Mn     [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA
11445;N          # Mc         NEWA SIGN VISARGA
11446;N          # Mn         NEWA SIGN NUKTA
11447..1144A;N   # Lo     [4] NEWA SIGN AVAGRAHA..NEWA SIDDHI
1144B..1144F;N   # Po     [5] NEWA DANDA..NEWA ABBREVIATION SIGN
11450..11459;N   # Nd    [10] NEWA DIGIT ZERO..NEWA DIGIT NINE
1145B;N          # Po         NEWA PLACEHOLDER MARK
1145D;N          # Po         NEWA INSERTION SIGN
1145E;N          # Mn         NEWA SANDHI MARK
11480..114AF;N   # Lo    [48] TIRHUTA ANJI..TIRHUTA LETTER HA
114B0..114B2;N   # Mc     [3] TIRHUTA VOWEL SIGN AA..TIRHUTA VOWEL SIGN II
114B3..114B8;N   # Mn     [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL
114B9;N          # Mc         TIRHUTA VOWEL SIGN E
114BA;N          # Mn         TIRHUTA VOWEL SIGN SHORT E
114BB..114BE;N   # Mc     [4] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN AU
114BF..114C0;N   # Mn     [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA
114C1;N          # Mc         TIRHUTA SIGN VISARGA
114C2..114C3;N   # Mn     [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA
114C4..114C5;N   # Lo     [2] TIRHUTA SIGN AVAGRAHA..TIRHUTA GVANG
114C6;N          # Po         TIRHUTA ABBREVIATION SIGN
114C7;N          # Lo         TIRHUTA OM
114D0..114D9;N   # Nd    [10] TIRHUTA DIGIT ZERO..TIRHUTA DIGIT NINE
11580..115AE;N   # Lo    [47] SIDDHAM LETTER A..SIDDHAM LETTER HA
115AF..115B1;N   # Mc     [3] SIDDHAM VOWEL SIGN AA..SIDDHAM VOWEL SIGN II
115B2..115B5;N   # Mn     [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR
115B8..115BB;N   # Mc     [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU
115BC..115BD;N   # Mn     [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA
115BE;N          # Mc         SIDDHAM SIGN VISARGA
115BF..115C0;N   # Mn     [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA
115C1..115D7;N   # Po    [23] SIDDHAM SIGN SIDDHAM..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
115D8..115DB;N   # Lo     [4] SIDDHAM LETTER THREE-CIRCLE ALTERNATE I..SIDDHAM LETTER ALTERNATE U
115DC..115DD;N   # Mn     [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU
11600..1162F;N   # Lo    [48] MODI LETTER A..MODI LETTER LLA
11630..11632;N   # Mc     [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II
11633..1163A;N   # Mn     [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI
1163B..1163C;N   # Mc     [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU
1163D;N          # Mn         MODI SIGN ANUSVARA
1163E;N          # Mc         MODI SIGN VISARGA
1163F..11640;N   # Mn     [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA
11641..11643;N   # Po     [3] MODI DANDA..MODI ABBREVIATION SIGN
11644;N          # Lo         MODI SIGN HUVA
11650..11659;N   # Nd    [10] MODI DIGIT ZERO..MODI DIGIT NINE
11660..1166C;N   # Po    [13] MONGOLIAN BIRGA WITH ORNAMENT..MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT
11680..116AA;N   # Lo    [43] TAKRI LETTER A..TAKRI LETTER RRA
116AB;N          # Mn         TAKRI SIGN ANUSVARA
116AC;N          # Mc         TAKRI SIGN VISARGA
116AD;N          # Mn         TAKRI VOWEL SIGN AA
116AE..116AF;N   # Mc     [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II
116B0..116B5;N   # Mn     [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU
116B6;N          # Mc         TAKRI SIGN VIRAMA
116B7;N          # Mn         TAKRI SIGN NUKTA
116C0..116C9;N   # Nd    [10] TAKRI DIGIT ZERO..TAKRI DIGIT NINE
11700..1171A;N   # Lo    [27] AHOM LETTER KA..AHOM LETTER ALTERNATE BA
1171D..1171F;N   # Mn     [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA
11720..11721;N   # Mc     [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA
11722..11725;N   # Mn     [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU
11726;N          # Mc         AHOM VOWEL SIGN E
11727..1172B;N   # Mn     [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER
11730..11739;N   # Nd    [10] AHOM DIGIT ZERO..AHOM DIGIT NINE
1173A..1173B;N   # No     [2] AHOM NUMBER TEN..AHOM NUMBER TWENTY
1173C..1173E;N   # Po     [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI
1173F;N          # So         AHOM SYMBOL VI
11800..1182B;N   # Lo    [44] DOGRA LETTER A..DOGRA LETTER RRA
1182C..1182E;N   # Mc     [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II
1182F..11837;N   # Mn     [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA
11838;N          # Mc         DOGRA SIGN VISARGA
11839..1183A;N   # Mn     [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA
1183B;N          # Po         DOGRA ABBREVIATION SIGN
118A0..118DF;N   # L&    [64] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI SMALL LETTER VIYO
118E0..118E9;N   # Nd    [10] WARANG CITI DIGIT ZERO..WARANG CITI DIGIT NINE
118EA..118F2;N   # No     [9] WARANG CITI NUMBER TEN..WARANG CITI NUMBER NINETY
118FF;N          # Lo         WARANG CITI OM
11A00;N          # Lo         ZANABAZAR SQUARE LETTER A
11A01..11A0A;N   # Mn    [10] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL LENGTH MARK
11A0B..11A32;N   # Lo    [40] ZANABAZAR SQUARE LETTER KA..ZANABAZAR SQUARE LETTER KSSA
11A33..11A38;N   # Mn     [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA
11A39;N          # Mc         ZANABAZAR SQUARE SIGN VISARGA
11A3A;N          # Lo         ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA
11A3B..11A3E;N   # Mn     [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA
11A3F..11A46;N   # Po     [8] ZANABAZAR SQUARE INITIAL HEAD MARK..ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK
11A47;N          # Mn         ZANABAZAR SQUARE SUBJOINER
11A50;N          # Lo         SOYOMBO LETTER A
11A51..11A56;N   # Mn     [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE
11A57..11A58;N   # Mc     [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU
11A59..11A5B;N   # Mn     [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK
11A5C..11A83;N   # Lo    [40] SOYOMBO LETTER KA..SOYOMBO LETTER KSSA
11A86..11A89;N   # Lo     [4] SOYOMBO CLUSTER-INITIAL LETTER RA..SOYOMBO CLUSTER-INITIAL LETTER SA
11A8A..11A96;N   # Mn    [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA
11A97;N          # Mc         SOYOMBO SIGN VISARGA
11A98..11A99;N   # Mn     [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER
11A9A..11A9C;N   # Po     [3] SOYOMBO MARK TSHEG..SOYOMBO MARK DOUBLE SHAD
11A9D;N          # Lo         SOYOMBO MARK PLUTA
11A9E..11AA2;N   # Po     [5] SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME..SOYOMBO TERMINAL MARK-2
11AC0..11AF8;N   # Lo    [57] PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL
11C00..11C08;N   # Lo     [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L
11C0A..11C2E;N   # Lo    [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA
11C2F;N          # Mc         BHAIKSUKI VOWEL SIGN AA
11C30..11C36;N   # Mn     [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L
11C38..11C3D;N   # Mn     [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA
11C3E;N          # Mc         BHAIKSUKI SIGN VISARGA
11C3F;N          # Mn         BHAIKSUKI SIGN VIRAMA
11C40;N          # Lo         BHAIKSUKI SIGN AVAGRAHA
11C41..11C45;N   # Po     [5] BHAIKSUKI DANDA..BHAIKSUKI GAP FILLER-2
11C50..11C59;N   # Nd    [10] BHAIKSUKI DIGIT ZERO..BHAIKSUKI DIGIT NINE
11C5A..11C6C;N   # No    [19] BHAIKSUKI NUMBER ONE..BHAIKSUKI HUNDREDS UNIT MARK
11C70..11C71;N   # Po     [2] MARCHEN HEAD MARK..MARCHEN MARK SHAD
11C72..11C8F;N   # Lo    [30] MARCHEN LETTER KA..MARCHEN LETTER A
11C92..11CA7;N   # Mn    [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA
11CA9;N          # Mc         MARCHEN SUBJOINED LETTER YA
11CAA..11CB0;N   # Mn     [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA
11CB1;N          # Mc         MARCHEN VOWEL SIGN I
11CB2..11CB3;N   # Mn     [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E
11CB4;N          # Mc         MARCHEN VOWEL SIGN O
11CB5..11CB6;N   # Mn     [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU
11D00..11D06;N   # Lo     [7] MASARAM GONDI LETTER A..MASARAM GONDI LETTER E
11D08..11D09;N   # Lo     [2] MASARAM GONDI LETTER AI..MASARAM GONDI LETTER O
11D0B..11D30;N   # Lo    [38] MASARAM GONDI LETTER AU..MASARAM GONDI LETTER TRA
11D31..11D36;N   # Mn     [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R
11D3A;N          # Mn         MASARAM GONDI VOWEL SIGN E
11D3C..11D3D;N   # Mn     [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O
11D3F..11D45;N   # Mn     [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA
11D46;N          # Lo         MASARAM GONDI REPHA
11D47;N          # Mn         MASARAM GONDI RA-KARA
11D50..11D59;N   # Nd    [10] MASARAM GONDI DIGIT ZERO..MASARAM GONDI DIGIT NINE
11D60..11D65;N   # Lo     [6] GUNJALA GONDI LETTER A..GUNJALA GONDI LETTER UU
11D67..11D68;N   # Lo     [2] GUNJALA GONDI LETTER EE..GUNJALA GONDI LETTER AI
11D6A..11D89;N   # Lo    [32] GUNJALA GONDI LETTER OO..GUNJALA GONDI LETTER SA
11D8A..11D8E;N   # Mc     [5] GUNJALA GONDI VOWEL SIGN AA..GUNJALA GONDI VOWEL SIGN UU
11D90..11D91;N   # Mn     [2] GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI
11D93..11D94;N   # Mc     [2] GUNJALA GONDI VOWEL SIGN OO..GUNJALA GONDI VOWEL SIGN AU
11D95;N          # Mn         GUNJALA GONDI SIGN ANUSVARA
11D96;N          # Mc         GUNJALA GONDI SIGN VISARGA
11D97;N          # Mn         GUNJALA GONDI VIRAMA
11D98;N          # Lo         GUNJALA GONDI OM
11DA0..11DA9;N   # Nd    [10] GUNJALA GONDI DIGIT ZERO..GUNJALA GONDI DIGIT NINE
11EE0..11EF2;N   # Lo    [19] MAKASAR LETTER KA..MAKASAR ANGKA
11EF3..11EF4;N   # Mn     [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U
11EF5..11EF6;N   # Mc     [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O
11EF7..11EF8;N   # Po     [2] MAKASAR PASSIMBANG..MAKASAR END OF SECTION
12000..12399;N   # Lo   [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U
12400..1246E;N   # Nl   [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM
12470..12474;N   # Po     [5] CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON
12480..12543;N   # Lo   [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU
13000..1342E;N   # Lo  [1071] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH AA032
14400..14646;N   # Lo   [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530
16800..16A38;N   # Lo   [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ
16A40..16A5E;N   # Lo    [31] MRO LETTER TA..MRO LETTER TEK
16A60..16A69;N   # Nd    [10] MRO DIGIT ZERO..MRO DIGIT NINE
16A6E..16A6F;N   # Po     [2] MRO DANDA..MRO DOUBLE DANDA
16AD0..16AED;N   # Lo    [30] BASSA VAH LETTER ENNI..BASSA VAH LETTER I
16AF0..16AF4;N   # Mn     [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE
16AF5;N          # Po         BASSA VAH FULL STOP
16B00..16B2F;N   # Lo    [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU
16B30..16B36;N   # Mn     [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
16B37..16B3B;N   # Po     [5] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN VOS FEEM
16B3C..16B3F;N   # So     [4] PAHAWH HMONG SIGN XYEEM NTXIV..PAHAWH HMONG SIGN XYEEM FAIB
16B40..16B43;N   # Lm     [4] PAHAWH HMONG SIGN VOS SEEV..PAHAWH HMONG SIGN IB YAM
16B44;N          # Po         PAHAWH HMONG SIGN XAUS
16B45;N          # So         PAHAWH HMONG SIGN CIM TSOV ROG
16B50..16B59;N   # Nd    [10] PAHAWH HMONG DIGIT ZERO..PAHAWH HMONG DIGIT NINE
16B5B..16B61;N   # No     [7] PAHAWH HMONG NUMBER TENS..PAHAWH HMONG NUMBER TRILLIONS
16B63..16B77;N   # Lo    [21] PAHAWH HMONG SIGN VOS LUB..PAHAWH HMONG SIGN CIM NRES TOS
16B7D..16B8F;N   # Lo    [19] PAHAWH HMONG CLAN SIGN TSHEEJ..PAHAWH HMONG CLAN SIGN VWJ
16E40..16E7F;N   # L&    [64] MEDEFAIDRIN CAPITAL LETTER M..MEDEFAIDRIN SMALL LETTER Y
16E80..16E96;N   # No    [23] MEDEFAIDRIN DIGIT ZERO..MEDEFAIDRIN DIGIT THREE ALTERNATE FORM
16E97..16E9A;N   # Po     [4] MEDEFAIDRIN COMMA..MEDEFAIDRIN EXCLAMATION OH
16F00..16F44;N   # Lo    [69] MIAO LETTER PA..MIAO LETTER HHA
16F50;N          # Lo         MIAO LETTER NASALIZATION
16F51..16F7E;N   # Mc    [46] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN NG
16F8F..16F92;N   # Mn     [4] MIAO TONE RIGHT..MIAO TONE BELOW
16F93..16F9F;N   # Lm    [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8
16FE0..16FE1;W   # Lm     [2] TANGUT ITERATION MARK..NUSHU ITERATION MARK
17000..187F1;W   # Lo  [6130] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187F1
18800..18AF2;W   # Lo   [755] TANGUT COMPONENT-001..TANGUT COMPONENT-755
1B000..1B0FF;W   # Lo   [256] KATAKANA LETTER ARCHAIC E..HENTAIGANA LETTER RE-2
1B100..1B11E;W   # Lo    [31] HENTAIGANA LETTER RE-3..HENTAIGANA LETTER N-MU-MO-2
1B170..1B2FB;W   # Lo   [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB
1BC00..1BC6A;N   # Lo   [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M
1BC70..1BC7C;N   # Lo    [13] DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK
1BC80..1BC88;N   # Lo     [9] DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL
1BC90..1BC99;N   # Lo    [10] DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW
1BC9C;N          # So         DUPLOYAN SIGN O WITH CROSS
1BC9D..1BC9E;N   # Mn     [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK
1BC9F;N          # Po         DUPLOYAN PUNCTUATION CHINOOK FULL STOP
1BCA0..1BCA3;N   # Cf     [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
1D000..1D0F5;N   # So   [246] BYZANTINE MUSICAL SYMBOL PSILI..BYZANTINE MUSICAL SYMBOL GORGON NEO KATO
1D100..1D126;N   # So    [39] MUSICAL SYMBOL SINGLE BARLINE..MUSICAL SYMBOL DRUM CLEF-2
1D129..1D164;N   # So    [60] MUSICAL SYMBOL MULTIPLE MEASURE REST..MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE
1D165..1D166;N   # Mc     [2] MUSICAL SYMBOL COMBINING STEM..MUSICAL SYMBOL COMBINING SPRECHGESANG STEM
1D167..1D169;N   # Mn     [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3
1D16A..1D16C;N   # So     [3] MUSICAL SYMBOL FINGERED TREMOLO-1..MUSICAL SYMBOL FINGERED TREMOLO-3
1D16D..1D172;N   # Mc     [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5
1D173..1D17A;N   # Cf     [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
1D17B..1D182;N   # Mn     [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE
1D183..1D184;N   # So     [2] MUSICAL SYMBOL ARPEGGIATO UP..MUSICAL SYMBOL ARPEGGIATO DOWN
1D185..1D18B;N   # Mn     [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE
1D18C..1D1A9;N   # So    [30] MUSICAL SYMBOL RINFORZANDO..MUSICAL SYMBOL DEGREE SLASH
1D1AA..1D1AD;N   # Mn     [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO
1D1AE..1D1E8;N   # So    [59] MUSICAL SYMBOL PEDAL MARK..MUSICAL SYMBOL KIEVAN FLAT SIGN
1D200..1D241;N   # So    [66] GREEK VOCAL NOTATION SYMBOL-1..GREEK INSTRUMENTAL NOTATION SYMBOL-54
1D242..1D244;N   # Mn     [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME
1D245;N          # So         GREEK MUSICAL LEIMMA
1D2E0..1D2F3;N   # No    [20] MAYAN NUMERAL ZERO..MAYAN NUMERAL NINETEEN
1D300..1D356;N   # So    [87] MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING
1D360..1D378;N   # No    [25] COUNTING ROD UNIT DIGIT ONE..TALLY MARK FIVE
1D400..1D454;N   # L&    [85] MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL ITALIC SMALL G
1D456..1D49C;N   # L&    [71] MATHEMATICAL ITALIC SMALL I..MATHEMATICAL SCRIPT CAPITAL A
1D49E..1D49F;N   # Lu     [2] MATHEMATICAL SCRIPT CAPITAL C..MATHEMATICAL SCRIPT CAPITAL D
1D4A2;N          # Lu         MATHEMATICAL SCRIPT CAPITAL G
1D4A5..1D4A6;N   # Lu     [2] MATHEMATICAL SCRIPT CAPITAL J..MATHEMATICAL SCRIPT CAPITAL K
1D4A9..1D4AC;N   # Lu     [4] MATHEMATICAL SCRIPT CAPITAL N..MATHEMATICAL SCRIPT CAPITAL Q
1D4AE..1D4B9;N   # L&    [12] MATHEMATICAL SCRIPT CAPITAL S..MATHEMATICAL SCRIPT SMALL D
1D4BB;N          # Ll         MATHEMATICAL SCRIPT SMALL F
1D4BD..1D4C3;N   # Ll     [7] MATHEMATICAL SCRIPT SMALL H..MATHEMATICAL SCRIPT SMALL N
1D4C5..1D505;N   # L&    [65] MATHEMATICAL SCRIPT SMALL P..MATHEMATICAL FRAKTUR CAPITAL B
1D507..1D50A;N   # Lu     [4] MATHEMATICAL FRAKTUR CAPITAL D..MATHEMATICAL FRAKTUR CAPITAL G
1D50D..1D514;N   # Lu     [8] MATHEMATICAL FRAKTUR CAPITAL J..MATHEMATICAL FRAKTUR CAPITAL Q
1D516..1D51C;N   # Lu     [7] MATHEMATICAL FRAKTUR CAPITAL S..MATHEMATICAL FRAKTUR CAPITAL Y
1D51E..1D539;N   # L&    [28] MATHEMATICAL FRAKTUR SMALL A..MATHEMATICAL DOUBLE-STRUCK CAPITAL B
1D53B..1D53E;N   # Lu     [4] MATHEMATICAL DOUBLE-STRUCK CAPITAL D..MATHEMATICAL DOUBLE-STRUCK CAPITAL G
1D540..1D544;N   # Lu     [5] MATHEMATICAL DOUBLE-STRUCK CAPITAL I..MATHEMATICAL DOUBLE-STRUCK CAPITAL M
1D546;N          # Lu         MATHEMATICAL DOUBLE-STRUCK CAPITAL O
1D54A..1D550;N   # Lu     [7] MATHEMATICAL DOUBLE-STRUCK CAPITAL S..MATHEMATICAL DOUBLE-STRUCK CAPITAL Y
1D552..1D6A5;N   # L&   [340] MATHEMATICAL DOUBLE-STRUCK SMALL A..MATHEMATICAL ITALIC SMALL DOTLESS J
1D6A8..1D6C0;N   # Lu    [25] MATHEMATICAL BOLD CAPITAL ALPHA..MATHEMATICAL BOLD CAPITAL OMEGA
1D6C1;N          # Sm         MATHEMATICAL BOLD NABLA
1D6C2..1D6DA;N   # Ll    [25] MATHEMATICAL BOLD SMALL ALPHA..MATHEMATICAL BOLD SMALL OMEGA
1D6DB;N          # Sm         MATHEMATICAL BOLD PARTIAL DIFFERENTIAL
1D6DC..1D6FA;N   # L&    [31] MATHEMATICAL BOLD EPSILON SYMBOL..MATHEMATICAL ITALIC CAPITAL OMEGA
1D6FB;N          # Sm         MATHEMATICAL ITALIC NABLA
1D6FC..1D714;N   # Ll    [25] MATHEMATICAL ITALIC SMALL ALPHA..MATHEMATICAL ITALIC SMALL OMEGA
1D715;N          # Sm         MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL
1D716..1D734;N   # L&    [31] MATHEMATICAL ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD ITALIC CAPITAL OMEGA
1D735;N          # Sm         MATHEMATICAL BOLD ITALIC NABLA
1D736..1D74E;N   # Ll    [25] MATHEMATICAL BOLD ITALIC SMALL ALPHA..MATHEMATICAL BOLD ITALIC SMALL OMEGA
1D74F;N          # Sm         MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL
1D750..1D76E;N   # L&    [31] MATHEMATICAL BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA
1D76F;N          # Sm         MATHEMATICAL SANS-SERIF BOLD NABLA
1D770..1D788;N   # Ll    [25] MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA
1D789;N          # Sm         MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL
1D78A..1D7A8;N   # L&    [31] MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA
1D7A9;N          # Sm         MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA
1D7AA..1D7C2;N   # Ll    [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA
1D7C3;N          # Sm         MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL
1D7C4..1D7CB;N   # L&     [8] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD SMALL DIGAMMA
1D7CE..1D7FF;N   # Nd    [50] MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE
1D800..1D9FF;N   # So   [512] SIGNWRITING HAND-FIST INDEX..SIGNWRITING HEAD
1DA00..1DA36;N   # Mn    [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN
1DA37..1DA3A;N   # So     [4] SIGNWRITING AIR BLOW SMALL ROTATIONS..SIGNWRITING BREATH EXHALE
1DA3B..1DA6C;N   # Mn    [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT
1DA6D..1DA74;N   # So     [8] SIGNWRITING SHOULDER HIP SPINE..SIGNWRITING TORSO-FLOORPLANE TWISTING
1DA75;N          # Mn         SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS
1DA76..1DA83;N   # So    [14] SIGNWRITING LIMB COMBINATION..SIGNWRITING LOCATION DEPTH
1DA84;N          # Mn         SIGNWRITING LOCATION HEAD NECK
1DA85..1DA86;N   # So     [2] SIGNWRITING LOCATION TORSO..SIGNWRITING LOCATION LIMBS DIGITS
1DA87..1DA8B;N   # Po     [5] SIGNWRITING COMMA..SIGNWRITING PARENTHESIS
1DA9B..1DA9F;N   # Mn     [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6
1DAA1..1DAAF;N   # Mn    [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16
1E000..1E006;N   # Mn     [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE
1E008..1E018;N   # Mn    [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU
1E01B..1E021;N   # Mn     [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI
1E023..1E024;N   # Mn     [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS
1E026..1E02A;N   # Mn     [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA
1E800..1E8C4;N   # Lo   [197] MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON
1E8C7..1E8CF;N   # No     [9] MENDE KIKAKUI DIGIT ONE..MENDE KIKAKUI DIGIT NINE
1E8D0..1E8D6;N   # Mn     [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS
1E900..1E943;N   # L&    [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA
1E944..1E94A;N   # Mn     [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA
1E950..1E959;N   # Nd    [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE
1E95E..1E95F;N   # Po     [2] ADLAM INITIAL EXCLAMATION MARK..ADLAM INITIAL QUESTION MARK
1EC71..1ECAB;N   # No    [59] INDIC SIYAQ NUMBER ONE..INDIC SIYAQ NUMBER PREFIXED NINE
1ECAC;N          # So         INDIC SIYAQ PLACEHOLDER
1ECAD..1ECAF;N   # No     [3] INDIC SIYAQ FRACTION ONE QUARTER..INDIC SIYAQ FRACTION THREE QUARTERS
1ECB0;N          # Sc         INDIC SIYAQ RUPEE MARK
1ECB1..1ECB4;N   # No     [4] INDIC SIYAQ NUMBER ALTERNATE ONE..INDIC SIYAQ ALTERNATE LAKH MARK
1EE00..1EE03;N   # Lo     [4] ARABIC MATHEMATICAL ALEF..ARABIC MATHEMATICAL DAL
1EE05..1EE1F;N   # Lo    [27] ARABIC MATHEMATICAL WAW..ARABIC MATHEMATICAL DOTLESS QAF
1EE21..1EE22;N   # Lo     [2] ARABIC MATHEMATICAL INITIAL BEH..ARABIC MATHEMATICAL INITIAL JEEM
1EE24;N          # Lo         ARABIC MATHEMATICAL INITIAL HEH
1EE27;N          # Lo         ARABIC MATHEMATICAL INITIAL HAH
1EE29..1EE32;N   # Lo    [10] ARABIC MATHEMATICAL INITIAL YEH..ARABIC MATHEMATICAL INITIAL QAF
1EE34..1EE37;N   # Lo     [4] ARABIC MATHEMATICAL INITIAL SHEEN..ARABIC MATHEMATICAL INITIAL KHAH
1EE39;N          # Lo         ARABIC MATHEMATICAL INITIAL DAD
1EE3B;N          # Lo         ARABIC MATHEMATICAL INITIAL GHAIN
1EE42;N          # Lo         ARABIC MATHEMATICAL TAILED JEEM
1EE47;N          # Lo         ARABIC MATHEMATICAL TAILED HAH
1EE49;N          # Lo         ARABIC MATHEMATICAL TAILED YEH
1EE4B;N          # Lo         ARABIC MATHEMATICAL TAILED LAM
1EE4D..1EE4F;N   # Lo     [3] ARABIC MATHEMATICAL TAILED NOON..ARABIC MATHEMATICAL TAILED AIN
1EE51..1EE52;N   # Lo     [2] ARABIC MATHEMATICAL TAILED SAD..ARABIC MATHEMATICAL TAILED QAF
1EE54;N          # Lo         ARABIC MATHEMATICAL TAILED SHEEN
1EE57;N          # Lo         ARABIC MATHEMATICAL TAILED KHAH
1EE59;N          # Lo         ARABIC MATHEMATICAL TAILED DAD
1EE5B;N          # Lo         ARABIC MATHEMATICAL TAILED GHAIN
1EE5D;N          # Lo         ARABIC MATHEMATICAL TAILED DOTLESS NOON
1EE5F;N          # Lo         ARABIC MATHEMATICAL TAILED DOTLESS QAF
1EE61..1EE62;N   # Lo     [2] ARABIC MATHEMATICAL STRETCHED BEH..ARABIC MATHEMATICAL STRETCHED JEEM
1EE64;N          # Lo         ARABIC MATHEMATICAL STRETCHED HEH
1EE67..1EE6A;N   # Lo     [4] ARABIC MATHEMATICAL STRETCHED HAH..ARABIC MATHEMATICAL STRETCHED KAF
1EE6C..1EE72;N   # Lo     [7] ARABIC MATHEMATICAL STRETCHED MEEM..ARABIC MATHEMATICAL STRETCHED QAF
1EE74..1EE77;N   # Lo     [4] ARABIC MATHEMATICAL STRETCHED SHEEN..ARABIC MATHEMATICAL STRETCHED KHAH
1EE79..1EE7C;N   # Lo     [4] ARABIC MATHEMATICAL STRETCHED DAD..ARABIC MATHEMATICAL STRETCHED DOTLESS BEH
1EE7E;N          # Lo         ARABIC MATHEMATICAL STRETCHED DOTLESS FEH
1EE80..1EE89;N   # Lo    [10] ARABIC MATHEMATICAL LOOPED ALEF..ARABIC MATHEMATICAL LOOPED YEH
1EE8B..1EE9B;N   # Lo    [17] ARABIC MATHEMATICAL LOOPED LAM..ARABIC MATHEMATICAL LOOPED GHAIN
1EEA1..1EEA3;N   # Lo     [3] ARABIC MATHEMATICAL DOUBLE-STRUCK BEH..ARABIC MATHEMATICAL DOUBLE-STRUCK DAL
1EEA5..1EEA9;N   # Lo     [5] ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH
1EEAB..1EEBB;N   # Lo    [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN
1EEF0..1EEF1;N   # Sm     [2] ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL
1F000..1F003;N   # So     [4] MAHJONG TILE EAST WIND..MAHJONG TILE NORTH WIND
1F004;W          # So         MAHJONG TILE RED DRAGON
1F005..1F02B;N   # So    [39] MAHJONG TILE GREEN DRAGON..MAHJONG TILE BACK
1F030..1F093;N   # So   [100] DOMINO TILE HORIZONTAL BACK..DOMINO TILE VERTICAL-06-06
1F0A0..1F0AE;N   # So    [15] PLAYING CARD BACK..PLAYING CARD KING OF SPADES
1F0B1..1F0BF;N   # So    [15] PLAYING CARD ACE OF HEARTS..PLAYING CARD RED JOKER
1F0C1..1F0CE;N   # So    [14] PLAYING CARD ACE OF DIAMONDS..PLAYING CARD KING OF DIAMONDS
1F0CF;W          # So         PLAYING CARD BLACK JOKER
1F0D1..1F0F5;N   # So    [37] PLAYING CARD ACE OF CLUBS..PLAYING CARD TRUMP-21
1F100..1F10A;A   # No    [11] DIGIT ZERO FULL STOP..DIGIT NINE COMMA
1F10B..1F10C;N   # No     [2] DINGBAT CIRCLED SANS-SERIF DIGIT ZERO..DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO
1F110..1F12D;A   # So    [30] PARENTHESIZED LATIN CAPITAL LETTER A..CIRCLED CD
1F12E..1F12F;N   # So     [2] CIRCLED WZ..COPYLEFT SYMBOL
1F130..1F169;A   # So    [58] SQUARED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z
1F16A..1F16B;N   # So     [2] RAISED MC SIGN..RAISED MD SIGN
1F170..1F18D;A   # So    [30] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED SA
1F18E;W          # So         NEGATIVE SQUARED AB
1F18F..1F190;A   # So     [2] NEGATIVE SQUARED WC..SQUARE DJ
1F191..1F19A;W   # So    [10] SQUARED CL..SQUARED VS
1F19B..1F1AC;A   # So    [18] SQUARED THREE D..SQUARED VOD
1F1E6..1F1FF;N   # So    [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z
1F200..1F202;W   # So     [3] SQUARE HIRAGANA HOKA..SQUARED KATAKANA SA
1F210..1F23B;W   # So    [44] SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-914D
1F240..1F248;W   # So     [9] TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C..TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557
1F250..1F251;W   # So     [2] CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT
1F260..1F265;W   # So     [6] ROUNDED SYMBOL FOR FU..ROUNDED SYMBOL FOR CAI
1F300..1F320;W   # So    [33] CYCLONE..SHOOTING STAR
1F321..1F32C;N   # So    [12] THERMOMETER..WIND BLOWING FACE
1F32D..1F335;W   # So     [9] HOT DOG..CACTUS
1F336;N          # So         HOT PEPPER
1F337..1F37C;W   # So    [70] TULIP..BABY BOTTLE
1F37D;N          # So         FORK AND KNIFE WITH PLATE
1F37E..1F393;W   # So    [22] BOTTLE WITH POPPING CORK..GRADUATION CAP
1F394..1F39F;N   # So    [12] HEART WITH TIP ON THE LEFT..ADMISSION TICKETS
1F3A0..1F3CA;W   # So    [43] CAROUSEL HORSE..SWIMMER
1F3CB..1F3CE;N   # So     [4] WEIGHT LIFTER..RACING CAR
1F3CF..1F3D3;W   # So     [5] CRICKET BAT AND BALL..TABLE TENNIS PADDLE AND BALL
1F3D4..1F3DF;N   # So    [12] SNOW CAPPED MOUNTAIN..STADIUM
1F3E0..1F3F0;W   # So    [17] HOUSE BUILDING..EUROPEAN CASTLE
1F3F1..1F3F3;N   # So     [3] WHITE PENNANT..WAVING WHITE FLAG
1F3F4;W          # So         WAVING BLACK FLAG
1F3F5..1F3F7;N   # So     [3] ROSETTE..LABEL
1F3F8..1F3FA;W   # So     [3] BADMINTON RACQUET AND SHUTTLECOCK..AMPHORA
1F3FB..1F3FF;W   # Sk     [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6
1F400..1F43E;W   # So    [63] RAT..PAW PRINTS
1F43F;N          # So         CHIPMUNK
1F440;W          # So         EYES
1F441;N          # So         EYE
1F442..1F4FC;W   # So   [187] EAR..VIDEOCASSETTE
1F4FD..1F4FE;N   # So     [2] FILM PROJECTOR..PORTABLE STEREO
1F4FF..1F53D;W   # So    [63] PRAYER BEADS..DOWN-POINTING SMALL RED TRIANGLE
1F53E..1F54A;N   # So    [13] LOWER RIGHT SHADOWED WHITE CIRCLE..DOVE OF PEACE
1F54B..1F54E;W   # So     [4] KAABA..MENORAH WITH NINE BRANCHES
1F54F;N          # So         BOWL OF HYGIEIA
1F550..1F567;W   # So    [24] CLOCK FACE ONE OCLOCK..CLOCK FACE TWELVE-THIRTY
1F568..1F579;N   # So    [18] RIGHT SPEAKER..JOYSTICK
1F57A;W          # So         MAN DANCING
1F57B..1F594;N   # So    [26] LEFT HAND TELEPHONE RECEIVER..REVERSED VICTORY HAND
1F595..1F596;W   # So     [2] REVERSED HAND WITH MIDDLE FINGER EXTENDED..RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS
1F597..1F5A3;N   # So    [13] WHITE DOWN POINTING LEFT HAND INDEX..BLACK DOWN POINTING BACKHAND INDEX
1F5A4;W          # So         BLACK HEART
1F5A5..1F5FA;N   # So    [86] DESKTOP COMPUTER..WORLD MAP
1F5FB..1F5FF;W   # So     [5] MOUNT FUJI..MOYAI
1F600..1F64F;W   # So    [80] GRINNING FACE..PERSON WITH FOLDED HANDS
1F650..1F67F;N   # So    [48] NORTH WEST POINTING LEAF..REVERSE CHECKER BOARD
1F680..1F6C5;W   # So    [70] ROCKET..LEFT LUGGAGE
1F6C6..1F6CB;N   # So     [6] TRIANGLE WITH ROUNDED CORNERS..COUCH AND LAMP
1F6CC;W          # So         SLEEPING ACCOMMODATION
1F6CD..1F6CF;N   # So     [3] SHOPPING BAGS..BED
1F6D0..1F6D2;W   # So     [3] PLACE OF WORSHIP..SHOPPING TROLLEY
1F6D3..1F6D4;N   # So     [2] STUPA..PAGODA
1F6E0..1F6EA;N   # So    [11] HAMMER AND WRENCH..NORTHEAST-POINTING AIRPLANE
1F6EB..1F6EC;W   # So     [2] AIRPLANE DEPARTURE..AIRPLANE ARRIVING
1F6F0..1F6F3;N   # So     [4] SATELLITE..PASSENGER SHIP
1F6F4..1F6F9;W   # So     [6] SCOOTER..SKATEBOARD
1F700..1F773;N   # So   [116] ALCHEMICAL SYMBOL FOR QUINTESSENCE..ALCHEMICAL SYMBOL FOR HALF OUNCE
1F780..1F7D8;N   # So    [89] BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..NEGATIVE CIRCLED SQUARE
1F800..1F80B;N   # So    [12] LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD..DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD
1F810..1F847;N   # So    [56] LEFTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD..DOWNWARDS HEAVY ARROW
1F850..1F859;N   # So    [10] LEFTWARDS SANS-SERIF ARROW..UP DOWN SANS-SERIF ARROW
1F860..1F887;N   # So    [40] WIDE-HEADED LEFTWARDS LIGHT BARB ARROW..WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW
1F890..1F8AD;N   # So    [30] LEFTWARDS TRIANGLE ARROWHEAD..WHITE ARROW SHAFT WIDTH TWO THIRDS
1F900..1F90B;N   # So    [12] CIRCLED CROSS FORMEE WITH FOUR DOTS..DOWNWARD FACING NOTCHED HOOK WITH DOT
1F910..1F93E;W   # So    [47] ZIPPER-MOUTH FACE..HANDBALL
1F940..1F970;W   # So    [49] WILTED FLOWER..SMILING FACE WITH SMILING EYES AND THREE HEARTS
1F973..1F976;W   # So     [4] FACE WITH PARTY HORN AND PARTY HAT..FREEZING FACE
1F97A;W          # So         FACE WITH PLEADING EYES
1F97C..1F9A2;W   # So    [39] LAB COAT..SWAN
1F9B0..1F9B9;W   # So    [10] EMOJI COMPONENT RED HAIR..SUPERVILLAIN
1F9C0..1F9C2;W   # So     [3] CHEESE WEDGE..SALT SHAKER
1F9D0..1F9FF;W   # So    [48] FACE WITH MONOCLE..NAZAR AMULET
1FA60..1FA6D;N   # So    [14] XIANGQI RED GENERAL..XIANGQI BLACK SOLDIER
20000..2A6D6;W   # Lo [42711] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6
2A6D7..2A6FF;W   # Cn    [41] <reserved-2A6D7>..<reserved-2A6FF>
2A700..2B734;W   # Lo  [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734
2B735..2B73F;W   # Cn    [11] <reserved-2B735>..<reserved-2B73F>
2B740..2B81D;W   # Lo   [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
2B81E..2B81F;W   # Cn     [2] <reserved-2B81E>..<reserved-2B81F>
2B820..2CEA1;W   # Lo  [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
2CEA2..2CEAF;W   # Cn    [14] <reserved-2CEA2>..<reserved-2CEAF>
2CEB0..2EBE0;W   # Lo  [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
2EBE1..2F7FF;W   # Cn  [3103] <reserved-2EBE1>..<reserved-2F7FF>
2F800..2FA1D;W   # Lo   [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
2FA1E..2FA1F;W   # Cn     [2] <reserved-2FA1E>..<reserved-2FA1F>
2FA20..2FFFD;W   # Cn  [1502] <reserved-2FA20>..<reserved-2FFFD>
30000..3FFFD;W   # Cn [65534] <reserved-30000>..<reserved-3FFFD>
E0001;N          # Cf         LANGUAGE TAG
E0020..E007F;N   # Cf    [96] TAG SPACE..CANCEL TAG
E0100..E01EF;A   # Mn   [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
F0000..FFFFD;A   # Co [65534] <private-use-F0000>..<private-use-FFFFD>
100000..10FFFD;A # Co [65534] <private-use-100000>..<private-use-10FFFD>

# EOF

Added modules/textutil/build/build.tcl.









































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
set srcdir [file dirname [file normalize [file join [pwd] [info script]]]]
set moddir [file dirname $srcdir]

set fout [open [file join $moddir wcswidth.tcl] w]
puts $fout {###
# This file is automatically generated by the build/build.tcl file
# based on information in the following database:
# http://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt
#
# (This is the 35th edition, thus version 35 for our package)
#
# Author: Sean Woods <[email protected]>
###
package provide textutil::wcswidth 35.1}

set fin [open [file join $srcdir EastAsianWidth.txt] r]
puts $fout "proc ::textutil::wcswidth_type char \{"
set hash #
while {[gets $fin line]>=0} {
  set commentidx [string first $hash $line]
  if {$commentidx==0} continue
  set data [string trim [string range $line 0 [expr $commentidx-1]]]
  set comment [string range $line [expr {$commentidx+1}] end]
  if {[scan $line {%6x..%6x;%1s} start end code]==3} {
  } elseif {[scan $line {%5x..%5x;%1s} start end code]==3} {
  } elseif {[scan $line {%4x..%4x;%1s} start end code]==3} {
  } elseif {[scan $line  {%5x;%1s} start code]==2} {
    set end $start
  } elseif {[scan $line  {%4x;%1s} start code]==2} {
    set end $start
  } else {
    puts "Ignored line: '$line'"
    continue
  }
  if {$code eq "N"} continue
  dict set map %start% $start
  dict set map %end% $end
  dict set map %code% $code
  dict set map %comment% [string trim $comment]
  #puts $fout "  $hash $comment"
  if {$start eq $end} {
    puts $fout [string map $map {  if {$char == %start%} { return %code% }}]
  } else {
    puts $fout [string map $map {  if {$char >= %start% && $char <= %end% } { return %code% }}]
  }
}
puts $fout {  return N}
puts $fout "\}"

seek $fin 0
puts $fout "proc ::textutil::wcswidth_char char \{"
while {[gets $fin line]>=0} {
  set commentidx [string first $hash $line]
  if {$commentidx==0} continue
  set data [string trim [string range $line 0 [expr $commentidx-1]]]
  set comment [string range $line [expr {$commentidx+1}] end]
  if {[scan $line {%6x..%6x;%1s} start end code]==3} {
  } elseif {[scan $line {%5x..%5x;%1s} start end code]==3} {
  } elseif {[scan $line {%4x..%4x;%1s} start end code]==3} {
  } elseif {[scan $line  {%5x;%1s} start code]==2} {
    set end $start
  } elseif {[scan $line  {%4x;%1s} start code]==2} {
    set end $start
  } else {
    puts "Ignored line: '$line'"
    continue
  }
  dict set map %start% $start
  dict set map %end% $end
  dict set map %width% 1

  ###
  # Per the unicode recommendations:
  # http://www.unicode.org/reports/tr11/
  #
  #When processing or displaying data:
  #
  # * Wide characters behave like ideographs in important ways, such as layout. Except for
  #   certain punctuation characters, they are not rotated when appearing in vertical text
  #   runs. In fixed-pitch fonts, they take up one Em of space.
  # * Halfwidth characters behave like ideographs in some ways, however, they are rotated
  #   like narrow characters when appearing in vertical text runs. In fixed-pitch fonts,
  #   they take up 1/2 Em of space.
  # * Narrow characters behave like Western characters, for example, in line breaking.
  #   They are rotated sideways, when appearing in vertical text. In fixed-pitch East
  #   Asian fonts, they take up 1/2 Em of space, but in rendering, a non-East Asian,
  #   proportional font is often substituted.
  # * Ambiguous characters behave like wide or narrow characters depending on the context
  #   (language tag, script identification, associated font, source of data, or explicit
  #   markup; all can provide the context). If the context cannot be established reliably,
  #   they should be treated as narrow characters by default.
  # * [UTS51] emoji presentation sequences behave as though they were East Asian Wide,
  #   regardless of their assigned East_Asian_Width property value. (Not implemented here)
  ###
  switch $code {
    W -
    F {
      dict set map %width% 2
    }
    A -
    N -
    Na -
    H {
      continue
    }
  }
  dict set map %code% $code
  dict set map %comment% [string trim $comment]
  #puts $fout "  # $comment"
  if {$start eq $end} {
    puts $fout [string map $map {  if {$char == %start%} { return %width% }}]
  } else {
    puts $fout [string map $map {  if {$char >= %start% && $char <= %end% } { return %width% }}]
  }
}
puts $fout {  return 1}
puts $fout "\}"
puts $fout {
proc ::textutil::wcswidth {string} {
  set width 0
  set len [string length $string]
  foreach c [split $string {}] {
    scan $c %c char
    set n [::textutil::wcswidth_char $char]
    if {$n < 0} {
      return -1
    }
    incr width $n
  }
  return $width
}
}

Changes to modules/textutil/expander.man.

503
504
505
506
507
508
509
510
511

[section HISTORY]

[cmd expander] was written by William H. Duquette; it is a repackaging
of the central algorithm of the expand macro processing tool.

[vset CATEGORY textutil]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

503
504
505
506
507
508
509
510
511

[section HISTORY]

[cmd expander] was written by William H. Duquette; it is a repackaging
of the central algorithm of the expand macro processing tool.

[vset CATEGORY textutil]
[include ../common-text/feedback.inc]
[manpage_end]

Added modules/textutil/patch.man.































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
[vset VERSION 0.1]
[manpage_begin textutil::patch n [vset VERSION]]
[keywords {diff, unified format} {unified format diff} patch {diff -ruN} git fossil]
[moddesc   {Text and string utilities}]
[titledesc {Application of uni-diff patches to directory trees}]
[category  {Text processing}]
[require Tcl 8.2]
[require textutil::patch [opt [vset VERSION]]]
[description]

This package provides a single command which applies a patch in
[uri \
	https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html \
	{unified format}]
to a directory tree.

[list_begin definitions]

[call [cmd ::textutil::patch::apply] [arg basedirectory] \
	[arg striplevel] [arg patch] [arg reportcmd]]

Applies the [arg patch] (text of the path, not file) to the files in
the [arg basedirectory] using the specified [arg striplevel].

The result of the command is the empty string.

[para] The [arg striplevel] argument is equivalent to option
[option -p] of the [syscmd patch] command.

[para] Errors are thrown when the [arg patch] does not parse, and
nothing is done to the files in [arg basedirectory].

[para] All activities during the application of the patch, including
the inability to apply a hunk are reported through the command prefix
[arg reportcmd] instead. Files with problems are left unchanged.  Note
however that this does [strong {not prevent}] changes to files with no
problems, before and after the problematic file(s).

[para] The command prefix is called in 3 possible forms:

[list_begin definitions]

[call [cmd {{*}reportcmd}] [method apply] [arg filename]]

The caller begins operation on file [arg fname], applying all hunks
collected for said file.

[call [cmd {{*}reportcmd}] [method fail] [arg filename] [arg hunk] [arg expected] [arg seen]]

Application of hunk number [arg hunk] of file [arg filename] has failed.
The command expected to find the text [arg expected], and saw [arg seen] instead.

[call [cmd {{*}reportcmd}] [method fail-already] [arg filename] [arg hunk]]

Application of hunk number [arg hunk] of file [arg filename] has failed.
The command believes that this hunk has already been applied to the file.

[list_end]
[list_end]

[vset CATEGORY textutil]
[include ../common-text/feedback.inc]
[manpage_end]

Added modules/textutil/patch.tcl.









































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# patch.tcl --
#
#	Application of a diff -ruN patch to a directory tree.
#
# Copyright (c) 2019 Christian Gollwitzer <[email protected]>
# with tweaks by Andreas Kupries
# - Factored patch parsing into a helper
# - Replaced `puts` with report callback.

package require Tcl 8.5
package provide textutil::patch 0.1

# # ## ### ##### ######## ############# #####################

namespace eval ::textutil::patch {
    namespace export apply
    namespace ensemble create
}

# # ## ### ##### ######## ############# #####################

proc ::textutil::patch::apply {dir striplevel patch reportcmd} {
    set patchdict [Parse $dir $striplevel $patch]

    # Apply, now that we have parsed the patch.
    dict for {fn hunks} $patchdict {
	Report apply $fn
	if {[catch {open $fn} fd]} {
	    set orig {}
	} else {
	    set orig [split [read $fd] \n]
	}
	close $fd

	set patched $orig

	set fail false
	set already_applied false
	set hunknr 1
	foreach hunk $hunks {
	    dict with hunk {
		set oldend [expr {$oldstart+[llength $oldcode]-1}]
		set newend [expr {$newstart+[llength $newcode]-1}]
		# check if the hunk matches
		set origcode [lrange $orig $oldstart $oldend]
		if {$origcode ne $oldcode} {
		    set fail true
		    # check if the patch is already applied
		    set origcode_applied [lrange $orig $newstart $newend]
		    if {$origcode_applied eq $newcode} {
			set already_applied true
			Report fail-already $fn $hunknr
		    } else {
			Report fail $fn $hunknr $oldcode $origcode
		    }
		    break
		}
		# apply patch
		set patched [list \
				 {*}[lrange $patched 0 $newstart-1] \
				 {*}$newcode \
				 {*}[lrange $orig $oldend+1 end]]
	    }
	    incr hunknr
	}

	if {!$fail} {
	    # success - write the result back
	    set fd [open $fn w]
	    puts -nonewline $fd [join $patched \n]
	    close $fd
	}
    }

    return
}

# # ## ### ##### ######## ############# #####################

proc ::textutil::patch::Report {args} {
    upvar 1 reportcmd reportcmd
    uplevel #0 [list {*}$reportcmd {*}$args]
    ##
    # apply        $fname
    # fail-already $fname $hunkno
    # fail         $fname $hunkno $expected $seen
    ##
}

proc ::textutil::patch::Parse {dir striplevel patch} {
    set patchlines [split $patch \n]
    set inhunk false
    set oldcode {}
    set newcode {}
    set n [llength $patchlines]

    set patchdict {}
    for {set lineidx 0} {$lineidx < $n} {incr lineidx} {
	set line [lindex $patchlines $lineidx]
	if {[string match ---* $line]} {
	    # a diff block starts. Current line should be
	    # --- oldfile date time TZ
	    # Next line should be
	    # +++ newfile date time TZ
	    set in $line
	    incr lineidx
	    set out [lindex $patchlines $lineidx]

	    if {![string match ---* $in] || ![string match +++* $out]} {
		#puts $in
		#puts $out
		return -code error "Patch not in unified diff format, line $lineidx $in $out"
	    }

	    # the quoting is compatible with list
	    lassign $in  -> oldfile
	    lassign $out -> newfile

	    set fntopatch [file join $dir {*}[lrange [file split $oldfile] $striplevel end]]
	    set inhunk false
	    #puts "Found diffline for $fntopatch"
	    continue
	}

	# state machine for parsing the hunks
	set typechar [string index $line 0]
	set codeline [string range $line 1 end]
	switch $typechar {
	    @ {
		if {![regexp {@@\s+\-(\d+),(\d+)\s+\+(\d+),(\d+)\s+@@} $line \
			  -> oldstart oldlen newstart newlen]} {
		    return code -error "Erroneous hunk in line $lindeidx, $line"
		}
		# adjust line numbers for 0-based indexing
		incr oldstart -1
		incr newstart -1
		#puts "New hunk"
		set newcode {}
		set oldcode {}
		set inhunk true
	    }
	    - { # line only in old code
		if {$inhunk} {
		    lappend oldcode $codeline
		}
	    }
	    + { # line only in new code
		if {$inhunk} {
		    lappend newcode $codeline
		}
	    }
	    " " { # common line
		if {$inhunk} {
		    lappend oldcode $codeline
		    lappend newcode $codeline
		}
	    }
	    default {
		# puts "Junk: $codeline";
		continue
	    }
	}
	# test if the hunk is complete
	if {[llength $oldcode]==$oldlen && [llength $newcode]==$newlen} {
	    set hunk [dict create \
			  oldcode $oldcode \
			  newcode $newcode \
			  oldstart $oldstart \
			  newstart $newstart]
	    #puts "hunk complete: $hunk"
	    set inhunk false
	    dict lappend patchdict $fntopatch $hunk
	}
    }

    return $patchdict
}

# # ## ### ##### ######## ############# #####################
return

Added modules/textutil/patch.test.























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
# -*- tcl -*-
# patch.test:  tests for application of `diff -ruN` patches.

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2

testing {
    useLocal patch.tcl textutil::patch
}

# -------------------------------------------------------------------------
set m {wrong # args: should be "textutil::patch apply dir striplevel patch reportcmd"}

test textutil-patch-1.0 {wrong args, not enough} -body {
    textutil::patch apply
} -returnCodes error -result $m

test textutil-patch-1.1 {wrong args, not enough} -body {
    textutil::patch apply D
} -returnCodes error -result $m

test textutil-patch-1.2 {wrong args, not enough} -body {
    textutil::patch apply D S
} -returnCodes error -result $m

test textutil-patch-1.3 {wrong args, not enough} -body {
    textutil::patch apply D S P
} -returnCodes error -result $m

test textutil-patch-1.4 {wrong args, too many} -body {
    textutil::patch apply D S P R X
} -returnCodes error -result $m

unset m

# -------------------------------------------------------------------------
## Patch application. All ok.

proc setup-scratch {} {
    # Create a temp directory hierarchy where we can perform patch application.
    # scratch
    # \- pkgIndex.tcl

    file mkdir [asset scratch]
    file copy  [asset pkgIndex.tcl] [asset scratch/pkgIndex.tcl]
    set ::trace {}
    return    
}

proc cleanup-scratch {} {
    # Drop scratch area again.
    unset ::trace
    file delete -force [asset scratch]
    return
}

proc record {args} { lappend ::trace $args }

proc recorded {} {
    lappend ::trace === [tcltest::viewFile [asset scratch/pkgIndex.tcl]]
    join $::trace \n
}

foreach {tool striplevel} {
    diff-ruN    1
    git-diff    2
    fossil-diff 2
} {
    incr k
    test textutil-patch-2.$k "apply $tool" -setup {
	setup-scratch
    } -cleanup {
	cleanup-scratch
    } -body {
	# Apply patch `pkgIndex.tcl.<tool>` to `scratch/pkgIndex.tcl`.
	# The result should match `pkgIndex.tcl.patched`.
	textutil::patch apply \
	    [asset scratch] $striplevel \
	    [asset-get pkgIndex.tcl.$tool] \
	    record
	recorded
    } -result [join \
		   [list \
			[list apply [asset scratch/pkgIndex.tcl]] \
			=== \
			[tcltest::viewFile [asset pkgIndex.tcl.patched]]] \
		   \n]
}
unset k

catch { unset trace }
rename setup-scratch {}
rename cleanup-scratch {}

# -------------------------------------------------------------------------
## Patch application. Trigger the various failures. TODO

# -------------------------------------------------------------------------

testsuiteCleanup
return

Changes to modules/textutil/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13




if {![package vsatisfies [package provide Tcl] 8.2]} {
    # FRINK: nocheck
    return
}
package ifneeded textutil           0.9   [list source [file join $dir textutil.tcl]]
package ifneeded textutil::adjust   0.7.3 [list source [file join $dir adjust.tcl]]
package ifneeded textutil::split    0.8   [list source [file join $dir split.tcl]]
package ifneeded textutil::trim     0.7   [list source [file join $dir trim.tcl]]
package ifneeded textutil::tabify   0.7   [list source [file join $dir tabify.tcl]]
package ifneeded textutil::repeat   0.7   [list source [file join $dir repeat.tcl]]
package ifneeded textutil::string   0.8   [list source [file join $dir string.tcl]]
package ifneeded textutil::expander 1.3.1 [list source [file join $dir expander.tcl]]
package ifneeded textutil::wcswidth 35.0  [list source [file join $dir wcswidth.tcl]]
















|
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if {![package vsatisfies [package provide Tcl] 8.2]} {
    # FRINK: nocheck
    return
}
package ifneeded textutil           0.9   [list source [file join $dir textutil.tcl]]
package ifneeded textutil::adjust   0.7.3 [list source [file join $dir adjust.tcl]]
package ifneeded textutil::split    0.8   [list source [file join $dir split.tcl]]
package ifneeded textutil::trim     0.7   [list source [file join $dir trim.tcl]]
package ifneeded textutil::tabify   0.7   [list source [file join $dir tabify.tcl]]
package ifneeded textutil::repeat   0.7   [list source [file join $dir repeat.tcl]]
package ifneeded textutil::string   0.8   [list source [file join $dir string.tcl]]
package ifneeded textutil::expander 1.3.1 [list source [file join $dir expander.tcl]]
package ifneeded textutil::wcswidth 35.1  [list source [file join $dir wcswidth.tcl]]

if {![package vsatisfies [package provide Tcl] 8.5]} { return }

package ifneeded textutil::patch 0.1 [list source [file join $dir patch.tcl]]

Changes to modules/textutil/repeat.man.

38
39
40
41
42
43
44
45
46
[call [cmd ::textutil::repeat::blank] [arg num]]

A convenience command. Returns a string of [arg num] spaces.

[list_end]

[vset CATEGORY textutil]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

38
39
40
41
42
43
44
45
46
[call [cmd ::textutil::repeat::blank] [arg num]]

A convenience command. Returns a string of [arg num] spaces.

[list_end]

[vset CATEGORY textutil]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/textutil/tabify.man.

64
65
66
67
68
69
70
71
72

There is one asymmetry though: A tab can be replaced with a single
space, but not the other way around.

[list_end]

[vset CATEGORY textutil]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

64
65
66
67
68
69
70
71
72

There is one asymmetry though: A tab can be replaced with a single
space, but not the other way around.

[list_end]

[vset CATEGORY textutil]
[include ../common-text/feedback.inc]
[manpage_end]

Added modules/textutil/test-assets/pkgIndex.tcl.



























>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
if {![package vsatisfies [package provide Tcl] 8.2]} {
    # FRINK: nocheck
    return
}
package ifneeded textutil           0.9   [list source [file join $dir textutil.tcl]]
package ifneeded textutil::adjust   0.7.3 [list source [file join $dir adjust.tcl]]
package ifneeded textutil::split    0.8   [list source [file join $dir split.tcl]]
package ifneeded textutil::trim     0.7   [list source [file join $dir trim.tcl]]
package ifneeded textutil::tabify   0.7   [list source [file join $dir tabify.tcl]]
package ifneeded textutil::repeat   0.7   [list source [file join $dir repeat.tcl]]
package ifneeded textutil::string   0.8   [list source [file join $dir string.tcl]]
package ifneeded textutil::expander 1.3.1 [list source [file join $dir expander.tcl]]
package ifneeded textutil::wcswidth 35.0  [list source [file join $dir wcswidth.tcl]]

Added modules/textutil/test-assets/pkgIndex.tcl.diff-ruN.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
diff -ruN old/pkgIndex.tcl new/pkgIndex.tcl
--- old/pkgIndex.tcl	2019-06-26 11:42:01.194722156 -0700
+++ new/pkgIndex.tcl	2019-06-26 11:42:43.690791588 -0700
@@ -11,3 +11,7 @@
 package ifneeded textutil::string   0.8   [list source [file join $dir string.tcl]]
 package ifneeded textutil::expander 1.3.1 [list source [file join $dir expander.tcl]]
 package ifneeded textutil::wcswidth 35.0  [list source [file join $dir wcswidth.tcl]]
+
+if {![package vsatisfies [package provide Tcl] 8.5]} { return }
+
+package ifneeded textutil::patch 0.1 [list source [file join $dir patch.tcl]]

Added modules/textutil/test-assets/pkgIndex.tcl.fossil-diff.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ADDED    modules/textutil/patch.tcl
ADDED    modules/textutil/patch.test
Index: modules/textutil/pkgIndex.tcl
==================================================================
--- modules/textutil/pkgIndex.tcl
+++ modules/textutil/pkgIndex.tcl
@@ -9,5 +9,9 @@
 package ifneeded textutil::tabify   0.7   [list source [file join $dir tabify.tcl]]
 package ifneeded textutil::repeat   0.7   [list source [file join $dir repeat.tcl]]
 package ifneeded textutil::string   0.8   [list source [file join $dir string.tcl]]
 package ifneeded textutil::expander 1.3.1 [list source [file join $dir expander.tcl]]
 package ifneeded textutil::wcswidth 35.0  [list source [file join $dir wcswidth.tcl]]
+
+if {![package vsatisfies [package provide Tcl] 8.5]} { return }
+
+package ifneeded textutil::patch 0.1 [list source [file join $dir patch.tcl]]

Added modules/textutil/test-assets/pkgIndex.tcl.git-diff.

























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
diff --git a/old/pkgIndex.tcl b/new/pkgIndex.tcl
index 280f627..88ca6b7 100644
--- a/old/pkgIndex.tcl
+++ b/new/pkgIndex.tcl
@@ -11,3 +11,7 @@ package ifneeded textutil::repeat   0.7   [list source [file join $dir repeat.tc
 package ifneeded textutil::string   0.8   [list source [file join $dir string.tcl]]
 package ifneeded textutil::expander 1.3.1 [list source [file join $dir expander.tcl]]
 package ifneeded textutil::wcswidth 35.0  [list source [file join $dir wcswidth.tcl]]
+
+if {![package vsatisfies [package provide Tcl] 8.5]} { return }
+
+package ifneeded textutil::patch 0.1 [list source [file join $dir patch.tcl]]

Added modules/textutil/test-assets/pkgIndex.tcl.patched.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if {![package vsatisfies [package provide Tcl] 8.2]} {
    # FRINK: nocheck
    return
}
package ifneeded textutil           0.9   [list source [file join $dir textutil.tcl]]
package ifneeded textutil::adjust   0.7.3 [list source [file join $dir adjust.tcl]]
package ifneeded textutil::split    0.8   [list source [file join $dir split.tcl]]
package ifneeded textutil::trim     0.7   [list source [file join $dir trim.tcl]]
package ifneeded textutil::tabify   0.7   [list source [file join $dir tabify.tcl]]
package ifneeded textutil::repeat   0.7   [list source [file join $dir repeat.tcl]]
package ifneeded textutil::string   0.8   [list source [file join $dir string.tcl]]
package ifneeded textutil::expander 1.3.1 [list source [file join $dir expander.tcl]]
package ifneeded textutil::wcswidth 35.0  [list source [file join $dir wcswidth.tcl]]

if {![package vsatisfies [package provide Tcl] 8.5]} { return }

package ifneeded textutil::patch 0.1 [list source [file join $dir patch.tcl]]

Changes to modules/textutil/textutil.man.

380
381
382
383
384
385
386
387
388
If no strings were specified the result is the empty string.  If only
one string was specified, the string itself is returned, as it is its
own longest common prefix.

[list_end]

[vset CATEGORY textutil]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

380
381
382
383
384
385
386
387
388
If no strings were specified the result is the empty string.  If only
one string was specified, the string itself is returned, as it is its
own longest common prefix.

[list_end]

[vset CATEGORY textutil]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/textutil/textutil_split.man.

48
49
50
51
52
53
54
55
56
like [cmd split] does.

The regular expression [arg regexp] defaults to "[lb]\\t \\r\\n[rb]+".

[list_end]

[vset CATEGORY textutil]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

48
49
50
51
52
53
54
55
56
like [cmd split] does.

The regular expression [arg regexp] defaults to "[lb]\\t \\r\\n[rb]+".

[list_end]

[vset CATEGORY textutil]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/textutil/textutil_string.man.

65
66
67
68
69
70
71
72
73
If no strings were specified the result is the empty string.  If only
one string was specified, the string itself is returned, as it is its
own longest common prefix.

[list_end]

[vset CATEGORY textutil]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

65
66
67
68
69
70
71
72
73
If no strings were specified the result is the empty string.  If only
one string was specified, the string itself is returned, as it is its
own longest common prefix.

[list_end]

[vset CATEGORY textutil]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/textutil/trim.man.

67
68
69
70
71
72
73
74
75
Looks for empty lines (including lines consisting of only whitespace)
at the beginning of the [arg string] and removes it. The modified
string is returned as the result of the command.

[list_end]

[vset CATEGORY textutil]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

67
68
69
70
71
72
73
74
75
Looks for empty lines (including lines consisting of only whitespace)
at the beginning of the [arg string] and removes it. The modified
string is returned as the result of the command.

[list_end]

[vset CATEGORY textutil]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/textutil/wcswidth.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
###
# This file is automatically generated by the build/build.tcl file
# based on information in the following database:
# http://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt
#
# (This is the 35th edition, thus version 35 for our package)
#
# Author: Sean Woods <[email protected]>
###
package provide textutil::wcswidth 35.0
proc ::textutil::wcswidth_type char {
  if {$char == 161} { return A }
  if {$char == 164} { return A }
  if {$char == 167} { return A }
  if {$char == 168} { return A }
  if {$char == 170} { return A }
  if {$char == 173} { return A }









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
###
# This file is automatically generated by the build/build.tcl file
# based on information in the following database:
# http://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt
#
# (This is the 35th edition, thus version 35 for our package)
#
# Author: Sean Woods <[email protected]>
###
package provide textutil::wcswidth 35.1
proc ::textutil::wcswidth_type char {
  if {$char == 161} { return A }
  if {$char == 164} { return A }
  if {$char == 167} { return A }
  if {$char == 168} { return A }
  if {$char == 170} { return A }
  if {$char == 173} { return A }
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
  if {$char >= 196608 && $char <= 262141 } { return 2 }
  return 1
}

proc ::textutil::wcswidth {string} {
  set width 0
  set len [string length $string]
  for {set i 0} {$i < $len} {incr i} {
    scan [string index $string $i] %c char
    set n [::textutil::wcswidth_char $char]
    if {$n < 0} {
      return -1
    }
    incr width $n
  }
  return $width
}








|
|









755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
  if {$char >= 196608 && $char <= 262141 } { return 2 }
  return 1
}

proc ::textutil::wcswidth {string} {
  set width 0
  set len [string length $string]
  foreach c [split $string {}] {
    scan $c %c char
    set n [::textutil::wcswidth_char $char]
    if {$n < 0} {
      return -1
    }
    incr width $n
  }
  return $width
}

Changes to modules/tie/tie.man.

527
528
529
530
531
532
533
534
535
        set a($idx) $val        ds setv   idx val
        unset a($idx)           ds unsetv idx
        $a($idx)                ds getv   idx
        -----------             -----------
}]

[vset CATEGORY tie]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

527
528
529
530
531
532
533
534
535
        set a($idx) $val        ds setv   idx val
        unset a($idx)           ds unsetv idx
        $a($idx)                ds getv   idx
        -----------             -----------
}]

[vset CATEGORY tie]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/tie/tie_std.man.

27
28
29
30
31
32
33
34
35
[para]

They are automatically loaded and registered by [package tie] when it
itself is requested, and as such there is no need to request them on
their own, although it is possible to do so.

[vset CATEGORY tie]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

27
28
29
30
31
32
33
34
35
[para]

They are automatically loaded and registered by [package tie] when it
itself is requested, and as such there is no need to request them on
their own, although it is possible to do so.

[vset CATEGORY tie]
[include ../common-text/feedback.inc]
[manpage_end]

Added modules/tiff/test-assets/IMG_7898.tiff.

cannot compute difference between binary files

Added modules/tiff/test-assets/IMG_7917.tiff.

cannot compute difference between binary files

Added modules/tiff/test-assets/IMG_7950.tiff.

cannot compute difference between binary files

Deleted modules/tiff/testimages/IMG_7898.tiff.

cannot compute difference between binary files

Deleted modules/tiff/testimages/IMG_7917.tiff.

cannot compute difference between binary files

Deleted modules/tiff/testimages/IMG_7950.tiff.

cannot compute difference between binary files

Changes to modules/tiff/tiff.man.

166
167
168
169
170
171
172
173
174
[list_begin enumerated]
[enum] Cannot write exif ifd
[enum] Reading limited to uncompressed 8 bit rgb and 8 bit palletized images
[enum] Writing limited to uncompressed 8 bit rgb
[list_end]

[vset CATEGORY tiff]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

166
167
168
169
170
171
172
173
174
[list_begin enumerated]
[enum] Cannot write exif ifd
[enum] Reading limited to uncompressed 8 bit rgb and 8 bit palletized images
[enum] Writing limited to uncompressed 8 bit rgb
[list_end]

[vset CATEGORY tiff]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/tiff/tiff.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# -*- tcl -*-
# tiff.test:  Tests for the TIFF utilities.
#
# Copyright (c) 2008 by Andreas Kupries <[email protected]>
# All rights reserved.
#
# TIFF: @(#) $Id: tiff.test,v 1.1 2008/03/24 03:48:59 andreas_kupries Exp $

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]






<
<







1
2
3
4
5


6
7
8
9
10
11
12
# -*- tcl -*-
# tiff.test:  Tests for the TIFF utilities.
#
# Copyright (c) 2008 by Andreas Kupries <[email protected]>
# All rights reserved.



# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    catch {::tiff::isTIFF foo bar} msg
    set msg
} [tcltest::tooManyArgs {::tiff::isTIFF} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.tiff] {
    test tiff-2.$n "isTIFF, ok, [file tail $f]" {
	::tiff::isTIFF $f
    } 1
    incr n
}

test tiff-2.$n "isTIFF, fail, [file tail [info script]]" {







|







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
    catch {::tiff::isTIFF foo bar} msg
    set msg
} [tcltest::tooManyArgs {::tiff::isTIFF} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.tiff] {
    test tiff-2.$n "isTIFF, ok, [file tail $f]" {
	::tiff::isTIFF $f
    } 1
    incr n
}

test tiff-2.$n "isTIFF, fail, [file tail [info script]]" {
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
    catch {::tiff::byteOrder foo bar} msg
    set msg
} [tcltest::tooManyArgs {::tiff::byteOrder} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.tiff] {
    test tiff-4.$n "byteOrder regular, [file tail $f]" {
	::tiff::byteOrder $f
    } little
    incr n
}

test tiff-5.0 "byteOrder, fail, [file tail [info script]]" {







|







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
    catch {::tiff::byteOrder foo bar} msg
    set msg
} [tcltest::tooManyArgs {::tiff::byteOrder} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.tiff] {
    test tiff-4.$n "byteOrder regular, [file tail $f]" {
	::tiff::byteOrder $f
    } little
    incr n
}

test tiff-5.0 "byteOrder, fail, [file tail [info script]]" {
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
    catch {::tiff::numImages foo bar} msg
    set msg
} [tcltest::tooManyArgs {::tiff::numImages} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.tiff] {
    test tiff-7.$n "numImages regular, [file tail $f]" {
	::tiff::numImages $f
    } 1
    incr n
}

test tiff-8.0 "numImages, fail, [file tail [info script]]" {







|







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
    catch {::tiff::numImages foo bar} msg
    set msg
} [tcltest::tooManyArgs {::tiff::numImages} {file}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.tiff] {
    test tiff-7.$n "numImages regular, [file tail $f]" {
	::tiff::numImages $f
    } 1
    incr n
}

test tiff-8.0 "numImages, fail, [file tail [info script]]" {
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
    catch {::tiff::dimensions foo bar glop} msg
    set msg
} [tcltest::tooManyArgs {::tiff::dimensions} {file ?image?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.tiff] {
    test tiff-10.$n "dimensions regular, [file tail $f]" {
	::tiff::dimensions $f
    } {320 240}
    incr n
}

test tiff-11.0 "dimensions, fail, [file tail [info script]]" {







|







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
    catch {::tiff::dimensions foo bar glop} msg
    set msg
} [tcltest::tooManyArgs {::tiff::dimensions} {file ?image?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.tiff] {
    test tiff-10.$n "dimensions regular, [file tail $f]" {
	::tiff::dimensions $f
    } {320 240}
    incr n
}

test tiff-11.0 "dimensions, fail, [file tail [info script]]" {
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
    catch {::tiff::imageInfo foo bar glop} msg
    set msg
} [tcltest::tooManyArgs {::tiff::imageInfo} {file ?image?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.tiff] {
    test tiff-13.$n "imageInfo regular, [file tail $f]" {
	dictsort [::tiff::imageInfo $f]
    } {Artist {} BitsPerSample {8 8 8} Compression 7 DateTime {} HostComputer {} ImageDescription {} ImageLength 240 ImageWidth 320 Orientation 1 PhotometricInterpretation 2 ResolutionUnit 2 XResolution 180 YResolution 180}
    incr n
}

test tiff-14.0 "imageInfo, fail, [file tail [info script]]" {







|







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
    catch {::tiff::imageInfo foo bar glop} msg
    set msg
} [tcltest::tooManyArgs {::tiff::imageInfo} {file ?image?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.tiff] {
    test tiff-13.$n "imageInfo regular, [file tail $f]" {
	dictsort [::tiff::imageInfo $f]
    } {Artist {} BitsPerSample {8 8 8} Compression 7 DateTime {} HostComputer {} ImageDescription {} ImageLength 240 ImageWidth 320 Orientation 1 PhotometricInterpretation 2 ResolutionUnit 2 XResolution 180 YResolution 180}
    incr n
}

test tiff-14.0 "imageInfo, fail, [file tail [info script]]" {
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
    catch {::tiff::entries foo bar glop} msg
    set msg
} [tcltest::tooManyArgs {::tiff::entries} {file ?image?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.tiff] {
    test tiff-16.$n "entries regular, [file tail $f]" {
	lsort [::tiff::entries $f]
    } {BitsPerSample Compression DocumentName FillOrder ImageLength ImageWidth JPEGTables Orientation PhotometricInterpretation PlanarConfiguration ResolutionUnit RowsPerStrip SamplesPerPixel Software StripByteCounts StripOffsets XResolution YCbCrSubSampling YResolution}
    incr n
}

test tiff-17.0 "entries, fail, [file tail [info script]]" {







|







172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
    catch {::tiff::entries foo bar glop} msg
    set msg
} [tcltest::tooManyArgs {::tiff::entries} {file ?image?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.tiff] {
    test tiff-16.$n "entries regular, [file tail $f]" {
	lsort [::tiff::entries $f]
    } {BitsPerSample Compression DocumentName FillOrder ImageLength ImageWidth JPEGTables Orientation PhotometricInterpretation PlanarConfiguration ResolutionUnit RowsPerStrip SamplesPerPixel Software StripByteCounts StripOffsets XResolution YCbCrSubSampling YResolution}
    incr n
}

test tiff-17.0 "entries, fail, [file tail [info script]]" {
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
    catch {::tiff::getEntry foo bar glop snarf} msg
    set msg
} [tcltest::tooManyArgs {::tiff::getEntry} {file entry ?image?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.tiff] {
    test tiff-19.$n "getEntry regular, [file tail $f]" {
	::tiff::getEntry $f {Artist Compression}
    } {Artist {} Compression 7}
    incr n
}

test tiff-20.0 "getEntry, fail, [file tail [info script]]" {







|







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
    catch {::tiff::getEntry foo bar glop snarf} msg
    set msg
} [tcltest::tooManyArgs {::tiff::getEntry} {file entry ?image?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.tiff] {
    test tiff-19.$n "getEntry regular, [file tail $f]" {
	::tiff::getEntry $f {Artist Compression}
    } {Artist {} Compression 7}
    incr n
}

test tiff-20.0 "getEntry, fail, [file tail [info script]]" {
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
    catch {::tiff::addEntry foo bar glop snarf} msg
    set msg
} [tcltest::tooManyArgs {::tiff::addEntry} {file entry ?image?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.tiff] {
    test tiff-22.$n "addEntry, new tag, [file tail $f]" {
	file copy -force $f [set fx [makeFile {} ttmp]]
	set res {}
	lappend res [tiff::getEntry $fx Artist]
	::tiff::addEntry $fx {{Artist 2 Andreas}}
	lappend res [tiff::getEntry $fx Artist]
	removeFile ttmp
	set res
    } {{Artist {}} {Artist Andreas}}
    incr n
}

set n 0
foreach f [TestFilesGlob testimages/*.tiff] {
    test tiff-23.$n "addEntry, overwrite tag, [file tail $f]" knownBug {
	file copy -force $f [set fx [makeFile {} ttmp]]
	set res {}
	::tiff::addEntry $fx {{Artist 2 Andreas}}
	lappend res [tiff::getEntry $fx Artist]
	::tiff::addEntry $fx {{Artist 2 AK}}
	lappend res [tiff::getEntry $fx Artist]







|













|







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
    catch {::tiff::addEntry foo bar glop snarf} msg
    set msg
} [tcltest::tooManyArgs {::tiff::addEntry} {file entry ?image?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.tiff] {
    test tiff-22.$n "addEntry, new tag, [file tail $f]" {
	file copy -force $f [set fx [makeFile {} ttmp]]
	set res {}
	lappend res [tiff::getEntry $fx Artist]
	::tiff::addEntry $fx {{Artist 2 Andreas}}
	lappend res [tiff::getEntry $fx Artist]
	removeFile ttmp
	set res
    } {{Artist {}} {Artist Andreas}}
    incr n
}

set n 0
foreach f [TestFilesGlob test-assets/*.tiff] {
    test tiff-23.$n "addEntry, overwrite tag, [file tail $f]" knownBug {
	file copy -force $f [set fx [makeFile {} ttmp]]
	set res {}
	::tiff::addEntry $fx {{Artist 2 Andreas}}
	lappend res [tiff::getEntry $fx Artist]
	::tiff::addEntry $fx {{Artist 2 AK}}
	lappend res [tiff::getEntry $fx Artist]
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
    catch {::tiff::deleteEntry foo bar glop snarf} msg
    set msg
} [tcltest::tooManyArgs {::tiff::deleteEntry} {file entry ?image?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.tiff] {
    test tiff-26.$n "deleteEntry, [file tail $f]" {
	file copy -force $f [set fx [makeFile {} ttmp]]
	set res {}
	lappend res [tiff::getEntry $fx Artist]
	::tiff::addEntry $fx {{Artist 2 Andreas}}
	lappend res [tiff::getEntry $fx Artist]
	::tiff::deleteEntry $fx Artist







|







289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
    catch {::tiff::deleteEntry foo bar glop snarf} msg
    set msg
} [tcltest::tooManyArgs {::tiff::deleteEntry} {file entry ?image?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.tiff] {
    test tiff-26.$n "deleteEntry, [file tail $f]" {
	file copy -force $f [set fx [makeFile {} ttmp]]
	set res {}
	lappend res [tiff::getEntry $fx Artist]
	::tiff::addEntry $fx {{Artist 2 Andreas}}
	lappend res [tiff::getEntry $fx Artist]
	::tiff::deleteEntry $fx Artist
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
    catch {::tiff::getImage foo bar glop snarf} msg
    set msg
} [tcltest::tooManyArgs {::tiff::getImage} {file ?image?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.tiff] {
    test tiff-29.$n "getImage, [file tail $f]" {tk unkownFormat} {
	set image [tiff::getImage $f]
	lappend res [image width  $image]
	lappend res [image height $image]
	image delete $image
	set res
    } {320 240}







|







323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
    catch {::tiff::getImage foo bar glop snarf} msg
    set msg
} [tcltest::tooManyArgs {::tiff::getImage} {file ?image?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.tiff] {
    test tiff-29.$n "getImage, [file tail $f]" {tk unkownFormat} {
	set image [tiff::getImage $f]
	lappend res [image width  $image]
	lappend res [image height $image]
	image delete $image
	set res
    } {320 240}
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
    catch {::tiff::writeImage foo bar glop snarf} msg
    set msg
} [tcltest::tooManyArgs {::tiff::writeImage} {image file ?entry?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob testimages/*.tiff] {
    test tiff-32.$n "writeImage, [file tail $f]" {tk unkownFormat} {
	set image [tiff::getImage $f]
	set fx [makeFile {} ttmp]
	tiff::writeImage $image $fx
	image delete $image
	foreach k [lsort [::tiff::entries $fx]] {
	    lappend res [tiff::getEntry $fx $k]







|







358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
    catch {::tiff::writeImage foo bar glop snarf} msg
    set msg
} [tcltest::tooManyArgs {::tiff::writeImage} {image file ?entry?}]

# -------------------------------------------------------------------------

set n 0
foreach f [TestFilesGlob test-assets/*.tiff] {
    test tiff-32.$n "writeImage, [file tail $f]" {tk unkownFormat} {
	set image [tiff::getImage $f]
	set fx [makeFile {} ttmp]
	tiff::writeImage $image $fx
	image delete $image
	foreach k [lsort [::tiff::entries $fx]] {
	    lappend res [tiff::getEntry $fx $k]
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
} [tcltest::tooManyArgs {::tiff::debug} {file}]

# -------------------------------------------------------------------------
# We do not try to actually run 'debug', because it prints its results
# to stdout. This may change when we can capture stdout as test result

set n 0
foreach f [TestFilesGlob testimages/*.tiff] {
    test tiff-41.$n "debug ok, [file tail $f]" donotrun {
	::tiff::debug $f
    } {}
    incr n
}

test tiff-42.0 "debug, fail, [file tail [info script]]" {
    list [catch {::tiff::debug [info script]} msg] $msg
} {1 {not a tiff file}}

# -------------------------------------------------------------------------
testsuiteCleanup







|












535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
} [tcltest::tooManyArgs {::tiff::debug} {file}]

# -------------------------------------------------------------------------
# We do not try to actually run 'debug', because it prints its results
# to stdout. This may change when we can capture stdout as test result

set n 0
foreach f [TestFilesGlob test-assets/*.tiff] {
    test tiff-41.$n "debug ok, [file tail $f]" donotrun {
	::tiff::debug $f
    } {}
    incr n
}

test tiff-42.0 "debug, fail, [file tail [info script]]" {
    list [catch {::tiff::debug [info script]} msg] $msg
} {1 {not a tiff file}}

# -------------------------------------------------------------------------
testsuiteCleanup

Changes to modules/tool/meta.man.

157
158
159
160
161
162
163
164
165

[list_end]

[section AUTHORS]
Donal Fellows, Andreas Kupries

[vset CATEGORY oo::util]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

157
158
159
160
161
162
163
164
165

[list_end]

[section AUTHORS]
Donal Fellows, Andreas Kupries

[vset CATEGORY oo::util]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/tool/tool.man.

226
227
228
229
230
231
232
233
234
235
236

[list_end]

[section AUTHORS]
Sean Woods

[vset CATEGORY tcloo]
[include ../doctools2base/include/feedback.inc]
[manpage_end]









|



226
227
228
229
230
231
232
233
234
235
236

[list_end]

[section AUTHORS]
Sean Woods

[vset CATEGORY tcloo]
[include ../common-text/feedback.inc]
[manpage_end]


Changes to modules/tool/tool_dict_ensemble.man.

26
27
28
29
30
31
32
33
34

[list_end]

[section AUTHORS]
Sean Woods

[vset CATEGORY tool]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

26
27
28
29
30
31
32
33
34

[list_end]

[section AUTHORS]
Sean Woods

[vset CATEGORY tool]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/transfer/connect.man.

160
161
162
163
164
165
166
167
168
[include include/connect_options.inc]
[list_end]

[vset OBJCREATE {transfer::connect C}]
[include include/secure.inc]

[vset CATEGORY transfer]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

160
161
162
163
164
165
166
167
168
[include include/connect_options.inc]
[list_end]

[vset OBJCREATE {transfer::connect C}]
[include include/secure.inc]

[vset CATEGORY transfer]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/transfer/copyops.man.

155
156
157
158
159
160
161
162
163
these options are required, and they default to the settings of the
output channel if not specified.

[list_end][comment options]
[list_end][comment definitions/api]

[vset CATEGORY transfer]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

155
156
157
158
159
160
161
162
163
these options are required, and they default to the settings of the
output channel if not specified.

[list_end][comment options]
[list_end][comment definitions/api]

[vset CATEGORY transfer]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/transfer/ddest.man.

114
115
116
117
118
119
120
121
122
configure the object.

[list_begin options]
[include include/ddest_options.inc]
[list_end]

[vset CATEGORY transfer]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

114
115
116
117
118
119
120
121
122
configure the object.

[list_begin options]
[include include/ddest_options.inc]
[list_end]

[vset CATEGORY transfer]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/transfer/dsource.man.

146
147
148
149
150
151
152
153
154
actually configure the object.

[list_begin options]
[include include/dsource_options.inc]
[list_end]

[vset CATEGORY transfer]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

146
147
148
149
150
151
152
153
154
actually configure the object.

[list_begin options]
[include include/dsource_options.inc]
[list_end]

[vset CATEGORY transfer]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/transfer/receiver.man.

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
[include include/ddest_options.inc]
[list_end]

[vset OBJCREATE {transfer::receiver R}]
[include include/secure.inc]

[vset CATEGORY transfer]
[include ../doctools2base/include/feedback.inc]
[comment {

This option specifies the command to invoke when the transmission of
the information in the data source has been completed. The arguments
given to this command are the same as given to the completion callback
of method [cmd receive], see package
[package transfer::data::destination].







|







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
[include include/ddest_options.inc]
[list_end]

[vset OBJCREATE {transfer::receiver R}]
[include include/secure.inc]

[vset CATEGORY transfer]
[include ../common-text/feedback.inc]
[comment {

This option specifies the command to invoke when the transmission of
the information in the data source has been completed. The arguments
given to this command are the same as given to the completion callback
of method [cmd receive], see package
[package transfer::data::destination].

Changes to modules/transfer/tqueue.man.

166
167
168
169
170
171
172
173
174

It should be noted that in this application the system also needs an
additional data structure which keeps track of outstanding results as
they may come back in a different order than the requests from the
client, and releases them to the actual queue in the proper order.

[vset CATEGORY transfer]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

166
167
168
169
170
171
172
173
174

It should be noted that in this application the system also needs an
additional data structure which keeps track of outstanding results as
they may come back in a different order than the requests from the
client, and releases them to the actual queue in the proper order.

[vset CATEGORY transfer]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/transfer/transmitter.man.

176
177
178
179
180
181
182
183
184
[include include/dsource_options.inc]
[list_end]

[vset OBJCREATE {transfer::transmitter T}]
[include include/secure.inc]

[vset CATEGORY transfer]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

176
177
178
179
180
181
182
183
184
[include include/dsource_options.inc]
[list_end]

[vset OBJCREATE {transfer::transmitter T}]
[include include/secure.inc]

[vset CATEGORY transfer]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/treeql/treeql.man.

811
812
813
814
815
816
817
818
819

[uri http://wiki.tcl.tk/treeql TreeQL] on the Tcler's Wiki. Discuss
this package there.

[list_end]

[vset CATEGORY treeql]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

811
812
813
814
815
816
817
818
819

[uri http://wiki.tcl.tk/treeql TreeQL] on the Tcler's Wiki. Discuss
this package there.

[list_end]

[vset CATEGORY treeql]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/try/tcllib_throw.man.

32
33
34
35
36
37
38
39
40
[section EXAMPLES]

[para][example_begin]
[cmd throw] {MYERROR CODE} "My error message"
[example_end]

[vset CATEGORY try]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

32
33
34
35
36
37
38
39
40
[section EXAMPLES]

[para][example_begin]
[cmd throw] {MYERROR CODE} "My error message"
[example_end]

[vset CATEGORY try]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/try/tcllib_try.man.

115
116
117
118
119
120
121
122
123
    puts "failed to open /some/file/name: it's a directory"
} [method trap] {POSIX ENOENT} {} {
    puts "failed to open /some/file/name: it doesn't exist"
}
[example_end]

[vset CATEGORY try]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

115
116
117
118
119
120
121
122
123
    puts "failed to open /some/file/name: it's a directory"
} [method trap] {POSIX ENOENT} {} {
    puts "failed to open /some/file/name: it doesn't exist"
}
[example_end]

[vset CATEGORY try]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/udpcluster/udpcluster.man.

51
52
53
54
55
56
57
58
59
Results will
Historical Notes:
[para]
This tool was originally known as nns::cluster, but as development progressed, it was
clear that it wasn't interacting with any of the other facilities in NNS.

[vset CATEGORY nameserv]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

51
52
53
54
55
56
57
58
59
Results will
Historical Notes:
[para]
This tool was originally known as nns::cluster, but as development progressed, it was
clear that it wasn't interacting with any of the other facilities in NNS.

[vset CATEGORY nameserv]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/uev/uevent.man.

188
189
190
191
192
193
194
195
196

[para] The result of the command is the empty string.

[comment ============================================================]
[list_end]

[vset CATEGORY uevent]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

188
189
190
191
192
193
194
195
196

[para] The result of the command is the empty string.

[comment ============================================================]
[list_end]

[vset CATEGORY uevent]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/uev/uevent_onidle.man.

56
57
58
59
60
61
62
63
64
[section Examples]

Examples of this type of deferal are buried in the (C-level)
implementations all the Tk widgets, defering geometry calculations and
window redraw activity in this manner.

[vset CATEGORY uevent]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

56
57
58
59
60
61
62
63
64
[section Examples]

Examples of this type of deferal are buried in the (C-level)
implementations all the Tk widgets, defering geometry calculations and
window redraw activity in this manner.

[vset CATEGORY uevent]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/units/units.man.

384
385
386
387
388
389
390
391
392
GNU Units program at [uri http://www.gnu.org/software/units/]

[section "AUTHORS"]

Robert W. Techentin

[vset CATEGORY units]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

384
385
386
387
388
389
390
391
392
GNU Units program at [uri http://www.gnu.org/software/units/]

[section "AUTHORS"]

Robert W. Techentin

[vset CATEGORY units]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/uri/uri.man.

385
386
387
388
389
390
391
392
393
[para]

Original code (regular expressions) by Andreas Kupries.
Modularisation by Steve Ball, also the split/join/resolve
functionality. RFC 3986 conformance by Keith Nash.

[vset CATEGORY uri]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

385
386
387
388
389
390
391
392
393
[para]

Original code (regular expressions) by Andreas Kupries.
Modularisation by Steve Ball, also the split/join/resolve
functionality. RFC 3986 conformance by Keith Nash.

[vset CATEGORY uri]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/uri/urn-scheme.man.

33
34
35
36
37
38
39
40
41
This commands performs the reverse of [cmd ::uri::urn::quote]. It
takes an [term urn] url, removes the quoting from all disallowed
characters, and returns the modified urls as its result.

[list_end]

[vset CATEGORY uri]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

33
34
35
36
37
38
39
40
41
This commands performs the reverse of [cmd ::uri::urn::quote]. It
takes an [term urn] url, removes the quoting from all disallowed
characters, and returns the modified urls as its result.

[list_end]

[vset CATEGORY uri]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/uuid/uuid.man.

47
48
49
50
51
52
53
54
55
[enum]
    Paul J. Leach, "UUIDs and GUIDs", February 1998.
    ([uri http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt])

[list_end]

[vset CATEGORY uuid]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

47
48
49
50
51
52
53
54
55
[enum]
    Paul J. Leach, "UUIDs and GUIDs", February 1998.
    ([uri http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt])

[list_end]

[vset CATEGORY uuid]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/valtype/include/vtype.inc.

94
95
96
97
98
99
100
101
102
th input may be an outright fake too.


[include [vset CODES].inc]
[list_end]

[vset CATEGORY valtype]
[include ../../doctools2base/include/feedback.inc]
[manpage_end]







|

94
95
96
97
98
99
100
101
102
th input may be an outright fake too.


[include [vset CODES].inc]
[list_end]

[vset CATEGORY valtype]
[include ../../common-text/feedback.inc]
[manpage_end]

Changes to modules/valtype/valtype_common.man.

102
103
104
105
106
107
108
109
110
data-entry error, with digits transposed, forgotten, etc. Of course,
th input may be an outright fake too.

[include include/c_lenpfx.inc]
[list_end]

[vset CATEGORY valtype]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

102
103
104
105
106
107
108
109
110
data-entry error, with digits transposed, forgotten, etc. Of course,
th input may be an outright fake too.

[include include/c_lenpfx.inc]
[list_end]

[vset CATEGORY valtype]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_base/ChangeLog.





1
2
3
4
5
6
7




2013-12-17  Andreas Kupries  <[email protected]>

	* randseed.man: Fixed package name.

2013-11-22  Andreas Kupries  <[email protected]>

	* memchan.tcl (Events): Ticket [864a0c83e3]. Do not suppress
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
2019-03-12  Aldo Buratti

    * cat.tcl - BUGFIX in event-handling . Version bumped to 1.0.3
    * 
2013-12-17  Andreas Kupries  <[email protected]>

	* randseed.man: Fixed package name.

2013-11-22  Andreas Kupries  <[email protected]>

	* memchan.tcl (Events): Ticket [864a0c83e3]. Do not suppress

Changes to modules/virtchannel_base/cat.man.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[comment {-*- tcl -*- doctools manpage}]

[manpage_begin tcl::chan::cat n 1]
[keywords {concatenation channel}]
[keywords {reflected channel}]
[keywords {tip 219}]
[keywords {virtual channel}]
[copyright {2011 Andreas Kupries <[email protected]>}]
[moddesc   {Reflected/virtual channel support}]
[category  Channels]
[titledesc {Concatenation channel}]
[require Tcl 8.5]
[require TclOO]
[require tcl::chan::core [opt 1]]
[require tcl::chan::cat [opt 1]]
[description]
[para]

The [package tcl::chan::cat] package provides a command creating
concatenation channels. These are non-seekable channels owning a list
of subordinate channels whose contents they return in order, until all
are exhausted. In this manner the channel is the concatentation of the

>
|











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[comment {-*- tcl -*- doctools manpage}]
[vset Version 1.0.3]
[manpage_begin tcl::chan::cat n [vset Version]]
[keywords {concatenation channel}]
[keywords {reflected channel}]
[keywords {tip 219}]
[keywords {virtual channel}]
[copyright {2011 Andreas Kupries <[email protected]>}]
[moddesc   {Reflected/virtual channel support}]
[category  Channels]
[titledesc {Concatenation channel}]
[require Tcl 8.5]
[require TclOO]
[require tcl::chan::core [opt 1]]
[require tcl::chan::cat [opt [vset Version]]]
[description]
[para]

The [package tcl::chan::cat] package provides a command creating
concatenation channels. These are non-seekable channels owning a list
of subordinate channels whose contents they return in order, until all
are exhausted. In this manner the channel is the concatentation of the
39
40
41
42
43
44
45
46
47

This command creates the concatenation channel using all the provided
channels, and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

40
41
42
43
44
45
46
47
48

This command creates the concatenation channel using all the provided
channels, and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_base/cat.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# -*- tcl -*-
# # ## ### ##### ######## #############
# (C) 2011 Andreas Kupries

# Facade concatenating the contents of the channels it was constructed
# with. Owns the sub-ordinate channels and closes them on exhaustion and/or
# when closed itself.

# @@ Meta Begin
# Package tcl::chan::cat 1.0.1
# Meta as::author {Andreas Kupries}
# Meta as::copyright 2011
# Meta as::license BSD
# Meta description Facade concatenating the contents of the channels it
# Meta description was constructed with. Owns the sub-ordinate channels
# Meta description and closes them on exhaustion and/or when closed itself.
# Meta platform tcl


|






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# -*- tcl -*-
# # ## ### ##### ######## #############
# (C) 2011,2019 Andreas Kupries

# Facade concatenating the contents of the channels it was constructed
# with. Owns the sub-ordinate channels and closes them on exhaustion and/or
# when closed itself.

# @@ Meta Begin
# Package tcl::chan::cat 1.0.3
# Meta as::author {Andreas Kupries}
# Meta as::copyright 2011
# Meta as::license BSD
# Meta description Facade concatenating the contents of the channels it
# Meta description was constructed with. Owns the sub-ordinate channels
# Meta description and closes them on exhaustion and/or when closed itself.
# Meta platform tcl
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

    # We are not using the standard event handling class, because here
    # it will not be timer-driven. We propagate anything related to
    # events to catin and catout instead and let them handle things.

    constructor {args} {
	set channels $args
	# Disable encoding and translation processing in the wrapped channels.
	# This will happen in our generic layer instead.
	foreach c $channels {
	    fconfigure $c -translation binary
	    fconfigure $c -translation binary
	}
	set delay 10
	set watching 0
	return
    }








|


<







39
40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55

    # We are not using the standard event handling class, because here
    # it will not be timer-driven. We propagate anything related to
    # events to catin and catout instead and let them handle things.

    constructor {args} {
	set channels $args
	# Disable translation (and hence encoding) in the wrapped channels.
	# This will happen in our generic layer instead.
	foreach c $channels {

	    fconfigure $c -translation binary
	}
	set delay 10
	set watching 0
	return
    }

66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
    method watch {c requestmask} {
	if {"read" in $requestmask} {
	    # Activate event handling.  Either drive an eof home via
	    # timers, or activate things in the foremost sub-ordinate.

	    set watching 1
	    if {![llength $channels]} {
		set timer [after $delay \
			       [namespace code [list my Post $c]]]
	    } else {
		set c [lindex $channels 0]
		fileevent readable $c [list chan postevent $c read]
	    }
	} else {
	    # Stop events. Kill timer, or disable in the foremost
	    # sub-ordinate.

	    set watching 0
	    if {![llength $channels]} {
		catch { after cancel $timer }
	    } else {
		fileevent readable [lindex $channels 0] {}
	    }
	}
	return
    }

    method read {c n} {
	if {![llength $channels]} {
	    # Actually should be EOF signal.
	    return {}
	}

	set buf {}
	while {([string length $buf] < $n) &&
	       [llength $channels]} {

	    set in     [lindex $channels 0]
	    set toread [expr {$n - [string length $buf]}]
	    append buf [::read $in $toread]

	    if {[eof $in]} {
		close $in
		set channels [lrange $channels 1 end]

		# The close above also killed any fileevent handling
		# we might have attached to this channel. We may have
		# to update the settings (i.e. move to next channel,
		# or to timer-based, to drive the eof home).


		if {$watching} {
		    my watch $c read
		}
	    }
	}

	if {$buf eq {}} {
	    return -code error EAGAIN
	}

	return $buf
    }

    method Post {c} {
	set timer [after $delay \
		       [namespace code [list my Post $c]]]
	chan postevent $c read
	return
    }
}

# # ## ### ##### ######## #############
package provide tcl::chan::cat 1.0.2
return







|
<

|
<


|
|





|







|















|
|
|
|
>







|
|
<
|




|
<






|

65
66
67
68
69
70
71
72

73
74

75
76
77
78
79
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
    method watch {c requestmask} {
	if {"read" in $requestmask} {
	    # Activate event handling.  Either drive an eof home via
	    # timers, or activate things in the foremost sub-ordinate.

	    set watching 1
	    if {![llength $channels]} {
		set timer [after $delay [namespace code [list my Post $c]]]

	    } else {
		chan event [lindex $channels 0] readable [list chan postevent $c read]

	    }
	} else {
	    # Stop events. Either kill timer, or disable in the
	    # foremost sub-ordinate.

	    set watching 0
	    if {![llength $channels]} {
		catch { after cancel $timer }
	    } else {
		chan event [lindex $channels 0] readable {}
	    }
	}
	return
    }

    method read {c n} {
	if {![llength $channels]} {
	    # This signals EOF higher up.
	    return {}
	}

	set buf {}
	while {([string length $buf] < $n) &&
	       [llength $channels]} {

	    set in     [lindex $channels 0]
	    set toread [expr {$n - [string length $buf]}]
	    append buf [::read $in $toread]

	    if {[eof $in]} {
		close $in
		set channels [lrange $channels 1 end]

		# The close of the exhausted subordinate killed any
		# fileevent handling we may have had attached to this
		# channel. Update the settings (i.e. move to the next
		# subordinate, or to timer-based, to drive the eof
		# home).

		if {$watching} {
		    my watch $c read
		}
	    }
	}

	# When `buf` is empty, all channels have been exhausted and
	# closed, therefore returning this empty string will cause an

	# EOF higher up.
	return $buf
    }

    method Post {c} {
	set timer [after $delay [namespace code [list my Post $c]]]

	chan postevent $c read
	return
    }
}

# # ## ### ##### ######## #############
package provide tcl::chan::cat 1.0.3
return

Added modules/virtchannel_base/cat.test.











































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#- - -- --- ----- -------- ------------- ---------------------
# cat.test -*- tcl -*-
# (C) 2019 Andreas Kupries. BSD licensed.
#- - -- --- ----- -------- ------------- ---------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2.0
testsNeed        TclOO 1

support {
    use virtchannel_core/core.tcl   tcl::chan::core
    use virtchannel_core/events.tcl tcl::chan::events
    useLocal string.tcl tcl::chan::string
}
testing {
    useLocal cat.tcl tcl::chan::cat
}

#- - -- --- ----- -------- ------------- ---------------------
## No wrong#args, allowed to zero and up

#- - -- --- ----- -------- ------------- ---------------------

test tcl-chan-cat-2.0 {tell, nothing} -setup {
    set c [tcl::chan::cat]
} -body {
    tell $c
} -cleanup {
    close $c
    unset c
} -result -1

test tcl-chan-cat-2.1 {ticket 1975182bdd - file events} -setup {
    # setup a cat'enated channel
    set fa [tcl::chan::string "ABCDE..XYZ"]
    set fb [tcl::chan::string "0123456789"]
    set ch [tcl::chan::cat $fa $fb]
} -body {
    set r {}
    chan event $ch readable {
        if { [eof $ch] } {
            set done .
        } else {
            lappend r [read $ch 4]
        }
    }    
    vwait done
    set r
} -cleanup {
    close $ch
    unset ch fa fb r
} -result {ABCD E..X YZ01 2345 6789 {}}

#- - -- --- ----- -------- ------------- ---------------------
# Explicit cleanup of loaded support classes.

rename tcl::chan::events {}
rename tcl::chan::core   {}
testsuiteCleanup
return

# Local Variables:
#  mode: tcl
#  indent-tabs-mode: nil
# End:

Changes to modules/virtchannel_base/facade.man.

65
66
67
68
69
70
71
72
73

This command creates the facade channel around the provided
channel [arg chan], and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

65
66
67
68
69
70
71
72
73

This command creates the facade channel around the provided
channel [arg chan], and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_base/fifo2.tcl.

70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
    }

    method closeda {c} {
	set a {}
	if {$b ne {}} {
	    close $b
	    set b {}
	}
	my destroy

	return
    }

    method closedb {c} {
	set b {}
	if {$a ne {}} {
	    close $a
	    set a {}
	}
	my destroy

	return
    }

    method froma {c bytes} {
	$hb put $bytes
	return
    }







|
|
>








|
|
>







70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
    }

    method closeda {c} {
	set a {}
	if {$b ne {}} {
	    close $b
	    set b {}
	} else {
	    my destroy
	}
	return
    }

    method closedb {c} {
	set b {}
	if {$a ne {}} {
	    close $a
	    set a {}
	} else {
	    my destroy
	}
	return
    }

    method froma {c bytes} {
	$hb put $bytes
	return
    }

Added modules/virtchannel_base/fifo2.test.





































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# -------------------------------------------------------------------------
# fifo2.test -*- tcl -*-
# (C) 2019 Andreas Kupries. BSD licensed.
# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.5
testsNeedTcltest 2.0
testsNeed        TclOO 1

support {
    use virtchannel_core/core.tcl   tcl::chan::core
    use virtchannel_core/events.tcl tcl::chan::events
}
testing {
    useLocal halfpipe.tcl tcl::chan::halfpipe
    useLocal fifo2.tcl    tcl::chan::fifo2
}

# -------------------------------------------------------------------------

test tcl-chan-fifo2-1.1 {constructor wrong\#args} -body {
    tcl::chan::fifo2 X
} -returnCodes error \
    -result {wrong # args: should be "tcl::chan::fifo2"}

test tcl-chan-fifo2-1.2 {destructor kills both sides and coordinator} -setup {
    lassign [tcl::chan::fifo2] a b
} -match glob -body {
    lappend r [lsort -dict [file channels]]
    lappend r [info class instances ::tcl::chan::fifo2::implementation]
    close $a
    lappend r [lsort -dict [file channels]]
    lappend r [info class instances ::tcl::chan::fifo2::implementation]
} -cleanup {
    unset a b r
} -result {{rc4 rc5 stderr stdin stdout} ::oo::Obj* {stderr stdin stdout} {}}

# -------------------------------------------------------------------------

test tcl-chan-fifo2-2.0 {tell, initial, empty} -setup {
    lassign [tcl::chan::fifo2] a b
} -body {
    list [tell $a] [tell $b]
} -cleanup {
    close $a
    unset a b
} -result {-1 -1}

# -------------------------------------------------------------------------

test tcl-chan-fifo2-tkt-3f48fd6ea2 {fixed misindexing} -setup {
    lassign [tcl::chan::fifo2] a b
    chan configure $a -buffersize 1
    chan configure $b -buffering none
    chan puts -nonewline $b foobar ;# push 6 chars
    chan read $a 2	     	   ;# read 2
    chan read $a 4		   ;# read 4, fifo has nothing left
    chan puts -nonewline $b baz	   ;# push 3 more
} -body {
    chan read $a 1	;# read 1, the `b`
} -cleanup {
    close $a
    unset a b
} -result b

# -------------------------------------------------------------------------
# Explicit cleanup of loaded (support) classes.
rename tcl::chan::events   {}
rename tcl::chan::core     {}
rename tcl::chan::halfpipe {}
rename tcl::chan::fifo2    {}
testsuiteCleanup
return

# Local Variables:
#  mode: tcl
#  indent-tabs-mode: nil
# End:

Changes to modules/virtchannel_base/halfpipe.man.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

[comment {-*- tcl -*- doctools manpage}]
[manpage_begin tcl::chan::halfpipe n 1]
[keywords callbacks]
[keywords fifo]
[keywords {in-memory channel}]
[keywords {reflected channel}]
[keywords {tip 219}]
[keywords {virtual channel}]
[copyright {2009 Andreas Kupries <[email protected]>}]
[moddesc   {Reflected/virtual channel support}]
[category  Channels]
[titledesc {In-memory channel, half of a fifo2}]
[require Tcl 8.5]
[require TclOO]
[require tcl::chan::events [opt 1]]
[require tcl::chan::halfpipe [opt 1]]
[require tcl::chan::halfpipe [opt 1]]
[description]
[para]

The [package tcl::chan::halfpipe] package provides a command creating
one half of a [package tcl::chan::fifo2] pair. Writing into such a
channel invokes a set of callbacks which then handle the data. This is
similar to a channel handler, except having a much simpler API.
>

|






|






|
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
[vset VERSION 1.0.1]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin tcl::chan::halfpipe n [vset VERSION]]
[keywords callbacks]
[keywords fifo]
[keywords {in-memory channel}]
[keywords {reflected channel}]
[keywords {tip 219}]
[keywords {virtual channel}]
[copyright {2009, 2019 Andreas Kupries <[email protected]>}]
[moddesc   {Reflected/virtual channel support}]
[category  Channels]
[titledesc {In-memory channel, half of a fifo2}]
[require Tcl 8.5]
[require TclOO]
[require tcl::chan::events [opt 1]]
[require tcl::chan::halfpipe [opt [vset VERSION]]]

[description]
[para]

The [package tcl::chan::halfpipe] package provides a command creating
one half of a [package tcl::chan::fifo2] pair. Writing into such a
channel invokes a set of callbacks which then handle the data. This is
similar to a channel handler, except having a much simpler API.
73
74
75
76
77
78
79
80
81

This callback is invoked when the channel has run out of data to read.
A single argument is supplied, the handle of the channel.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

73
74
75
76
77
78
79
80
81

This callback is invoked when the channel has run out of data to read.
A single argument is supplied, the handle of the channel.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_base/halfpipe.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# -*- tcl -*-
# # ## ### ##### ######## #############
# (C) 2009 Andreas Kupries

# @@ Meta Begin
# Package tcl::chan::halfpipe 1
# Meta as::author {Andreas Kupries}
# Meta as::copyright 2009
# Meta as::license BSD
# Meta description Implementation of one half of a pipe
# Meta description channel. Based on Tcl 8.5's channel
# Meta description reflection support. Exports a single
# Meta description command for the creation of new
# Meta description channels. Option arguments. Result is the
# Meta description handle of the new channel, and the object


|




|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# -*- tcl -*-
# # ## ### ##### ######## #############
# (C) 2009, 2019 Andreas Kupries

# @@ Meta Begin
# Package tcl::chan::halfpipe 1
# Meta as::author {Andreas Kupries}
# Meta as::copyright 2009,2019
# Meta as::license BSD
# Meta description Implementation of one half of a pipe
# Meta description channel. Based on Tcl 8.5's channel
# Meta description reflection support. Exports a single
# Meta description command for the creation of new
# Meta description channels. Option arguments. Result is the
# Meta description handle of the new channel, and the object
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
	next $c
    }

    method read {c n} {
	set max  [string length $read]
	set last [expr {$at + $n - 1}]
	set result {}

	#    last+1 <= max
	# <=> at+n <= max
	# <=> n <= max-at

	if {$n <= ($max - $at)} {
	    # The request is less than what we have left in the read
	    # buffer, we take it, and move the read pointer forward.

	    append result [string range $read $at $last]
	    incr at $n
	    incr $size -$n
	} else {
	    # We need the whole remaining read buffer, and more. For
	    # the latter we shift the write buffer contents over into
	    # the read buffer, and then read from the latter again.

	    append result [string range $read $at end]
	    incr n -[string length $result]

	    set at    0

	    set read  $write
	    set write {}
	    set size  [string length $read]
	    set max   $size

	    # at == 0
	    if {$n <= $max} {
		# The request is less than what we have in the updated
		# read buffer, we take it, and move the read pointer
		# forward.

		append result [string range $read 0 $last]
		set at $n
		incr $size -$n
	    } else {







|













|
|





>





|

|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
	next $c
    }

    method read {c n} {
	set max  [string length $read]
	set last [expr {$at + $n - 1}]
	set result {}
	
	#    last+1 <= max
	# <=> at+n <= max
	# <=> n <= max-at

	if {$n <= ($max - $at)} {
	    # The request is less than what we have left in the read
	    # buffer, we take it, and move the read pointer forward.

	    append result [string range $read $at $last]
	    incr at $n
	    incr $size -$n
	} else {
	    # We need the whole remaining read buffer, and more. For
	    # the latter we make the write buffer the new read buffer,
	    # and then read from it again.

	    append result [string range $read $at end]
	    incr n -[string length $result]

	    set at    0
            set last  [expr {$n - 1}]
	    set read  $write
	    set write {}
	    set size  [string length $read]
	    set max   $size

	    # at == 0 simplifies expressions
	    if {$n <= $max} {
		# The request is less than what we have in the new
		# read buffer, we take it, and move the read pointer
		# forward.

		append result [string range $read 0 $last]
		set at $n
		incr $size -$n
	    } else {
122
123
124
125
126
127
128








129













130
131
132
133
134
135
136
	my Readable
	return $n
    }

    # # ## ### ##### ######## #############

    variable at read write size options






















    # # ## ### ##### ######## #############

    constructor {args} {
	array set options {
	    -write-command {}
	    -empty-command {}
	    -close-command {}







>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>







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
	my Readable
	return $n
    }

    # # ## ### ##### ######## #############

    variable at read write size options
    # at      : first location in read buffer not yet read
    # read    : read buffer
    # write   : buffer for received data, i.e.
    #           written into the halfpipe from
    #           the other side.
    # size    : combined length of receive and read buffers
    #           == amount of stored data
    # options : configuration array

    # The halpipe uses a pointer (`at`) into the data buffer to
    # extract the characters read by the user, while not shifting the
    # data down in memory. Doing such a shift would cause a large
    # performance hit (O(n**2) operation vs O(n)). This however comes
    # with the danger of the buffer growing out of bounds as ever more
    # data is appended by the receiver while the reader is not
    # catching up, preventing a release. The solution to this in turn
    # is to split the buffer into two. An append-only receive buffer
    # (`write`) for incoming data, and a `read` buffer with the
    # pointer. When the current read buffer is entirely consumed the
    # current receive buffer becomes the new read buffer and a new
    # empty receive buffer is started.
    
    # # ## ### ##### ######## #############

    constructor {args} {
	array set options {
	    -write-command {}
	    -empty-command {}
	    -close-command {}
160
161
162
163
164
165
166
167
168
	if {![llength $options($o)]} return
	uplevel \#0 [list {*}$options($o) {*}$args]
	return
    }
}

# # ## ### ##### ######## #############
package provide tcl::chan::halfpipe 1
return







|

182
183
184
185
186
187
188
189
190
	if {![llength $options($o)]} return
	uplevel \#0 [list {*}$options($o) {*}$args]
	return
    }
}

# # ## ### ##### ######## #############
package provide tcl::chan::halfpipe 1.0.1
return

Changes to modules/virtchannel_base/nullzero.man.

36
37
38
39
40
41
42
43
44
[call [cmd ::tcl::chan::nullzero]]

This command creates a new nullzero channel and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

36
37
38
39
40
41
42
43
44
[call [cmd ::tcl::chan::nullzero]]

This command creates a new nullzero channel and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_base/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if {![package vsatisfies [package provide Tcl] 8.5]} {return}

package ifneeded tcl::chan::cat 1.0.2      [list source [file join $dir cat.tcl]]
package ifneeded tcl::chan::facade 1.0.1   [list source [file join $dir facade.tcl]]
package ifneeded tcl::chan::fifo 1         [list source [file join $dir fifo.tcl]]
package ifneeded tcl::chan::fifo2 1        [list source [file join $dir fifo2.tcl]]
package ifneeded tcl::chan::halfpipe 1     [list source [file join $dir halfpipe.tcl]]
package ifneeded tcl::chan::memchan 1.0.4  [list source [file join $dir memchan.tcl]]
package ifneeded tcl::chan::null 1         [list source [file join $dir null.tcl]]
package ifneeded tcl::chan::nullzero 1     [list source [file join $dir nullzero.tcl]]
package ifneeded tcl::chan::random 1       [list source [file join $dir random.tcl]]
package ifneeded tcl::chan::std 1.0.1      [list source [file join $dir std.tcl]]
package ifneeded tcl::chan::string 1.0.3   [list source [file join $dir string.tcl]]
package ifneeded tcl::chan::textwindow 1   [list source [file join $dir textwindow.tcl]]


|



|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
if {![package vsatisfies [package provide Tcl] 8.5]} {return}

package ifneeded tcl::chan::cat 1.0.3      [list source [file join $dir cat.tcl]]
package ifneeded tcl::chan::facade 1.0.1   [list source [file join $dir facade.tcl]]
package ifneeded tcl::chan::fifo 1         [list source [file join $dir fifo.tcl]]
package ifneeded tcl::chan::fifo2 1        [list source [file join $dir fifo2.tcl]]
package ifneeded tcl::chan::halfpipe 1.0.1 [list source [file join $dir halfpipe.tcl]]
package ifneeded tcl::chan::memchan 1.0.4  [list source [file join $dir memchan.tcl]]
package ifneeded tcl::chan::null 1         [list source [file join $dir null.tcl]]
package ifneeded tcl::chan::nullzero 1     [list source [file join $dir nullzero.tcl]]
package ifneeded tcl::chan::random 1       [list source [file join $dir random.tcl]]
package ifneeded tcl::chan::std 1.0.1      [list source [file join $dir std.tcl]]
package ifneeded tcl::chan::string 1.0.3   [list source [file join $dir string.tcl]]
package ifneeded tcl::chan::textwindow 1   [list source [file join $dir textwindow.tcl]]

Changes to modules/virtchannel_base/randseed.man.

35
36
37
38
39
40
41
42
43
This command takes to seed lists and combines them into a single list
by XORing them elementwise, modulo 256. If the lists are not of equial
length the shorter of the two is padded with 0s before merging.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

35
36
37
38
39
40
41
42
43
This command takes to seed lists and combines them into a single list
by XORing them elementwise, modulo 256. If the lists are not of equial
length the shorter of the two is padded with 0s before merging.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_base/std.man.

35
36
37
38
39
40
41
42
43

[para] The channel is created only once, on the first call, and all
future calls simply return this handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

35
36
37
38
39
40
41
42
43

[para] The channel is created only once, on the first call, and all
future calls simply return this handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_base/tcllib_fifo.man.

35
36
37
38
39
40
41
42
43
[call [cmd ::tcl::chan::fifo]]

This command creates a new fifo channel and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

35
36
37
38
39
40
41
42
43
[call [cmd ::tcl::chan::fifo]]

This command creates a new fifo channel and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_base/tcllib_fifo2.man.

42
43
44
45
46
47
48
49
50

This command creates a new connected pair of fifo channels and returns
their handles, as a list containing two elements.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

42
43
44
45
46
47
48
49
50

This command creates a new connected pair of fifo channels and returns
their handles, as a list containing two elements.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_base/tcllib_memchan.man.

37
38
39
40
41
42
43
44
45
[call [cmd ::tcl::chan::memchan]]

This command creates a new memchan channel and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

37
38
39
40
41
42
43
44
45
[call [cmd ::tcl::chan::memchan]]

This command creates a new memchan channel and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_base/tcllib_null.man.

37
38
39
40
41
42
43
44
45
[call [cmd ::tcl::chan::null]]

This command creates a new null channel and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

37
38
39
40
41
42
43
44
45
[call [cmd ::tcl::chan::null]]

This command creates a new null channel and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_base/tcllib_random.man.

38
39
40
41
42
43
44
45
46

The seed is a list of integer numbers used to initialize the
internal feedback shift register of the generator.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

38
39
40
41
42
43
44
45
46

The seed is a list of integer numbers used to initialize the
internal feedback shift register of the generator.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_base/tcllib_string.man.

38
39
40
41
42
43
44
45
46

This command creates a new string channel and returns its handle. The
channel provides random read-only access to the [arg content] string.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

38
39
40
41
42
43
44
45
46

This command creates a new string channel and returns its handle. The
channel provides random read-only access to the [arg content] string.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_base/tcllib_variable.man.

39
40
41
42
43
44
45
46
47
This command creates a new variable channel and returns its handle.
The content of the channel is stored in the associated namespace
variable [arg varname].

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

39
40
41
42
43
44
45
46
47
This command creates a new variable channel and returns its handle.
The content of the channel is stored in the associated namespace
variable [arg varname].

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_base/tcllib_zero.man.

37
38
39
40
41
42
43
44
45
[call [cmd ::tcl::chan::zero]]

This command creates a new zero channel and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

37
38
39
40
41
42
43
44
45
[call [cmd ::tcl::chan::zero]]

This command creates a new zero channel and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_base/textwindow.man.

31
32
33
34
35
36
37
38
39

This command creates a new textwindow channel and returns its handle.
Data written to this channel will appear in the associated [arg widget].

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

31
32
33
34
35
36
37
38
39

This command creates a new textwindow channel and returns its handle.
Data written to this channel will appear in the associated [arg widget].

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_core/core.man.

64
65
66
67
68
69
70
71
72
initialized for, see the method [method initialize]. When destroyed
from within a call of [method finalize] this does not happen, under
the assumption that the channel is being destroyed by Tcl.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

64
65
66
67
68
69
70
71
72
initialized for, see the method [method initialize]. When destroyed
from within a call of [method finalize] this does not happen, under
the assumption that the channel is being destroyed by Tcl.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_core/events.man.

71
72
73
74
75
76
77
78
79
system coming in through the [method watch] method the event core is
able to determine which events it should (not) generate and act
accordingly.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

71
72
73
74
75
76
77
78
79
system coming in through the [method watch] method the event core is
able to determine which events it should (not) generate and act
accordingly.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_core/transformcore.man.

64
65
66
67
68
69
70
71
72
it was initialized for, see the method [method initialize]. When destroyed
from within a call of [method finalize] this does not happen, under
the assumption that the channel and transform are being destroyed by Tcl.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

64
65
66
67
68
69
70
71
72
it was initialized for, see the method [method initialize]. When destroyed
from within a call of [method finalize] this does not happen, under
the assumption that the channel and transform are being destroyed by Tcl.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_transform/adler32.man.

62
63
64
65
66
67
68
69
70
[para] If not specified, or the empty string, the checksum of the
write direction is not saved.

[list_end]
[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

62
63
64
65
66
67
68
69
70
[para] If not specified, or the empty string, the checksum of the
write direction is not saved.

[list_end]
[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_transform/hex.man.

35
36
37
38
39
40
41
42
43

This command creates a hex transformation on top of the channel
[arg chan] and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

35
36
37
38
39
40
41
42
43

This command creates a hex transformation on top of the channel
[arg chan] and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_transform/identity.man.

42
43
44
45
46
47
48
49
50

This command creates an identity transformation on top of the channel
[arg chan] and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

42
43
44
45
46
47
48
49
50

This command creates an identity transformation on top of the channel
[arg chan] and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_transform/limitsize.man.

38
39
40
41
42
43
44
45
46
[para] [arg max] is the number of bytes which can be read from the
channel before EOF is signaled by the transformation. Note that
popping the transformation clears the EOF it generated as well.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

38
39
40
41
42
43
44
45
46
[para] [arg max] is the number of bytes which can be read from the
channel before EOF is signaled by the transformation. Note that
popping the transformation clears the EOF it generated as well.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_transform/observe.man.

42
43
44
45
46
47
48
49
50
This command creates an observer transformation on top of the channel
[arg chan] and returns its handle. The channel handles [arg logr] and
[arg logw] are there the data is copied to.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

42
43
44
45
46
47
48
49
50
This command creates an observer transformation on top of the channel
[arg chan] and returns its handle. The channel handles [arg logr] and
[arg logw] are there the data is copied to.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_transform/rot.man.

49
50
51
52
53
54
55
56
57
ASCII 65...90, and 97...122, i.e. the upper- and lower-case alphabetic
characters, i.e. "A...Z" and "a...z". All other bytes are passed
through unchanged.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

49
50
51
52
53
54
55
56
57
ASCII 65...90, and 97...122, i.e. the upper- and lower-case alphabetic
characters, i.e. "A...Z" and "a...z". All other bytes are passed
through unchanged.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_transform/spacer.man.

37
38
39
40
41
42
43
44
45
bytes of data written, and on the read side the same is done in
reverse, removing the spacing. If [arg space] is not specified it
defaults to a single space character (ASCII 32).

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

37
38
39
40
41
42
43
44
45
bytes of data written, and on the read side the same is done in
reverse, removing the spacing. If [arg space] is not specified it
defaults to a single space character (ASCII 32).

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_transform/tcllib_zlib.man.

38
39
40
41
42
43
44
45
46

[para] The [arg level] specifies how much effort is put into the
compression, from [const 0] to [const 9], and defaults to [const 4].

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

38
39
40
41
42
43
44
45
46

[para] The [arg level] specifies how much effort is put into the
compression, from [const 0] to [const 9], and defaults to [const 4].

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_transform/vt_base64.man.

36
37
38
39
40
41
42
43
44

This command creates a base64 transformation on top of the channel
[arg chan] and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

36
37
38
39
40
41
42
43
44

This command creates a base64 transformation on top of the channel
[arg chan] and returns its handle.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_transform/vt_counter.man.

60
61
62
63
64
65
66
67
68
[para] If not specified, or the empty string, the counter of the
write direction is not saved.

[list_end]
[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

60
61
62
63
64
65
66
67
68
[para] If not specified, or the empty string, the counter of the
write direction is not saved.

[list_end]
[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_transform/vt_crc32.man.

62
63
64
65
66
67
68
69
70
[para] If not specified, or the empty string, the checksum of the
write direction is not saved.

[list_end]
[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

62
63
64
65
66
67
68
69
70
[para] If not specified, or the empty string, the checksum of the
write direction is not saved.

[list_end]
[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/virtchannel_transform/vt_otp.man.

45
46
47
48
49
50
51
52
53
one-time pads for the write and read directions, respectively. Their
contents are reads and xored with the bytes written to and read from
the channel.

[list_end]

[vset CATEGORY virtchannel]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

45
46
47
48
49
50
51
52
53
one-time pads for the write and read directions, respectively. Their
contents are reads and xored with the bytes written to and read from
the channel.

[list_end]

[vset CATEGORY virtchannel]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/websocket/websocket.man.

377
378
379
380
381
382
383
384
385
after 400 test $sock
vwait forever
[example_end]

[include ../common-text/tls-security-notes.inc]

[vset CATEGORY websocket]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

377
378
379
380
381
382
383
384
385
after 400 test $sock
vwait forever
[example_end]

[include ../common-text/tls-security-notes.inc]

[vset CATEGORY websocket]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/wip/wip.man.

376
377
378
379
380
381
382
383
384
[list_end]

[section EXAMPLES]

No examples yet.

[vset CATEGORY wip]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

376
377
378
379
380
381
382
383
384
[list_end]

[section EXAMPLES]

No examples yet.

[vset CATEGORY wip]
[include ../common-text/feedback.inc]
[manpage_end]

Deleted modules/yaml/06eef112da.data.

1
2
3
4
5
6
7
---
- &foo
- &bar
- alpha: 43
  beta:
    houston: [*foo]
    newyork:  [[*bar,[aaa]]]
<
<
<
<
<
<
<














Changes to modules/yaml/huddle.man.

550
551
552
553
554
555
556
557
558

[section LIMITATIONS]

[para]
now printing.

[vset CATEGORY huddle]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

550
551
552
553
554
555
556
557
558

[section LIMITATIONS]

[para]
now printing.

[vset CATEGORY huddle]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/yaml/huddle.test.

140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#                }
#                set val [eval huddle list $subs]
#            }
#            lappend result $key $val
#        }
#        return [eval huddle create $result]
#    }
#    set fd [open [file join [file dirname [info script]] layers.txt] r]
#    set json1 [read $fd]
#    close $fd
#
#    set data [json::json2dict $json1]
##    set data [huddle_build $data]
##
##    set json2 [huddle jsondump $data]







|







140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#                }
#                set val [eval huddle list $subs]
#            }
#            lappend result $key $val
#        }
#        return [eval huddle create $result]
#    }
#    set fd [open [asset layers.txt] r]
#    set json1 [read $fd]
#    close $fd
#
#    set data [json::json2dict $json1]
##    set data [huddle_build $data]
##
##    set json2 [huddle jsondump $data]

Deleted modules/yaml/layers.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
{
  "filename": "022_05small.psd",
  "layers": [
    {
      "layer": "トンボ(必ず表示させる",
      "visible": false,
      "haschild": false
    },
    {
      "layer": "アタリ線(最終的に消す",
      "visible": false,
      "haschild": false
    },
    {
      "layer": "title",
      "visible": false,
      "haschild": true,
      "layers": [
        {
          "layer": "title 5.4",
          "visible": false,
          "haschild": false
        }
      ]
    },
    {
      "layer": "logos",
      "visible": false,
      "haschild": true,
      "layers": [
        {
          "layer": "niji_logo",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "+imoto+",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "レイヤー 2",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "nijiura 3",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "Here",
          "visible": false,
          "haschild": false
        }
      ]
    },
    {
      "layer": "nijiura 2.3",
      "visible": false,
      "haschild": true,
      "layers": [
        {
          "layer": "レイヤー 1",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "nijiura cap",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "nijiura 2.2",
          "visible": false,
          "haschild": false
        }
      ]
    },
    {
      "layer": "name",
      "visible": false,
      "haschild": true,
      "layers": [
        {
          "layer": "jal L",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "ana L_3",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "a380 L",
          "visible": false,
          "haschild": false
        }
      ]
    },
    {
      "layer": "rainbow flash",
      "visible": false,
      "haschild": true,
      "layers": [
        {
          "layer": "rainbow 7",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "rainbow 6",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "rainbow 5",
          "visible": false,
          "haschild": false
        }
      ]
    },
    {
      "layer": "hikari",
      "visible": false,
      "haschild": true,
      "layers": [
        {
          "layer": "kousen 6",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "kousen 5",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "kousen 4",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "kousen 3",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "kousen 2",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "kousen 1",
          "visible": false,
          "haschild": false
        }
      ]
    },
    {
      "layer": "チャンネルミキサー",
      "visible": true,
      "haschild": false
    },
    {
      "layer": "original",
      "visible": true,
      "haschild": false
    },
    {
      "layer": "チャンネルミキサー 1",
      "visible": true,
      "haschild": false
    },
    {
      "layer": "original 2",
      "visible": true,
      "haschild": false
    },
    {
      "layer": "white light",
      "visible": false,
      "haschild": false
    },
    {
      "layer": "ushiro",
      "visible": false,
      "haschild": true,
      "layers": [
        {
          "layer": "色相・彩度1",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "sora 1",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "gurade",
          "visible": false,
          "haschild": false
        }
      ]
    },
    {
      "layer": "背景 のコピー 2",
      "visible": true,
      "haschild": false
    },
    {
      "layer": "用紙ゲージ",
      "visible": false,
      "haschild": false
    },
    {
      "layer": "背景",
      "visible": true,
      "haschild": false
    }
  ]
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































































































































































































































































































Added modules/yaml/test-assets/06eef112da.data.















>
>
>
>
>
>
>
1
2
3
4
5
6
7
---
- &foo
- &bar
- alpha: 43
  beta:
    houston: [*foo]
    newyork:  [[*bar,[aaa]]]

Added modules/yaml/test-assets/layers.txt.

































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
{
  "filename": "022_05small.psd",
  "layers": [
    {
      "layer": "トンボ(必ず表示させる",
      "visible": false,
      "haschild": false
    },
    {
      "layer": "アタリ線(最終的に消す",
      "visible": false,
      "haschild": false
    },
    {
      "layer": "title",
      "visible": false,
      "haschild": true,
      "layers": [
        {
          "layer": "title 5.4",
          "visible": false,
          "haschild": false
        }
      ]
    },
    {
      "layer": "logos",
      "visible": false,
      "haschild": true,
      "layers": [
        {
          "layer": "niji_logo",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "+imoto+",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "レイヤー 2",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "nijiura 3",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "Here",
          "visible": false,
          "haschild": false
        }
      ]
    },
    {
      "layer": "nijiura 2.3",
      "visible": false,
      "haschild": true,
      "layers": [
        {
          "layer": "レイヤー 1",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "nijiura cap",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "nijiura 2.2",
          "visible": false,
          "haschild": false
        }
      ]
    },
    {
      "layer": "name",
      "visible": false,
      "haschild": true,
      "layers": [
        {
          "layer": "jal L",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "ana L_3",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "a380 L",
          "visible": false,
          "haschild": false
        }
      ]
    },
    {
      "layer": "rainbow flash",
      "visible": false,
      "haschild": true,
      "layers": [
        {
          "layer": "rainbow 7",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "rainbow 6",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "rainbow 5",
          "visible": false,
          "haschild": false
        }
      ]
    },
    {
      "layer": "hikari",
      "visible": false,
      "haschild": true,
      "layers": [
        {
          "layer": "kousen 6",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "kousen 5",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "kousen 4",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "kousen 3",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "kousen 2",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "kousen 1",
          "visible": false,
          "haschild": false
        }
      ]
    },
    {
      "layer": "チャンネルミキサー",
      "visible": true,
      "haschild": false
    },
    {
      "layer": "original",
      "visible": true,
      "haschild": false
    },
    {
      "layer": "チャンネルミキサー 1",
      "visible": true,
      "haschild": false
    },
    {
      "layer": "original 2",
      "visible": true,
      "haschild": false
    },
    {
      "layer": "white light",
      "visible": false,
      "haschild": false
    },
    {
      "layer": "ushiro",
      "visible": false,
      "haschild": true,
      "layers": [
        {
          "layer": "色相・彩度1",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "sora 1",
          "visible": false,
          "haschild": false
        },
        {
          "layer": "gurade",
          "visible": false,
          "haschild": false
        }
      ]
    },
    {
      "layer": "背景 のコピー 2",
      "visible": true,
      "haschild": false
    },
    {
      "layer": "用紙ゲージ",
      "visible": false,
      "haschild": false
    },
    {
      "layer": "背景",
      "visible": true,
      "haschild": false
    }
  ]
}

Changes to modules/yaml/yaml.man.

181
182
183
184
185
186
187
188
189
[para]
Too many braces, or too few braces.

[para]
Not enough character set of line feeds. Please use only "\n" as line breaks.

[vset CATEGORY yaml]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

181
182
183
184
185
186
187
188
189
[para]
Too many braces, or too few braces.

[para]
Not enough character set of line feeds. Please use only "\n" as line breaks.

[vset CATEGORY yaml]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/yaml/yaml.test.

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
    }
    error
}

# ------------

test yaml-21.0.06eef112da {ticket 06eef112da} -body {
    yaml::yaml2dict -file [localPath 06eef112da.data]
} -result {{} {} {alpha 43 beta {houston {{}} newyork {{{} aaa}}}}}

# ------------
# error  .....

test yaml-1.1 "error" -body {
    set error1 {







|







70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
    }
    error
}

# ------------

test yaml-21.0.06eef112da {ticket 06eef112da} -body {
    yaml::yaml2dict -file [asset 06eef112da.data]
} -result {{} {} {alpha 43 beta {houston {{}} newyork {{{} aaa}}}}}

# ------------
# error  .....

test yaml-1.1 "error" -body {
    set error1 {

Changes to modules/zip/decode.man.

127
128
129
130
131
132
133
134
135
[arg archive] file in the given destination directory [arg dstdir].

[para] The result of the command is the empty string.

[list_end]

[vset CATEGORY zipfile]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

127
128
129
130
131
132
133
134
135
[arg archive] file in the given destination directory [arg dstdir].

[para] The result of the command is the empty string.

[list_end]

[vset CATEGORY zipfile]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/zip/encode.man.

84
85
86
87
88
89
90
91
92
specific order was documented. It was lexicographically sorted. The
change was made to support [cmd zip]-based file formats which require
a specific order of files in the archive, for example [file .epub].

[list_end]

[vset CATEGORY zipfile]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

84
85
86
87
88
89
90
91
92
specific order was documented. It was lexicographically sorted. The
change was made to support [cmd zip]-based file formats which require
a specific order of files in the archive, for example [file .epub].

[list_end]

[vset CATEGORY zipfile]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/zip/mkzip.man.

1
2
3
4
5
6
7
8
[vset ZIP_mkzip_VERSION 1.2]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin zipfile::mkzip n [vset ZIP_mkzip_VERSION]]
[keywords decompression zip]
[copyright {2009 Pat Thoyts}]
[moddesc {Zip archive creation}]
[titledesc {Build a zip archive}]
[category  File]
|







1
2
3
4
5
6
7
8
[vset ZIP_mkzip_VERSION 1.2.1]
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin zipfile::mkzip n [vset ZIP_mkzip_VERSION]]
[keywords decompression zip]
[copyright {2009 Pat Thoyts}]
[moddesc {Zip archive creation}]
[titledesc {Build a zip archive}]
[category  File]
96
97
98
99
100
101
102
103
104
is specified.

[list_end]

[list_end]

[vset CATEGORY zipfile]
[include ../doctools2base/include/feedback.inc]
[manpage_end]







|

96
97
98
99
100
101
102
103
104
is specified.

[list_end]

[list_end]

[vset CATEGORY zipfile]
[include ../common-text/feedback.inc]
[manpage_end]

Changes to modules/zip/mkzip.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- tcl -*-
# mkzip.tcl -- Copyright (C) 2009 Pat Thoyts <[email protected]>
#
#        Create ZIP archives in Tcl.
#
# Create a zipkit using mkzip filename.zkit -zipkit -directory xyz.vfs
# or a zipfile using mkzip filename.zip -directory dirname -exclude "*~"
#
## BSD License
##
# Package providing commands for the generation of a zip archive.
# version 1.2

package require Tcl 8.6

namespace eval ::zipfile {}
namespace eval ::zipfile::decode {}
namespace eval ::zipfile::encode {}
namespace eval ::zipfile::mkzip {}











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- tcl -*-
# mkzip.tcl -- Copyright (C) 2009 Pat Thoyts <[email protected]>
#
#        Create ZIP archives in Tcl.
#
# Create a zipkit using mkzip filename.zkit -zipkit -directory xyz.vfs
# or a zipfile using mkzip filename.zip -directory dirname -exclude "*~"
#
## BSD License
##
# Package providing commands for the generation of a zip archive.
# version 1.2.1

package require Tcl 8.6

namespace eval ::zipfile {}
namespace eval ::zipfile::decode {}
namespace eval ::zipfile::encode {}
namespace eval ::zipfile::mkzip {}
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#        a set of glob expressions to match against files and to avoid.
#        The match arg is internal.
#        eg: walk library {CVS/* *~ .#*} to exclude CVS and emacs cruft.
#
proc ::zipfile::mkzip::walk {base {excludes ""} {match *} {path {}}} {
    set result {}
    set imatch [file join $path $match]
    set files [glob -nocomplain -tails -types f -directory $base $imatch]
    foreach file $files {
        set excluded 0
        foreach glob $excludes {
            if {[string match $glob $file]} {
                set excluded 1
                break
            }
        }
        if {!$excluded} {lappend result $file}
    }
    foreach dir [glob -nocomplain -tails -types d -directory $base $imatch] {
        set subdir [walk $base $excludes $match $dir]
        if {[llength $subdir]>0} {
            set result [concat $result [list $dir] $subdir]
        }
    }
    return $result
}







|










|







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#        a set of glob expressions to match against files and to avoid.
#        The match arg is internal.
#        eg: walk library {CVS/* *~ .#*} to exclude CVS and emacs cruft.
#
proc ::zipfile::mkzip::walk {base {excludes ""} {match *} {path {}}} {
    set result {}
    set imatch [file join $path $match]
    set files [glob -nocomplain -tails -types f -directory $base -- $imatch]
    foreach file $files {
        set excluded 0
        foreach glob $excludes {
            if {[string match $glob $file]} {
                set excluded 1
                break
            }
        }
        if {!$excluded} {lappend result $file}
    }
    foreach dir [glob -nocomplain -tails -types d -directory $base -- $imatch] {
        set subdir [walk $base $excludes $match $dir]
        if {[llength $subdir]>0} {
            set result [concat $result [list $dir] $subdir]
        }
    }
    return $result
}
275
276
277
278
279
280
281
282
  close $zf

  return
}

# ### ### ### ######### ######### #########
## Ready
package provide zipfile::mkzip 1.2







|
275
276
277
278
279
280
281
282
  close $zf

  return
}

# ### ### ### ######### ######### #########
## Ready
package provide zipfile::mkzip 1.2.1

Added modules/zip/mkzip.test.

















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# mkzip.test - Copyright (C) 2019 Andreas Kupries <[email protected]>

# -------------------------------------------------------------------------

source [file join \
	[file dirname [file dirname [file join [pwd] [info script]]]] \
	devtools testutilities.tcl]

testsNeedTcl     8.6
testsNeedTcltest 2

testing {
    useLocal mkzip.tcl zipfile::mkzip
}

# -------------------------------------------------------------------------

test zipfile-mkzip-mkzip-1.0 {mkzip, wrong args, not enough} -body {
    zipfile::mkzip::mkzip
} -returnCodes error -result {wrong # args: should be "zipfile::mkzip::mkzip filename ?arg ...?"}

test zipfile-mkzip-mkzip-2.0 {mkzip, tkt b9725d990b} -setup {
    tcltest::makeDirectory foo
    tcltest::makeDirectory foo/-1
} -cleanup {
    tcltest::removeDirectory foo
    file delete foo.zip
} -body {
    zipfile::mkzip::mkzip foo.zip -directory foo
} -result {}

# -------------------------------------------------------------------------

testsuiteCleanup

# -------------------------------------------------------------------------
# Local Variables:
#   mode: tcl
#   indent-tabs-mode: nil
# End:

Changes to modules/zip/pkgIndex.tcl.

1
2
3
4
5
6
7
8
if {![package vsatisfies [package provide Tcl] 8.4]} {return}

package ifneeded zipfile::decode 0.7.1 [list source [file join $dir decode.tcl]]
package ifneeded zipfile::encode 0.4   [list source [file join $dir encode.tcl]]

if {![package vsatisfies [package provide Tcl] 8.6]} {return}

package ifneeded zipfile::mkzip 1.2 [list source [file join $dir mkzip.tcl]]







|
1
2
3
4
5
6
7
8
if {![package vsatisfies [package provide Tcl] 8.4]} {return}

package ifneeded zipfile::decode 0.7.1 [list source [file join $dir decode.tcl]]
package ifneeded zipfile::encode 0.4   [list source [file join $dir encode.tcl]]

if {![package vsatisfies [package provide Tcl] 8.6]} {return}

package ifneeded zipfile::mkzip 1.2.1 [list source [file join $dir mkzip.tcl]]

Changes to support/devel/all.tcl.

192
193
194
195
196
197
198
199



200
201
202
203
204
205
206
207
	set ::auto_path [pSet ::auto_path]

	namespace import ::tcltest::*
	set ::tcltest::testSingleFile false
	set ::tcltest::testsDirectory [pSet ::tcltest::testsDirectory]

	# configure not present in tcltest 1.x
	if {[catch {::tcltest::configure -verbose bstep}]} {



	    set ::tcltest::verbose psb
	}
    }

    interp alias \
	    $c ::tcltest::cleanupTestsHook \
	    {} ::tcltest::cleanupTestsHook $c








|
>
>
>
|







192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
	set ::auto_path [pSet ::auto_path]

	namespace import ::tcltest::*
	set ::tcltest::testSingleFile false
	set ::tcltest::testsDirectory [pSet ::tcltest::testsDirectory]

	# configure not present in tcltest 1.x
	if {[catch {::tcltest::configure -verbose {
	    body skip start error pass usec line
	}}]} {
	    # ^ body skip start error pass usec line
	    set ::tcltest::verbose psb ;# pass skip body
	}
    }

    interp alias \
	    $c ::tcltest::cleanupTestsHook \
	    {} ::tcltest::cleanupTestsHook $c

Changes to support/devel/sak/doc/kwic.txt.

671
672
673
674
675
676
677




678
679
680
681
682
683
684
[key dict]
[manpage modules/dicttool/dicttool.man dicttool]
[key diff]
[manpage modules/docstrip/docstrip_util.man docstrip_util]
[manpage modules/struct/struct_list.man     struct::list]
[key {diff -n format}]
[manpage modules/rcs/rcs.man rcs]




[key difference]
[manpage modules/struct/struct_set.man struct::set]
[key differential]
[manpage modules/struct/struct_list.man struct::list]
[key {differential equations}]
[manpage modules/math/calculus.man math::calculus]
[key dijkstra]







>
>
>
>







671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
[key dict]
[manpage modules/dicttool/dicttool.man dicttool]
[key diff]
[manpage modules/docstrip/docstrip_util.man docstrip_util]
[manpage modules/struct/struct_list.man     struct::list]
[key {diff -n format}]
[manpage modules/rcs/rcs.man rcs]
[key {diff -ruN}]
[manpage modules/textutil/patch.man textutil::patch]
[key {diff, unified format}]
[manpage modules/textutil/patch.man textutil::patch]
[key difference]
[manpage modules/struct/struct_set.man struct::set]
[key differential]
[manpage modules/struct/struct_list.man struct::list]
[key {differential equations}]
[manpage modules/math/calculus.man math::calculus]
[key dijkstra]
1171
1172
1173
1174
1175
1176
1177


1178
1179
1180
1181
1182
1183
1184
[manpage modules/textutil/adjust.man               textutil::adjust]
[manpage modules/textutil/textutil_string.man      textutil::string]
[manpage modules/textutil/tabify.man               textutil::tabify]
[key {formatting engine}]
[manpage modules/doctools/docidx_plugin_apiref.man   docidx_plugin_apiref]
[manpage modules/doctools/doctoc_plugin_apiref.man   doctoc_plugin_apiref]
[manpage modules/doctools/doctools_plugin_apiref.man doctools_plugin_apiref]


[key {Fourier transform}]
[manpage modules/math/fourier.man math::fourier]
[key FR]
[manpage modules/doctools2idx/idx_msgcat_fr.man doctools::msgcat::idx::fr]
[manpage modules/doctools2toc/toc_msgcat_fr.man doctools::msgcat::toc::fr]
[key frame]
[manpage modules/term/ansi_cmacros.man term::ansi::code::macros]







>
>







1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
[manpage modules/textutil/adjust.man               textutil::adjust]
[manpage modules/textutil/textutil_string.man      textutil::string]
[manpage modules/textutil/tabify.man               textutil::tabify]
[key {formatting engine}]
[manpage modules/doctools/docidx_plugin_apiref.man   docidx_plugin_apiref]
[manpage modules/doctools/doctoc_plugin_apiref.man   doctoc_plugin_apiref]
[manpage modules/doctools/doctools_plugin_apiref.man doctools_plugin_apiref]
[key fossil]
[manpage modules/textutil/patch.man textutil::patch]
[key {Fourier transform}]
[manpage modules/math/fourier.man math::fourier]
[key FR]
[manpage modules/doctools2idx/idx_msgcat_fr.man doctools::msgcat::idx::fr]
[manpage modules/doctools2toc/toc_msgcat_fr.man doctools::msgcat::toc::fr]
[key frame]
[manpage modules/term/ansi_cmacros.man term::ansi::code::macros]
1214
1215
1216
1217
1218
1219
1220


1221
1222
1223
1224
1225
1226
1227
[key geography]
[manpage modules/map/map_slippy.man map::slippy]
[key {get character}]
[manpage modules/term/receive.man term::receive]
[key gets]
[manpage modules/coroutine/tcllib_coroutine.man coroutine]
[manpage modules/coroutine/coro_auto.man        coroutine::auto]


[key global]
[manpage modules/coroutine/tcllib_coroutine.man coroutine]
[manpage modules/coroutine/coro_auto.man        coroutine::auto]
[key golang]
[manpage modules/defer/defer.man defer]
[key gopher]
[manpage modules/uri/uri.man uri]







>
>







1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
[key geography]
[manpage modules/map/map_slippy.man map::slippy]
[key {get character}]
[manpage modules/term/receive.man term::receive]
[key gets]
[manpage modules/coroutine/tcllib_coroutine.man coroutine]
[manpage modules/coroutine/coro_auto.man        coroutine::auto]
[key git]
[manpage modules/textutil/patch.man textutil::patch]
[key global]
[manpage modules/coroutine/tcllib_coroutine.man coroutine]
[manpage modules/coroutine/coro_auto.man        coroutine::auto]
[key golang]
[manpage modules/defer/defer.man defer]
[key gopher]
[manpage modules/uri/uri.man uri]
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
[key html]
[manpage modules/html/html.man             html]
[manpage modules/htmlparse/htmlparse.man   htmlparse]
[manpage modules/javascript/javascript.man javascript]
[manpage modules/ncgi/ncgi.man             ncgi]
[key http]
[manpage modules/http/autoproxy.man            autoproxy]

[manpage modules/map/map_geocode_nominatim.man map::geocode::nominatim]
[manpage modules/map/map_slippy_fetcher.man    map::slippy::fetcher]
[manpage modules/httpd/httpd.man               tool]
[manpage modules/uri/uri.man                   uri]
[manpage modules/websocket/websocket.man       websocket]
[key httpd]
[manpage modules/httpd/httpd.man tool]
[key https]
[manpage modules/uri/uri.man uri]
[key httpserver]
[manpage modules/httpd/httpd.man tool]
[key huddle]
[manpage modules/yaml/huddle.man huddle]
[manpage modules/yaml/yaml.man   yaml]
[key {human readable}]
[manpage modules/bench/bench_read.man  bench::in]
[manpage modules/bench/bench_wtext.man bench::out::text]
[key hyphenation]







>


<



|



|







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
[key html]
[manpage modules/html/html.man             html]
[manpage modules/htmlparse/htmlparse.man   htmlparse]
[manpage modules/javascript/javascript.man javascript]
[manpage modules/ncgi/ncgi.man             ncgi]
[key http]
[manpage modules/http/autoproxy.man            autoproxy]
[manpage modules/httpd/httpd.man               httpd]
[manpage modules/map/map_geocode_nominatim.man map::geocode::nominatim]
[manpage modules/map/map_slippy_fetcher.man    map::slippy::fetcher]

[manpage modules/uri/uri.man                   uri]
[manpage modules/websocket/websocket.man       websocket]
[key httpd]
[manpage modules/httpd/httpd.man httpd]
[key https]
[manpage modules/uri/uri.man uri]
[key httpserver]
[manpage modules/httpd/httpd.man httpd]
[key huddle]
[manpage modules/yaml/huddle.man huddle]
[manpage modules/yaml/yaml.man   yaml]
[key {human readable}]
[manpage modules/bench/bench_read.man  bench::in]
[manpage modules/bench/bench_wtext.man bench::out::text]
[key hyphenation]
1872
1873
1874
1875
1876
1877
1878
1879

1880
1881
1882
1883
1884
1885
1886
1887
[manpage modules/math/rational_funcs.man          math::rationalfunctions]
[manpage modules/math/special.man                 math::special]
[manpage modules/math/trig.man                    math::trig]
[manpage modules/simulation/annealing.man         simulation::annealing]
[manpage modules/simulation/montecarlo.man        simulation::montecarlo]
[manpage modules/simulation/simulation_random.man simulation::random]
[key mathematics]
[manpage modules/math/fourier.man    math::fourier]

[manpage modules/math/statistics.man math::statistics]
[key matrices]
[manpage modules/math/linalg.man math::linearalgebra]
[key matrix]
[manpage modules/csv/csv.man        csv]
[manpage modules/math/linalg.man    math::linearalgebra]
[manpage modules/report/report.man  report]
[manpage modules/struct/matrix.man  struct::matrix]







|
>
|







1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
[manpage modules/math/rational_funcs.man          math::rationalfunctions]
[manpage modules/math/special.man                 math::special]
[manpage modules/math/trig.man                    math::trig]
[manpage modules/simulation/annealing.man         simulation::annealing]
[manpage modules/simulation/montecarlo.man        simulation::montecarlo]
[manpage modules/simulation/simulation_random.man simulation::random]
[key mathematics]
[manpage modules/math/fourier.man     math::fourier]
[manpage modules/math/quasirandom.man math::quasirandom]
[manpage modules/math/statistics.man  math::statistics]
[key matrices]
[manpage modules/math/linalg.man math::linearalgebra]
[key matrix]
[manpage modules/csv/csv.man        csv]
[manpage modules/math/linalg.man    math::linearalgebra]
[manpage modules/report/report.man  report]
[manpage modules/struct/matrix.man  struct::matrix]
2106
2107
2108
2109
2110
2111
2112


2113
2114
2115
2116
2117
2118
2119
[manpage modules/cron/cron.man             cron]
[manpage modules/nettool/nettool.man       nettool]
[manpage modules/processman/processman.man processman]
[key on-idle]
[manpage modules/uev/uevent_onidle.man uevent::onidle]
[key {one time pad}]
[manpage modules/virtchannel_transform/vt_otp.man tcl::transform::otp]


[key optimization]
[manpage modules/math/optimize.man        math::optimize]
[manpage modules/simulation/annealing.man simulation::annealing]
[key {ordered list}]
[manpage modules/struct/prioqueue.man struct::prioqueue]
[key otp]
[manpage modules/virtchannel_transform/vt_otp.man tcl::transform::otp]







>
>







2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
[manpage modules/cron/cron.man             cron]
[manpage modules/nettool/nettool.man       nettool]
[manpage modules/processman/processman.man processman]
[key on-idle]
[manpage modules/uev/uevent_onidle.man uevent::onidle]
[key {one time pad}]
[manpage modules/virtchannel_transform/vt_otp.man tcl::transform::otp]
[key oo]
[manpage modules/clay/clay.man clay]
[key optimization]
[manpage modules/math/optimize.man        math::optimize]
[manpage modules/simulation/annealing.man simulation::annealing]
[key {ordered list}]
[manpage modules/struct/prioqueue.man struct::prioqueue]
[key otp]
[manpage modules/virtchannel_transform/vt_otp.man tcl::transform::otp]
2327
2328
2329
2330
2331
2332
2333

2334
2335
2336
2337
2338
2339
2340
[manpage modules/struct/disjointset.man struct::disjointset]
[key passive]
[manpage modules/transfer/connect.man transfer::connect]
[key password]
[manpage modules/otp/otp.man otp]
[key patch]
[manpage modules/docstrip/docstrip_util.man docstrip_util]

[key patching]
[manpage modules/rcs/rcs.man rcs]
[key PCA]
[manpage modules/math/pca.man math::PCA]
[key PEG]
[manpage modules/grammar_me/me_intro.man         grammar::me_intro]
[manpage modules/page/page_util_norm_peg.man     page_util_norm_peg]







>







2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
[manpage modules/struct/disjointset.man struct::disjointset]
[key passive]
[manpage modules/transfer/connect.man transfer::connect]
[key password]
[manpage modules/otp/otp.man otp]
[key patch]
[manpage modules/docstrip/docstrip_util.man docstrip_util]
[manpage modules/textutil/patch.man         textutil::patch]
[key patching]
[manpage modules/rcs/rcs.man rcs]
[key PCA]
[manpage modules/math/pca.man math::PCA]
[key PEG]
[manpage modules/grammar_me/me_intro.man         grammar::me_intro]
[manpage modules/page/page_util_norm_peg.man     page_util_norm_peg]
2534
2535
2536
2537
2538
2539
2540


2541
2542
2543
2544
2545
2546
2547
[manpage modules/pt/pt_util.man                  pt::util]
[manpage modules/pt/pt_to_api.man                pt_export_api]
[manpage modules/pt/pt_from_api.man              pt_import_api]
[manpage modules/pt/pt_introduction.man          pt_introduction]
[manpage modules/pt/pt_parse_peg.man             pt_parse_peg]
[manpage modules/pt/pt_parser_api.man            pt_parser_api]
[manpage modules/pt/pt_peg_op.man                pt_peg_op]


[key queue]
[manpage modules/csv/csv.man             csv]
[manpage modules/htmlparse/htmlparse.man htmlparse]
[manpage modules/struct/stack.man        struct::stack]
[manpage modules/transfer/tqueue.man     transfer::copy::queue]
[key quoting]
[manpage modules/page/page_util_quote.man page_util_quote]







>
>







2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
[manpage modules/pt/pt_util.man                  pt::util]
[manpage modules/pt/pt_to_api.man                pt_export_api]
[manpage modules/pt/pt_from_api.man              pt_import_api]
[manpage modules/pt/pt_introduction.man          pt_introduction]
[manpage modules/pt/pt_parse_peg.man             pt_parse_peg]
[manpage modules/pt/pt_parser_api.man            pt_parser_api]
[manpage modules/pt/pt_peg_op.man                pt_peg_op]
[key quasi-random]
[manpage modules/math/quasirandom.man math::quasirandom]
[key queue]
[manpage modules/csv/csv.man             csv]
[manpage modules/htmlparse/htmlparse.man htmlparse]
[manpage modules/struct/stack.man        struct::stack]
[manpage modules/transfer/tqueue.man     transfer::copy::queue]
[key quoting]
[manpage modules/page/page_util_quote.man page_util_quote]
2944
2945
2946
2947
2948
2949
2950

2951
2952
2953
2954
2955
2956
2957
2958
2959
[manpage modules/nns/nns_intro.man             nns_intro]
[manpage apps/nnsd.man                         nnsd]
[manpage modules/udpcluster/udpcluster.man     udpcluster]
[key service]
[manpage modules/log/logger.man logger]
[key services]
[manpage modules/ftpd/ftpd.man   ftpd]

[manpage modules/smtpd/smtpd.man smtpd]
[manpage modules/httpd/httpd.man tool]
[key set]
[manpage modules/struct/queue.man      struct::queue]
[manpage modules/struct/struct_set.man struct::set]
[key sha1]
[manpage modules/sha1/sha1.man sha1]
[key sha256]
[manpage modules/sha1/sha256.man sha256]







>

<







2958
2959
2960
2961
2962
2963
2964
2965
2966

2967
2968
2969
2970
2971
2972
2973
[manpage modules/nns/nns_intro.man             nns_intro]
[manpage apps/nnsd.man                         nnsd]
[manpage modules/udpcluster/udpcluster.man     udpcluster]
[key service]
[manpage modules/log/logger.man logger]
[key services]
[manpage modules/ftpd/ftpd.man   ftpd]
[manpage modules/httpd/httpd.man httpd]
[manpage modules/smtpd/smtpd.man smtpd]

[key set]
[manpage modules/struct/queue.man      struct::queue]
[manpage modules/struct/struct_set.man struct::set]
[key sha1]
[manpage modules/sha1/sha1.man sha1]
[key sha256]
[manpage modules/sha1/sha256.man sha256]
3192
3193
3194
3195
3196
3197
3198


3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
[manpage modules/doctools2idx/idx_container.man doctools::idx]
[manpage modules/doctools2idx/idx_export.man    doctools::idx::export]
[manpage modules/doctools2toc/toc_container.man doctools::toc]
[manpage modules/doctools2toc/toc_export.man    doctools::toc::export]
[key tcllib]
[manpage modules/csv/csv.man csv]
[key TclOO]


[manpage modules/ooutil/ooutil.man           oo::util]
[manpage modules/tool/meta.man               oo::util]
[manpage modules/oometa/oometa.man           oometa]
[manpage modules/tool/tool.man               tool]
[manpage modules/httpd/httpd.man             tool]
[manpage modules/tool/tool_dict_ensemble.man tool::dict_ensemble]
[key TCLPARAM]
[manpage modules/pt/pt_peg_to_tclparam.man pt::peg::to::tclparam]
[key TDPL]
[manpage modules/grammar_peg/peg.man             grammar::peg]
[manpage modules/grammar_peg/peg_interp.man      grammar::peg::interp]
[manpage apps/pt.man                             pt]







>
>




<







3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218

3219
3220
3221
3222
3223
3224
3225
[manpage modules/doctools2idx/idx_container.man doctools::idx]
[manpage modules/doctools2idx/idx_export.man    doctools::idx::export]
[manpage modules/doctools2toc/toc_container.man doctools::toc]
[manpage modules/doctools2toc/toc_export.man    doctools::toc::export]
[key tcllib]
[manpage modules/csv/csv.man csv]
[key TclOO]
[manpage modules/clay/clay.man               clay]
[manpage modules/httpd/httpd.man             httpd]
[manpage modules/ooutil/ooutil.man           oo::util]
[manpage modules/tool/meta.man               oo::util]
[manpage modules/oometa/oometa.man           oometa]
[manpage modules/tool/tool.man               tool]

[manpage modules/tool/tool_dict_ensemble.man tool::dict_ensemble]
[key TCLPARAM]
[manpage modules/pt/pt_peg_to_tclparam.man pt::peg::to::tclparam]
[key TDPL]
[manpage modules/grammar_peg/peg.man             grammar::peg]
[manpage modules/grammar_peg/peg_interp.man      grammar::peg::interp]
[manpage apps/pt.man                             pt]
3620
3621
3622
3623
3624
3625
3626


3627
3628
3629
3630
3631
3632
3633
[key undenting]
[manpage modules/textutil/adjust.man textutil::adjust]
[key unicode]
[manpage modules/stringprep/stringprep.man      stringprep]
[manpage modules/stringprep/stringprep_data.man stringprep::data]
[manpage modules/stringprep/unicode.man         unicode]
[manpage modules/stringprep/unicode_data.man    unicode::data]


[key union]
[manpage modules/struct/disjointset.man struct::disjointset]
[manpage modules/struct/struct_set.man  struct::set]
[key unit]
[manpage modules/units/units.man units]
[key {unknown hooking}]
[manpage modules/namespacex/namespacex.man namespacex]







>
>







3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
[key undenting]
[manpage modules/textutil/adjust.man textutil::adjust]
[key unicode]
[manpage modules/stringprep/stringprep.man      stringprep]
[manpage modules/stringprep/stringprep_data.man stringprep::data]
[manpage modules/stringprep/unicode.man         unicode]
[manpage modules/stringprep/unicode_data.man    unicode::data]
[key {unified format diff}]
[manpage modules/textutil/patch.man textutil::patch]
[key union]
[manpage modules/struct/disjointset.man struct::disjointset]
[manpage modules/struct/struct_set.man  struct::set]
[key unit]
[manpage modules/units/units.man units]
[key {unknown hooking}]
[manpage modules/namespacex/namespacex.man namespacex]
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
[manpage modules/doctools/doctoc.man              doctools::toc]
[manpage modules/doctools2toc/toc_export.man      doctools::toc::export]
[manpage modules/doctools2toc/toc_export_wiki.man doctools::toc::export::wiki]
[key word]
[manpage modules/doctools2base/tcl_parse.man doctools::tcl::parse]
[manpage modules/wip/wip.man                 wip]
[key WWW]
[manpage modules/httpd/httpd.man tool]
[key www]
[manpage modules/uri/uri.man uri]
[key x.208]
[manpage modules/asn/asn.man asn]
[key x.209]
[manpage modules/asn/asn.man asn]
[key x.500]







|







3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
[manpage modules/doctools/doctoc.man              doctools::toc]
[manpage modules/doctools2toc/toc_export.man      doctools::toc::export]
[manpage modules/doctools2toc/toc_export_wiki.man doctools::toc::export::wiki]
[key word]
[manpage modules/doctools2base/tcl_parse.man doctools::tcl::parse]
[manpage modules/wip/wip.man                 wip]
[key WWW]
[manpage modules/httpd/httpd.man httpd]
[key www]
[manpage modules/uri/uri.man uri]
[key x.208]
[manpage modules/asn/asn.man asn]
[key x.209]
[manpage modules/asn/asn.man asn]
[key x.500]

Changes to support/devel/sak/doc/manpages.txt.

23
24
25
26
27
28
29

30
31
32
33
34
35
36
modules/bench/bench_lang_spec.man
modules/bench/bench_read.man
modules/bench/bench_wcsv.man
modules/bench/bench_wtext.man
modules/bibtex/bibtex.man
modules/blowfish/blowfish.man
modules/cache/async.man

modules/clock/iso8601.man
modules/clock/rfc2822.man
modules/cmdline/cmdline.man
modules/comm/comm.man
modules/comm/comm_wire.man
modules/control/control.man
modules/coroutine/coro_auto.man







>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
modules/bench/bench_lang_spec.man
modules/bench/bench_read.man
modules/bench/bench_wcsv.man
modules/bench/bench_wtext.man
modules/bibtex/bibtex.man
modules/blowfish/blowfish.man
modules/cache/async.man
modules/clay/clay.man
modules/clock/iso8601.man
modules/clock/rfc2822.man
modules/cmdline/cmdline.man
modules/comm/comm.man
modules/comm/comm_wire.man
modules/control/control.man
modules/coroutine/coro_auto.man
119
120
121
122
123
124
125

126
127
128
129
130
131
132
modules/doctools2toc/toc_msgcat_fr.man
modules/doctools2toc/toc_parse.man
modules/doctools2toc/toc_structure.man
modules/dtplite/pkg_dtplite.man
modules/fileutil/fileutil.man
modules/fileutil/multi.man
modules/fileutil/multiop.man

modules/fileutil/traverse.man
modules/ftp/ftp.man
modules/ftp/ftp_geturl.man
modules/ftpd/ftpd.man
modules/fumagic/cfront.man
modules/fumagic/cgen.man
modules/fumagic/filetypes.man







>







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
modules/doctools2toc/toc_msgcat_fr.man
modules/doctools2toc/toc_parse.man
modules/doctools2toc/toc_structure.man
modules/dtplite/pkg_dtplite.man
modules/fileutil/fileutil.man
modules/fileutil/multi.man
modules/fileutil/multiop.man
modules/fileutil/paths.man
modules/fileutil/traverse.man
modules/ftp/ftp.man
modules/ftp/ftp_geturl.man
modules/ftpd/ftpd.man
modules/fumagic/cfront.man
modules/fumagic/cgen.man
modules/fumagic/filetypes.man
194
195
196
197
198
199
200

201
202
203
204
205
206
207
modules/math/math.man
modules/math/math_geometry.man
modules/math/numtheory.man
modules/math/optimize.man
modules/math/pca.man
modules/math/polynomials.man
modules/math/qcomplex.man

modules/math/rational_funcs.man
modules/math/roman.man
modules/math/romberg.man
modules/math/special.man
modules/math/statistics.man
modules/math/symdiff.man
modules/math/trig.man







>







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
modules/math/math.man
modules/math/math_geometry.man
modules/math/numtheory.man
modules/math/optimize.man
modules/math/pca.man
modules/math/polynomials.man
modules/math/qcomplex.man
modules/math/quasirandom.man
modules/math/rational_funcs.man
modules/math/roman.man
modules/math/romberg.man
modules/math/special.man
modules/math/statistics.man
modules/math/symdiff.man
modules/math/trig.man
322
323
324
325
326
327
328

329
330
331
332
333
334
335
modules/struct/pool.man
modules/struct/prioqueue.man
modules/struct/queue.man
modules/struct/record.man
modules/struct/skiplist.man
modules/struct/stack.man
modules/struct/struct_list.man

modules/struct/struct_set.man
modules/struct/struct_tree.man
modules/struct/struct_tree1.man
modules/tar/tar.man
modules/tepam/tepam_argument_dialogbox.man
modules/tepam/tepam_doc_gen.man
modules/tepam/tepam_introduction.man







>







325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
modules/struct/pool.man
modules/struct/prioqueue.man
modules/struct/queue.man
modules/struct/record.man
modules/struct/skiplist.man
modules/struct/stack.man
modules/struct/struct_list.man
modules/struct/struct_map.man
modules/struct/struct_set.man
modules/struct/struct_tree.man
modules/struct/struct_tree1.man
modules/tar/tar.man
modules/tepam/tepam_argument_dialogbox.man
modules/tepam/tepam_doc_gen.man
modules/tepam/tepam_introduction.man
344
345
346
347
348
349
350

351
352
353
354
355
356
357
modules/term/ipager.man
modules/term/receive.man
modules/term/term.man
modules/term/term_bind.man
modules/term/term_send.man
modules/textutil/adjust.man
modules/textutil/expander.man

modules/textutil/repeat.man
modules/textutil/tabify.man
modules/textutil/textutil.man
modules/textutil/textutil_split.man
modules/textutil/textutil_string.man
modules/textutil/trim.man
modules/tie/tie.man







>







348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
modules/term/ipager.man
modules/term/receive.man
modules/term/term.man
modules/term/term_bind.man
modules/term/term_send.man
modules/textutil/adjust.man
modules/textutil/expander.man
modules/textutil/patch.man
modules/textutil/repeat.man
modules/textutil/tabify.man
modules/textutil/textutil.man
modules/textutil/textutil_split.man
modules/textutil/textutil_string.man
modules/textutil/trim.man
modules/tie/tie.man

Changes to support/devel/sak/doc/toc.txt.

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
[item modules/math/math_geometry.man           math::geometry          {Geometrical computations}]
[item modules/math/interpolate.man             math::interpolate       {Interpolation routines}]
[item modules/math/linalg.man                  math::linearalgebra     {Linear Algebra}]
[item modules/math/numtheory.man               math::numtheory         {Number Theory}]
[item modules/math/optimize.man                math::optimize          {Optimisation routines}]
[item modules/math/pca.man                     math::PCA               {Package for Principal Component Analysis}]
[item modules/math/polynomials.man             math::polynomials       {Polynomial functions}]

[item modules/math/rational_funcs.man          math::rationalfunctions {Polynomial functions}]
[item modules/math/roman.man                   math::roman             {Tools for creating and manipulating roman numerals}]
[item modules/math/special.man                 math::special           {Special mathematical functions}]
[item modules/math/statistics.man              math::statistics        {Basic statistical functions and procedures}]
[item modules/math/trig.man                    math::trig              {Trigonometric anf hyperbolic functions}]
[item modules/simulation/annealing.man         simulation::annealing   {Simulated annealing}]
[item modules/simulation/montecarlo.man        simulation::montecarlo  {Monte Carlo simulations}]
[item modules/simulation/simulation_random.man simulation::random      {Pseudo-random number generators}]
[division_end]
[division_start Networking]
[item modules/asn/asn.man               asn                {ASN.1 BER encoder/decoder}]
[item modules/http/autoproxy.man        autoproxy          {Automatic HTTP proxy usage and authentication}]
[item modules/bee/bee.man               bee                {BitTorrent Serialization Format Encoder/Decoder}]
[item modules/dns/tcllib_dns.man        dns                {Tcl Domain Name Service Client}]
[item modules/ftp/ftp.man               ftp                {Client-side tcl implementation of the ftp protocol}]
[item modules/ftp/ftp_geturl.man        ftp::geturl        {Uri handler for ftp urls}]
[item modules/ftpd/ftpd.man             ftpd               {Tcl FTP server implementation}]

[item modules/ident/ident.man           ident              {Ident protocol client}]

[item modules/irc/irc.man               irc                {Create IRC connection and interface.}]
[item modules/ldap/ldap.man             ldap               {LDAP client}]
[item modules/ldap/ldapx.man            ldapx              {LDAP extended object interface}]
[item modules/nns/nns_client.man        nameserv           {Name service facility, Client}]
[item modules/nns/nns_auto.man          nameserv::auto     {Name service facility, Client Extension}]
[item modules/nns/nns_common.man        nameserv::common   {Name service facility, shared definitions}]
[item modules/nns/nns_protocol.man      nameserv::protocol {Name service facility, client/server protocol}]







>

















>

>







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
[item modules/math/math_geometry.man           math::geometry          {Geometrical computations}]
[item modules/math/interpolate.man             math::interpolate       {Interpolation routines}]
[item modules/math/linalg.man                  math::linearalgebra     {Linear Algebra}]
[item modules/math/numtheory.man               math::numtheory         {Number Theory}]
[item modules/math/optimize.man                math::optimize          {Optimisation routines}]
[item modules/math/pca.man                     math::PCA               {Package for Principal Component Analysis}]
[item modules/math/polynomials.man             math::polynomials       {Polynomial functions}]
[item modules/math/quasirandom.man             math::quasirandom       {Quasi-random points for integration and Monte Carlo type methods}]
[item modules/math/rational_funcs.man          math::rationalfunctions {Polynomial functions}]
[item modules/math/roman.man                   math::roman             {Tools for creating and manipulating roman numerals}]
[item modules/math/special.man                 math::special           {Special mathematical functions}]
[item modules/math/statistics.man              math::statistics        {Basic statistical functions and procedures}]
[item modules/math/trig.man                    math::trig              {Trigonometric anf hyperbolic functions}]
[item modules/simulation/annealing.man         simulation::annealing   {Simulated annealing}]
[item modules/simulation/montecarlo.man        simulation::montecarlo  {Monte Carlo simulations}]
[item modules/simulation/simulation_random.man simulation::random      {Pseudo-random number generators}]
[division_end]
[division_start Networking]
[item modules/asn/asn.man               asn                {ASN.1 BER encoder/decoder}]
[item modules/http/autoproxy.man        autoproxy          {Automatic HTTP proxy usage and authentication}]
[item modules/bee/bee.man               bee                {BitTorrent Serialization Format Encoder/Decoder}]
[item modules/dns/tcllib_dns.man        dns                {Tcl Domain Name Service Client}]
[item modules/ftp/ftp.man               ftp                {Client-side tcl implementation of the ftp protocol}]
[item modules/ftp/ftp_geturl.man        ftp::geturl        {Uri handler for ftp urls}]
[item modules/ftpd/ftpd.man             ftpd               {Tcl FTP server implementation}]
[item modules/httpd/httpd.man           httpd              {A TclOO and coroutine based web server}]
[item modules/ident/ident.man           ident              {Ident protocol client}]
[item modules/imap4/imap4.man           imap4              {imap client-side tcl implementation of imap protocol}]
[item modules/irc/irc.man               irc                {Create IRC connection and interface.}]
[item modules/ldap/ldap.man             ldap               {LDAP client}]
[item modules/ldap/ldapx.man            ldapx              {LDAP extended object interface}]
[item modules/nns/nns_client.man        nameserv           {Name service facility, Client}]
[item modules/nns/nns_auto.man          nameserv::auto     {Name service facility, Client Extension}]
[item modules/nns/nns_common.man        nameserv::common   {Name service facility, shared definitions}]
[item modules/nns/nns_protocol.man      nameserv::protocol {Name service facility, client/server protocol}]
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
[item modules/sasl/sasl.man             SASL               {Implementation of SASL mechanisms for Tcl}]
[item modules/sasl/ntlm.man             SASL::NTLM         {Implementation of SASL NTLM mechanism for Tcl}]
[item modules/sasl/scram.man            SASL::SCRAM        {Implementation of SASL SCRAM mechanism for Tcl}]
[item modules/sasl/gtoken.man           SASL::XGoogleToken {Implementation of SASL NTLM mechanism for Tcl}]
[item modules/mime/smtp.man             smtp               {Client-side tcl implementation of the smtp protocol}]
[item modules/smtpd/smtpd.man           smtpd              {Tcl SMTP server implementation}]
[item modules/dns/tcllib_ip.man         tcllib_ip          {IPv4 and IPv6 address manipulation}]
[item modules/httpd/httpd.man           tool               {A TclOO and coroutine based web server}]
[item modules/udpcluster/udpcluster.man udpcluster         {UDP Peer-to-Peer cluster}]
[item modules/uri/uri.man               uri                {URI utilities}]
[item modules/uri/urn-scheme.man        uri_urn            {URI utilities, URN scheme}]
[item modules/websocket/websocket.man   websocket          {Tcl implementation of the websocket protocol}]
[division_end]
[division_start {Page Parser Generator}]
[item apps/page.man                         page                 {Parser Generator}]







<







257
258
259
260
261
262
263

264
265
266
267
268
269
270
[item modules/sasl/sasl.man             SASL               {Implementation of SASL mechanisms for Tcl}]
[item modules/sasl/ntlm.man             SASL::NTLM         {Implementation of SASL NTLM mechanism for Tcl}]
[item modules/sasl/scram.man            SASL::SCRAM        {Implementation of SASL SCRAM mechanism for Tcl}]
[item modules/sasl/gtoken.man           SASL::XGoogleToken {Implementation of SASL NTLM mechanism for Tcl}]
[item modules/mime/smtp.man             smtp               {Client-side tcl implementation of the smtp protocol}]
[item modules/smtpd/smtpd.man           smtpd              {Tcl SMTP server implementation}]
[item modules/dns/tcllib_ip.man         tcllib_ip          {IPv4 and IPv6 address manipulation}]

[item modules/udpcluster/udpcluster.man udpcluster         {UDP Peer-to-Peer cluster}]
[item modules/uri/uri.man               uri                {URI utilities}]
[item modules/uri/urn-scheme.man        uri_urn            {URI utilities, URN scheme}]
[item modules/websocket/websocket.man   websocket          {Tcl implementation of the websocket protocol}]
[division_end]
[division_start {Page Parser Generator}]
[item apps/page.man                         page                 {Parser Generator}]
320
321
322
323
324
325
326

327
328
329
330
331
332
333
[item modules/pt/pt_peg_op.man                pt_peg_op                          {Parser Tools PE Grammar Utility Operations}]
[division_end]
[division_start {Procedures, arguments, parameters, options}]
[item modules/tepam/tepam_introduction.man tepam            {An introduction into TEPAM, Tcl's Enhanced Procedure and Argument Manager}]
[item modules/tepam/tepam_procedure.man    tepam::procedure {TEPAM procedure, reference manual}]
[division_end]
[division_start {Programming tools}]

[item modules/cmdline/cmdline.man         cmdline                   {Procedures to process command lines and options.}]
[item modules/comm/comm.man               comm                      {A remote communication facility for Tcl (8.3 and later)}]
[item modules/comm/comm_wire.man          comm_wire                 {The comm wire protocol}]
[item modules/control/control.man         control                   {Procedures for control flow structures.}]
[item modules/interp/deleg_method.man     deleg_method              {Creation of comm delegates (snit methods)}]
[item modules/interp/deleg_proc.man       deleg_proc                {Creation of comm delegates (procedures)}]
[item modules/fileutil/fileutil.man       fileutil                  {Procedures implementing some file utilities}]







>







322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
[item modules/pt/pt_peg_op.man                pt_peg_op                          {Parser Tools PE Grammar Utility Operations}]
[division_end]
[division_start {Procedures, arguments, parameters, options}]
[item modules/tepam/tepam_introduction.man tepam            {An introduction into TEPAM, Tcl's Enhanced Procedure and Argument Manager}]
[item modules/tepam/tepam_procedure.man    tepam::procedure {TEPAM procedure, reference manual}]
[division_end]
[division_start {Programming tools}]
[item modules/clay/clay.man               clay                      {A minimalist framework for large scale OO Projects}]
[item modules/cmdline/cmdline.man         cmdline                   {Procedures to process command lines and options.}]
[item modules/comm/comm.man               comm                      {A remote communication facility for Tcl (8.3 and later)}]
[item modules/comm/comm_wire.man          comm_wire                 {The comm wire protocol}]
[item modules/control/control.man         control                   {Procedures for control flow structures.}]
[item modules/interp/deleg_method.man     deleg_method              {Creation of comm delegates (snit methods)}]
[item modules/interp/deleg_proc.man       deleg_proc                {Creation of comm delegates (procedures)}]
[item modules/fileutil/fileutil.man       fileutil                  {Procedures implementing some file utilities}]
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
[item modules/markdown/markdown.man        markdown             {Converts Markdown text to HTML}]
[item modules/mime/mime.man                mime                 {Manipulation of MIME body parts}]
[item modules/rcs/rcs.man                  rcs                  {RCS low level utilities}]
[item modules/string/token.man             string::token        {Regex based iterative lexing}]
[item modules/string/token_shell.man       string::token::shell {Parsing of shell command line}]
[item modules/textutil/textutil.man        textutil             {Procedures to manipulate texts and strings.}]
[item modules/textutil/adjust.man          textutil::adjust     {Procedures to adjust, indent, and undent paragraphs}]

[item modules/textutil/repeat.man          textutil::repeat     {Procedures to repeat strings.}]
[item modules/textutil/textutil_split.man  textutil::split      {Procedures to split texts}]
[item modules/textutil/textutil_string.man textutil::string     {Procedures to manipulate texts and strings.}]
[item modules/textutil/tabify.man          textutil::tabify     {Procedures to (un)tabify strings}]
[item modules/textutil/trim.man            textutil::trim       {Procedures to trim strings}]
[item modules/base64/uuencode.man          uuencode             {UU-encode/decode binary data}]
[item modules/amazon-s3/xsxp.man           xsxp                 {eXtremely Simple Xml Parser}]
[item modules/base64/yencode.man           yencode              {Y-encode/decode binary data}]
[division_end]
[division_start {Transfer module}]
[item modules/transfer/connect.man     transfer::connect           {Connection setup}]
[item modules/transfer/copyops.man     transfer::copy              {Data transfer foundation}]
[item modules/transfer/tqueue.man      transfer::copy::queue       {Queued transfers}]
[item modules/transfer/ddest.man       transfer::data::destination {Data destination}]
[item modules/transfer/dsource.man     transfer::data::source      {Data source}]
[item modules/transfer/receiver.man    transfer::receiver          {Data source}]
[item modules/transfer/transmitter.man transfer::transmitter       {Data source}]
[division_end]
[division_start Unfiled]
[item modules/cache/async.man                cache::async             {Asynchronous in-memory cache}]

[item modules/generator/generator.man        generator                {Procedures for creating and using generators.}]
[item modules/yaml/huddle.man                huddle                   {Create and manipulate huddle object}]
[item modules/imap4/imap4.man                imap4                    {imap client-side tcl implementation of imap protocol}]
[item modules/map/map_geocode_nominatim.man  map::geocode::nominatim  {Resolving geographical names with a Nominatim service}]
[item modules/map/map_slippy.man             map::slippy              {Common code for slippy based map packages}]
[item modules/map/map_slippy_cache.man       map::slippy::cache       {Management of a tile cache in the local filesystem}]
[item modules/map/map_slippy_fetcher.man     map::slippy::fetcher     {Accessing a server providing tiles for slippy-based maps}]
[item modules/mapproj/mapproj.man            mapproj                  {Map projection routines}]
[item modules/math/symdiff.man               math::calculus::symdiff  {Symbolic differentiation for Tcl}]
[item modules/namespacex/namespacex.man      namespacex               {Namespace utility commands}]
[item modules/rest/rest.man                  rest                     {define REST web APIs and call them inline or asychronously}]
[item modules/stringprep/stringprep.man      stringprep               {Implementation of stringprep}]
[item modules/stringprep/stringprep_data.man stringprep::data         {stringprep data tables, generated, internal}]

[item modules/math/machineparameters.man     tclrep/machineparameters {Compute double precision machine parameters.}]
[item modules/uev/uevent_onidle.man          uevent::onidle           {Request merging and deferal to idle time}]
[item modules/stringprep/unicode.man         unicode                  {Implementation of Unicode normalization}]
[item modules/stringprep/unicode_data.man    unicode::data            {unicode data tables, generated, internal}]
[item modules/units/units.man                units                    {unit conversion}]
[item modules/yaml/yaml.man                  yaml                     {YAML Format Encoder/Decoder}]
[division_end]







>




















>


<










>







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
[item modules/markdown/markdown.man        markdown             {Converts Markdown text to HTML}]
[item modules/mime/mime.man                mime                 {Manipulation of MIME body parts}]
[item modules/rcs/rcs.man                  rcs                  {RCS low level utilities}]
[item modules/string/token.man             string::token        {Regex based iterative lexing}]
[item modules/string/token_shell.man       string::token::shell {Parsing of shell command line}]
[item modules/textutil/textutil.man        textutil             {Procedures to manipulate texts and strings.}]
[item modules/textutil/adjust.man          textutil::adjust     {Procedures to adjust, indent, and undent paragraphs}]
[item modules/textutil/patch.man           textutil::patch      {Application of uni-diff patches to directory trees}]
[item modules/textutil/repeat.man          textutil::repeat     {Procedures to repeat strings.}]
[item modules/textutil/textutil_split.man  textutil::split      {Procedures to split texts}]
[item modules/textutil/textutil_string.man textutil::string     {Procedures to manipulate texts and strings.}]
[item modules/textutil/tabify.man          textutil::tabify     {Procedures to (un)tabify strings}]
[item modules/textutil/trim.man            textutil::trim       {Procedures to trim strings}]
[item modules/base64/uuencode.man          uuencode             {UU-encode/decode binary data}]
[item modules/amazon-s3/xsxp.man           xsxp                 {eXtremely Simple Xml Parser}]
[item modules/base64/yencode.man           yencode              {Y-encode/decode binary data}]
[division_end]
[division_start {Transfer module}]
[item modules/transfer/connect.man     transfer::connect           {Connection setup}]
[item modules/transfer/copyops.man     transfer::copy              {Data transfer foundation}]
[item modules/transfer/tqueue.man      transfer::copy::queue       {Queued transfers}]
[item modules/transfer/ddest.man       transfer::data::destination {Data destination}]
[item modules/transfer/dsource.man     transfer::data::source      {Data source}]
[item modules/transfer/receiver.man    transfer::receiver          {Data source}]
[item modules/transfer/transmitter.man transfer::transmitter       {Data source}]
[division_end]
[division_start Unfiled]
[item modules/cache/async.man                cache::async             {Asynchronous in-memory cache}]
[item modules/fileutil/paths.man             fileutil::paths          {Manage search path pools}]
[item modules/generator/generator.man        generator                {Procedures for creating and using generators.}]
[item modules/yaml/huddle.man                huddle                   {Create and manipulate huddle object}]

[item modules/map/map_geocode_nominatim.man  map::geocode::nominatim  {Resolving geographical names with a Nominatim service}]
[item modules/map/map_slippy.man             map::slippy              {Common code for slippy based map packages}]
[item modules/map/map_slippy_cache.man       map::slippy::cache       {Management of a tile cache in the local filesystem}]
[item modules/map/map_slippy_fetcher.man     map::slippy::fetcher     {Accessing a server providing tiles for slippy-based maps}]
[item modules/mapproj/mapproj.man            mapproj                  {Map projection routines}]
[item modules/math/symdiff.man               math::calculus::symdiff  {Symbolic differentiation for Tcl}]
[item modules/namespacex/namespacex.man      namespacex               {Namespace utility commands}]
[item modules/rest/rest.man                  rest                     {define REST web APIs and call them inline or asychronously}]
[item modules/stringprep/stringprep.man      stringprep               {Implementation of stringprep}]
[item modules/stringprep/stringprep_data.man stringprep::data         {stringprep data tables, generated, internal}]
[item modules/struct/struct_map.man          struct::map              {Manage key/value maps}]
[item modules/math/machineparameters.man     tclrep/machineparameters {Compute double precision machine parameters.}]
[item modules/uev/uevent_onidle.man          uevent::onidle           {Request merging and deferal to idle time}]
[item modules/stringprep/unicode.man         unicode                  {Implementation of Unicode normalization}]
[item modules/stringprep/unicode_data.man    unicode::data            {unicode data tables, generated, internal}]
[item modules/units/units.man                units                    {unit conversion}]
[item modules/yaml/yaml.man                  yaml                     {YAML Format Encoder/Decoder}]
[division_end]
535
536
537
538
539
540
541



542
543
544
545
546
547
548
[division_end]
[division_start blowfish]
[item modules/blowfish/blowfish.man blowfish {Implementation of the Blowfish block cipher}]
[division_end]
[division_start cache]
[item modules/cache/async.man cache::async {Asynchronous in-memory cache}]
[division_end]



[division_start clock]
[item modules/clock/iso8601.man clock_iso8601 {Parsing ISO 8601 dates/times}]
[item modules/clock/rfc2822.man clock_rfc2822 {Parsing ISO 8601 dates/times}]
[division_end]
[division_start cmdline]
[item modules/cmdline/cmdline.man cmdline {Procedures to process command lines and options.}]
[division_end]







>
>
>







540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
[division_end]
[division_start blowfish]
[item modules/blowfish/blowfish.man blowfish {Implementation of the Blowfish block cipher}]
[division_end]
[division_start cache]
[item modules/cache/async.man cache::async {Asynchronous in-memory cache}]
[division_end]
[division_start clay]
[item modules/clay/clay.man clay {A minimalist framework for large scale OO Projects}]
[division_end]
[division_start clock]
[item modules/clock/iso8601.man clock_iso8601 {Parsing ISO 8601 dates/times}]
[item modules/clock/rfc2822.man clock_rfc2822 {Parsing ISO 8601 dates/times}]
[division_end]
[division_start cmdline]
[item modules/cmdline/cmdline.man cmdline {Procedures to process command lines and options.}]
[division_end]
672
673
674
675
676
677
678

679
680
681
682
683
684
685
[division_start dtplite]
[item modules/dtplite/pkg_dtplite.man dtplite {Lightweight DocTools Markup Processor}]
[division_end]
[division_start fileutil]
[item modules/fileutil/fileutil.man fileutil            {Procedures implementing some file utilities}]
[item modules/fileutil/multi.man    fileutil::multi     {Multi-file operation, scatter/gather, standard object}]
[item modules/fileutil/multiop.man  fileutil::multi::op {Multi-file operation, scatter/gather}]

[item modules/fileutil/traverse.man fileutil_traverse   {Iterative directory traversal}]
[division_end]
[division_start ftp]
[item modules/ftp/ftp.man        ftp         {Client-side tcl implementation of the ftp protocol}]
[item modules/ftp/ftp_geturl.man ftp::geturl {Uri handler for ftp urls}]
[division_end]
[division_start ftpd]







>







680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
[division_start dtplite]
[item modules/dtplite/pkg_dtplite.man dtplite {Lightweight DocTools Markup Processor}]
[division_end]
[division_start fileutil]
[item modules/fileutil/fileutil.man fileutil            {Procedures implementing some file utilities}]
[item modules/fileutil/multi.man    fileutil::multi     {Multi-file operation, scatter/gather, standard object}]
[item modules/fileutil/multiop.man  fileutil::multi::op {Multi-file operation, scatter/gather}]
[item modules/fileutil/paths.man    fileutil::paths     {Manage search path pools}]
[item modules/fileutil/traverse.man fileutil_traverse   {Iterative directory traversal}]
[division_end]
[division_start ftp]
[item modules/ftp/ftp.man        ftp         {Client-side tcl implementation of the ftp protocol}]
[item modules/ftp/ftp_geturl.man ftp::geturl {Uri handler for ftp urls}]
[division_end]
[division_start ftpd]
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
[division_start htmlparse]
[item modules/htmlparse/htmlparse.man htmlparse {Procedures to parse HTML strings}]
[division_end]
[division_start http]
[item modules/http/autoproxy.man autoproxy {Automatic HTTP proxy usage and authentication}]
[division_end]
[division_start httpd]
[item modules/httpd/httpd.man tool {A TclOO and coroutine based web server}]
[division_end]
[division_start ident]
[item modules/ident/ident.man ident {Ident protocol client}]
[division_end]
[division_start imap4]
[item modules/imap4/imap4.man imap4 {imap client-side tcl implementation of imap protocol}]
[division_end]







|







738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
[division_start htmlparse]
[item modules/htmlparse/htmlparse.man htmlparse {Procedures to parse HTML strings}]
[division_end]
[division_start http]
[item modules/http/autoproxy.man autoproxy {Automatic HTTP proxy usage and authentication}]
[division_end]
[division_start httpd]
[item modules/httpd/httpd.man httpd {A TclOO and coroutine based web server}]
[division_end]
[division_start ident]
[item modules/ident/ident.man ident {Ident protocol client}]
[division_end]
[division_start imap4]
[item modules/imap4/imap4.man imap4 {imap client-side tcl implementation of imap protocol}]
[division_end]
808
809
810
811
812
813
814

815
816
817
818
819
820
821
[item modules/math/math_geometry.man     math::geometry           {Geometrical computations}]
[item modules/math/interpolate.man       math::interpolate        {Interpolation routines}]
[item modules/math/linalg.man            math::linearalgebra      {Linear Algebra}]
[item modules/math/numtheory.man         math::numtheory          {Number Theory}]
[item modules/math/optimize.man          math::optimize           {Optimisation routines}]
[item modules/math/pca.man               math::PCA                {Package for Principal Component Analysis}]
[item modules/math/polynomials.man       math::polynomials        {Polynomial functions}]

[item modules/math/rational_funcs.man    math::rationalfunctions  {Polynomial functions}]
[item modules/math/roman.man             math::roman              {Tools for creating and manipulating roman numerals}]
[item modules/math/special.man           math::special            {Special mathematical functions}]
[item modules/math/statistics.man        math::statistics         {Basic statistical functions and procedures}]
[item modules/math/trig.man              math::trig               {Trigonometric anf hyperbolic functions}]
[item modules/math/machineparameters.man tclrep/machineparameters {Compute double precision machine parameters.}]
[division_end]







>







817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
[item modules/math/math_geometry.man     math::geometry           {Geometrical computations}]
[item modules/math/interpolate.man       math::interpolate        {Interpolation routines}]
[item modules/math/linalg.man            math::linearalgebra      {Linear Algebra}]
[item modules/math/numtheory.man         math::numtheory          {Number Theory}]
[item modules/math/optimize.man          math::optimize           {Optimisation routines}]
[item modules/math/pca.man               math::PCA                {Package for Principal Component Analysis}]
[item modules/math/polynomials.man       math::polynomials        {Polynomial functions}]
[item modules/math/quasirandom.man       math::quasirandom        {Quasi-random points for integration and Monte Carlo type methods}]
[item modules/math/rational_funcs.man    math::rationalfunctions  {Polynomial functions}]
[item modules/math/roman.man             math::roman              {Tools for creating and manipulating roman numerals}]
[item modules/math/special.man           math::special            {Special mathematical functions}]
[item modules/math/statistics.man        math::statistics         {Basic statistical functions and procedures}]
[item modules/math/trig.man              math::trig               {Trigonometric anf hyperbolic functions}]
[item modules/math/machineparameters.man tclrep/machineparameters {Compute double precision machine parameters.}]
[division_end]
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
[division_end]
[division_start struct]
[item modules/struct/disjointset.man  struct::disjointset {Disjoint set data structure}]
[item modules/struct/graph.man        struct::graph       {Create and manipulate directed graph objects}]
[item modules/struct/graphops.man     struct::graph::op   {Operation for (un)directed graph objects}]
[item modules/struct/graph1.man       struct::graph_v1    {Create and manipulate directed graph objects}]
[item modules/struct/struct_list.man  struct::list        {Procedures for manipulating lists}]

[item modules/struct/matrix.man       struct::matrix      {Create and manipulate matrix objects}]
[item modules/struct/matrix1.man      struct::matrix_v1   {Create and manipulate matrix objects}]
[item modules/struct/pool.man         struct::pool        {Create and manipulate pool objects (of discrete items)}]
[item modules/struct/prioqueue.man    struct::prioqueue   {Create and manipulate prioqueue objects}]
[item modules/struct/queue.man        struct::queue       {Create and manipulate queue objects}]
[item modules/struct/record.man       struct::record      {Define and create records (similar to 'C' structures)}]
[item modules/struct/struct_set.man   struct::set         {Procedures for manipulating sets}]







>







1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
[division_end]
[division_start struct]
[item modules/struct/disjointset.man  struct::disjointset {Disjoint set data structure}]
[item modules/struct/graph.man        struct::graph       {Create and manipulate directed graph objects}]
[item modules/struct/graphops.man     struct::graph::op   {Operation for (un)directed graph objects}]
[item modules/struct/graph1.man       struct::graph_v1    {Create and manipulate directed graph objects}]
[item modules/struct/struct_list.man  struct::list        {Procedures for manipulating lists}]
[item modules/struct/struct_map.man   struct::map         {Manage key/value maps}]
[item modules/struct/matrix.man       struct::matrix      {Create and manipulate matrix objects}]
[item modules/struct/matrix1.man      struct::matrix_v1   {Create and manipulate matrix objects}]
[item modules/struct/pool.man         struct::pool        {Create and manipulate pool objects (of discrete items)}]
[item modules/struct/prioqueue.man    struct::prioqueue   {Create and manipulate prioqueue objects}]
[item modules/struct/queue.man        struct::queue       {Create and manipulate queue objects}]
[item modules/struct/record.man       struct::record      {Define and create records (similar to 'C' structures)}]
[item modules/struct/struct_set.man   struct::set         {Procedures for manipulating sets}]
1048
1049
1050
1051
1052
1053
1054

1055
1056
1057
1058
1059
1060
1061
[item modules/term/term_bind.man    term::receive::bind      {Keyboard dispatch from terminals}]
[item modules/term/term_send.man    term::send               {General output to terminals}]
[division_end]
[division_start textutil]
[item modules/textutil/textutil.man        textutil           {Procedures to manipulate texts and strings.}]
[item modules/textutil/adjust.man          textutil::adjust   {Procedures to adjust, indent, and undent paragraphs}]
[item modules/textutil/expander.man        textutil::expander {Procedures to process templates and expand text.}]

[item modules/textutil/repeat.man          textutil::repeat   {Procedures to repeat strings.}]
[item modules/textutil/textutil_split.man  textutil::split    {Procedures to split texts}]
[item modules/textutil/textutil_string.man textutil::string   {Procedures to manipulate texts and strings.}]
[item modules/textutil/tabify.man          textutil::tabify   {Procedures to (un)tabify strings}]
[item modules/textutil/trim.man            textutil::trim     {Procedures to trim strings}]
[division_end]
[division_start tie]







>







1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
[item modules/term/term_bind.man    term::receive::bind      {Keyboard dispatch from terminals}]
[item modules/term/term_send.man    term::send               {General output to terminals}]
[division_end]
[division_start textutil]
[item modules/textutil/textutil.man        textutil           {Procedures to manipulate texts and strings.}]
[item modules/textutil/adjust.man          textutil::adjust   {Procedures to adjust, indent, and undent paragraphs}]
[item modules/textutil/expander.man        textutil::expander {Procedures to process templates and expand text.}]
[item modules/textutil/patch.man           textutil::patch    {Application of uni-diff patches to directory trees}]
[item modules/textutil/repeat.man          textutil::repeat   {Procedures to repeat strings.}]
[item modules/textutil/textutil_split.man  textutil::split    {Procedures to split texts}]
[item modules/textutil/textutil_string.man textutil::string   {Procedures to manipulate texts and strings.}]
[item modules/textutil/tabify.man          textutil::tabify   {Procedures to (un)tabify strings}]
[item modules/textutil/trim.man            textutil::trim     {Procedures to trim strings}]
[division_end]
[division_start tie]

Changes to support/devel/sak/doc/toc_cats.txt.

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
[item modules/math/math_geometry.man           math::geometry          {Geometrical computations}]
[item modules/math/interpolate.man             math::interpolate       {Interpolation routines}]
[item modules/math/linalg.man                  math::linearalgebra     {Linear Algebra}]
[item modules/math/numtheory.man               math::numtheory         {Number Theory}]
[item modules/math/optimize.man                math::optimize          {Optimisation routines}]
[item modules/math/pca.man                     math::PCA               {Package for Principal Component Analysis}]
[item modules/math/polynomials.man             math::polynomials       {Polynomial functions}]

[item modules/math/rational_funcs.man          math::rationalfunctions {Polynomial functions}]
[item modules/math/roman.man                   math::roman             {Tools for creating and manipulating roman numerals}]
[item modules/math/special.man                 math::special           {Special mathematical functions}]
[item modules/math/statistics.man              math::statistics        {Basic statistical functions and procedures}]
[item modules/math/trig.man                    math::trig              {Trigonometric anf hyperbolic functions}]
[item modules/simulation/annealing.man         simulation::annealing   {Simulated annealing}]
[item modules/simulation/montecarlo.man        simulation::montecarlo  {Monte Carlo simulations}]
[item modules/simulation/simulation_random.man simulation::random      {Pseudo-random number generators}]
[division_end]
[division_start Networking]
[item modules/asn/asn.man               asn                {ASN.1 BER encoder/decoder}]
[item modules/http/autoproxy.man        autoproxy          {Automatic HTTP proxy usage and authentication}]
[item modules/bee/bee.man               bee                {BitTorrent Serialization Format Encoder/Decoder}]
[item modules/dns/tcllib_dns.man        dns                {Tcl Domain Name Service Client}]
[item modules/ftp/ftp.man               ftp                {Client-side tcl implementation of the ftp protocol}]
[item modules/ftp/ftp_geturl.man        ftp::geturl        {Uri handler for ftp urls}]
[item modules/ftpd/ftpd.man             ftpd               {Tcl FTP server implementation}]

[item modules/ident/ident.man           ident              {Ident protocol client}]

[item modules/irc/irc.man               irc                {Create IRC connection and interface.}]
[item modules/ldap/ldap.man             ldap               {LDAP client}]
[item modules/ldap/ldapx.man            ldapx              {LDAP extended object interface}]
[item modules/nns/nns_client.man        nameserv           {Name service facility, Client}]
[item modules/nns/nns_auto.man          nameserv::auto     {Name service facility, Client Extension}]
[item modules/nns/nns_common.man        nameserv::common   {Name service facility, shared definitions}]
[item modules/nns/nns_protocol.man      nameserv::protocol {Name service facility, client/server protocol}]







>

















>

>







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
[item modules/math/math_geometry.man           math::geometry          {Geometrical computations}]
[item modules/math/interpolate.man             math::interpolate       {Interpolation routines}]
[item modules/math/linalg.man                  math::linearalgebra     {Linear Algebra}]
[item modules/math/numtheory.man               math::numtheory         {Number Theory}]
[item modules/math/optimize.man                math::optimize          {Optimisation routines}]
[item modules/math/pca.man                     math::PCA               {Package for Principal Component Analysis}]
[item modules/math/polynomials.man             math::polynomials       {Polynomial functions}]
[item modules/math/quasirandom.man             math::quasirandom       {Quasi-random points for integration and Monte Carlo type methods}]
[item modules/math/rational_funcs.man          math::rationalfunctions {Polynomial functions}]
[item modules/math/roman.man                   math::roman             {Tools for creating and manipulating roman numerals}]
[item modules/math/special.man                 math::special           {Special mathematical functions}]
[item modules/math/statistics.man              math::statistics        {Basic statistical functions and procedures}]
[item modules/math/trig.man                    math::trig              {Trigonometric anf hyperbolic functions}]
[item modules/simulation/annealing.man         simulation::annealing   {Simulated annealing}]
[item modules/simulation/montecarlo.man        simulation::montecarlo  {Monte Carlo simulations}]
[item modules/simulation/simulation_random.man simulation::random      {Pseudo-random number generators}]
[division_end]
[division_start Networking]
[item modules/asn/asn.man               asn                {ASN.1 BER encoder/decoder}]
[item modules/http/autoproxy.man        autoproxy          {Automatic HTTP proxy usage and authentication}]
[item modules/bee/bee.man               bee                {BitTorrent Serialization Format Encoder/Decoder}]
[item modules/dns/tcllib_dns.man        dns                {Tcl Domain Name Service Client}]
[item modules/ftp/ftp.man               ftp                {Client-side tcl implementation of the ftp protocol}]
[item modules/ftp/ftp_geturl.man        ftp::geturl        {Uri handler for ftp urls}]
[item modules/ftpd/ftpd.man             ftpd               {Tcl FTP server implementation}]
[item modules/httpd/httpd.man           httpd              {A TclOO and coroutine based web server}]
[item modules/ident/ident.man           ident              {Ident protocol client}]
[item modules/imap4/imap4.man           imap4              {imap client-side tcl implementation of imap protocol}]
[item modules/irc/irc.man               irc                {Create IRC connection and interface.}]
[item modules/ldap/ldap.man             ldap               {LDAP client}]
[item modules/ldap/ldapx.man            ldapx              {LDAP extended object interface}]
[item modules/nns/nns_client.man        nameserv           {Name service facility, Client}]
[item modules/nns/nns_auto.man          nameserv::auto     {Name service facility, Client Extension}]
[item modules/nns/nns_common.man        nameserv::common   {Name service facility, shared definitions}]
[item modules/nns/nns_protocol.man      nameserv::protocol {Name service facility, client/server protocol}]
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
[item modules/sasl/sasl.man             SASL               {Implementation of SASL mechanisms for Tcl}]
[item modules/sasl/ntlm.man             SASL::NTLM         {Implementation of SASL NTLM mechanism for Tcl}]
[item modules/sasl/scram.man            SASL::SCRAM        {Implementation of SASL SCRAM mechanism for Tcl}]
[item modules/sasl/gtoken.man           SASL::XGoogleToken {Implementation of SASL NTLM mechanism for Tcl}]
[item modules/mime/smtp.man             smtp               {Client-side tcl implementation of the smtp protocol}]
[item modules/smtpd/smtpd.man           smtpd              {Tcl SMTP server implementation}]
[item modules/dns/tcllib_ip.man         tcllib_ip          {IPv4 and IPv6 address manipulation}]
[item modules/httpd/httpd.man           tool               {A TclOO and coroutine based web server}]
[item modules/udpcluster/udpcluster.man udpcluster         {UDP Peer-to-Peer cluster}]
[item modules/uri/uri.man               uri                {URI utilities}]
[item modules/uri/urn-scheme.man        uri_urn            {URI utilities, URN scheme}]
[item modules/websocket/websocket.man   websocket          {Tcl implementation of the websocket protocol}]
[division_end]
[division_start {Page Parser Generator}]
[item apps/page.man                         page                 {Parser Generator}]







<







257
258
259
260
261
262
263

264
265
266
267
268
269
270
[item modules/sasl/sasl.man             SASL               {Implementation of SASL mechanisms for Tcl}]
[item modules/sasl/ntlm.man             SASL::NTLM         {Implementation of SASL NTLM mechanism for Tcl}]
[item modules/sasl/scram.man            SASL::SCRAM        {Implementation of SASL SCRAM mechanism for Tcl}]
[item modules/sasl/gtoken.man           SASL::XGoogleToken {Implementation of SASL NTLM mechanism for Tcl}]
[item modules/mime/smtp.man             smtp               {Client-side tcl implementation of the smtp protocol}]
[item modules/smtpd/smtpd.man           smtpd              {Tcl SMTP server implementation}]
[item modules/dns/tcllib_ip.man         tcllib_ip          {IPv4 and IPv6 address manipulation}]

[item modules/udpcluster/udpcluster.man udpcluster         {UDP Peer-to-Peer cluster}]
[item modules/uri/uri.man               uri                {URI utilities}]
[item modules/uri/urn-scheme.man        uri_urn            {URI utilities, URN scheme}]
[item modules/websocket/websocket.man   websocket          {Tcl implementation of the websocket protocol}]
[division_end]
[division_start {Page Parser Generator}]
[item apps/page.man                         page                 {Parser Generator}]
320
321
322
323
324
325
326

327
328
329
330
331
332
333
[item modules/pt/pt_peg_op.man                pt_peg_op                          {Parser Tools PE Grammar Utility Operations}]
[division_end]
[division_start {Procedures, arguments, parameters, options}]
[item modules/tepam/tepam_introduction.man tepam            {An introduction into TEPAM, Tcl's Enhanced Procedure and Argument Manager}]
[item modules/tepam/tepam_procedure.man    tepam::procedure {TEPAM procedure, reference manual}]
[division_end]
[division_start {Programming tools}]

[item modules/cmdline/cmdline.man         cmdline                   {Procedures to process command lines and options.}]
[item modules/comm/comm.man               comm                      {A remote communication facility for Tcl (8.3 and later)}]
[item modules/comm/comm_wire.man          comm_wire                 {The comm wire protocol}]
[item modules/control/control.man         control                   {Procedures for control flow structures.}]
[item modules/interp/deleg_method.man     deleg_method              {Creation of comm delegates (snit methods)}]
[item modules/interp/deleg_proc.man       deleg_proc                {Creation of comm delegates (procedures)}]
[item modules/fileutil/fileutil.man       fileutil                  {Procedures implementing some file utilities}]







>







322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
[item modules/pt/pt_peg_op.man                pt_peg_op                          {Parser Tools PE Grammar Utility Operations}]
[division_end]
[division_start {Procedures, arguments, parameters, options}]
[item modules/tepam/tepam_introduction.man tepam            {An introduction into TEPAM, Tcl's Enhanced Procedure and Argument Manager}]
[item modules/tepam/tepam_procedure.man    tepam::procedure {TEPAM procedure, reference manual}]
[division_end]
[division_start {Programming tools}]
[item modules/clay/clay.man               clay                      {A minimalist framework for large scale OO Projects}]
[item modules/cmdline/cmdline.man         cmdline                   {Procedures to process command lines and options.}]
[item modules/comm/comm.man               comm                      {A remote communication facility for Tcl (8.3 and later)}]
[item modules/comm/comm_wire.man          comm_wire                 {The comm wire protocol}]
[item modules/control/control.man         control                   {Procedures for control flow structures.}]
[item modules/interp/deleg_method.man     deleg_method              {Creation of comm delegates (snit methods)}]
[item modules/interp/deleg_proc.man       deleg_proc                {Creation of comm delegates (procedures)}]
[item modules/fileutil/fileutil.man       fileutil                  {Procedures implementing some file utilities}]
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
[item modules/markdown/markdown.man        markdown             {Converts Markdown text to HTML}]
[item modules/mime/mime.man                mime                 {Manipulation of MIME body parts}]
[item modules/rcs/rcs.man                  rcs                  {RCS low level utilities}]
[item modules/string/token.man             string::token        {Regex based iterative lexing}]
[item modules/string/token_shell.man       string::token::shell {Parsing of shell command line}]
[item modules/textutil/textutil.man        textutil             {Procedures to manipulate texts and strings.}]
[item modules/textutil/adjust.man          textutil::adjust     {Procedures to adjust, indent, and undent paragraphs}]

[item modules/textutil/repeat.man          textutil::repeat     {Procedures to repeat strings.}]
[item modules/textutil/textutil_split.man  textutil::split      {Procedures to split texts}]
[item modules/textutil/textutil_string.man textutil::string     {Procedures to manipulate texts and strings.}]
[item modules/textutil/tabify.man          textutil::tabify     {Procedures to (un)tabify strings}]
[item modules/textutil/trim.man            textutil::trim       {Procedures to trim strings}]
[item modules/base64/uuencode.man          uuencode             {UU-encode/decode binary data}]
[item modules/amazon-s3/xsxp.man           xsxp                 {eXtremely Simple Xml Parser}]
[item modules/base64/yencode.man           yencode              {Y-encode/decode binary data}]
[division_end]
[division_start {Transfer module}]
[item modules/transfer/connect.man     transfer::connect           {Connection setup}]
[item modules/transfer/copyops.man     transfer::copy              {Data transfer foundation}]
[item modules/transfer/tqueue.man      transfer::copy::queue       {Queued transfers}]
[item modules/transfer/ddest.man       transfer::data::destination {Data destination}]
[item modules/transfer/dsource.man     transfer::data::source      {Data source}]
[item modules/transfer/receiver.man    transfer::receiver          {Data source}]
[item modules/transfer/transmitter.man transfer::transmitter       {Data source}]
[division_end]
[division_start Unfiled]
[item modules/cache/async.man                cache::async             {Asynchronous in-memory cache}]

[item modules/generator/generator.man        generator                {Procedures for creating and using generators.}]
[item modules/yaml/huddle.man                huddle                   {Create and manipulate huddle object}]
[item modules/imap4/imap4.man                imap4                    {imap client-side tcl implementation of imap protocol}]
[item modules/map/map_geocode_nominatim.man  map::geocode::nominatim  {Resolving geographical names with a Nominatim service}]
[item modules/map/map_slippy.man             map::slippy              {Common code for slippy based map packages}]
[item modules/map/map_slippy_cache.man       map::slippy::cache       {Management of a tile cache in the local filesystem}]
[item modules/map/map_slippy_fetcher.man     map::slippy::fetcher     {Accessing a server providing tiles for slippy-based maps}]
[item modules/mapproj/mapproj.man            mapproj                  {Map projection routines}]
[item modules/math/symdiff.man               math::calculus::symdiff  {Symbolic differentiation for Tcl}]
[item modules/namespacex/namespacex.man      namespacex               {Namespace utility commands}]
[item modules/rest/rest.man                  rest                     {define REST web APIs and call them inline or asychronously}]
[item modules/stringprep/stringprep.man      stringprep               {Implementation of stringprep}]
[item modules/stringprep/stringprep_data.man stringprep::data         {stringprep data tables, generated, internal}]

[item modules/math/machineparameters.man     tclrep/machineparameters {Compute double precision machine parameters.}]
[item modules/uev/uevent_onidle.man          uevent::onidle           {Request merging and deferal to idle time}]
[item modules/stringprep/unicode.man         unicode                  {Implementation of Unicode normalization}]
[item modules/stringprep/unicode_data.man    unicode::data            {unicode data tables, generated, internal}]
[item modules/units/units.man                units                    {unit conversion}]
[item modules/yaml/yaml.man                  yaml                     {YAML Format Encoder/Decoder}]
[division_end]







>




















>


<










>







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
[item modules/markdown/markdown.man        markdown             {Converts Markdown text to HTML}]
[item modules/mime/mime.man                mime                 {Manipulation of MIME body parts}]
[item modules/rcs/rcs.man                  rcs                  {RCS low level utilities}]
[item modules/string/token.man             string::token        {Regex based iterative lexing}]
[item modules/string/token_shell.man       string::token::shell {Parsing of shell command line}]
[item modules/textutil/textutil.man        textutil             {Procedures to manipulate texts and strings.}]
[item modules/textutil/adjust.man          textutil::adjust     {Procedures to adjust, indent, and undent paragraphs}]
[item modules/textutil/patch.man           textutil::patch      {Application of uni-diff patches to directory trees}]
[item modules/textutil/repeat.man          textutil::repeat     {Procedures to repeat strings.}]
[item modules/textutil/textutil_split.man  textutil::split      {Procedures to split texts}]
[item modules/textutil/textutil_string.man textutil::string     {Procedures to manipulate texts and strings.}]
[item modules/textutil/tabify.man          textutil::tabify     {Procedures to (un)tabify strings}]
[item modules/textutil/trim.man            textutil::trim       {Procedures to trim strings}]
[item modules/base64/uuencode.man          uuencode             {UU-encode/decode binary data}]
[item modules/amazon-s3/xsxp.man           xsxp                 {eXtremely Simple Xml Parser}]
[item modules/base64/yencode.man           yencode              {Y-encode/decode binary data}]
[division_end]
[division_start {Transfer module}]
[item modules/transfer/connect.man     transfer::connect           {Connection setup}]
[item modules/transfer/copyops.man     transfer::copy              {Data transfer foundation}]
[item modules/transfer/tqueue.man      transfer::copy::queue       {Queued transfers}]
[item modules/transfer/ddest.man       transfer::data::destination {Data destination}]
[item modules/transfer/dsource.man     transfer::data::source      {Data source}]
[item modules/transfer/receiver.man    transfer::receiver          {Data source}]
[item modules/transfer/transmitter.man transfer::transmitter       {Data source}]
[division_end]
[division_start Unfiled]
[item modules/cache/async.man                cache::async             {Asynchronous in-memory cache}]
[item modules/fileutil/paths.man             fileutil::paths          {Manage search path pools}]
[item modules/generator/generator.man        generator                {Procedures for creating and using generators.}]
[item modules/yaml/huddle.man                huddle                   {Create and manipulate huddle object}]

[item modules/map/map_geocode_nominatim.man  map::geocode::nominatim  {Resolving geographical names with a Nominatim service}]
[item modules/map/map_slippy.man             map::slippy              {Common code for slippy based map packages}]
[item modules/map/map_slippy_cache.man       map::slippy::cache       {Management of a tile cache in the local filesystem}]
[item modules/map/map_slippy_fetcher.man     map::slippy::fetcher     {Accessing a server providing tiles for slippy-based maps}]
[item modules/mapproj/mapproj.man            mapproj                  {Map projection routines}]
[item modules/math/symdiff.man               math::calculus::symdiff  {Symbolic differentiation for Tcl}]
[item modules/namespacex/namespacex.man      namespacex               {Namespace utility commands}]
[item modules/rest/rest.man                  rest                     {define REST web APIs and call them inline or asychronously}]
[item modules/stringprep/stringprep.man      stringprep               {Implementation of stringprep}]
[item modules/stringprep/stringprep_data.man stringprep::data         {stringprep data tables, generated, internal}]
[item modules/struct/struct_map.man          struct::map              {Manage key/value maps}]
[item modules/math/machineparameters.man     tclrep/machineparameters {Compute double precision machine parameters.}]
[item modules/uev/uevent_onidle.man          uevent::onidle           {Request merging and deferal to idle time}]
[item modules/stringprep/unicode.man         unicode                  {Implementation of Unicode normalization}]
[item modules/stringprep/unicode_data.man    unicode::data            {unicode data tables, generated, internal}]
[item modules/units/units.man                units                    {unit conversion}]
[item modules/yaml/yaml.man                  yaml                     {YAML Format Encoder/Decoder}]
[division_end]

Changes to support/devel/sak/doc/toc_mods.txt.

38
39
40
41
42
43
44



45
46
47
48
49
50
51
[division_end]
[division_start blowfish]
[item modules/blowfish/blowfish.man blowfish {Implementation of the Blowfish block cipher}]
[division_end]
[division_start cache]
[item modules/cache/async.man cache::async {Asynchronous in-memory cache}]
[division_end]



[division_start clock]
[item modules/clock/iso8601.man clock_iso8601 {Parsing ISO 8601 dates/times}]
[item modules/clock/rfc2822.man clock_rfc2822 {Parsing ISO 8601 dates/times}]
[division_end]
[division_start cmdline]
[item modules/cmdline/cmdline.man cmdline {Procedures to process command lines and options.}]
[division_end]







>
>
>







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
[division_end]
[division_start blowfish]
[item modules/blowfish/blowfish.man blowfish {Implementation of the Blowfish block cipher}]
[division_end]
[division_start cache]
[item modules/cache/async.man cache::async {Asynchronous in-memory cache}]
[division_end]
[division_start clay]
[item modules/clay/clay.man clay {A minimalist framework for large scale OO Projects}]
[division_end]
[division_start clock]
[item modules/clock/iso8601.man clock_iso8601 {Parsing ISO 8601 dates/times}]
[item modules/clock/rfc2822.man clock_rfc2822 {Parsing ISO 8601 dates/times}]
[division_end]
[division_start cmdline]
[item modules/cmdline/cmdline.man cmdline {Procedures to process command lines and options.}]
[division_end]
175
176
177
178
179
180
181

182
183
184
185
186
187
188
[division_start dtplite]
[item modules/dtplite/pkg_dtplite.man dtplite {Lightweight DocTools Markup Processor}]
[division_end]
[division_start fileutil]
[item modules/fileutil/fileutil.man fileutil            {Procedures implementing some file utilities}]
[item modules/fileutil/multi.man    fileutil::multi     {Multi-file operation, scatter/gather, standard object}]
[item modules/fileutil/multiop.man  fileutil::multi::op {Multi-file operation, scatter/gather}]

[item modules/fileutil/traverse.man fileutil_traverse   {Iterative directory traversal}]
[division_end]
[division_start ftp]
[item modules/ftp/ftp.man        ftp         {Client-side tcl implementation of the ftp protocol}]
[item modules/ftp/ftp_geturl.man ftp::geturl {Uri handler for ftp urls}]
[division_end]
[division_start ftpd]







>







178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
[division_start dtplite]
[item modules/dtplite/pkg_dtplite.man dtplite {Lightweight DocTools Markup Processor}]
[division_end]
[division_start fileutil]
[item modules/fileutil/fileutil.man fileutil            {Procedures implementing some file utilities}]
[item modules/fileutil/multi.man    fileutil::multi     {Multi-file operation, scatter/gather, standard object}]
[item modules/fileutil/multiop.man  fileutil::multi::op {Multi-file operation, scatter/gather}]
[item modules/fileutil/paths.man    fileutil::paths     {Manage search path pools}]
[item modules/fileutil/traverse.man fileutil_traverse   {Iterative directory traversal}]
[division_end]
[division_start ftp]
[item modules/ftp/ftp.man        ftp         {Client-side tcl implementation of the ftp protocol}]
[item modules/ftp/ftp_geturl.man ftp::geturl {Uri handler for ftp urls}]
[division_end]
[division_start ftpd]
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
[division_start htmlparse]
[item modules/htmlparse/htmlparse.man htmlparse {Procedures to parse HTML strings}]
[division_end]
[division_start http]
[item modules/http/autoproxy.man autoproxy {Automatic HTTP proxy usage and authentication}]
[division_end]
[division_start httpd]
[item modules/httpd/httpd.man tool {A TclOO and coroutine based web server}]
[division_end]
[division_start ident]
[item modules/ident/ident.man ident {Ident protocol client}]
[division_end]
[division_start imap4]
[item modules/imap4/imap4.man imap4 {imap client-side tcl implementation of imap protocol}]
[division_end]







|







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
[division_start htmlparse]
[item modules/htmlparse/htmlparse.man htmlparse {Procedures to parse HTML strings}]
[division_end]
[division_start http]
[item modules/http/autoproxy.man autoproxy {Automatic HTTP proxy usage and authentication}]
[division_end]
[division_start httpd]
[item modules/httpd/httpd.man httpd {A TclOO and coroutine based web server}]
[division_end]
[division_start ident]
[item modules/ident/ident.man ident {Ident protocol client}]
[division_end]
[division_start imap4]
[item modules/imap4/imap4.man imap4 {imap client-side tcl implementation of imap protocol}]
[division_end]
311
312
313
314
315
316
317

318
319
320
321
322
323
324
[item modules/math/math_geometry.man     math::geometry           {Geometrical computations}]
[item modules/math/interpolate.man       math::interpolate        {Interpolation routines}]
[item modules/math/linalg.man            math::linearalgebra      {Linear Algebra}]
[item modules/math/numtheory.man         math::numtheory          {Number Theory}]
[item modules/math/optimize.man          math::optimize           {Optimisation routines}]
[item modules/math/pca.man               math::PCA                {Package for Principal Component Analysis}]
[item modules/math/polynomials.man       math::polynomials        {Polynomial functions}]

[item modules/math/rational_funcs.man    math::rationalfunctions  {Polynomial functions}]
[item modules/math/roman.man             math::roman              {Tools for creating and manipulating roman numerals}]
[item modules/math/special.man           math::special            {Special mathematical functions}]
[item modules/math/statistics.man        math::statistics         {Basic statistical functions and procedures}]
[item modules/math/trig.man              math::trig               {Trigonometric anf hyperbolic functions}]
[item modules/math/machineparameters.man tclrep/machineparameters {Compute double precision machine parameters.}]
[division_end]







>







315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
[item modules/math/math_geometry.man     math::geometry           {Geometrical computations}]
[item modules/math/interpolate.man       math::interpolate        {Interpolation routines}]
[item modules/math/linalg.man            math::linearalgebra      {Linear Algebra}]
[item modules/math/numtheory.man         math::numtheory          {Number Theory}]
[item modules/math/optimize.man          math::optimize           {Optimisation routines}]
[item modules/math/pca.man               math::PCA                {Package for Principal Component Analysis}]
[item modules/math/polynomials.man       math::polynomials        {Polynomial functions}]
[item modules/math/quasirandom.man       math::quasirandom        {Quasi-random points for integration and Monte Carlo type methods}]
[item modules/math/rational_funcs.man    math::rationalfunctions  {Polynomial functions}]
[item modules/math/roman.man             math::roman              {Tools for creating and manipulating roman numerals}]
[item modules/math/special.man           math::special            {Special mathematical functions}]
[item modules/math/statistics.man        math::statistics         {Basic statistical functions and procedures}]
[item modules/math/trig.man              math::trig               {Trigonometric anf hyperbolic functions}]
[item modules/math/machineparameters.man tclrep/machineparameters {Compute double precision machine parameters.}]
[division_end]
512
513
514
515
516
517
518

519
520
521
522
523
524
525
[division_end]
[division_start struct]
[item modules/struct/disjointset.man  struct::disjointset {Disjoint set data structure}]
[item modules/struct/graph.man        struct::graph       {Create and manipulate directed graph objects}]
[item modules/struct/graphops.man     struct::graph::op   {Operation for (un)directed graph objects}]
[item modules/struct/graph1.man       struct::graph_v1    {Create and manipulate directed graph objects}]
[item modules/struct/struct_list.man  struct::list        {Procedures for manipulating lists}]

[item modules/struct/matrix.man       struct::matrix      {Create and manipulate matrix objects}]
[item modules/struct/matrix1.man      struct::matrix_v1   {Create and manipulate matrix objects}]
[item modules/struct/pool.man         struct::pool        {Create and manipulate pool objects (of discrete items)}]
[item modules/struct/prioqueue.man    struct::prioqueue   {Create and manipulate prioqueue objects}]
[item modules/struct/queue.man        struct::queue       {Create and manipulate queue objects}]
[item modules/struct/record.man       struct::record      {Define and create records (similar to 'C' structures)}]
[item modules/struct/struct_set.man   struct::set         {Procedures for manipulating sets}]







>







517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
[division_end]
[division_start struct]
[item modules/struct/disjointset.man  struct::disjointset {Disjoint set data structure}]
[item modules/struct/graph.man        struct::graph       {Create and manipulate directed graph objects}]
[item modules/struct/graphops.man     struct::graph::op   {Operation for (un)directed graph objects}]
[item modules/struct/graph1.man       struct::graph_v1    {Create and manipulate directed graph objects}]
[item modules/struct/struct_list.man  struct::list        {Procedures for manipulating lists}]
[item modules/struct/struct_map.man   struct::map         {Manage key/value maps}]
[item modules/struct/matrix.man       struct::matrix      {Create and manipulate matrix objects}]
[item modules/struct/matrix1.man      struct::matrix_v1   {Create and manipulate matrix objects}]
[item modules/struct/pool.man         struct::pool        {Create and manipulate pool objects (of discrete items)}]
[item modules/struct/prioqueue.man    struct::prioqueue   {Create and manipulate prioqueue objects}]
[item modules/struct/queue.man        struct::queue       {Create and manipulate queue objects}]
[item modules/struct/record.man       struct::record      {Define and create records (similar to 'C' structures)}]
[item modules/struct/struct_set.man   struct::set         {Procedures for manipulating sets}]
551
552
553
554
555
556
557

558
559
560
561
562
563
564
[item modules/term/term_bind.man    term::receive::bind      {Keyboard dispatch from terminals}]
[item modules/term/term_send.man    term::send               {General output to terminals}]
[division_end]
[division_start textutil]
[item modules/textutil/textutil.man        textutil           {Procedures to manipulate texts and strings.}]
[item modules/textutil/adjust.man          textutil::adjust   {Procedures to adjust, indent, and undent paragraphs}]
[item modules/textutil/expander.man        textutil::expander {Procedures to process templates and expand text.}]

[item modules/textutil/repeat.man          textutil::repeat   {Procedures to repeat strings.}]
[item modules/textutil/textutil_split.man  textutil::split    {Procedures to split texts}]
[item modules/textutil/textutil_string.man textutil::string   {Procedures to manipulate texts and strings.}]
[item modules/textutil/tabify.man          textutil::tabify   {Procedures to (un)tabify strings}]
[item modules/textutil/trim.man            textutil::trim     {Procedures to trim strings}]
[division_end]
[division_start tie]







>







557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
[item modules/term/term_bind.man    term::receive::bind      {Keyboard dispatch from terminals}]
[item modules/term/term_send.man    term::send               {General output to terminals}]
[division_end]
[division_start textutil]
[item modules/textutil/textutil.man        textutil           {Procedures to manipulate texts and strings.}]
[item modules/textutil/adjust.man          textutil::adjust   {Procedures to adjust, indent, and undent paragraphs}]
[item modules/textutil/expander.man        textutil::expander {Procedures to process templates and expand text.}]
[item modules/textutil/patch.man           textutil::patch    {Application of uni-diff patches to directory trees}]
[item modules/textutil/repeat.man          textutil::repeat   {Procedures to repeat strings.}]
[item modules/textutil/textutil_split.man  textutil::split    {Procedures to split texts}]
[item modules/textutil/textutil_string.man textutil::string   {Procedures to manipulate texts and strings.}]
[item modules/textutil/tabify.man          textutil::tabify   {Procedures to (un)tabify strings}]
[item modules/textutil/trim.man            textutil::trim     {Procedures to trim strings}]
[division_end]
[division_start tie]

Changes to support/devel/sak/localdoc/localdoc.tcl.

40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
    set nav ../../../../home

    puts "Reindex the documentation..."
    sak::doc::imake __dummy__ $excluded
    sak::doc::index __dummy__ $excluded

    puts "Removing old documentation..."
    # but keep the main index around, manually created, edited, not to be touched

    # TODO: catch errors and restore automatically
    file rename embedded/index.md e_index.md

    file delete -force embedded
    file mkdir embedded/md

    # Put the saved main page back into place, early.
    file rename e_index.md embedded/index.md

    run-idoc-man $baseconfig







|
>


<







40
41
42
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
    set nav ../../../../home

    puts "Reindex the documentation..."
    sak::doc::imake __dummy__ $excluded
    sak::doc::index __dummy__ $excluded

    puts "Removing old documentation..."
    # Keep the main index around however, manually created, edited,
    # not to be touched
    # TODO: catch errors and restore automatically
    file rename embedded/index.md e_index.md

    file delete -force embedded
    file mkdir embedded/md

    # Put the saved main page back into place, early.
    file rename e_index.md embedded/index.md

    run-idoc-man $baseconfig

Changes to support/devel/sak/test/run.tcl.

69
70
71
72
73
74
75

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

94




95
96
97
98
99
100
101
# ###

proc ::sak::test::run::Do {cv modules} {
    upvar 1 $cv config
    variable valgrind
    variable araw     $config(raw)
    variable alog     $config(log)

    # alog => !araw

    set shells $config(shells)
    if {![llength $shells]} {
	catch {set shells [sak::test::shell::list]}
    }
    if {![llength $shells]} {
	set shells [list [info nameofexecutable]]
    }

    if {$alog} {
	variable logext [open $config(stem).log         w]
	variable logsum [open $config(stem).summary     w]
	variable logfai [open $config(stem).failures    w]
	variable logski [open $config(stem).skipped     w]
	variable lognon [open $config(stem).none        w]
	variable logerd [open $config(stem).errdetails  w]
	variable logfad [open $config(stem).faildetails w]

	variable logtim [open $config(stem).timings     w]




    } else {
	variable logext stdout
    }

    # Preprocessing of module names and shell versions to allows
    # better formatting of the progress output, i.e. vertically
    # aligned columns







>


















>

>
>
>
>







69
70
71
72
73
74
75
76
77
78
79
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
# ###

proc ::sak::test::run::Do {cv modules} {
    upvar 1 $cv config
    variable valgrind
    variable araw     $config(raw)
    variable alog     $config(log)
    variable xttimes {}
    # alog => !araw

    set shells $config(shells)
    if {![llength $shells]} {
	catch {set shells [sak::test::shell::list]}
    }
    if {![llength $shells]} {
	set shells [list [info nameofexecutable]]
    }

    if {$alog} {
	variable logext [open $config(stem).log         w]
	variable logsum [open $config(stem).summary     w]
	variable logfai [open $config(stem).failures    w]
	variable logski [open $config(stem).skipped     w]
	variable lognon [open $config(stem).none        w]
	variable logerd [open $config(stem).errdetails  w]
	variable logfad [open $config(stem).faildetails w]
	# Timings per testsuite (sec), average test timings (usec)
	variable logtim [open $config(stem).timings     w]
	variable logtmt [open $config(stem).timetable   w]
	# Timings per test (usec)
	variable logtti [open $config(stem).t-timings   w]
	variable logtmi [open $config(stem).t-timetable w]
    } else {
	variable logext stdout
    }

    # Preprocessing of module names and shell versions to allows
    # better formatting of the progress output, i.e. vertically
    # aligned columns
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
    }
    if {$err} {
	puts $logext "#Errors [mag][format %6d $err][rst]"
    } else {
	puts $logext "#Errors [format %6d $err]"
    }





    if {$alog} {




	variable xtimes
	array set times $xtimes

	struct::matrix M
	M add columns 6
	foreach k [lsort -dict [array names times]] {


	    #foreach {shell module testfile} $k break

	    foreach {testnum delta score} $times($k) break
	    M add row [linsert $k end $testnum $delta $score]
	}
	M sort rows -decreasing 5













	M insert row 0 {Shell Module Testsuite Tests Seconds uSec/Test}
	M insert row 1 {===== ====== ========= ===== ======= =========}






	M add    row   {===== ====== ========= ===== ======= =========}

	puts $logsum \nTimings...
	puts $logsum [M format 2string]



    }

    exit [expr {($err || $fail) ? 1 : 0}]
    return
}

# ###







>
>
>
>

>
>
>
>

<



|
>
>
|
>
|


|
>

>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
|

|
|
>
>
>







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
    }
    if {$err} {
	puts $logext "#Errors [mag][format %6d $err][rst]"
    } else {
	puts $logext "#Errors [format %6d $err]"
    }

    flush $logext

    =| "... Done"
    
    if {$alog} {
	# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	# Timings per testsuite
	=| "... Postprocessing per-testsuite timings ..."
	
	variable xtimes


	struct::matrix M
	M add columns 6

	M add row {Shell Module Testsuite Tests Seconds uSec/Test}
	M add row {===== ====== ========= ===== ======= =========}

	foreach item [lsort -decreasing -int -index 3 [lsort -dict -index 0 $xtimes]] {
	    foreach {k testnum delta score} $item break
	    M add row [linsert $k end $testnum $delta $score]
	}

	M add row {===== ====== ========= ===== ======= =========}

	puts $logtmt "\nTiming Table..."
	puts $logtmt [M format 2string]

	# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	# Timings per testcase.
	=| "... Postprocessing per-test timings ..."
	
	variable xttimes
	struct::matrix MX
	MX add columns 5

	MX add row {Shell Module Testsuite Test uSec}
	MX add row {===== ====== ========= ==== ====}

	foreach item [lsort -index 1 -integer -decreasing [lsort -index 0 -dict $xttimes]] {
	    foreach {k usec} $item break
	    MX add row [linsert $k end $usec]
	}

	MX add row {===== ====== ========= ==== ====}

	puts $logtmi "\nTiming Table..."
	puts $logtmi [MX format 2string]

	# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	=| "... Postprocessing Done"
    }

    exit [expr {($err || $fail) ? 1 : 0}]
    return
}

# ###
288
289
290
291
292
293
294

295
296
297
298
299
300
301
	CaptureFailureCollectActual   ; # xcollect 3 => 4
	CaptureFailureCollectExpected ; # xcollect 4 => 0
	CaptureFailureCollectError    ; # xcollect 5 => 0
	CaptureStackStart
	CaptureStack

	TestStart

	TestSkipped
	TestPassed
	TestFailed                    ; # xcollect => 1

	SetupError
	Aborted
	AbortCause







>







325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
	CaptureFailureCollectActual   ; # xcollect 3 => 4
	CaptureFailureCollectExpected ; # xcollect 4 => 0
	CaptureFailureCollectError    ; # xcollect 5 => 0
	CaptureStackStart
	CaptureStack

	TestStart
	TestTook
	TestSkipped
	TestPassed
	TestFailed                    ; # xcollect => 1

	SetupError
	Aborted
	AbortCause
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
proc ::sak::test::run::EndFile {} {
    upvar 1 line line
    if {![regexp "^@@ EndFile (.*)$" $line -> end]} return
    variable xfile
    variable xstartfile
    variable xtimes
    variable xtestnum


    set k [lreplace $xfile 0 3]
    set k [lreplace $k 2 2 [file tail [lindex $k 2]]]
    set delta [expr {$end - $xstartfile}]


    if {$xtestnum == 0} {
	set score $delta
    } else {
	# average number of microseconds per test.
	set score [expr {int(($delta/double($xtestnum))*1000000)}]
	#set score [expr {$delta/double($xtestnum)}]
    }

    lappend xtimes $k [list $xtestnum $delta $score]

    variable alog
    if {$alog} {
	variable logtim
	puts $logtim [linsert [linsert $k end $xtestnum $delta $score] 0 TIME]
    }

    #sak::registry::local set $xshell End $end
    return -code continue
}

proc ::sak::test::run::Module {} {
    upvar 1 line line ; variable xmodule
    if {![regexp "^@@ Module (.*)$" $line -> xmodule]} return
    variable xshell
    variable xstatus ok
    variable maxml

    += ${xmodule}[blank [expr {$maxml - [string length $xmodule]}]]
    set xmodule [linsert $xshell end $xmodule]
    #sak::registry::local set $xmodule
    return -code continue
}

proc ::sak::test::run::Testsuite {} {







>




>









|

















>







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
proc ::sak::test::run::EndFile {} {
    upvar 1 line line
    if {![regexp "^@@ EndFile (.*)$" $line -> end]} return
    variable xfile
    variable xstartfile
    variable xtimes
    variable xtestnum
    variable xduration

    set k [lreplace $xfile 0 3]
    set k [lreplace $k 2 2 [file tail [lindex $k 2]]]
    set delta [expr {$end - $xstartfile}]
    incr xduration $delta

    if {$xtestnum == 0} {
	set score $delta
    } else {
	# average number of microseconds per test.
	set score [expr {int(($delta/double($xtestnum))*1000000)}]
	#set score [expr {$delta/double($xtestnum)}]
    }

    lappend xtimes [list $k $xtestnum $delta $score]

    variable alog
    if {$alog} {
	variable logtim
	puts $logtim [linsert [linsert $k end $xtestnum $delta $score] 0 TIME]
    }

    #sak::registry::local set $xshell End $end
    return -code continue
}

proc ::sak::test::run::Module {} {
    upvar 1 line line ; variable xmodule
    if {![regexp "^@@ Module (.*)$" $line -> xmodule]} return
    variable xshell
    variable xstatus ok
    variable maxml
    variable xduration 0
    += ${xmodule}[blank [expr {$maxml - [string length $xmodule]}]]
    set xmodule [linsert $xshell end $xmodule]
    #sak::registry::local set $xmodule
    return -code continue
}

proc ::sak::test::run::Testsuite {} {
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

proc ::sak::test::run::Summary {} {
    upvar 1 line line
    if {![regexp "^all\\.tcl:(.*)$" $line -> line]} return
    variable xmodule
    variable xstatus
    variable xvstatus

    foreach {_ t _ p _ s _ f} [split [string trim $line]] break
    #sak::registry::local set $xmodule Total   $t ; set t [format %5d $t]
    #sak::registry::local set $xmodule Passed  $p ; set p [format %5d $p]
    #sak::registry::local set $xmodule Skipped $s ; set s [format %5d $s]
    #sak::registry::local set $xmodule Failed  $f ; set f [format %5d $f]

    upvar 2 total _total ; incr _total $t
    upvar 2 pass  _pass  ; incr _pass  $p
    upvar 2 skip  _skip  ; incr _skip  $s
    upvar 2 fail  _fail  ; incr _fail  $f
    upvar 2 err   _err

    set t [format %5d $t]
    set p [format %5d $p]
    set s [format %5d $s]
    set f [format %5d $f]

    if {$xstatus == "ok" && $t == 0} {
	set xstatus none











    }

    set st $xvstatus($xstatus)

    if {$xstatus == "ok"} {
	# Quick return for ok suite.
	=| "~~ $st T $t P $p S $s F $f"
	return -code continue
    }

    # Clean out progress display using a non-highlighted
    # string. Prevents the char couint from being off. This is
    # followed by construction and display of the highlighted version.

    = "   $st T $t P $p S $s F $f"
    switch -exact -- $xstatus {
	none    {=| "~~ [yel]$st T $t[rst] P $p S $s F $f"}
	aborted {=| "~~ [whi]$st[rst] T $t P $p S $s F $f"}
	error   {
	    =| "~~ [mag]$st[rst] T $t P $p S $s F $f"
	    incr _err
	}
	fail    {=| "~~ [red]$st[rst] T $t P $p S $s [red]F $f[rst]"}
    }
    return -code continue
}

proc ::sak::test::run::TestStart {} {
    upvar 1 line line
    if {![string match {---- * start} $line]} return
    set testname [string range $line 5 end-6]
    = "---- $testname"
    variable xfile

    variable xtest [linsert $xfile end $testname]
    variable xtestnum
    incr     xtestnum
    return -code continue
}













proc ::sak::test::run::TestSkipped {} {
    upvar 1 line line
    if {![string match {++++ * SKIPPED:*} $line]} return
    regexp {^[^ ]* (.*)SKIPPED:.*$} $line -> testname
    set              testname [string trim $testname]
    variable xtest







>



















>
>
>
>
>
>
>
>
>
>
>






|




|


|


|
<
|
<
<
|










>





>
>
>
>
>
>
>
>
>
>
>
>







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

proc ::sak::test::run::Summary {} {
    upvar 1 line line
    if {![regexp "^all\\.tcl:(.*)$" $line -> line]} return
    variable xmodule
    variable xstatus
    variable xvstatus
    
    foreach {_ t _ p _ s _ f} [split [string trim $line]] break
    #sak::registry::local set $xmodule Total   $t ; set t [format %5d $t]
    #sak::registry::local set $xmodule Passed  $p ; set p [format %5d $p]
    #sak::registry::local set $xmodule Skipped $s ; set s [format %5d $s]
    #sak::registry::local set $xmodule Failed  $f ; set f [format %5d $f]

    upvar 2 total _total ; incr _total $t
    upvar 2 pass  _pass  ; incr _pass  $p
    upvar 2 skip  _skip  ; incr _skip  $s
    upvar 2 fail  _fail  ; incr _fail  $f
    upvar 2 err   _err

    set t [format %5d $t]
    set p [format %5d $p]
    set s [format %5d $s]
    set f [format %5d $f]

    if {$xstatus == "ok" && $t == 0} {
	set xstatus none
	set spent ""
    } else {
	# Time spent on all the files in the module.
	variable xduration
	#set sec $xduration
	#set min [expr {$sec / 60}]
	#set sec [expr {$sec % 60}]
	#set hor [expr {$min / 60}]
	#set min [expr {$min % 60}]
	#set spent " :[format %02d $hor]h[format %02d $min]m[format %02d $sec]s"
	set spent " @${xduration}s"
    }

    set st $xvstatus($xstatus)

    if {$xstatus == "ok"} {
	# Quick return for ok suite.
	=| "~~ $st T $t P $p S $s F $f$spent"
	return -code continue
    }

    # Clean out progress display using a non-highlighted
    # string. Prevents the char count from being off. This is
    # followed by construction and display of the highlighted version.

    = "   $st T $t P $p S $s F $f$spent"
    switch -exact -- $xstatus {
	none    {=| "~~ [yel]$st T $t[rst] P $p S $s F $f"}
	aborted {=| "~~ [whi]$st[rst] T $t P $p S $s F $f$spent"}

	error   {=| "~~ [mag]$st[rst] T $t P $p S $s F $f$spent" ; incr _err }


	fail    {=| "~~ [red]$st[rst] T $t P $p S $s [red]F $f[rst]$spent"}
    }
    return -code continue
}

proc ::sak::test::run::TestStart {} {
    upvar 1 line line
    if {![string match {---- * start} $line]} return
    set testname [string range $line 5 end-6]
    = "---- $testname"
    variable xfile
    variable xtesttime -1
    variable xtest [linsert $xfile end $testname]
    variable xtestnum
    incr     xtestnum
    return -code continue
}

proc ::sak::test::run::TestTook {} {
    upvar 1 line line
    if {![string match {++++ * took *} $line]} return
    # Dynamic search for the marker because the name of the test may
    # contain spaces, causing the field position to vary.
    set  pos [lsearch -exact $line took]
    incr pos
    set usec [lindex $line $pos]
    variable xtesttime $usec
    return -code continue
}

proc ::sak::test::run::TestSkipped {} {
    upvar 1 line line
    if {![string match {++++ * SKIPPED:*} $line]} return
    regexp {^[^ ]* (.*)SKIPPED:.*$} $line -> testname
    set              testname [string trim $testname]
    variable xtest
567
568
569
570
571
572
573

574

575
576
577
578
579
580











581
582
583
584
585
586
587
    return -code continue
}

proc ::sak::test::run::TestPassed {} {
    upvar 1 line line
    if {![string match {++++ * PASSED} $line]} return
    set             testname [string range $line 5 end-7]

    variable xtest

    = "PASS $testname"
    if {$xtest == {}} {
	variable xfile
	set xtest [linsert $xfile end $testname]
    }
    #sak::registry::local set $xtest Status Pass











    set xtest {}
    return -code continue
}

proc ::sak::test::run::TestFailed {} {
    upvar 1 line line
    if {![string match {==== * FAILED} $line]} return







>

>
|





>
>
>
>
>
>
>
>
>
>
>







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
    return -code continue
}

proc ::sak::test::run::TestPassed {} {
    upvar 1 line line
    if {![string match {++++ * PASSED} $line]} return
    set             testname [string range $line 5 end-7]
    variable xtesttime
    variable xtest
    if {$xtesttime < 0} { set xtesttime "" }
    = [string trimright "PASS $testname $xtesttime"]
    if {$xtest == {}} {
	variable xfile
	set xtest [linsert $xfile end $testname]
    }
    #sak::registry::local set $xtest Status Pass
    variable alog
    if {$alog && ($xtesttime ne {})} {
	variable xttimes
	variable logtti
	set k [lreplace $xtest 0 3]
	set k [lreplace $k 2 2 [file tail [lindex $k 2]]]
	# k = shell module testfile testname
	puts $logtti [linsert [linsert $k 0 TIME] end $xtesttime]

	lappend xttimes [list $k $xtesttime]
    }
    set xtest {}
    return -code continue
}

proc ::sak::test::run::TestFailed {} {
    upvar 1 line line
    if {![string match {==== * FAILED} $line]} return

Changes to support/installation/modules.tcl.

29
30
31
32
33
34
35





36
37
38
39
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54

# --------------------------------------------------------------
# @@ Registration START

Exclude calendar
Exclude exif






#       name         pkg   doc   example
Module  aes         _tcl  _man  _null
Module  amazon-s3   _tcl  _man  _null
Module  asn         _tcl  _man  _null
Module  base32      _tcl  _man  _null
Module  base64      _tcl  _man  _null
Module  bee         _tcl  _man  _null
Module  bench       _tcl _null  _null
Module  bibtex      _tcl  _man  _exa
Module  blowfish    _tcl  _man  _null
Module  cache       _tcl  _man  _null
Module  calendar     _tci _man  _null

Module  clock       _tcl  _man _null
Module  cmdline     _tcl  _man  _null
Module  comm        _tcl  _man  _null
Module  control      _tci _man  _null
Module  coroutine   _tcl _null  _null
Module  counter     _tcl  _man  _null
Module  crc         _tcl  _man  _null







>
>
>
>
>












>







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

# --------------------------------------------------------------
# @@ Registration START

Exclude calendar
Exclude exif

#       name           pkg   doc   example
Module  0compatibility _tcl  _null  _null
# Wrapper packages redirecting deprecated/moved packages to their old
# implementations. See pkgIndex.tcl for more notes.

#       name         pkg   doc   example
Module  aes         _tcl  _man  _null
Module  amazon-s3   _tcl  _man  _null
Module  asn         _tcl  _man  _null
Module  base32      _tcl  _man  _null
Module  base64      _tcl  _man  _null
Module  bee         _tcl  _man  _null
Module  bench       _tcl _null  _null
Module  bibtex      _tcl  _man  _exa
Module  blowfish    _tcl  _man  _null
Module  cache       _tcl  _man  _null
Module  calendar     _tci _man  _null
Module  clay        _tcl  _man _null
Module  clock       _tcl  _man _null
Module  cmdline     _tcl  _man  _null
Module  comm        _tcl  _man  _null
Module  control      _tci _man  _null
Module  coroutine   _tcl _null  _null
Module  counter     _tcl  _man  _null
Module  crc         _tcl  _man  _null